1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct Manifest {
6 pub metadata: Metadata,
7 #[serde(default)]
8 pub packages: Vec<Package>,
9}
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Metadata {
14 pub version: String,
16 pub generated_at: String,
18 pub uv_lock_path: Option<String>,
20}
21
22impl Default for Manifest {
23 fn default() -> Self {
24 Manifest {
25 metadata: Metadata {
26 version: "2.0".to_string(),
27 generated_at: chrono::Utc::now().to_rfc3339(),
28 uv_lock_path: None,
29 },
30 packages: Vec::new(),
31 }
32 }
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct Package {
38 pub name: String,
39 pub entry_points_dist_info: String,
40 #[serde(default)]
41 pub editable_install: bool,
42 pub pth_file: Option<String>,
43 pub resolved_source_path: Option<String>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub install_type: Option<String>,
46 #[serde(default)]
47 #[serde(skip_serializing_if = "Vec::is_empty")]
48 pub installed_by: Vec<String>,
49 #[serde(default)]
50 #[serde(skip_serializing_if = "Vec::is_empty")]
51 pub dependencies: Vec<String>,
52 #[serde(default)]
53 pub plugins: Vec<PluginSpec>,
54 #[serde(default)]
55 pub decorator_registrations: Vec<DecoratorRegistration>,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct PluginSpec {
61 pub name: String,
62 pub kind: PluginKind,
63 pub entry: String,
64 pub invocation: InvocationSpec,
65 pub io: IOContract,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub resources: Option<ResourceSpec>,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub upgrade: Option<UpgradeSpec>,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub description: Option<String>,
72 #[serde(default)]
73 #[serde(skip_serializing_if = "Vec::is_empty")]
74 pub tags: Vec<String>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
79#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
80pub enum PluginKind {
81 Parser,
82 Exporter,
83 Modifier,
84 Upgrader,
85 Utility,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct InvocationSpec {
91 pub implementation: ImplementationType,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub method: Option<String>,
94 #[serde(default)]
95 #[serde(skip_serializing_if = "Vec::is_empty")]
96 pub constructor: Vec<ArgumentSpec>,
97 #[serde(default)]
98 #[serde(skip_serializing_if = "Vec::is_empty")]
99 pub call: Vec<ArgumentSpec>,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
104#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
105pub enum ImplementationType {
106 Class,
107 Function,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct ArgumentSpec {
113 pub name: String,
114 #[serde(skip_serializing_if = "Option::is_none")]
115 pub annotation: Option<String>,
116 #[serde(skip_serializing_if = "Option::is_none")]
117 pub default: Option<String>,
118 pub required: bool,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct IOContract {
124 #[serde(default)]
125 #[serde(skip_serializing_if = "Vec::is_empty")]
126 pub consumes: Vec<IOSlot>,
127 #[serde(default)]
128 #[serde(skip_serializing_if = "Vec::is_empty")]
129 pub produces: Vec<IOSlot>,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
134#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
135pub enum IOSlot {
136 System,
137 ConfigFile,
138 StoreFolder,
139 File,
140 Folder,
141 Data,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct ResourceSpec {
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub store: Option<StoreSpec>,
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub config: Option<ConfigSpec>,
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct StoreSpec {
156 pub mode: StoreMode,
157 #[serde(skip_serializing_if = "Option::is_none")]
158 pub path: Option<String>,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
163#[serde(rename_all = "lowercase")]
164pub enum StoreMode {
165 Folder,
166 Manifest,
167 Inline,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct ConfigSpec {
173 pub module: String,
174 pub name: String,
175 #[serde(default)]
176 #[serde(skip_serializing_if = "Vec::is_empty")]
177 pub fields: Vec<ConfigField>,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct ConfigField {
183 pub name: String,
184 #[serde(skip_serializing_if = "Option::is_none")]
185 pub annotation: Option<String>,
186 #[serde(skip_serializing_if = "Option::is_none")]
187 pub default: Option<String>,
188 pub required: bool,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct UpgradeSpec {
194 #[serde(skip_serializing_if = "Option::is_none")]
195 pub version_strategy_json: Option<String>,
196 #[serde(skip_serializing_if = "Option::is_none")]
197 pub version_reader_json: Option<String>,
198 #[serde(skip_serializing_if = "Option::is_none")]
199 pub upgrade_steps_json: Option<String>,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
204pub struct DecoratorRegistration {
205 pub decorator_class: String,
206 pub decorator_method: String,
207 pub function_name: String,
208 pub function_module: String,
209 pub source_file: Option<String>,
210 pub line_number: Option<usize>,
211 #[serde(default)]
212 pub decorator_args: toml::Table,
213 pub function_signature: Option<FunctionSignature>,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct FunctionSignature {
219 pub return_type: String,
220 #[serde(default)]
221 pub parameters: Vec<FunctionParameter>,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct FunctionParameter {
227 pub name: String,
228 pub param_type: String,
229 pub default: Option<String>,
230 #[serde(default)]
231 pub is_keyword_only: bool,
232 pub is_var_arg: Option<VarArgType>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
237#[serde(rename_all = "lowercase")]
238pub enum VarArgType {
239 Args,
240 Kwargs,
241}