a3s_boot/module/mod.rs
1use crate::{
2 BoxFuture, ControllerDefinition, MessagePatternDefinition, Middleware, MiddlewareConsumer,
3 ModuleRef, ProviderDefinition, ProviderToken, Result, RouteDefinition,
4 WebSocketGatewayDefinition,
5};
6use std::sync::Arc;
7
8mod dynamic;
9
10pub use dynamic::DynamicModule;
11
12/// A module contributes imports, providers, controllers, and routes.
13///
14/// This is the Rust equivalent of a Nest module boundary. Modules organize the
15/// application graph; HTTP serving remains delegated to an adapter.
16pub trait Module: Send + Sync + 'static {
17 /// Stable module name used for deduplication and diagnostics.
18 fn name(&self) -> &'static str;
19
20 /// Imported modules that should be registered before this module.
21 fn imports(&self) -> Vec<Arc<dyn Module>> {
22 Vec::new()
23 }
24
25 /// Forward module imports for intentional circular module relationships.
26 ///
27 /// This mirrors the module side of Nest's `forwardRef(...)`. Forward imports
28 /// can reference a module that is currently being registered; exported
29 /// providers become visible once the target module finishes registration.
30 /// Provider cycles should still use lazy [`crate::ProviderRef`] handles.
31 fn forward_imports(&self) -> Vec<Arc<dyn Module>> {
32 Vec::new()
33 }
34
35 /// Providers exported into the application container.
36 fn providers(&self) -> Result<Vec<ProviderDefinition>> {
37 Ok(Vec::new())
38 }
39
40 /// Providers this module exposes to importing modules.
41 fn exports(&self) -> Result<Vec<ProviderToken>> {
42 Ok(Vec::new())
43 }
44
45 /// Whether exported providers should be visible to every module scope.
46 fn is_global(&self) -> bool {
47 false
48 }
49
50 /// Optional HTTP route prefix applied to controllers and direct routes in this module and its imports.
51 fn route_prefix(&self) -> Option<&str> {
52 None
53 }
54
55 /// Middleware applied to controllers and direct routes declared by this module.
56 fn middleware(&self) -> Vec<Arc<dyn Middleware>> {
57 Vec::new()
58 }
59
60 /// Configure route-scoped middleware with a Nest-style consumer.
61 fn configure(&self, _consumer: &mut MiddlewareConsumer, _module_ref: &ModuleRef) -> Result<()> {
62 Ok(())
63 }
64
65 /// Controller route groups built with access to the provider container.
66 fn controllers(&self, _module_ref: &ModuleRef) -> Result<Vec<ControllerDefinition>> {
67 Ok(Vec::new())
68 }
69
70 /// Framework-neutral routes contributed directly by this module.
71 fn routes(&self) -> Result<Vec<RouteDefinition>> {
72 Ok(Vec::new())
73 }
74
75 /// WebSocket gateways contributed by this module.
76 fn gateways(&self, _module_ref: &ModuleRef) -> Result<Vec<WebSocketGatewayDefinition>> {
77 Ok(Vec::new())
78 }
79
80 /// Microservice message patterns contributed by this module.
81 fn message_patterns(&self, _module_ref: &ModuleRef) -> Result<Vec<MessagePatternDefinition>> {
82 Ok(Vec::new())
83 }
84
85 /// Lifecycle hook called after imports and providers are registered.
86 fn on_module_init(&self, _module_ref: &ModuleRef) -> Result<()> {
87 Ok(())
88 }
89
90 /// Async lifecycle hook called by hosts that want startup work before serve.
91 fn on_application_bootstrap(&self, _module_ref: ModuleRef) -> BoxFuture<'static, Result<()>> {
92 Box::pin(async { Ok(()) })
93 }
94
95 /// Async lifecycle hook called when shutdown begins.
96 fn on_module_destroy(
97 &self,
98 _module_ref: ModuleRef,
99 _signal: Option<String>,
100 ) -> BoxFuture<'static, Result<()>> {
101 Box::pin(async { Ok(()) })
102 }
103
104 /// Async lifecycle hook called after module destroy hooks and before final shutdown hooks.
105 fn before_application_shutdown(
106 &self,
107 _module_ref: ModuleRef,
108 _signal: Option<String>,
109 ) -> BoxFuture<'static, Result<()>> {
110 Box::pin(async { Ok(()) })
111 }
112
113 /// Async lifecycle hook called by hosts that need graceful shutdown cleanup.
114 fn on_application_shutdown(&self, _module_ref: ModuleRef) -> BoxFuture<'static, Result<()>> {
115 Box::pin(async { Ok(()) })
116 }
117
118 /// Signal-aware variant of [`Module::on_application_shutdown`].
119 fn on_application_shutdown_with_signal(
120 &self,
121 module_ref: ModuleRef,
122 _signal: Option<String>,
123 ) -> BoxFuture<'static, Result<()>> {
124 self.on_application_shutdown(module_ref)
125 }
126}