Skip to main content

ruest/
bootstrap.rs

1//! Bootstrap HTTP : assemble le routeur Axum au compile-time via `Module::wire_routes`.
2
3use crate::core::{bootstrap, CoreError, Module, RuestApplication};
4use crate::http::axum::Router;
5use crate::security::{apply_jwt_layer, JwtService, SecurityConfig};
6
7/// Application prête à écouter (DI + routeur Axum monomorphisé).
8pub struct AppBuilder {
9    pub app: RuestApplication,
10    pub router: Router,
11}
12
13/// Bootstrap DI + montage des routes compile-time.
14///
15/// Nécessite que `#[module]` ait généré `wire_routes` sur le type module.
16pub fn bootstrap_app<M>(root: M) -> Result<AppBuilder, CoreError>
17where
18    M: Module + ModuleWireRoutes,
19{
20    let app = bootstrap(root)?;
21    let router = M::wire_routes(Router::new(), &app.container)
22        .map_err(|e| CoreError::ModuleConfig(e.to_string()))?;
23    Ok(AppBuilder { app, router })
24}
25
26/// Trait généré implicitement par `#[module]` (via `wire_routes` inherent).
27pub trait ModuleWireRoutes {
28    fn wire_routes(
29        router: Router,
30        container: &crate::di::Container,
31    ) -> Result<Router, crate::di::DiError>;
32}
33
34impl AppBuilder {
35    pub fn port(mut self, port: u16) -> Self {
36        self.app.set_port(port);
37        self
38    }
39
40    pub fn host(mut self, host: impl Into<String>) -> Self {
41        self.app.set_host(host);
42        self
43    }
44
45    pub async fn listen(self) -> Result<(), CoreError> {
46        crate::http::serve(self.app, self.router)
47            .await
48            .map_err(|e| CoreError::Bootstrap(e.to_string()))
49    }
50
51    pub fn build(self) -> (RuestApplication, Router) {
52        (self.app, self.router)
53    }
54
55    /// Active l'authentification JWT (enregistre [`JwtService`] si besoin + middleware).
56    ///
57    /// Enregistrez `JwtService` plus tôt via `JwtService::register_dev_provider` ou
58    /// `register_jwt_provider` dans un `#[module]` si des contrôleurs l'injectent au câblage des routes.
59    pub fn with_jwt_auth(mut self, config: SecurityConfig) -> Result<Self, CoreError> {
60        if self.app.container.get::<JwtService>().is_err() {
61            crate::security::register_jwt_provider(&self.app.container, config.clone())
62                .map_err(|e| CoreError::ModuleConfig(e.to_string()))?;
63        }
64
65        let jwt = self
66            .app
67            .container
68            .get::<JwtService>()
69            .map_err(|e| CoreError::ModuleConfig(e.to_string()))?;
70
71        self.router = apply_jwt_layer(self.router, jwt, &config);
72        Ok(self)
73    }
74}