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}