Skip to main content

renox_core/
lib.rs

1//! Core of the Renox web framework.
2//!
3//! Most applications should depend on the `renox` crate instead, which
4//! re-exports everything here through `renox::prelude`.
5#![recursion_limit = "256"]
6// the built-in auth texts are one large `json!`
7// Every public item is documented; clippy's `-D warnings` in CI keeps it so.
8#![warn(missing_docs)]
9
10/// An enum for a setting written as one word in `.env` (`SESSION_DRIVER=database`):
11/// `#[non_exhaustive]`, with `as_str`, `Display` and a parser that names the variable.
12macro_rules! setting_enum {
13    (
14        $(#[$meta:meta])*
15        pub enum $name:ident ($variable:literal) {
16            $( $(#[$vmeta:meta])* $variant:ident = $text:literal ),+ $(,)?
17        }
18    ) => {
19        $(#[$meta])*
20        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21        #[non_exhaustive]
22        pub enum $name {
23            $( $(#[$vmeta])* $variant ),+
24        }
25
26        impl $name {
27            /// The value as written in `.env`.
28            pub fn as_str(&self) -> &'static str {
29                match self {
30                    $( Self::$variant => $text ),+
31                }
32            }
33
34            /// Reads the value of `
35            #[doc = $variable]
36            /// `.
37            #[allow(dead_code)]
38            pub(crate) fn parse(value: &str) -> anyhow::Result<Self> {
39                Self::parse_as(value, $variable)
40            }
41
42            /// Reads `value`, naming `variable` in the error.
43            #[allow(dead_code)]
44            pub(crate) fn parse_as(value: &str, variable: &str) -> anyhow::Result<Self> {
45                let value = value.trim().to_ascii_lowercase();
46                $( if value == $text { return Ok(Self::$variant); } )+
47                let expected: &[&str] = &[$($text),+];
48                anyhow::bail!("{variable} must be one of {}, got `{value}`", expected.join(", "))
49            }
50        }
51
52        impl ::std::fmt::Display for $name {
53            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
54                f.write_str(self.as_str())
55            }
56        }
57
58        impl ::serde::Serialize for $name {
59            fn serialize<S: ::serde::Serializer>(&self, s: S) -> ::std::result::Result<S::Ok, S::Error> {
60                s.serialize_str(self.as_str())
61            }
62        }
63    };
64}
65
66pub mod analytics;
67mod app;
68mod assets;
69pub mod audit;
70pub mod auth;
71pub mod cache;
72pub mod chart;
73mod client_ip;
74mod clock;
75pub mod command;
76mod config;
77pub mod context;
78mod cookies;
79mod counters;
80mod crypto;
81mod csrf;
82pub mod db;
83mod domain;
84mod download;
85mod embedded;
86mod error;
87pub mod events;
88pub mod grid;
89mod health;
90mod htmx;
91pub mod http;
92pub mod i18n;
93mod icons;
94pub mod import;
95mod inspector;
96mod live;
97pub mod mail;
98pub mod maintenance;
99mod method;
100mod module;
101mod path;
102pub mod prompt;
103mod provided;
104pub mod queue;
105pub mod rate_limit;
106mod redirect;
107mod registry;
108pub mod report;
109mod request_id;
110mod routing;
111pub mod schedule;
112pub mod security;
113pub mod select;
114pub mod seo;
115mod session;
116pub mod shell;
117pub mod signed;
118mod state;
119pub mod storage;
120#[cfg(test)]
121mod test_logs;
122pub mod testing;
123pub mod timezone;
124pub mod toast;
125pub mod upload;
126pub mod validation;
127/// Views: MiniJinja templates, the `View` response and template globals.
128pub mod view;
129mod view_filters;
130mod view_stack;
131pub mod webhook;
132
133pub use app::{App, Kernel};
134pub use assets::{ALPINE_VERSION, CALLY_VERSION, HTMX_VERSION};
135pub use auth::{AuthUser, Policy};
136pub use client_ip::{ClientIp, TrustedProxies};
137pub use config::{
138    AnalyticsConfig, CacheStore, Config, CspMode, Environment, LogFormat, SessionDriver,
139};
140pub use cookies::{Cookies, SetCookie};
141pub use crypto::{generate_key, random_token};
142pub use csrf::{CSRF_FIELD, CSRF_HEADER, XSRF_COOKIE, XSRF_HEADER};
143pub use domain::DomainParams;
144pub use download::Download;
145pub use embedded::Embedded;
146pub use error::{Error, Result, abort, abort_if, abort_unless};
147pub use htmx::{Back, Htmx, HxPushUrl, HxRedirect, HxRefresh, HxReswap, HxRetarget, HxTrigger};
148pub use i18n::Lang;
149pub use method::METHOD_FIELD;
150pub use module::Module;
151pub use path::{Found, Path};
152pub use provided::Provided;
153pub use redirect::RedirectExt;
154pub use registry::Registry;
155pub use request_id::RequestId;
156pub use routing::Resource;
157pub(crate) use routing::RouteTable;
158pub use routing::{CurrentRoute, RouteInfo, Routes};
159pub use session::Session;
160pub use state::{AppState, AppStateInner};
161pub use state::{SentBroadcast, SentNotification};
162pub use toast::{Toast, ToastAction, ToastKind};
163pub use upload::Upload;
164pub use validation::{Errors, KeyValues, Valid, Validate, ValidationError, Validator};
165pub(crate) use view::Views;
166pub use view::{View, view};
167pub use view_filters::{currency_decimals, format_money, format_number};
168
169pub use minijinja::context;
170
171/// `anyhow`, for errors with context: `renox::anyhow::anyhow!("…")`,
172/// `.context("…")`, `Error::permanent(err)`.
173pub use anyhow;
174pub use chrono;
175pub use clap;
176#[cfg(feature = "fake")]
177pub use fake;
178/// `minijinja`, for the app's own template filters and functions
179/// (`App::templates(|env| …)` gets a `minijinja::Environment`).
180pub use minijinja;
181pub use serde;
182pub use serde_json;
183#[doc(hidden)]
184pub use sqlx as __sqlx;
185/// CORS configuration for `Routes::cors_layer`.
186pub use tower_http::cors;
187/// `uuid`, for `Uuid` model keys and fields (the `uuid` feature):
188/// `renox::uuid::Uuid`.
189#[cfg(feature = "uuid")]
190pub use uuid;