this/server/
host.rs

1//! Server host for transport-agnostic API exposure
2//!
3//! This module provides a `ServerHost` structure that contains all framework state
4//! needed to expose the API via any protocol (REST, GraphQL, gRPC, etc.)
5//!
6//! The host is completely agnostic to the transport protocol and serves as the
7//! single source of truth for the application state.
8
9use crate::config::LinksConfig;
10use crate::core::{EntityCreator, EntityFetcher, service::LinkService};
11use crate::links::registry::LinkRouteRegistry;
12use crate::server::entity_registry::EntityRegistry;
13use anyhow::Result;
14use std::collections::HashMap;
15use std::sync::Arc;
16
17/// Host context containing all framework state
18///
19/// This structure is transport-agnostic and contains all the information
20/// needed to expose the API via any protocol (REST, GraphQL, gRPC, etc.)
21///
22/// # Example
23///
24/// ```rust,ignore
25/// let host = ServerHost::from_builder_components(
26///     link_service,
27///     config,
28///     entity_registry,
29///     fetchers,
30///     creators,
31/// )?;
32///
33/// // Use host with any exposure
34/// let host_arc = Arc::new(host);
35/// let rest_app = RestExposure::build_router(host_arc.clone())?;
36/// let graphql_app = GraphQLExposure::build_router(host_arc)?;
37/// ```
38pub struct ServerHost {
39    /// Merged configuration from all modules
40    pub config: Arc<LinksConfig>,
41
42    /// Link service for relationship management
43    pub link_service: Arc<dyn LinkService>,
44
45    /// Link route registry for semantic URL resolution
46    pub registry: Arc<LinkRouteRegistry>,
47
48    /// Entity registry for CRUD routes
49    pub entity_registry: EntityRegistry,
50
51    /// Entity fetchers map (for link enrichment)
52    pub entity_fetchers: Arc<HashMap<String, Arc<dyn EntityFetcher>>>,
53
54    /// Entity creators map (for automatic entity + link creation)
55    pub entity_creators: Arc<HashMap<String, Arc<dyn EntityCreator>>>,
56}
57
58impl ServerHost {
59    /// Build the host from builder components
60    ///
61    /// This method takes all the components that have been registered with
62    /// the builder and constructs the host structure.
63    ///
64    /// # Arguments
65    ///
66    /// * `link_service` - The link service for relationship management
67    /// * `config` - Merged configuration from all modules
68    /// * `entity_registry` - Registry of all entity descriptors
69    /// * `fetchers` - Map of entity type to fetcher implementation
70    /// * `creators` - Map of entity type to creator implementation
71    ///
72    /// # Returns
73    ///
74    /// Returns a `ServerHost` ready to be used with any exposure (REST, GraphQL, gRPC, etc.)
75    pub fn from_builder_components(
76        link_service: Arc<dyn LinkService>,
77        config: LinksConfig,
78        entity_registry: EntityRegistry,
79        fetchers: HashMap<String, Arc<dyn EntityFetcher>>,
80        creators: HashMap<String, Arc<dyn EntityCreator>>,
81    ) -> Result<Self> {
82        let config = Arc::new(config);
83        let registry = Arc::new(LinkRouteRegistry::new(config.clone()));
84
85        Ok(Self {
86            config,
87            link_service,
88            registry,
89            entity_registry,
90            entity_fetchers: Arc::new(fetchers),
91            entity_creators: Arc::new(creators),
92        })
93    }
94
95    /// Get entity types registered in the host
96    pub fn entity_types(&self) -> Vec<&str> {
97        self.entity_registry.entity_types()
98    }
99
100    /// Check if host is properly initialized
101    pub fn is_ready(&self) -> bool {
102        !self.entity_fetchers.is_empty()
103    }
104}