1use super::entity_registry::EntityRegistry;
4use super::router::build_link_routes;
5use crate::config::LinksConfig;
6use crate::core::module::Module;
7use crate::core::service::LinkService;
8use crate::core::{EntityCreator, EntityFetcher};
9use crate::links::handlers::AppState;
10use crate::links::registry::LinkRouteRegistry;
11use anyhow::Result;
12use axum::Router;
13use std::collections::HashMap;
14use std::sync::Arc;
15
16pub struct ServerBuilder {
27 link_service: Option<Arc<dyn LinkService>>,
28 entity_registry: EntityRegistry,
29 configs: Vec<LinksConfig>,
30 modules: Vec<Arc<dyn Module>>,
31}
32
33impl ServerBuilder {
34 pub fn new() -> Self {
36 Self {
37 link_service: None,
38 entity_registry: EntityRegistry::new(),
39 configs: Vec::new(),
40 modules: Vec::new(),
41 }
42 }
43
44 pub fn with_link_service(mut self, service: impl LinkService + 'static) -> Self {
46 self.link_service = Some(Arc::new(service));
47 self
48 }
49
50 pub fn register_module(mut self, module: impl Module + 'static) -> Result<Self> {
57 let module = Arc::new(module);
58
59 let config = module.links_config()?;
61 self.configs.push(config);
62
63 module.register_entities(&mut self.entity_registry);
65
66 self.modules.push(module);
68
69 Ok(self)
70 }
71
72 pub fn build(mut self) -> Result<Router> {
79 let merged_config = self.merge_configs()?;
81 let config = Arc::new(merged_config);
82
83 let link_service = self
85 .link_service
86 .take()
87 .ok_or_else(|| anyhow::anyhow!("LinkService is required. Call .with_link_service()"))?;
88
89 let registry = Arc::new(LinkRouteRegistry::new(config.clone()));
91
92 let mut fetchers_map: HashMap<String, Arc<dyn EntityFetcher>> = HashMap::new();
94 for module in &self.modules {
95 for entity_type in module.entity_types() {
96 if let Some(fetcher) = module.get_entity_fetcher(entity_type) {
97 fetchers_map.insert(entity_type.to_string(), fetcher);
98 }
99 }
100 }
101
102 let mut creators_map: HashMap<String, Arc<dyn EntityCreator>> = HashMap::new();
104 for module in &self.modules {
105 for entity_type in module.entity_types() {
106 if let Some(creator) = module.get_entity_creator(entity_type) {
107 creators_map.insert(entity_type.to_string(), creator);
108 }
109 }
110 }
111
112 let link_state = AppState {
114 link_service,
115 config,
116 registry,
117 entity_fetchers: Arc::new(fetchers_map),
118 entity_creators: Arc::new(creators_map),
119 };
120
121 let entity_routes = self.entity_registry.build_routes();
123
124 let link_routes = build_link_routes(link_state);
126
127 let app = entity_routes.merge(link_routes);
129
130 Ok(app)
131 }
132
133 fn merge_configs(&self) -> Result<LinksConfig> {
135 if self.configs.is_empty() {
136 return Ok(LinksConfig {
137 entities: vec![],
138 links: vec![],
139 validation_rules: None,
140 });
141 }
142
143 Ok(self.configs[0].clone())
146 }
147}
148
149impl Default for ServerBuilder {
150 fn default() -> Self {
151 Self::new()
152 }
153}