Skip to main content

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::events::EventBus;
11use crate::core::{EntityCreator, EntityFetcher, service::LinkService};
12use crate::links::registry::LinkRouteRegistry;
13use crate::server::entity_registry::EntityRegistry;
14use anyhow::Result;
15use std::collections::HashMap;
16use std::sync::Arc;
17
18/// Host context containing all framework state
19///
20/// This structure is transport-agnostic and contains all the information
21/// needed to expose the API via any protocol (REST, GraphQL, gRPC, etc.)
22///
23/// # Example
24///
25/// ```rust,ignore
26/// let host = ServerHost::from_builder_components(
27///     link_service,
28///     config,
29///     entity_registry,
30///     fetchers,
31///     creators,
32/// )?;
33///
34/// // Use host with any exposure
35/// let host_arc = Arc::new(host);
36/// let rest_app = RestExposure::build_router(host_arc.clone())?;
37/// let graphql_app = GraphQLExposure::build_router(host_arc)?;
38/// ```
39pub struct ServerHost {
40    /// Merged configuration from all modules
41    pub config: Arc<LinksConfig>,
42
43    /// Link service for relationship management
44    pub link_service: Arc<dyn LinkService>,
45
46    /// Link route registry for semantic URL resolution
47    pub registry: Arc<LinkRouteRegistry>,
48
49    /// Entity registry for CRUD routes
50    pub entity_registry: EntityRegistry,
51
52    /// Entity fetchers map (for link enrichment)
53    pub entity_fetchers: Arc<HashMap<String, Arc<dyn EntityFetcher>>>,
54
55    /// Entity creators map (for automatic entity + link creation)
56    pub entity_creators: Arc<HashMap<String, Arc<dyn EntityCreator>>>,
57
58    /// Optional event bus for real-time notifications (WebSocket, SSE)
59    ///
60    /// When present, REST/GraphQL handlers will publish events for mutations.
61    /// WebSocket and other real-time exposures subscribe to this bus.
62    pub event_bus: Option<Arc<EventBus>>,
63}
64
65impl ServerHost {
66    /// Build the host from builder components
67    ///
68    /// This method takes all the components that have been registered with
69    /// the builder and constructs the host structure.
70    ///
71    /// # Arguments
72    ///
73    /// * `link_service` - The link service for relationship management
74    /// * `config` - Merged configuration from all modules
75    /// * `entity_registry` - Registry of all entity descriptors
76    /// * `fetchers` - Map of entity type to fetcher implementation
77    /// * `creators` - Map of entity type to creator implementation
78    ///
79    /// # Returns
80    ///
81    /// Returns a `ServerHost` ready to be used with any exposure (REST, GraphQL, gRPC, etc.)
82    pub fn from_builder_components(
83        link_service: Arc<dyn LinkService>,
84        config: LinksConfig,
85        entity_registry: EntityRegistry,
86        fetchers: HashMap<String, Arc<dyn EntityFetcher>>,
87        creators: HashMap<String, Arc<dyn EntityCreator>>,
88    ) -> Result<Self> {
89        let config = Arc::new(config);
90        let registry = Arc::new(LinkRouteRegistry::new(config.clone()));
91
92        Ok(Self {
93            config,
94            link_service,
95            registry,
96            entity_registry,
97            entity_fetchers: Arc::new(fetchers),
98            entity_creators: Arc::new(creators),
99            event_bus: None,
100        })
101    }
102
103    /// Get entity types registered in the host
104    pub fn entity_types(&self) -> Vec<&str> {
105        self.entity_registry.entity_types()
106    }
107
108    /// Check if host is properly initialized
109    pub fn is_ready(&self) -> bool {
110        !self.entity_fetchers.is_empty()
111    }
112
113    /// Set the event bus for real-time notifications
114    pub fn with_event_bus(mut self, event_bus: EventBus) -> Self {
115        self.event_bus = Some(Arc::new(event_bus));
116        self
117    }
118
119    /// Get a reference to the event bus (if configured)
120    pub fn event_bus(&self) -> Option<&Arc<EventBus>> {
121        self.event_bus.as_ref()
122    }
123}