rustango 0.27.0

Django-shaped batteries-included web framework for Rust: ORM + migrations + auto-admin + multi-tenancy + audit log + auth (sessions, JWT, OAuth2/OIDC, HMAC) + APIs (ViewSet, OpenAPI auto-derive, JSON:API) + jobs (in-mem + Postgres) + email + media (S3 / R2 / B2 / MinIO + presigned uploads + collections + tags) + production middleware (CSRF, CSP, rate-limiting, compression, idempotency, etc.).
Documentation
//! `run-server` verb — boot the operator console + tenant admin
//! using the project's existing models. Thin wrapper around
//! [`crate::tenancy::server::run`].

use std::io::Write;

use crate::tenancy::error::TenancyError;
use crate::tenancy::manage::args::next_value;
use crate::tenancy::pools::TenantPools;

pub(super) async fn run_server_cmd<W: Write + Send>(
    pools: &TenantPools,
    registry_url: &str,
    args: &[String],
    w: &mut W,
) -> Result<(), TenancyError> {
    let mut cfg = crate::tenancy::server::ServerConfig::from_env();
    let mut iter = args.iter();
    while let Some(flag) = iter.next() {
        match flag.as_str() {
            "--bind" => cfg.bind = next_value(&mut iter, "--bind")?,
            "--apex" | "--apex-domain" => {
                cfg.apex_domain = next_value(&mut iter, "--apex")?;
            }
            "--help" | "-h" => {
                return Err(TenancyError::Validation(
                    "run-server [--bind <addr>] [--apex <domain>]\n  \
                     Boots the operator console (apex) + tenant admin\n  \
                     (subdomains) with sensible defaults. Reads RUSTANGO_BIND,\n  \
                     RUSTANGO_APEX_DOMAIN, RUSTANGO_SESSION_SECRET from env.\n  \
                     Ctrl-C to stop."
                        .into(),
                ));
            }
            other => {
                return Err(TenancyError::Validation(format!(
                    "run-server: unknown argument `{other}`"
                )));
            }
        }
    }
    // Pools is borrowed; the server takes an `Arc<TenantPools>` so it
    // can clone into per-request closures. Build a fresh Arc carrying
    // a clone of the registry pool — the existing pools' database-mode
    // cache stays distinct, but for `run-server` the freshly-built
    // registry uses the same connection-pool handle so the existing
    // cache isn't lost.
    let arc_pools = std::sync::Arc::new(crate::tenancy::TenantPools::new(pools.registry().clone()));
    crate::tenancy::server::run(arc_pools, registry_url.to_owned(), cfg, w).await
}