Skip to main content

vs_core/service/
add.rs

1//! Plugin registration services.
2
3use vs_plugin_api::PluginBackendKind;
4use vs_registry::RegistryEntry;
5
6use crate::plugin_source::is_remote_source;
7use crate::registry_source::fetch_plugin_manifest;
8use crate::{App, CoreError};
9
10impl App {
11    /// Adds a plugin to the local home.
12    pub fn add_plugin(
13        &self,
14        name: Option<&str>,
15        source: Option<String>,
16        backend: Option<PluginBackendKind>,
17        alias: Option<&str>,
18    ) -> Result<RegistryEntry, CoreError> {
19        let entry = if let Some(source) = source {
20            let backend = backend.unwrap_or(self.default_backend()?);
21            self.ensure_backend_supported(backend)?;
22            let requested_name = name.or(alias).unwrap_or("plugin");
23            let seed_entry = RegistryEntry {
24                name: requested_name.to_string(),
25                source: if is_remote_source(&source) {
26                    source
27                } else {
28                    self.normalize_source_path(&source).display().to_string()
29                },
30                backend,
31                description: None,
32                aliases: Vec::new(),
33            };
34            let materialized = self.materialize_plugin_entry(&seed_entry)?;
35            let plugin = self.load_plugin(&materialized)?;
36            let manifest = plugin.manifest().clone();
37            let final_name = alias.or(name).unwrap_or(&manifest.name).to_string();
38            let mut aliases = manifest.aliases;
39            push_alias(&mut aliases, name);
40            push_alias(&mut aliases, Some(&manifest.name));
41            aliases.retain(|entry_alias| entry_alias != &final_name);
42            RegistryEntry {
43                name: final_name,
44                source: materialized.source,
45                backend,
46                description: manifest.description,
47                aliases,
48            }
49        } else {
50            let name = name.ok_or_else(|| {
51                CoreError::Unsupported(String::from(
52                    "add requires a plugin name unless --source is provided",
53                ))
54            })?;
55            let mut entry = self.resolve_registry_entry(name)?;
56            if entry.backend == PluginBackendKind::Lua {
57                let config = self.app_config()?;
58                if !config.registry.address.is_empty() {
59                    if let Ok(manifest) = fetch_plugin_manifest(
60                        &config.registry.address,
61                        &entry.name,
62                        self.proxy_url(),
63                    ) {
64                        entry.source = manifest.download_url;
65                        entry.description = manifest.description.or(entry.description);
66                    }
67                }
68            }
69            let materialized = self.materialize_plugin_entry(&entry)?;
70            let plugin = self.load_plugin(&materialized)?;
71            let manifest = plugin.manifest().clone();
72            let final_name = alias.unwrap_or(name).to_string();
73            let mut aliases = entry.aliases;
74            push_alias(&mut aliases, Some(name));
75            push_alias(&mut aliases, Some(&manifest.name));
76            aliases.extend(manifest.aliases);
77            aliases.sort();
78            aliases.dedup();
79            aliases.retain(|entry_alias| entry_alias != &final_name);
80            RegistryEntry {
81                name: final_name,
82                source: materialized.source,
83                backend: entry.backend,
84                description: manifest.description.or(entry.description),
85                aliases,
86            }
87        };
88
89        self.registry.add_plugin(entry.clone())?;
90        Ok(entry)
91    }
92}
93
94fn push_alias(aliases: &mut Vec<String>, alias: Option<&str>) {
95    if let Some(alias) = alias {
96        let alias = alias.trim();
97        if !alias.is_empty() {
98            aliases.push(alias.to_string());
99        }
100    }
101}