| Crates.io | pluggable |
| lib.rs | pluggable |
| version | 0.1.0 |
| created_at | 2025-08-04 17:48:37.392798+00 |
| updated_at | 2025-08-04 17:48:37.392798+00 |
| description | A comprehensive, async plugin system for Rust applications with dependency management and security |
| homepage | https://github.com/tomerlichtash/pluggable |
| repository | https://github.com/tomerlichtash/pluggable |
| max_upload_size | |
| id | 1780990 |
| size | 319,631 |
A comprehensive, async plugin system for Rust applications with dependency management, security, and extensibility.
async/await supportAdd to your Cargo.toml:
[dependencies]
pluggable = "0.1.0"
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");
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(())
}
The repository includes several comprehensive examples:
Run examples with:
cargo run --example text_processor
The plugin system is built around several core components:
For detailed architecture information, see ARCHITECTURE.md.
Pluggable includes a comprehensive testing framework:
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();
}
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
This project is licensed under either of
at your option.
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.