apcore_toolkit/
serializers.rs1use serde_json::{json, Value};
7use tracing::warn;
8
9use apcore::module::ModuleAnnotations;
10
11use crate::types::ScannedModule;
12
13pub fn annotations_to_value(annotations: Option<&ModuleAnnotations>) -> Value {
17 match annotations {
18 Some(ann) => serde_json::to_value(ann).unwrap_or_else(|e| {
19 warn!("Failed to serialize ModuleAnnotations: {e}");
20 Value::Null
21 }),
22 None => Value::Null,
23 }
24}
25
26pub fn module_to_value(module: &ScannedModule) -> Value {
28 let examples = serde_json::to_value(&module.examples).unwrap_or_else(|e| {
29 warn!(
30 module_id = %module.module_id,
31 "Failed to serialize examples: {e}"
32 );
33 json!([])
34 });
35
36 json!({
37 "module_id": module.module_id,
38 "description": module.description,
39 "documentation": module.documentation,
40 "tags": module.tags,
41 "version": module.version,
42 "target": module.target,
43 "annotations": annotations_to_value(module.annotations.as_ref()),
44 "examples": examples,
45 "metadata": module.metadata,
46 "input_schema": module.input_schema,
47 "output_schema": module.output_schema,
48 "warnings": module.warnings,
49 })
50}
51
52pub fn modules_to_values(modules: &[ScannedModule]) -> Vec<Value> {
54 modules.iter().map(module_to_value).collect()
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use serde_json::json;
61
62 fn sample_module() -> ScannedModule {
63 ScannedModule::new(
64 "users.get".into(),
65 "Get user".into(),
66 json!({"type": "object"}),
67 json!({"type": "object"}),
68 vec!["users".into()],
69 "app:get_user".into(),
70 )
71 }
72
73 #[test]
74 fn test_annotations_to_value_none() {
75 assert_eq!(annotations_to_value(None), Value::Null);
76 }
77
78 #[test]
79 fn test_annotations_to_value_some() {
80 let ann = ModuleAnnotations {
81 readonly: true,
82 ..Default::default()
83 };
84 let val = annotations_to_value(Some(&ann));
85 assert_eq!(val["readonly"], true);
86 }
87
88 #[test]
89 fn test_module_to_value() {
90 let m = sample_module();
91 let val = module_to_value(&m);
92 assert_eq!(val["module_id"], "users.get");
93 assert_eq!(val["description"], "Get user");
94 assert_eq!(val["version"], "1.0.0");
95 assert_eq!(val["target"], "app:get_user");
96 assert!(val["tags"].is_array());
97 }
98
99 #[test]
100 fn test_modules_to_values() {
101 let modules = vec![sample_module(), sample_module()];
102 let values = modules_to_values(&modules);
103 assert_eq!(values.len(), 2);
104 }
105
106 #[test]
107 fn test_module_to_value_with_annotations() {
108 let mut m = sample_module();
109 m.annotations = Some(ModuleAnnotations {
110 destructive: true,
111 ..Default::default()
112 });
113 let val = module_to_value(&m);
114 assert_eq!(val["annotations"]["destructive"], true);
115 }
116
117 #[test]
118 fn test_module_to_value_all_keys() {
119 let val = module_to_value(&sample_module());
120 let obj = val.as_object().unwrap();
121 let expected_keys: std::collections::HashSet<&str> = [
122 "module_id",
123 "description",
124 "documentation",
125 "tags",
126 "version",
127 "target",
128 "annotations",
129 "examples",
130 "metadata",
131 "input_schema",
132 "output_schema",
133 "warnings",
134 ]
135 .into_iter()
136 .collect();
137
138 let actual_keys: std::collections::HashSet<&str> = obj.keys().map(|k| k.as_str()).collect();
139
140 assert_eq!(actual_keys, expected_keys);
141 }
142
143 #[test]
144 fn test_module_to_value_warnings_empty_default() {
145 let val = module_to_value(&sample_module());
146 let warnings = val["warnings"].as_array().unwrap();
147 assert!(warnings.is_empty());
148 }
149
150 #[test]
151 fn test_module_to_value_with_documentation() {
152 let mut m = sample_module();
153 m.documentation = Some("Detailed documentation".into());
154 let val = module_to_value(&m);
155 assert_eq!(val["documentation"], "Detailed documentation");
156 }
157
158 #[test]
159 fn test_module_to_value_examples_empty_default() {
160 let val = module_to_value(&sample_module());
161 let examples = val["examples"].as_array().unwrap();
162 assert!(examples.is_empty());
163 }
164
165 #[test]
166 fn test_modules_to_values_empty() {
167 let values = modules_to_values(&[]);
168 assert!(values.is_empty());
169 }
170}