📝 [config] Amplía y corrige documentación

This commit is contained in:
Manuel Cillero 2025-07-06 20:08:17 +02:00
parent f7dbd90af2
commit 6b8eee46f9
4 changed files with 108 additions and 19 deletions

View file

@ -16,7 +16,7 @@ la creación de soluciones web SSR (*renderizadas en el servidor*) basadas en HT
La aplicación más sencilla de `PageTop` se ve así:
```rust#ignore
```rust
use pagetop::prelude::*;
#[pagetop::main]

View file

@ -21,7 +21,7 @@ use quote::quote;
///
/// # Ejemplos
///
/// ```rust#ignore
/// ```rust,ignore
/// #[pagetop::main]
/// async fn main() {
/// async { println!("Hello world!"); }.await
@ -42,7 +42,7 @@ pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
///
/// # Ejemplos
///
/// ```rust#ignore
/// ```rust,ignore
/// #[pagetop::test]
/// async fn test() {
/// assert_eq!(async { "Hello world" }.await, "Hello world");

View file

@ -55,7 +55,7 @@
//! Y usa la macro [`include_config!`](crate::include_config) para inicializar tus ajustes en una
//! estructura con tipos seguros. Por ejemplo:
//!
//! ```rust#ignore
//! ```rust,no_run
//! use pagetop::prelude::*;
//! use serde::Deserialize;
//!
@ -94,7 +94,7 @@
//!
//! # Usando tus opciones de configuración
//!
//! ```rust#ignore
//! ```rust,ignore
//! use pagetop::prelude::*;
//! use crate::config;
//!
@ -160,20 +160,109 @@ pub static CONFIG_VALUES: LazyLock<ConfigBuilder<DefaultState>> = LazyLock::new(
.expect("Failed to set application run mode")
});
/// Incluye los ajustes necesarios de la configuración anticipando valores por defecto.
///
/// ### Sintaxis
///
/// Hay que añadir en nuestra librería el siguiente código:
///
/// ```rust,ignore
/// include_config!(SETTINGS: Settings => [
/// "ruta.clave" => valor,
/// // …
/// ]);
/// ```
///
/// donde:
///
/// * **`SETTINGS_NAME`** es el nombre de la variable global que se usará para referenciar los
/// ajustes. Se recomienda usar `SETTINGS`, aunque no es obligatorio.
/// * **`Settings_Type`** es la referencia a la estructura que define los tipos para deserializar la
/// configuración. Debe implementar `Deserialize` (derivable con `#[derive(Deserialize)]`).
/// * **Lista de pares** con las claves TOML que requieran valores por defecto. Siguen la notación
/// `"seccion.subclave"` para coincidir con el árbol TOML.
///
/// ### Ejemplo básico
///
/// ```rust,no_run
/// use pagetop::prelude::*;
/// use serde::Deserialize;
///
/// include_config!(SETTINGS: BlogSettings => [
/// // [blog]
/// "blog.title" => "Mi Blog",
/// "blog.port" => 8080,
/// ]);
///
/// #[derive(Debug, Deserialize)]
/// pub struct BlogSettings {
/// pub blog: Blog,
/// }
///
/// #[derive(Debug, Deserialize)]
/// pub struct Blog {
/// pub title: String,
/// pub description: Option<String>,
/// pub port: u16,
/// }
///
/// fn print_title() {
/// // Lectura en tiempo de ejecución.
/// println!("Título: {}", SETTINGS.blog.title);
/// }
/// ```
///
/// ### Buenas prácticas
///
/// * **Valores por defecto**. Declara un valor por defecto para cada clave obligatoria. Las claves
/// opcionales pueden ser `Option<T>`.
///
/// * **Secciones únicas**. Agrupa tus claves dentro de una sección exclusiva (p.e. `[blog]`) para
/// evitar colisiones con otras librerías.
///
/// * **Solo lectura**. La variable generada es inmutable durante toda la vida del programa. Para
/// configurar distintos entornos (*dev*, *staging*, *prod*) usa los archivos TOML descritos en la
/// documentación de [`config`](crate::config).
///
/// * **Errores explícitos**. Si la deserialización falla, la macro lanzará un `panic!` con un
/// mensaje que indica la estructura problemática, facilitando la depuración.
///
/// ### Requisitos
///
/// * Dependencia `serde` con la *feature* `derive`.
/// * Las claves deben coincidir con los campos (*snake case*) de tu estructura `Settings_Type`.
///
/// ```toml
/// [dependencies]
/// serde = { version = "1.0", features = ["derive"] }
/// ```
#[macro_export]
macro_rules! include_config {
( $SETTINGS:ident : $Settings:ty => [ $( $key:expr => $value:expr ),* $(,)? ] ) => {
/// Valores asignados o predefinidos para la configuración de [`$Settings`].
pub static $SETTINGS: std::sync::LazyLock<$Settings> = std::sync::LazyLock::new(|| {
( $SETTINGS_NAME:ident : $Settings_Type:ty => [ $( $k:literal => $v:expr ),* $(,)? ] ) => {
#[doc = concat!(
"Referencia a los ajustes de configuración deserializados de [`",
stringify!($Settings_Type),
"`]."
)]
#[doc = ""]
#[doc = "Valores por defecto:"]
#[doc = "```text"]
$(
#[doc = concat!($k, " = ", stringify!($v))]
)*
#[doc = "```"]
pub static $SETTINGS_NAME: std::sync::LazyLock<$Settings_Type> =
std::sync::LazyLock::new(|| {
let mut settings = $crate::config::CONFIG_VALUES.clone();
$(
settings = settings.set_default($key, $value).unwrap();
settings = settings.set_default($k, $v).unwrap();
)*
settings
.build()
.expect(concat!("Failed to build config for ", stringify!($Settings)))
.try_deserialize::<$Settings>()
.expect(concat!("Error parsing settings for ", stringify!($Settings)))
.expect(concat!("Failed to build config for ", stringify!($Settings_Type)))
.try_deserialize::<$Settings_Type>()
.expect(concat!("Error parsing settings for ", stringify!($Settings_Type)))
});
};
}

View file

@ -19,7 +19,7 @@
//!
//! La aplicación más sencilla de `PageTop` se ve así:
//!
//! ```rust#ignore
//! ```rust,no_run
//! use pagetop::prelude::*;
//!
//! #[pagetop::main]