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::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 link_state = AppState {
104 link_service,
105 config,
106 registry,
107 entity_fetchers: Arc::new(fetchers_map),
108 };
109
110 let entity_routes = self.entity_registry.build_routes();
112
113 let link_routes = build_link_routes(link_state);
115
116 let app = entity_routes.merge(link_routes);
118
119 Ok(app)
120 }
121
122 fn merge_configs(&self) -> Result<LinksConfig> {
124 if self.configs.is_empty() {
125 return Ok(LinksConfig {
126 entities: vec![],
127 links: vec![],
128 validation_rules: None,
129 });
130 }
131
132 Ok(self.configs[0].clone())
135 }
136}
137
138impl Default for ServerBuilder {
139 fn default() -> Self {
140 Self::new()
141 }
142}