this/core/module.rs
1//! Module system for This-RS
2//!
3//! Defines traits for microservice modules
4
5use crate::config::LinksConfig;
6use crate::server::entity_registry::EntityRegistry;
7use anyhow::Result;
8use async_trait::async_trait;
9use std::sync::Arc;
10use uuid::Uuid;
11
12/// Trait for fetching entities dynamically
13///
14/// This allows the link system to enrich links with full entity data
15/// without knowing the concrete entity types at compile time.
16#[async_trait]
17pub trait EntityFetcher: Send + Sync {
18 /// Fetch an entity by ID and return it as JSON
19 ///
20 /// # Arguments
21 /// * `entity_id` - The unique ID of the entity to fetch
22 ///
23 /// # Returns
24 /// The entity serialized as JSON, or an error if not found
25 async fn fetch_as_json(&self, entity_id: &Uuid) -> Result<serde_json::Value>;
26
27 /// Get a sample entity for schema introspection
28 ///
29 /// This method returns an entity with all fields populated (can be dummy data)
30 /// to allow the GraphQL schema generator to discover the entity structure.
31 ///
32 /// Default implementation returns an empty object.
33 async fn get_sample_entity(&self) -> Result<serde_json::Value> {
34 Ok(serde_json::json!({}))
35 }
36
37 /// List entities with pagination
38 ///
39 /// # Arguments
40 /// * `limit` - Maximum number of entities to return
41 /// * `offset` - Number of entities to skip
42 ///
43 /// # Returns
44 /// A vector of entities serialized as JSON
45 ///
46 /// Default implementation returns an empty list.
47 async fn list_as_json(
48 &self,
49 _limit: Option<i32>,
50 _offset: Option<i32>,
51 ) -> Result<Vec<serde_json::Value>> {
52 Ok(vec![])
53 }
54}
55
56/// Trait for creating entities dynamically
57///
58/// This allows the link system to create new entities with automatic linking
59/// without knowing the concrete entity types at compile time.
60#[async_trait]
61pub trait EntityCreator: Send + Sync {
62 /// Create a new entity from JSON data
63 ///
64 /// # Arguments
65 /// * `entity_data` - The entity data as JSON
66 ///
67 /// # Returns
68 /// The created entity serialized as JSON (with generated ID, timestamps, etc.)
69 async fn create_from_json(&self, entity_data: serde_json::Value) -> Result<serde_json::Value>;
70
71 /// Update an existing entity from JSON data
72 ///
73 /// # Arguments
74 /// * `entity_id` - The ID of the entity to update
75 /// * `entity_data` - The updated entity data as JSON
76 ///
77 /// # Returns
78 /// The updated entity serialized as JSON
79 ///
80 /// Default implementation returns an error.
81 async fn update_from_json(
82 &self,
83 _entity_id: &Uuid,
84 _entity_data: serde_json::Value,
85 ) -> Result<serde_json::Value> {
86 Err(anyhow::anyhow!(
87 "Update operation not implemented for this entity type"
88 ))
89 }
90
91 /// Delete an entity by ID
92 ///
93 /// # Arguments
94 /// * `entity_id` - The ID of the entity to delete
95 ///
96 /// # Returns
97 /// Ok(()) if successful, error otherwise
98 ///
99 /// Default implementation returns an error.
100 async fn delete(&self, _entity_id: &Uuid) -> Result<()> {
101 Err(anyhow::anyhow!(
102 "Delete operation not implemented for this entity type"
103 ))
104 }
105}
106
107/// Trait for a microservice module
108pub trait Module: Send + Sync {
109 /// Unique module name
110 fn name(&self) -> &str;
111
112 /// Module version
113 fn version(&self) -> &str {
114 "1.0.0"
115 }
116
117 /// List of entity types managed by this module
118 fn entity_types(&self) -> Vec<&str>;
119
120 /// Load links configuration
121 fn links_config(&self) -> Result<LinksConfig>;
122
123 /// Register entities with the entity registry
124 ///
125 /// This method should register all entity descriptors for the module.
126 /// Each entity descriptor provides the CRUD routes for that entity.
127 fn register_entities(&self, registry: &mut EntityRegistry);
128
129 /// Get an entity fetcher for a specific entity type
130 ///
131 /// This allows the framework to dynamically load entities when enriching links.
132 ///
133 /// # Arguments
134 /// * `entity_type` - The type of entity (e.g., "order", "invoice")
135 ///
136 /// # Returns
137 /// An `EntityFetcher` implementation, or `None` if the entity type is not managed by this module
138 fn get_entity_fetcher(&self, entity_type: &str) -> Option<Arc<dyn EntityFetcher>>;
139
140 /// Get an entity creator for a specific entity type
141 ///
142 /// This allows the framework to create new entities dynamically when creating linked entities.
143 ///
144 /// # Arguments
145 /// * `entity_type` - The type of entity (e.g., "order", "invoice")
146 ///
147 /// # Returns
148 /// An `EntityCreator` implementation, or `None` if the entity type is not managed by this module
149 fn get_entity_creator(&self, entity_type: &str) -> Option<Arc<dyn EntityCreator>>;
150}