this/server/
builder.rs

1//! ServerBuilder for fluent API to build HTTP servers
2
3use 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
16/// Builder for creating HTTP servers with auto-registered routes
17///
18/// # Example
19///
20/// ```ignore
21/// let app = ServerBuilder::new()
22///     .with_link_service(InMemoryLinkService::new())
23///     .register_module(MyModule)
24///     .build()?;
25/// ```
26pub 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    /// Create a new ServerBuilder
35    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    /// Set the link service (required)
45    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    /// Register a module
51    ///
52    /// This will:
53    /// 1. Load the module's configuration
54    /// 2. Register all entities from the module
55    /// 3. Store the module for entity fetching
56    pub fn register_module(mut self, module: impl Module + 'static) -> Result<Self> {
57        let module = Arc::new(module);
58
59        // Load the module's configuration
60        let config = module.links_config()?;
61        self.configs.push(config);
62
63        // Register entities from the module
64        module.register_entities(&mut self.entity_registry);
65
66        // Store module for fetchers
67        self.modules.push(module);
68
69        Ok(self)
70    }
71
72    /// Build the final router
73    ///
74    /// This generates:
75    /// - CRUD routes for all registered entities
76    /// - Link routes (bidirectional)
77    /// - Introspection routes
78    pub fn build(mut self) -> Result<Router> {
79        // Merge all configs
80        let merged_config = self.merge_configs()?;
81        let config = Arc::new(merged_config);
82
83        // Extract link service
84        let link_service = self
85            .link_service
86            .take()
87            .ok_or_else(|| anyhow::anyhow!("LinkService is required. Call .with_link_service()"))?;
88
89        // Create link registry
90        let registry = Arc::new(LinkRouteRegistry::new(config.clone()));
91
92        // Build entity fetchers map from all modules
93        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        // Build entity creators map from all modules
103        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        // Create link app state
113        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        // Build entity routes
122        let entity_routes = self.entity_registry.build_routes();
123
124        // Build link routes
125        let link_routes = build_link_routes(link_state);
126
127        // Merge all routes
128        let app = entity_routes.merge(link_routes);
129
130        Ok(app)
131    }
132
133    /// Merge all configurations from registered modules
134    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        // For now, just use the first config
144        // TODO: Implement proper config merging
145        Ok(self.configs[0].clone())
146    }
147}
148
149impl Default for ServerBuilder {
150    fn default() -> Self {
151        Self::new()
152    }
153}