a3s-boot 0.1.0

Adapter-first modular Rust web framework for A3S inspired by Nest.js
Documentation
use crate::pipeline::PipelineComponents;
use crate::{BootError, ControllerDefinition, Module, ModuleRef, Result, RouteDefinition};
use std::collections::BTreeSet;
use std::sync::Arc;

pub(super) fn register_module(
    module: Arc<dyn Module>,
    module_ref: &ModuleRef,
    global_pipeline: &PipelineComponents,
    seen: &mut BTreeSet<String>,
    modules: &mut Vec<String>,
    module_instances: &mut Vec<Arc<dyn Module>>,
    routes: &mut Vec<RouteDefinition>,
) -> Result<()> {
    let name = module.name();
    if name.trim().is_empty() {
        return Err(BootError::EmptyModuleName);
    }
    if !seen.insert(name.to_string()) {
        return Ok(());
    }

    for imported in module.imports() {
        register_module(
            imported,
            module_ref,
            global_pipeline,
            seen,
            modules,
            module_instances,
            routes,
        )?;
    }

    for provider in module.providers()? {
        module_ref.register(provider)?;
    }

    module.on_module_init(module_ref)?;

    for controller in module.controllers(module_ref)? {
        register_controller(name, controller, global_pipeline, routes);
    }

    routes.extend(module.routes()?.into_iter().map(|route| {
        route
            .with_pipeline_prefix(global_pipeline)
            .with_module_name(name)
    }));
    modules.push(name.to_string());
    module_instances.push(module);
    Ok(())
}

fn register_controller(
    module_name: &str,
    controller: ControllerDefinition,
    global_pipeline: &PipelineComponents,
    routes: &mut Vec<RouteDefinition>,
) {
    routes.extend(controller.into_routes().into_iter().map(|route| {
        route
            .with_pipeline_prefix(global_pipeline)
            .with_module_name(module_name)
    }));
}