use async_trait::async_trait;
use std::path::Path;
use vx_plugin::{
Ecosystem, PackageSpec, PluginRegistryBuilder, Result, VersionInfo, VxPackageManager, VxPlugin,
VxTool,
};
struct ExampleTool;
#[async_trait]
impl VxTool for ExampleTool {
fn name(&self) -> &str {
"example-tool"
}
fn description(&self) -> &str {
"An example development tool"
}
fn aliases(&self) -> Vec<&str> {
vec!["et", "example"]
}
async fn fetch_versions(&self, include_prerelease: bool) -> Result<Vec<VersionInfo>> {
let mut versions = vec![
VersionInfo::new("1.0.0"),
VersionInfo::new("1.1.0"),
VersionInfo::new("1.2.0"),
];
if include_prerelease {
versions.push(VersionInfo::new("1.3.0-beta.1").as_prerelease());
}
Ok(versions)
}
}
struct ExamplePackageManager;
#[async_trait]
impl VxPackageManager for ExamplePackageManager {
fn name(&self) -> &str {
"example-pm"
}
fn ecosystem(&self) -> Ecosystem {
Ecosystem::Node
}
fn description(&self) -> &str {
"An example package manager"
}
fn get_config_files(&self) -> Vec<&str> {
vec!["example.json", "example.lock"]
}
async fn install_packages(&self, packages: &[PackageSpec], project_path: &Path) -> Result<()> {
println!("Installing packages in {:?}:", project_path);
for package in packages {
println!(" - {}", package.name);
}
Ok(())
}
}
struct CombinedPlugin {
name: String,
description: String,
version: String,
}
impl CombinedPlugin {
pub fn new() -> Self {
Self {
name: "combined-example-plugin".to_string(),
description: "A plugin that provides both tools and package managers".to_string(),
version: "1.0.0".to_string(),
}
}
}
#[async_trait]
impl VxPlugin for CombinedPlugin {
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> &str {
&self.description
}
fn version(&self) -> &str {
&self.version
}
fn author(&self) -> Option<&str> {
Some("Example Author <author@example.com>")
}
fn homepage(&self) -> Option<&str> {
Some("https://github.com/example/combined-plugin")
}
fn tools(&self) -> Vec<Box<dyn VxTool>> {
vec![Box::new(ExampleTool)]
}
fn package_managers(&self) -> Vec<Box<dyn VxPackageManager>> {
vec![Box::new(ExamplePackageManager)]
}
async fn initialize(&mut self) -> Result<()> {
println!("Initializing combined plugin: {}", self.name);
Ok(())
}
async fn shutdown(&mut self) -> Result<()> {
println!("Shutting down combined plugin: {}", self.name);
Ok(())
}
fn dependencies(&self) -> Vec<&str> {
vec![] }
fn is_compatible_with(&self, vx_version: &str) -> bool {
vx_version.starts_with("0.") || vx_version.starts_with("1.")
}
}
#[tokio::main]
async fn main() -> Result<()> {
println!("=== Combined Plugin Example ===\n");
let plugin = Box::new(CombinedPlugin::new());
println!("Plugin Information:");
println!(" Name: {}", plugin.name());
println!(" Description: {}", plugin.description());
println!(" Version: {}", plugin.version());
println!(" Author: {}", plugin.author().unwrap_or("Unknown"));
println!(" Homepage: {}", plugin.homepage().unwrap_or("None"));
println!(
" Compatible with vx 0.2.6: {}",
plugin.is_compatible_with("0.2.6")
);
println!();
println!("Tools provided:");
let tools = plugin.tools();
for tool in &tools {
println!(" - {} ({})", tool.name(), tool.description());
println!(" Aliases: {:?}", tool.aliases());
match tool.fetch_versions(false).await {
Ok(versions) => {
println!(" Available versions:");
for version in versions {
println!(" - {}", version.version);
}
}
Err(e) => {
println!(" Error fetching versions: {}", e);
}
}
}
println!();
println!("Package managers provided:");
let package_managers = plugin.package_managers();
for pm in &package_managers {
println!(" - {} ({})", pm.name(), pm.description());
println!(" Ecosystem: {:?}", pm.ecosystem());
println!(" Config files: {:?}", pm.get_config_files());
}
println!();
println!("=== Plugin Registry Demo ===\n");
let registry = PluginRegistryBuilder::new()
.with_plugin(Box::new(CombinedPlugin::new()))
.build()
.await?;
println!("Registry contents:");
println!(" Plugins: {:?}", registry.list_plugins());
println!(" Tools: {:?}", registry.list_tools());
println!(" Package managers: {:?}", registry.list_package_managers());
println!();
if let Some(tool) = registry.get_tool("example-tool") {
println!("Found tool: {}", tool.name());
}
if let Some(tool) = registry.get_tool("et") {
println!("Found tool by alias: {}", tool.name());
}
if let Some(pm) = registry.get_package_manager("example-pm") {
println!("Found package manager: {}", pm.name());
}
println!("Tool availability:");
println!(" example-tool: {}", registry.has_tool("example-tool"));
println!(" et (alias): {}", registry.has_tool("et"));
println!(" nonexistent: {}", registry.has_tool("nonexistent"));
println!("Package manager availability:");
println!(
" example-pm: {}",
registry.has_package_manager("example-pm")
);
println!(
" nonexistent: {}",
registry.has_package_manager("nonexistent")
);
println!();
if let Some(metadata) = registry.get_plugin_info("combined-example-plugin") {
println!("Plugin metadata:");
for (key, value) in metadata {
println!(" {}: {}", key, value);
}
}
println!("\nShutting down registry...");
registry.shutdown_all().await?;
Ok(())
}