teo_runtime/schema/load/
load_schema.rs

1use std::process::exit;
2use teo_parser::ast::middleware::MiddlewareType;
3use teo_parser::ast::reference_space::ReferenceSpace;
4use teo_parser::ast::schema::Schema;
5use teo_parser::ast::span::Span;
6use teo_parser::diagnostics::diagnostics::{Diagnostics, DiagnosticsError};
7use teo_parser::diagnostics::printer::print_diagnostics;
8use teo_parser::traits::has_availability::HasAvailability;
9use teo_parser::traits::identifiable::Identifiable;
10use teo_parser::traits::info_provider::InfoProvider;
11use teo_parser::traits::named_identifiable::NamedIdentifiable;
12use teo_parser::traits::node_trait::NodeTrait;
13use teo_result::Result;
14use crate::namespace;
15use crate::schema::load::load_admin::load_admin;
16use crate::schema::load::load_client::load_client;
17use crate::schema::load::load_connector::load_connector;
18use crate::schema::load::load_database_information::load_database_information;
19use crate::schema::load::load_debug::load_debug;
20use crate::schema::load::load_entity::load_entity;
21use crate::schema::load::load_enum::load_enum;
22use crate::schema::load::load_handler::load_handler;
23use crate::schema::load::load_handler_group::load_handler_group;
24use crate::schema::load::load_handler_template::load_handler_template;
25use crate::schema::load::load_interface::load_interface;
26use crate::schema::load::load_model::load_model;
27use crate::schema::load::load_model_opposite_relations::load_model_opposite_relations;
28use crate::schema::load::load_server::load_server;
29use crate::schema::load::load_use_middlewares::load_use_middlewares;
30
31pub async fn load_schema(main_namespace_builder: &namespace::Builder, schema: &Schema, ignores_loading: bool) -> Result<()> {
32
33    // diagnostics for schema loading
34    let mut diagnostics = Diagnostics::new();
35
36    // some of these are just load from schema, while some are validate and load
37
38    // setup namespaces, this is used for recursively setting database information
39    for namespace in schema.namespaces() {
40        let _ = main_namespace_builder.descendant_namespace_or_create_at_path(&namespace.string_path());
41    }
42
43    // load server
44    let mut server_loaded = false;
45    if let Some(server) = schema.server() {
46        if server.is_available() {
47            load_server(main_namespace_builder, schema, server, &mut diagnostics)?;
48            server_loaded = true;
49        }
50    }
51    if !server_loaded {
52        let source = schema.main_source();
53        diagnostics.insert(DiagnosticsError::new(Span::default(), "server config is not found", source.file_path.clone()));
54    }
55
56    // load connectors
57    for connector in schema.connectors() {
58        if connector.is_available() {
59            load_connector(main_namespace_builder, schema, connector, &mut diagnostics)?;
60        }
61    }
62
63    // setting up database information
64    load_database_information(main_namespace_builder);
65
66    // load debug
67    if let Some(debug) = schema.debug() {
68        if debug.is_available() {
69            load_debug(main_namespace_builder, schema, debug, &mut diagnostics)?;
70        }
71    }
72
73    // load entities
74    for entity in schema.entities() {
75        if entity.is_available() {
76            load_entity(main_namespace_builder, schema, entity, &mut diagnostics)?;
77        }
78    }
79
80    // load clients
81    for debug in schema.clients() {
82        if debug.is_available() {
83            load_client(main_namespace_builder, schema, debug, &mut diagnostics)?;
84        }
85    }
86
87    // load admin dashboard
88    if let Some(admin) = schema.admin() {
89        if admin.is_available() {
90            load_admin(main_namespace_builder, schema, admin, &mut diagnostics)?;
91        }
92    }
93
94    if !ignores_loading {
95
96        // validate decorator declarations
97        for decorator_declaration in schema.decorator_declarations() {
98            let dest_namespace_builder = main_namespace_builder.descendant_namespace_or_create_at_path(&decorator_declaration.namespace_string_path());
99            match decorator_declaration.decorator_class {
100                ReferenceSpace::EnumDecorator => if dest_namespace_builder.enum_decorator(decorator_declaration.identifier().name()).is_none() {
101                    diagnostics.insert(DiagnosticsError::new(decorator_declaration.identifier().span(), "enum decorator implementation is not found", schema.source(decorator_declaration.source_id()).unwrap().file_path.clone()))
102                },
103                ReferenceSpace::EnumMemberDecorator => if dest_namespace_builder.enum_member_decorator(decorator_declaration.identifier().name()).is_none() {
104                    diagnostics.insert(DiagnosticsError::new(decorator_declaration.identifier().span(), "enum member decorator implementation is not found", schema.source(decorator_declaration.source_id()).unwrap().file_path.clone()))
105                },
106                ReferenceSpace::ModelDecorator => if dest_namespace_builder.model_decorator(decorator_declaration.identifier().name()).is_none() {
107                    diagnostics.insert(DiagnosticsError::new(decorator_declaration.identifier().span(), "model decorator implementation is not found", schema.source(decorator_declaration.source_id()).unwrap().file_path.clone()))
108                },
109                ReferenceSpace::ModelFieldDecorator => if dest_namespace_builder.model_field_decorator(decorator_declaration.identifier().name()).is_none() {
110                    diagnostics.insert(DiagnosticsError::new(decorator_declaration.identifier().span(), "model field decorator implementation is not found", schema.source(decorator_declaration.source_id()).unwrap().file_path.clone()))
111                },
112                ReferenceSpace::ModelRelationDecorator => if dest_namespace_builder.model_relation_decorator(decorator_declaration.identifier().name()).is_none() {
113                    diagnostics.insert(DiagnosticsError::new(decorator_declaration.identifier().span(), "model relation decorator implementation is not found", schema.source(decorator_declaration.source_id()).unwrap().file_path.clone()))
114                },
115                ReferenceSpace::ModelPropertyDecorator => if dest_namespace_builder.model_property_decorator(decorator_declaration.identifier().name()).is_none() {
116                    diagnostics.insert(DiagnosticsError::new(decorator_declaration.identifier().span(), "model property decorator implementation is not found", schema.source(decorator_declaration.source_id()).unwrap().file_path.clone()))
117                },
118                ReferenceSpace::InterfaceDecorator => if dest_namespace_builder.interface_decorator(decorator_declaration.identifier().name()).is_none() {
119                    diagnostics.insert(DiagnosticsError::new(decorator_declaration.identifier().span(), "interface decorator implementation is not found", schema.source(decorator_declaration.source_id()).unwrap().file_path.clone()))
120                },
121                ReferenceSpace::InterfaceFieldDecorator => if dest_namespace_builder.interface_field_decorator(decorator_declaration.identifier().name()).is_none() {
122                    diagnostics.insert(DiagnosticsError::new(decorator_declaration.identifier().span(), "interface field decorator implementation is not found", schema.source(decorator_declaration.source_id()).unwrap().file_path.clone()))
123                },
124                ReferenceSpace::HandlerDecorator => if dest_namespace_builder.handler_decorator(decorator_declaration.identifier().name()).is_none() {
125                    diagnostics.insert(DiagnosticsError::new(decorator_declaration.identifier().span(), "handler decorator implementation is not found", schema.source(decorator_declaration.source_id()).unwrap().file_path.clone()))
126                },
127                _ => (),
128            }
129        }
130
131        // validate pipeline item declarations
132        for pipeline_item_declaration in schema.pipeline_item_declarations() {
133            let dest_namespace_builder = main_namespace_builder.descendant_namespace_or_create_at_path(&pipeline_item_declaration.namespace_string_path());
134            if dest_namespace_builder.pipeline_item(pipeline_item_declaration.identifier().name()).is_none() {
135                diagnostics.insert(DiagnosticsError::new(pipeline_item_declaration.identifier().span(), "pipeline item implementation is not found", schema.source(pipeline_item_declaration.source_id()).unwrap().file_path.clone()))
136            }
137        }
138
139        // validate struct declarations
140        for struct_declaration in schema.struct_declarations() {
141            let dest_namespace_builder = main_namespace_builder.descendant_namespace_or_create_at_path(&struct_declaration.namespace_string_path());
142            if let Some(struct_implementation) = dest_namespace_builder.r#struct(struct_declaration.identifier().name()) {
143                for function_declaration in struct_declaration.function_declarations() {
144                    if function_declaration.r#static {
145                        if struct_implementation.static_functions.get(function_declaration.identifier().name()).is_none() {
146                            diagnostics.insert(DiagnosticsError::new(function_declaration.identifier().span(), "function implementation is not found", schema.source(struct_declaration.source_id()).unwrap().file_path.clone()));
147                        }
148                    } else {
149                        if struct_implementation.functions.get(function_declaration.identifier().name()).is_none() {
150                            diagnostics.insert(DiagnosticsError::new(function_declaration.identifier().span(), "function implementation is not found", schema.source(struct_declaration.source_id()).unwrap().file_path.clone()));
151                        }
152                    }
153                }
154            } else {
155                diagnostics.insert(DiagnosticsError::new(struct_declaration.identifier().span(), "struct implementation is not found", schema.source(struct_declaration.source_id()).unwrap().file_path.clone()))
156            }
157        }
158
159        // validate handlers
160        for handler_declaration in schema.handler_declarations() {
161            let dest_namespace_builder = main_namespace_builder.descendant_namespace_or_create_at_path(&handler_declaration.namespace_string_path());
162            if dest_namespace_builder.handler(handler_declaration.identifier().name()).is_none() {
163                diagnostics.insert(DiagnosticsError::new(handler_declaration.identifier().span(), "handler implementation is not found", schema.source(handler_declaration.source_id()).unwrap().file_path.clone()));
164            }
165        }
166
167        // validate handler templates
168        for handler_template_declaration in schema.handler_template_declarations() {
169            let dest_namespace_builder = main_namespace_builder.descendant_namespace_or_create_at_path(&handler_template_declaration.namespace_string_path());
170            if dest_namespace_builder.handler_template(handler_template_declaration.identifier().name()).is_none() {
171                diagnostics.insert(DiagnosticsError::new(handler_template_declaration.identifier().span(), "handler template implementation is not found", schema.source(handler_template_declaration.source_id()).unwrap().file_path.clone()));
172            }
173        }
174
175        // validate handler groups
176        for handler_group_declaration in schema.handler_group_declarations() {
177            let dest_namespace_builder = main_namespace_builder.descendant_namespace_or_create_at_path(&handler_group_declaration.namespace_string_path());
178            if dest_namespace_builder.handler_group(handler_group_declaration.identifier().name()).is_none() {
179                diagnostics.insert(DiagnosticsError::new(handler_group_declaration.identifier().span(), "handler group implementation is not found", schema.source(handler_group_declaration.source_id()).unwrap().file_path.clone()));
180            }
181            if let Some(group) = dest_namespace_builder.handler_group(handler_group_declaration.identifier().name()) {
182                for handler_declaration in handler_group_declaration.handler_declarations() {
183                    if group.handler(handler_declaration.name()).is_none() {
184                        diagnostics.insert(DiagnosticsError::new(handler_declaration.identifier().span(), "handler implementation is not found", schema.source(handler_group_declaration.source_id()).unwrap().file_path.clone()));
185                    }
186                }
187            }
188        }
189
190        // validate middleware declarations
191        for middleware_declaration in schema.middleware_declarations() {
192            let dest_namespace_builder = main_namespace_builder.descendant_namespace_or_create_at_path(&middleware_declaration.namespace_string_path());
193            match middleware_declaration.middleware_type() {
194                MiddlewareType::HandlerMiddleware => {
195                    if dest_namespace_builder.handler_middleware(middleware_declaration.identifier().name()).is_none() {
196                        diagnostics.insert(DiagnosticsError::new(middleware_declaration.identifier().span(), "handle middleware implementation not found", schema.source(middleware_declaration.source_id()).unwrap().file_path.clone()))
197                    }
198                },
199                MiddlewareType::RequestMiddleware => {
200                    if dest_namespace_builder.request_middleware(middleware_declaration.identifier().name()).is_none() {
201                        diagnostics.insert(DiagnosticsError::new(middleware_declaration.identifier().span(), "request middleware implementation not found", schema.source(middleware_declaration.source_id()).unwrap().file_path.clone()))
202                    }
203                }
204            }
205        }
206
207        // load middlewares
208        load_use_middlewares(main_namespace_builder, schema, &mut diagnostics)?;
209    }
210
211    // load enums
212    for enum_declaration in schema.enums() {
213        if enum_declaration.is_available() {
214            load_enum(main_namespace_builder, schema, enum_declaration, &mut diagnostics)?;
215        }
216    }
217
218    // load interfaces
219    for interface_declaration in schema.interfaces() {
220        if interface_declaration.is_available() {
221            load_interface(main_namespace_builder, schema, interface_declaration, &mut diagnostics)?;
222        }
223    }
224
225    // load handler templates
226    for handler_template_declaration in schema.handler_template_declarations() {
227        load_handler_template(main_namespace_builder, schema, handler_template_declaration, &mut diagnostics)?;
228    }
229
230    // load handlers
231    for handler_declaration in schema.handler_declarations() {
232        load_handler(main_namespace_builder, schema, handler_declaration, &mut diagnostics)?;
233    }
234
235    // load handler groups
236    for handler_group_declaration in schema.handler_group_declarations() {
237        load_handler_group(main_namespace_builder, schema, handler_group_declaration, &mut diagnostics)?;
238    }
239
240    // load models
241    for model_declaration in schema.models() {
242        let database = main_namespace_builder.descendant_namespace_or_create_at_path(&model_declaration.namespace_string_path()).database();
243        if database.is_some() && model_declaration.is_available() {
244            load_model(main_namespace_builder, schema, model_declaration, &mut diagnostics)?;
245        }
246    }
247
248    // load model opposite relations
249    load_model_opposite_relations(main_namespace_builder);
250
251    // diagnostics
252    if !ignores_loading {
253        print_diagnostics(&diagnostics, true);
254        if diagnostics.has_errors() {
255            exit(1);
256        }
257    }
258
259    Ok(())
260}