# Pluggable
[](https://crates.io/crates/pluggable)
[](https://docs.rs/pluggable)
[](https://github.com/tomerlichtash/pluggable/actions)
[](LICENSE)
A comprehensive, async plugin system for Rust applications with dependency management, security, and extensibility.
## Features
- ๐ **Async-first**: Built from the ground up with `async`/`await` support
- ๐ **Dependency Management**: Automatic plugin dependency resolution and execution ordering
- ๐ **Security**: Capability-based permission system with sandboxing support
- โก **Performance**: Parallel plugin execution where dependencies allow
- ๐งช **Testing**: Comprehensive testing framework with mocks and harnesses
- ๐ **Observability**: Event system with lifecycle hooks and logging
- ๐ **Developer Experience**: Clean APIs, auto-discovery, and rich configuration
## Quick Start
Add to your `Cargo.toml`:
```toml
[dependencies]
pluggable = "0.1.0"
```
### Basic Plugin Example
```rust
use pluggable::prelude::*;
#[derive(Default)]
pub struct HelloPlugin {
metadata: PluginMetadata,
}
impl HelloPlugin {
pub fn new() -> Self {
Self {
metadata: PluginMetadata::new("hello", "1.0.0"),
}
}
}
#[async_trait]
impl Plugin for HelloPlugin {
fn metadata(&self) -> &PluginMetadata {
&self.metadata
}
fn schema(&self) -> serde_json::Value {
json!({
"type": "object",
"properties": {
"name": { "type": "string", "default": "World" }
}
})
}
async fn initialize(
&mut self,
_config: serde_json::Value,
_context: &PluginContext,
) -> PluginResult<()> {
Ok(())
}
async fn execute(&mut self, _context: &mut PluginContext) -> PluginResult<PluginOutput> {
Ok(PluginOutput::success(json!({
"message": "Hello, World!"
})))
}
async fn cleanup(&mut self, _context: &PluginContext) -> PluginResult<()> {
Ok(())
}
}
// Auto-register the plugin
pluggable::register_plugin!(HelloPlugin, "hello", "1.0.0", "A simple greeting plugin");
```
### Running a Plugin Pipeline
```rust
use pluggable::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create plugin registry and discover plugins
let mut registry = PluginRegistry::new();
let mut discovery = PluginDiscovery::new();
discovery.auto_register_all(&mut registry)?;
// Set up workspace and executor
let workspace = std::path::PathBuf::from("./workspace");
let executor = PluginExecutor::new(registry, workspace);
// Execute the pipeline with automatic dependency resolution
let results = executor.execute_pipeline().await?;
println!("Pipeline completed with {} plugins", results.plugin_outputs.len());
Ok(())
}
```
## Key Concepts
### Plugin System
- **Plugin Trait**: Core trait that all plugins implement
- **Auto-Discovery**: Plugins are automatically discovered and registered
- **Lifecycle Management**: Initialize โ Execute โ Cleanup phases
### Dependency Management
- **Automatic Resolution**: Dependencies are resolved and executed in correct order
- **Parallel Execution**: Independent plugins run concurrently
- **Output Passing**: Plugin outputs are available to dependent plugins
### Security
- **Permission-Based**: Plugins declare required permissions
- **Capability System**: Fine-grained access control
- **Sandboxing**: Optional isolation for untrusted plugins
### Configuration
- **JSON Schema**: Type-safe configuration with validation
- **Flexible Loading**: Support for TOML, YAML, and JSON
- **Environment Integration**: Environment variable expansion
## Examples
The repository includes several comprehensive examples:
- **Text Processor**: Multi-plugin text processing pipeline
- **Plugin Testing**: Comprehensive testing framework usage
- **Security**: Permission system and sandboxing
Run examples with:
```bash
cargo run --example text_processor
```
## Architecture
The plugin system is built around several core components:
- **Registry**: Manages plugin discovery and registration
- **Executor**: Handles plugin lifecycle and dependency resolution
- **Context**: Provides plugins with workspace access and communication
- **Security Manager**: Enforces permission-based access control
- **Event System**: Enables plugin communication and observability
For detailed architecture information, see [ARCHITECTURE.md](ARCHITECTURE.md).
## Testing
Pluggable includes a comprehensive testing framework:
```rust
use pluggable::testing::*;
#[tokio::test]
async fn test_my_plugin() {
let mut harness = PluginTestHarness::new().unwrap();
let plugin = MyPlugin::new();
harness = harness.with_plugin(plugin).unwrap();
let output = harness.execute("my-plugin").await.unwrap();
harness.assert_success(&output).unwrap();
harness.assert_output_contains(&output, "result", &json!("expected")).unwrap();
}
```
## Performance
- **Parallel Execution**: Independent plugins run concurrently
- **Efficient Dependencies**: Topological sorting for optimal execution order
- **Minimal Overhead**: Zero-cost abstractions where possible
- **Resource Management**: Automatic cleanup and memory management
## Contributing
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
## License
This project is licensed under either of
- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.