1use pylon_kernel::{AppManifest, ManifestField, ManifestQuery};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct QueryDescriptor {
12 pub name: String,
13 pub input: Vec<InputField>,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct InputField {
19 pub name: String,
20 pub field_type: String,
21 pub optional: bool,
22}
23
24impl InputField {
25 pub fn from_manifest_field(f: &ManifestField) -> Self {
26 Self {
27 name: f.name.clone(),
28 field_type: f.field_type.clone(),
29 optional: f.optional,
30 }
31 }
32}
33
34impl QueryDescriptor {
35 pub fn from_manifest(mq: &ManifestQuery) -> Self {
36 Self {
37 name: mq.name.clone(),
38 input: mq
39 .input
40 .iter()
41 .map(InputField::from_manifest_field)
42 .collect(),
43 }
44 }
45}
46
47#[derive(Debug, Clone, PartialEq, Eq)]
53pub struct QueryRegistry {
54 pub queries: Vec<QueryDescriptor>,
55}
56
57impl QueryRegistry {
58 pub fn from_manifest(manifest: &AppManifest) -> Self {
59 Self {
60 queries: manifest
61 .queries
62 .iter()
63 .map(QueryDescriptor::from_manifest)
64 .collect(),
65 }
66 }
67
68 pub fn get(&self, name: &str) -> Option<&QueryDescriptor> {
69 self.queries.iter().find(|q| q.name == name)
70 }
71
72 pub fn names(&self) -> Vec<&str> {
73 self.queries.iter().map(|q| q.name.as_str()).collect()
74 }
75}
76
77#[cfg(test)]
82mod tests {
83 use super::*;
84 use pylon_kernel::ManifestField;
85
86 fn test_manifest() -> AppManifest {
87 serde_json::from_str(include_str!(
88 "../../../examples/todo-app/pylon.manifest.json"
89 ))
90 .unwrap()
91 }
92
93 #[test]
94 fn registry_from_manifest() {
95 let reg = QueryRegistry::from_manifest(&test_manifest());
96 assert_eq!(reg.queries.len(), 3);
97 assert_eq!(reg.names(), vec!["todosByAuthor", "allTodos", "todoById"]);
98 }
99
100 #[test]
101 fn get_query_by_name() {
102 let reg = QueryRegistry::from_manifest(&test_manifest());
103 let q = reg.get("todosByAuthor").unwrap();
104 assert_eq!(q.name, "todosByAuthor");
105 assert_eq!(q.input.len(), 1);
106 assert_eq!(q.input[0].name, "authorId");
107 assert_eq!(q.input[0].field_type, "id(User)");
108 assert!(!q.input[0].optional);
109 }
110
111 #[test]
112 fn get_query_with_optional_input() {
113 let reg = QueryRegistry::from_manifest(&test_manifest());
114 let q = reg.get("allTodos").unwrap();
115 assert_eq!(q.input.len(), 1);
116 assert_eq!(q.input[0].name, "done");
117 assert!(q.input[0].optional);
118 }
119
120 #[test]
121 fn get_missing_query_returns_none() {
122 let reg = QueryRegistry::from_manifest(&test_manifest());
123 assert!(reg.get("nonexistent").is_none());
124 }
125
126 #[test]
127 fn descriptor_from_manifest_query() {
128 let mq = ManifestQuery {
129 name: "test".into(),
130 input: vec![ManifestField {
131 name: "id".into(),
132 field_type: "string".into(),
133 optional: false,
134 unique: false,
135 crdt: None,
136 }],
137 };
138 let desc = QueryDescriptor::from_manifest(&mq);
139 assert_eq!(desc.name, "test");
140 assert_eq!(desc.input.len(), 1);
141 assert_eq!(desc.input[0].name, "id");
142 }
143}