arcature-cli 2026.1.1

Developer lifecycle CLI for Arcature applications.
Documentation
//! `arc make middleware <name> --module <module>` — generate a middleware fn.
//!
//! Creates `src/<module>/<name>.rs` with a `#[middleware]` async function, and
//! appends `pub mod <name>;` to the module's `mod.rs`. The middleware name is
//! snake_case (e.g. `require_token`).

use std::path::Path;

use super::naming::{
    append_mod_declaration, mod_declaration, module_file_path, validate_module_name,
    validate_type_name,
};
use super::write::{GeneratedFile, module_mod_rs};

pub(crate) fn generate(
    root: &Path,
    raw_name: &str,
    raw_module: &str,
) -> Result<(GeneratedFile, String), String> {
    let name = validate_type_name(raw_name)?;
    let module = validate_module_name(raw_module)?;
    let fn_name = super::naming::snake_case(&name);
    let path = module_file_path(root, &module, &format!("{fn_name}.rs"))?;
    let content = render(&fn_name, &module);
    let file = GeneratedFile {
        path: path.clone(),
        content,
    };
    let mod_rs = module_mod_rs(root, &module);
    let declaration = mod_declaration(&fn_name)?;
    let mod_msg = append_mod_declaration(&mod_rs, &declaration)?;
    Ok((file, mod_msg))
}

fn render(fn_name: &str, module: &str) -> String {
    format!(
        "//! `{fn_name}` — middleware for the `{module}` module.\n\
         \n\
         use arcature::prelude::*;\n\
         \n\
         /// A middleware function. The `#[middleware]` macro validates the\n\
         /// signature and passes the function through unchanged so it remains a\n\
         /// genuine Axum `from_fn` middleware.\n\
         #[arcature::middleware]\n\
         pub async fn {fn_name}(request: Request, next: Next) -> Response {{\n\
         \x20   next.run(request).await\n\
         }}\n"
    )
}