Skip to main content

mangofetch_plugin_sdk/
manifest.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct PluginManifest {
6    pub id: String,
7    pub name: String,
8    pub version: String,
9    pub description: String,
10    pub author: String,
11    #[serde(default)]
12    pub min_mangofetch_version: Option<String>,
13    #[serde(default)]
14    pub license: Option<String>,
15    #[serde(default)]
16    pub homepage: Option<String>,
17    #[serde(default)]
18    pub icon: Option<String>,
19    #[serde(default)]
20    pub nav: Vec<PluginNavItem>,
21    #[serde(default)]
22    pub events: PluginEvents,
23    #[serde(default)]
24    pub capabilities: Vec<String>,
25    #[serde(default)]
26    pub settings_schema: Option<serde_json::Value>,
27    #[serde(default)]
28    pub rust_crate: Option<String>,
29    #[serde(default)]
30    pub frontend_dir: Option<String>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct PluginNavItem {
35    pub route: String,
36    pub label: HashMap<String, String>,
37    #[serde(default)]
38    pub icon_svg: Option<String>,
39    #[serde(default = "default_nav_group")]
40    pub group: NavGroup,
41    #[serde(default = "default_nav_order")]
42    pub order: u32,
43}
44
45#[derive(Debug, Clone, Default, Serialize, Deserialize)]
46pub struct PluginEvents {
47    #[serde(default)]
48    pub progress: Vec<String>,
49    #[serde(default)]
50    pub complete: Vec<String>,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
54#[serde(rename_all = "lowercase")]
55pub enum NavGroup {
56    Primary,
57    #[default]
58    Secondary,
59}
60
61fn default_nav_group() -> NavGroup {
62    NavGroup::Secondary
63}
64
65fn default_nav_order() -> u32 {
66    50
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct InstalledPlugin {
71    pub id: String,
72    pub version: String,
73    pub installed_at: String,
74    pub updated_at: String,
75    pub enabled: bool,
76    pub repo: Option<String>,
77    pub source_release: Option<String>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct RegistryEntry {
82    pub id: String,
83    pub name: String,
84    pub description: String,
85    pub author: String,
86    pub repo: String,
87    #[serde(default)]
88    pub homepage: Option<String>,
89    #[serde(default)]
90    pub tags: Vec<String>,
91    #[serde(default)]
92    pub official: bool,
93    #[serde(default)]
94    pub capabilities: Vec<String>,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct PluginRegistry {
99    #[serde(default)]
100    pub schema_version: u32,
101    pub plugins: Vec<RegistryEntry>,
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107
108    #[test]
109    fn test_plugin_manifest_default_deserialization() {
110        let json = r#"{
111            "id": "test-plugin",
112            "name": "Test Plugin",
113            "version": "1.0.0",
114            "description": "A test plugin",
115            "author": "Test Author"
116        }"#;
117
118        let manifest: PluginManifest = serde_json::from_str(json).unwrap();
119
120        assert_eq!(manifest.id, "test-plugin");
121        assert_eq!(manifest.min_mangofetch_version, None);
122        assert_eq!(manifest.license, None);
123        assert_eq!(manifest.homepage, None);
124        assert_eq!(manifest.icon, None);
125        assert!(manifest.nav.is_empty());
126        assert!(manifest.events.progress.is_empty());
127        assert!(manifest.events.complete.is_empty());
128        assert!(manifest.capabilities.is_empty());
129        assert_eq!(manifest.settings_schema, None);
130        assert_eq!(manifest.rust_crate, None);
131        assert_eq!(manifest.frontend_dir, None);
132    }
133
134    #[test]
135    fn test_plugin_nav_item_default_deserialization() {
136        let json = r#"{
137            "route": "/test",
138            "label": {
139                "en": "Test"
140            }
141        }"#;
142
143        let nav_item: PluginNavItem = serde_json::from_str(json).unwrap();
144
145        assert_eq!(nav_item.route, "/test");
146        assert_eq!(nav_item.icon_svg, None);
147        assert_eq!(nav_item.group, NavGroup::Secondary);
148        assert_eq!(nav_item.order, 50);
149    }
150
151    #[test]
152    fn test_registry_entry_default_deserialization() {
153        let json = r#"{
154            "id": "test-plugin",
155            "name": "Test Plugin",
156            "description": "A test plugin",
157            "author": "Test Author",
158            "repo": "https://github.com/test/repo"
159        }"#;
160
161        let entry: RegistryEntry = serde_json::from_str(json).unwrap();
162
163        assert_eq!(entry.id, "test-plugin");
164        assert_eq!(entry.homepage, None);
165        assert!(entry.tags.is_empty());
166        assert_eq!(entry.official, false);
167        assert!(entry.capabilities.is_empty());
168    }
169}