1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//! Auto-generated CRUD admin for rustango models.
//!
//! Walks the `inventory` registry every `#[derive(Model)]` populates and
//! serves an axum [`axum::Router`] over it — no per-model code required.
//!
//! ```ignore
//! use rustango::{migrate, admin};
//! use rustango::sql::sqlx::PgPool;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let pool = PgPool::connect(&std::env::var("DATABASE_URL")?).await?;
//! migrate::apply_all(&pool).await?;
//!
//! let app = admin::router(pool);
//! let listener = tokio::net::TcpListener::bind("127.0.0.1:8080").await?;
//! axum::serve(listener, app).await?;
//! Ok(())
//! }
//! ```
//!
//! Routes:
//! * `GET /` — list every registered model
//! * `GET /<table>` — list rows
//! * `GET /__admin/<table>/new` — create form
//! * `POST /<table>` — submit create
//! * `GET /<table>/<pk>` — detail view
//! * `GET /<table>/<pk>/edit` — edit form (PK readonly)
//! * `POST /<table>/<pk>` — submit edit
//! * `POST /<table>/<pk>/delete` — submit delete
//!
//! ## Crate layout (Django-shape)
//!
//! - [`urls`] — `router(pool)`, `Builder`, `Config`, `AppState` (route table).
//! - [`views`] — one async fn per route; consumes the inventory registry.
//! - [`helpers`] — model lookup, FK joins, render_cell, render_form, pager.
//! - [`templates`] — bundled Tera registry + render entry-point.
//! - [`errors`] — `AdminError` and its `IntoResponse` impl.
//! - `forms`, `render`, `auth` — value parsing, HTML rendering primitives,
//! HTTP Basic auth middleware.
// `pub(crate)` so the operator console can reuse `render_input` /
// `render_value_for_input` for its `/orgs/{slug}/edit` form. Stays
// non-public outside the crate — the helpers' signatures are still
// internal-only.
pub
pub use protect_with_basic_auth;
pub use AdminError;
pub use ;