1use crate::{
2 ABI_VERSION, Authority, IntersticeType, ModuleDependency, NodeDependency, QuerySchema,
3 ReducerSchema, SubscriptionSchema, TableSchema, TableVisibility, Version,
4 interstice_type_def::IntersticeTypeDef,
5};
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
10pub struct ReplicatedTableSchema {
11 pub node_name: String,
12 pub module_name: String,
13 pub table_name: String,
14}
15
16#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
17pub enum ModuleVisibility {
18 Public,
20 Private,
22}
23
24#[derive(Debug, Clone, Deserialize, Serialize)]
25pub struct ModuleSchema {
26 pub abi_version: u16,
27 pub name: String,
28 pub version: Version,
29 pub visibility: ModuleVisibility,
30 pub reducers: Vec<ReducerSchema>,
31 pub queries: Vec<QuerySchema>,
32 pub tables: Vec<TableSchema>,
33 pub subscriptions: Vec<SubscriptionSchema>,
34 pub type_definitions: HashMap<String, IntersticeTypeDef>,
35 pub authorities: Vec<Authority>,
36 pub module_dependencies: Vec<ModuleDependency>,
37 pub node_dependencies: Vec<NodeDependency>,
38 pub replicated_tables: Vec<ReplicatedTableSchema>,
39}
40
41impl ModuleSchema {
42 pub fn empty() -> Self {
43 Self {
44 abi_version: 0,
45 name: "".into(),
46 version: Version {
47 major: 0,
48 minor: 0,
49 patch: 0,
50 },
51 visibility: ModuleVisibility::Private,
52 reducers: Vec::new(),
53 queries: Vec::new(),
54 tables: Vec::new(),
55 subscriptions: Vec::new(),
56 type_definitions: HashMap::new(),
57 authorities: Vec::new(),
58 module_dependencies: Vec::new(),
59 node_dependencies: Vec::new(),
60 replicated_tables: Vec::new(),
61 }
62 }
63
64 pub fn new(
65 name: impl Into<String>,
66 version: Version,
67 visibility: ModuleVisibility,
68 reducers: Vec<ReducerSchema>,
69 queries: Vec<QuerySchema>,
70 tables: Vec<TableSchema>,
71 subscriptions: Vec<SubscriptionSchema>,
72 type_definitions: HashMap<String, IntersticeTypeDef>,
73 authorities: Vec<Authority>,
74 module_dependencies: Vec<ModuleDependency>,
75 node_dependencies: Vec<NodeDependency>,
76 replicated_tables: Vec<ReplicatedTableSchema>,
77 ) -> Self {
78 Self {
79 abi_version: ABI_VERSION,
80 name: name.into(),
81 visibility,
82 version,
83 reducers,
84 queries,
85 tables,
86 subscriptions,
87 type_definitions,
88 authorities,
89 module_dependencies,
90 node_dependencies,
91 replicated_tables,
92 }
93 }
94
95 pub fn to_public(self) -> Self {
96 let mut type_definitions = HashMap::new();
97
98 fn extract_named_types(it: &IntersticeType, names: &mut Vec<String>) {
100 match it {
101 IntersticeType::Named(name) => names.push(name.clone()),
102 IntersticeType::Vec(inner) | IntersticeType::Option(inner) => {
103 extract_named_types(inner, names);
104 }
105 IntersticeType::Tuple(types) => {
106 for ty in types {
107 extract_named_types(ty, names);
108 }
109 }
110 _ => {} }
112 }
113
114 let collect_type_recursively =
116 |type_name: &str,
117 collected: &mut HashMap<String, IntersticeTypeDef>,
118 all_types: &HashMap<String, IntersticeTypeDef>| {
119 let mut stack = vec![type_name.to_string()];
120
121 while let Some(current_name) = stack.pop() {
122 if collected.contains_key(¤t_name) {
124 continue;
125 }
126
127 if let Some(type_def) = all_types.get(¤t_name) {
129 collected.insert(current_name.clone(), type_def.clone());
130
131 if let IntersticeTypeDef::Struct { fields, .. } = type_def {
133 for field in fields {
134 let mut nested_names = Vec::new();
135 extract_named_types(&field.field_type, &mut nested_names);
136 for nested_name in nested_names {
137 if !collected.contains_key(&nested_name) {
138 stack.push(nested_name);
139 }
140 }
141 }
142 }
143 }
144 }
145 };
146
147 let mut tables = Vec::new();
149 for table_schema in &self.tables {
150 if table_schema.visibility == TableVisibility::Public {
151 tables.push(table_schema.clone());
152
153 collect_type_recursively(
155 &table_schema.type_name,
156 &mut type_definitions,
157 &self.type_definitions,
158 );
159
160 for field in &table_schema.fields {
162 let mut nested_names = Vec::new();
163 extract_named_types(&field.field_type, &mut nested_names);
164 for type_name in nested_names {
165 collect_type_recursively(
166 &type_name,
167 &mut type_definitions,
168 &self.type_definitions,
169 );
170 }
171 }
172 }
173 }
174
175 let mut reducers = Vec::new();
177 for reducer_schema in &self.reducers {
178 let mut add_reducer = true;
179 for subscription in &self.subscriptions {
180 if subscription.reducer_name == reducer_schema.name {
181 add_reducer = false;
182 break;
183 }
184 }
185 if add_reducer {
186 reducers.push(reducer_schema.clone());
187
188 for arg in &reducer_schema.arguments {
190 let mut nested_names = Vec::new();
191 extract_named_types(&arg.field_type, &mut nested_names);
192 for type_name in nested_names {
193 collect_type_recursively(
194 &type_name,
195 &mut type_definitions,
196 &self.type_definitions,
197 );
198 }
199 }
200 }
201 }
202
203 let queries = self.queries.clone();
205 for query_schema in &queries {
206 for arg in &query_schema.arguments {
208 let mut nested_names = Vec::new();
209 extract_named_types(&arg.field_type, &mut nested_names);
210 for type_name in nested_names {
211 collect_type_recursively(
212 &type_name,
213 &mut type_definitions,
214 &self.type_definitions,
215 );
216 }
217 }
218
219 let mut nested_names = Vec::new();
221 extract_named_types(&query_schema.return_type, &mut nested_names);
222 for type_name in nested_names {
223 collect_type_recursively(&type_name, &mut type_definitions, &self.type_definitions);
224 }
225 }
226
227 Self {
228 abi_version: self.abi_version,
229 name: self.name,
230 visibility: self.visibility,
231 version: self.version,
232 reducers,
233 queries,
234 tables,
235 subscriptions: Vec::new(),
236 type_definitions,
237 authorities: self.authorities,
238 module_dependencies: self.module_dependencies,
239 node_dependencies: self.node_dependencies,
240 replicated_tables: self.replicated_tables,
241 }
242 }
243
244 pub fn from_toml_string(toml_string: &str) -> Result<Self, toml::de::Error> {
245 toml::from_str(toml_string)
246 }
247
248 pub fn to_toml_string(&self) -> Result<String, toml::ser::Error> {
249 toml::to_string(&self)
250 }
251}