use crate::{Result, VxPackageManager, VxTool};
use async_trait::async_trait;
use std::collections::HashMap;
#[async_trait]
pub trait VxPlugin: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str {
"A vx plugin"
}
fn version(&self) -> &str {
"0.1.0"
}
fn author(&self) -> Option<&str> {
None
}
fn homepage(&self) -> Option<&str> {
None
}
fn tools(&self) -> Vec<Box<dyn VxTool>> {
vec![]
}
fn package_managers(&self) -> Vec<Box<dyn VxPackageManager>> {
vec![]
}
async fn initialize(&mut self) -> Result<()> {
Ok(())
}
async fn shutdown(&mut self) -> Result<()> {
Ok(())
}
fn supports_tool(&self, tool_name: &str) -> bool {
self.tools()
.iter()
.any(|tool| tool.name() == tool_name || tool.aliases().contains(&tool_name))
}
fn supports_package_manager(&self, pm_name: &str) -> bool {
self.package_managers()
.iter()
.any(|pm| pm.name() == pm_name)
}
fn get_tool(&self, tool_name: &str) -> Option<Box<dyn VxTool>> {
self.tools()
.into_iter()
.find(|tool| tool.name() == tool_name || tool.aliases().contains(&tool_name))
}
fn get_package_manager(&self, pm_name: &str) -> Option<Box<dyn VxPackageManager>> {
self.package_managers()
.into_iter()
.find(|pm| pm.name() == pm_name)
}
fn is_compatible_with(&self, vx_version: &str) -> bool {
let _ = vx_version;
true
}
fn dependencies(&self) -> Vec<&str> {
vec![]
}
fn config_schema(&self) -> Option<serde_json::Value> {
None
}
fn validate_config(&self, _config: &serde_json::Value) -> Result<()> {
Ok(())
}
fn metadata(&self) -> HashMap<String, String> {
let mut metadata = HashMap::new();
metadata.insert("name".to_string(), self.name().to_string());
metadata.insert("version".to_string(), self.version().to_string());
metadata.insert("description".to_string(), self.description().to_string());
if let Some(author) = self.author() {
metadata.insert("author".to_string(), author.to_string());
}
if let Some(homepage) = self.homepage() {
metadata.insert("homepage".to_string(), homepage.to_string());
}
metadata
}
}
pub struct StandardPlugin {
name: String,
description: String,
version: String,
author: Option<String>,
homepage: Option<String>,
tool_factory: Box<dyn Fn() -> Box<dyn VxTool> + Send + Sync>,
}
impl StandardPlugin {
pub fn new<F>(
name: impl Into<String>,
description: impl Into<String>,
version: impl Into<String>,
tool_factory: F,
) -> Self
where
F: Fn() -> Box<dyn VxTool> + Send + Sync + 'static,
{
Self {
name: name.into(),
description: description.into(),
version: version.into(),
author: None,
homepage: None,
tool_factory: Box::new(tool_factory),
}
}
pub fn with_author(mut self, author: impl Into<String>) -> Self {
self.author = Some(author.into());
self
}
pub fn with_homepage(mut self, homepage: impl Into<String>) -> Self {
self.homepage = Some(homepage.into());
self
}
}
#[async_trait]
impl VxPlugin for StandardPlugin {
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> &str {
&self.description
}
fn version(&self) -> &str {
&self.version
}
fn author(&self) -> Option<&str> {
self.author.as_deref()
}
fn homepage(&self) -> Option<&str> {
self.homepage.as_deref()
}
fn tools(&self) -> Vec<Box<dyn VxTool>> {
vec![(self.tool_factory)()]
}
}