Skip to main content

a3s_boot/module/
dynamic.rs

1use super::Module;
2use crate::{
3    BoxFuture, ControllerDefinition, MessagePatternDefinition, Middleware, MiddlewareConsumer,
4    ModuleRef, ProviderDefinition, ProviderToken, Result, RouteDefinition,
5    WebSocketGatewayDefinition,
6};
7use std::sync::Arc;
8
9/// Runtime-built module for configuration-driven imports and providers.
10#[derive(Clone)]
11pub struct DynamicModule {
12    name: &'static str,
13    imports: Vec<Arc<dyn Module>>,
14    forward_imports: Vec<Arc<dyn Module>>,
15    providers: Vec<ProviderDefinition>,
16    exports: Vec<ProviderToken>,
17    middleware: Vec<Arc<dyn Middleware>>,
18    controllers: Vec<ControllerDefinition>,
19    routes: Vec<RouteDefinition>,
20    gateways: Vec<WebSocketGatewayDefinition>,
21    message_patterns: Vec<MessagePatternDefinition>,
22    global: bool,
23    route_prefix: Option<String>,
24    middleware_consumer: MiddlewareConsumer,
25}
26
27impl DynamicModule {
28    pub fn new(name: &'static str) -> Self {
29        Self {
30            name,
31            imports: Vec::new(),
32            forward_imports: Vec::new(),
33            providers: Vec::new(),
34            exports: Vec::new(),
35            middleware: Vec::new(),
36            controllers: Vec::new(),
37            routes: Vec::new(),
38            gateways: Vec::new(),
39            message_patterns: Vec::new(),
40            global: false,
41            route_prefix: None,
42            middleware_consumer: MiddlewareConsumer::new(),
43        }
44    }
45
46    pub fn import<M>(mut self, module: M) -> Self
47    where
48        M: Module,
49    {
50        self.imports.push(Arc::new(module));
51        self
52    }
53
54    pub fn import_arc(mut self, module: Arc<dyn Module>) -> Self {
55        self.imports.push(module);
56        self
57    }
58
59    pub fn forward_import<M>(mut self, module: M) -> Self
60    where
61        M: Module,
62    {
63        self.forward_imports.push(Arc::new(module));
64        self
65    }
66
67    pub fn forward_import_arc(mut self, module: Arc<dyn Module>) -> Self {
68        self.forward_imports.push(module);
69        self
70    }
71
72    pub fn provider(mut self, provider: ProviderDefinition) -> Self {
73        self.providers.push(provider);
74        self
75    }
76
77    pub fn export<T>(self) -> Self
78    where
79        T: Send + Sync + 'static,
80    {
81        self.export_token(ProviderToken::of::<T>())
82    }
83
84    pub fn export_named(self, token: impl Into<String>) -> Self {
85        self.export_token(ProviderToken::named(token))
86    }
87
88    pub fn export_token(mut self, token: ProviderToken) -> Self {
89        if !self.exports.contains(&token) {
90            self.exports.push(token);
91        }
92        self
93    }
94
95    pub fn middleware<M>(mut self, middleware: M) -> Self
96    where
97        M: Middleware,
98    {
99        self.middleware.push(Arc::new(middleware));
100        self
101    }
102
103    pub fn middleware_arc(mut self, middleware: Arc<dyn Middleware>) -> Self {
104        self.middleware.push(middleware);
105        self
106    }
107
108    pub fn configure_middleware<F>(mut self, configure: F) -> Result<Self>
109    where
110        F: FnOnce(&mut MiddlewareConsumer) -> Result<()>,
111    {
112        configure(&mut self.middleware_consumer)?;
113        Ok(self)
114    }
115
116    pub fn controller(mut self, controller: ControllerDefinition) -> Self {
117        self.controllers.push(controller);
118        self
119    }
120
121    pub fn route(mut self, route: RouteDefinition) -> Self {
122        self.routes.push(route);
123        self
124    }
125
126    pub fn route_prefix(mut self, prefix: impl Into<String>) -> Self {
127        self.route_prefix = Some(prefix.into());
128        self
129    }
130
131    pub fn gateway(mut self, gateway: WebSocketGatewayDefinition) -> Self {
132        self.gateways.push(gateway);
133        self
134    }
135
136    pub fn message_pattern(mut self, pattern: MessagePatternDefinition) -> Self {
137        self.message_patterns.push(pattern);
138        self
139    }
140
141    pub fn global(mut self) -> Self {
142        self.global = true;
143        self
144    }
145}
146
147impl Module for DynamicModule {
148    fn name(&self) -> &'static str {
149        self.name
150    }
151
152    fn imports(&self) -> Vec<Arc<dyn Module>> {
153        self.imports.clone()
154    }
155
156    fn forward_imports(&self) -> Vec<Arc<dyn Module>> {
157        self.forward_imports.clone()
158    }
159
160    fn providers(&self) -> Result<Vec<ProviderDefinition>> {
161        Ok(self.providers.clone())
162    }
163
164    fn exports(&self) -> Result<Vec<ProviderToken>> {
165        Ok(self.exports.clone())
166    }
167
168    fn is_global(&self) -> bool {
169        self.global
170    }
171
172    fn route_prefix(&self) -> Option<&str> {
173        self.route_prefix.as_deref()
174    }
175
176    fn middleware(&self) -> Vec<Arc<dyn Middleware>> {
177        self.middleware.clone()
178    }
179
180    fn configure(&self, consumer: &mut MiddlewareConsumer, _module_ref: &ModuleRef) -> Result<()> {
181        consumer.extend(self.middleware_consumer.clone());
182        Ok(())
183    }
184
185    fn controllers(&self, _module_ref: &ModuleRef) -> Result<Vec<ControllerDefinition>> {
186        Ok(self.controllers.clone())
187    }
188
189    fn routes(&self) -> Result<Vec<RouteDefinition>> {
190        Ok(self.routes.clone())
191    }
192
193    fn gateways(&self, _module_ref: &ModuleRef) -> Result<Vec<WebSocketGatewayDefinition>> {
194        Ok(self.gateways.clone())
195    }
196
197    fn message_patterns(&self, _module_ref: &ModuleRef) -> Result<Vec<MessagePatternDefinition>> {
198        Ok(self.message_patterns.clone())
199    }
200
201    fn on_application_bootstrap(&self, _module_ref: ModuleRef) -> BoxFuture<'static, Result<()>> {
202        Box::pin(async { Ok(()) })
203    }
204
205    fn on_application_shutdown(&self, _module_ref: ModuleRef) -> BoxFuture<'static, Result<()>> {
206        Box::pin(async { Ok(()) })
207    }
208}