arcature 2026.1.0

Arcature application framework: a high-level Application facade over the certified Arcature subsystems, with the low-level Axum/Tower escape hatch preserved.
Documentation
use super::App;
use axum::Router;

impl<S> App<S>
where
    S: Clone + Send + Sync + 'static,
{
    /// Create an empty Arcature application.
    ///
    /// Mirrors [`axum::Router::new`]: the state type `S` is inferred from the
    /// routes added. A stateless app (handlers extract no [`axum::extract::State`])
    /// infers `S = ()` and is ready to serve; a stateful app infers its state
    /// type from the handlers, then resolves it with [`App::with_state`].
    ///
    /// Add routes with [`App::route`], compose with [`App::merge`], apply
    /// middleware with [`App::layer`], or bring in a pre-built router with
    /// [`App::from_router`].
    pub fn new() -> App<S> {
        App {
            router: Router::new(),
        }
    }
}

/// `App::default()` constructs a stateless `App<()>`, for the common case
/// where no state type is yet in play. (`App::new()` is generic and infers `S`
/// from routes; `default()` pins `()` so bare construction is unambiguous.)
impl Default for App<()> {
    fn default() -> Self {
        App {
            router: Router::new(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn empty_stateless_app_constructs() {
        let _app = App::default();
    }

    #[test]
    fn generic_new_infers_state_from_route() {
        use axum::extract::State;
        use axum::routing::get;

        #[derive(Clone)]
        struct S;
        // App::new() is generic; the route's handler extracts State<S>, so S is
        // inferred and the app becomes App<S>. with_state resolves to App<()>.
        let _app: App<()> = App::new()
            .route("/", get(|_state: State<S>| async { "ok" }))
            .with_state(S);
    }
}