actus 1.0.0

The ergonomic web framework for Rust.
Documentation
//! # Actus
//!
//! The pragmatic web framework for Rust: auditable controllers, persistent
//! services, real HTTP — out of the box. Built directly on [hyper] and
//! [tokio]; there is no separate server to run it on.
//!
//! This crate is the façade you depend on. It re-exports the public API of the
//! implementation crates ([`actus-server`], [`actus-controller`],
//! [`actus-reply`]) and the two macros that declare your application's URL
//! surface. Add it with:
//!
//! ```toml
//! [dependencies]
//! actus = "1.0"
//! tokio = { version = "1", features = ["full"] }
//! serde_json = "1"
//! ```
//!
//! Optional features: `compression` (gzip/brotli responses), `websocket`
//! ([`ws::upgrade`]), and `openapi` (OpenAPI 3.x generation).
//!
//! # Quick start
//!
//! Two macros declare everything: `routes!` (one controller's API surface) and
//! `app_routes!` (the whole application's URL blueprint). A reviewer can see
//! every endpoint by reading just those two places.
//!
//! ```no_run
//! use actus::prelude::*;
//! use serde_json::json;
//!
//! // A controller owns a URL prefix and declares its routes in one block.
//! struct Greeter;
//!
//! #[controller]
//! impl Greeter {
//!     routes! {
//!         GET ""       => index(),
//!         GET "{name}" => greet(name: String),
//!     }
//!
//!     pub async fn index(&self) -> Reply {
//!         reply!(json!({ "hello": "world" }))
//!     }
//!
//!     pub async fn greet(&self, name: String) -> Reply {
//!         reply!(json!({ "hello": name }))
//!     }
//! }
//!
//! // The application's URL blueprint, declared in one place. (The `deps`
//! // block — for injected services — is optional and omitted here.)
//! app_routes! {
//!     routes {
//!         "greet" => Greeter,
//!     }
//! }
//!
//! // `init()` is generated by `app_routes!`; it builds the router.
//! #[tokio::main]
//! async fn main() -> actus::InitResult<()> {
//!     let router = init().await?;
//!     Server::new(router).run(3000).await?;
//!     Ok(())
//! }
//! ```
//!
//! See the [`prelude`] for the common imports, and the repository's
//! `examples/` directory for auth, typed bodies, CORS, compression,
//! WebSockets, SSE, and middleware in working code.
//!
//! [hyper]: https://hyper.rs/
//! [tokio]: https://tokio.rs/
//! [`actus-server`]: https://docs.rs/actus-server
//! [`actus-controller`]: https://docs.rs/actus-controller
//! [`actus-reply`]: https://docs.rs/actus-reply

pub use actus_reply::Finalizer;

// Re-exported at the crate root so the `app_routes!` macro can resolve
// `::actus::Router` / `::actus::RouterBuilder` from generated code without
// requiring downstream crates to depend on `actus-server` directly.
pub use actus_server::{GIB, KIB, MIB, RateLimitClass, Router, RouterBuilder, Server};

/// WebSocket support — [`ws::upgrade`], [`ws::WebSocket`], [`ws::Message`].
/// Available with the `websocket` feature.
#[cfg(feature = "websocket")]
pub use actus_server::websocket as ws;

/// OpenAPI 3.x doc generation — [`openapi::generate`], [`openapi::Options`].
/// Available with the `openapi` feature.
#[cfg(feature = "openapi")]
pub use actus_server::openapi;

/// Error type used by `app_routes!`'s generated `init()` for startup-time
/// failures (DB connection refused, env var missing, migrations failing,
/// etc.). Aliased to `anyhow::Error` so any error implementing
/// `std::error::Error + Send + Sync + 'static` converts via `?`, and the
/// generated `init()` slots cleanly into an `anyhow::Result<()>` `main`.
pub type InitError = anyhow::Error;

/// `Result<T, actus::InitError>`. The macro-generated `init()` returns this.
pub type InitResult<T> = ::std::result::Result<T, InitError>;

/// Implementation re-exports used by the procedural macros.
///
/// This module exists so generated code can refer to types from the
/// implementation crates (`actus-controller`, etc.) via stable absolute paths
/// like `::actus::__internal::Verb`. End users should not import from here —
/// use [`prelude`] instead.
#[doc(hidden)]
pub mod __internal {
    pub use actus_controller::*;
    pub use anyhow;
}

/// Common imports for Actus applications.
pub mod prelude {
    pub use actus_controller::{
        Controller, ExtractedParams, Params, RouteDef, Verb, app_routes, controller, routes,
    };
    // Needed to `impl Middleware` (the trait is `#[async_trait]`).
    pub use actus_controller::async_trait;
    pub use actus_reply::prelude::*;
    #[cfg(feature = "compression")]
    pub use actus_server::CompressionLayer;
    #[cfg(feature = "websocket")]
    pub use actus_server::{Message, WebSocket};
    // The `ws` module itself, so `ws::upgrade(...)` works after a glob import.
    #[cfg(feature = "websocket")]
    pub use crate::ws;
    pub use actus_server::{
        CorsLayer, GIB, KIB, MIB, Middleware, Outcome, RateLimitClass, Request, RequestLogger,
        Router, RouterBuilder, Server, ServerError,
    };
    // Re-exported so handlers can declare `body: Bytes` in `routes!`
    // without an extra `use bytes::Bytes;` line. There is one canonical
    // zero-copy bytes type in the Rust HTTP ecosystem; pinning it here
    // means generated extraction code and the handler signature
    // resolve to the same `bytes::Bytes`.
    pub use bytes::Bytes;
}