♻️ Refactor config initialization by name and type
This commit is contained in:
parent
3ff00ac38f
commit
b599e2f7d4
18 changed files with 193 additions and 192 deletions
18
src/app.rs
18
src/app.rs
|
|
@ -6,7 +6,7 @@ use crate::core::{package, package::PackageRef};
|
||||||
use crate::html::Markup;
|
use crate::html::Markup;
|
||||||
use crate::response::page::{ErrorPage, ResultPage};
|
use crate::response::page::{ErrorPage, ResultPage};
|
||||||
use crate::service::HttpRequest;
|
use crate::service::HttpRequest;
|
||||||
use crate::{config, locale, service, trace};
|
use crate::{global, locale, service, trace};
|
||||||
|
|
||||||
use actix_session::config::{BrowserSession, PersistentSession, SessionLifecycle};
|
use actix_session::config::{BrowserSession, PersistentSession, SessionLifecycle};
|
||||||
use actix_session::storage::CookieSessionStore;
|
use actix_session::storage::CookieSessionStore;
|
||||||
|
|
@ -63,9 +63,9 @@ impl Application {
|
||||||
fn show_banner() {
|
fn show_banner() {
|
||||||
use terminal_size::{terminal_size, Width};
|
use terminal_size::{terminal_size, Width};
|
||||||
|
|
||||||
if config::SETTINGS.app.startup_banner.to_lowercase() != "off" {
|
if global::SETTINGS.app.startup_banner.to_lowercase() != "off" {
|
||||||
// Application name, formatted for the terminal width if necessary.
|
// Application name, formatted for the terminal width if necessary.
|
||||||
let mut app_name = config::SETTINGS.app.name.to_string();
|
let mut app_name = global::SETTINGS.app.name.to_string();
|
||||||
if let Some((Width(term_width), _)) = terminal_size() {
|
if let Some((Width(term_width), _)) = terminal_size() {
|
||||||
if term_width >= 80 {
|
if term_width >= 80 {
|
||||||
let maxlen: usize = ((term_width / 10) - 2).into();
|
let maxlen: usize = ((term_width / 10) - 2).into();
|
||||||
|
|
@ -81,8 +81,8 @@ impl Application {
|
||||||
println!("\n{app_name}");
|
println!("\n{app_name}");
|
||||||
|
|
||||||
// Application description.
|
// Application description.
|
||||||
if !config::SETTINGS.app.description.is_empty() {
|
if !global::SETTINGS.app.description.is_empty() {
|
||||||
println!("{}\n", config::SETTINGS.app.description);
|
println!("{}\n", global::SETTINGS.app.description);
|
||||||
};
|
};
|
||||||
|
|
||||||
// PageTop version.
|
// PageTop version.
|
||||||
|
|
@ -101,12 +101,12 @@ impl Application {
|
||||||
.wrap(tracing_actix_web::TracingLogger::default())
|
.wrap(tracing_actix_web::TracingLogger::default())
|
||||||
.wrap(
|
.wrap(
|
||||||
SessionMiddleware::builder(CookieSessionStore::default(), secret_key.clone())
|
SessionMiddleware::builder(CookieSessionStore::default(), secret_key.clone())
|
||||||
.session_lifecycle(match config::SETTINGS.server.session_lifetime {
|
.session_lifecycle(match global::SETTINGS.server.session_lifetime {
|
||||||
0 => SessionLifecycle::BrowserSession(BrowserSession::default()),
|
0 => SessionLifecycle::BrowserSession(BrowserSession::default()),
|
||||||
_ => SessionLifecycle::PersistentSession(
|
_ => SessionLifecycle::PersistentSession(
|
||||||
PersistentSession::default().session_ttl(
|
PersistentSession::default().session_ttl(
|
||||||
service::cookie::time::Duration::seconds(
|
service::cookie::time::Duration::seconds(
|
||||||
config::SETTINGS.server.session_lifetime,
|
global::SETTINGS.server.session_lifetime,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -116,8 +116,8 @@ impl Application {
|
||||||
})
|
})
|
||||||
.bind(format!(
|
.bind(format!(
|
||||||
"{}:{}",
|
"{}:{}",
|
||||||
&config::SETTINGS.server.bind_address,
|
&global::SETTINGS.server.bind_address,
|
||||||
&config::SETTINGS.server.bind_port
|
&global::SETTINGS.server.bind_port
|
||||||
))?
|
))?
|
||||||
.run())
|
.run())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::config;
|
use crate::global;
|
||||||
|
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ pub static FIGFONT: LazyLock<FIGfont> = LazyLock::new(|| {
|
||||||
let starwars = include_str!("starwars.flf");
|
let starwars = include_str!("starwars.flf");
|
||||||
|
|
||||||
FIGfont::from_content(
|
FIGfont::from_content(
|
||||||
match config::SETTINGS.app.startup_banner.to_lowercase().as_str() {
|
match global::SETTINGS.app.startup_banner.to_lowercase().as_str() {
|
||||||
"off" => slant,
|
"off" => slant,
|
||||||
"slant" => slant,
|
"slant" => slant,
|
||||||
"small" => small,
|
"small" => small,
|
||||||
|
|
@ -20,7 +20,7 @@ pub static FIGFONT: LazyLock<FIGfont> = LazyLock::new(|| {
|
||||||
_ => {
|
_ => {
|
||||||
println!(
|
println!(
|
||||||
"\n FIGfont \"{}\" not found for banner. Using \"Slant\". Check settings files.",
|
"\n FIGfont \"{}\" not found for banner. Using \"Slant\". Check settings files.",
|
||||||
config::SETTINGS.app.startup_banner,
|
global::SETTINGS.app.startup_banner,
|
||||||
);
|
);
|
||||||
slant
|
slant
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::prelude::*;
|
||||||
#[derive(AutoDefault)]
|
#[derive(AutoDefault)]
|
||||||
pub struct Branding {
|
pub struct Branding {
|
||||||
id : OptionId,
|
id : OptionId,
|
||||||
#[default(_code = "config::SETTINGS.app.name.to_owned()")]
|
#[default(_code = "global::SETTINGS.app.name.to_owned()")]
|
||||||
app_name : String,
|
app_name : String,
|
||||||
slogan : OptionTranslated,
|
slogan : OptionTranslated,
|
||||||
logo : OptionComponent<Image>,
|
logo : OptionComponent<Image>,
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ pub struct PoweredBy {
|
||||||
impl ComponentTrait for PoweredBy {
|
impl ComponentTrait for PoweredBy {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let year = Utc::now().format("%Y").to_string();
|
let year = Utc::now().format("%Y").to_string();
|
||||||
let c = concat_string!(year, " © ", config::SETTINGS.app.name);
|
let c = concat_string!(year, " © ", global::SETTINGS.app.name);
|
||||||
PoweredBy {
|
PoweredBy {
|
||||||
copyright: Some(c),
|
copyright: Some(c),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ fn hello_world() -> flex::Container {
|
||||||
"app",
|
"app",
|
||||||
format!(
|
format!(
|
||||||
"<span class=\"app-name\">{}</span>",
|
"<span class=\"app-name\">{}</span>",
|
||||||
&config::SETTINGS.app.name,
|
&global::SETTINGS.app.name,
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
.with_font_size(FontSize::Medium),
|
.with_font_size(FontSize::Medium),
|
||||||
|
|
@ -125,7 +125,7 @@ fn welcome() -> flex::Container {
|
||||||
"app",
|
"app",
|
||||||
format!(
|
format!(
|
||||||
"<span class=\"app-name\">{}</span>",
|
"<span class=\"app-name\">{}</span>",
|
||||||
&config::SETTINGS.app.name
|
&global::SETTINGS.app.name
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
.with_size(HeadingSize::Subtitle),
|
.with_size(HeadingSize::Subtitle),
|
||||||
|
|
@ -230,7 +230,7 @@ fn reporting_issues() -> flex::Container {
|
||||||
"app",
|
"app",
|
||||||
format!(
|
format!(
|
||||||
"<span class=\"app-name\">{}</span>",
|
"<span class=\"app-name\">{}</span>",
|
||||||
&config::SETTINGS.app.name,
|
&global::SETTINGS.app.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
|
|
||||||
150
src/config.rs
150
src/config.rs
|
|
@ -51,8 +51,8 @@
|
||||||
//! serde = { version = "1.0", features = ["derive"] }
|
//! serde = { version = "1.0", features = ["derive"] }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Y luego inicializa con la macro [`default_settings!`](crate::default_settings) tus ajustes,
|
//! Y luego inicializa con la macro [`config_defaults!`](crate::config_defaults) tus ajustes, usando
|
||||||
//! usando tipos seguros y asignando los valores predefinidos para la estructura asociada:
|
//! tipos seguros y asignando los valores predefinidos para la estructura asociada:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use pagetop::prelude::*;
|
//! use pagetop::prelude::*;
|
||||||
|
|
@ -71,12 +71,12 @@
|
||||||
//! pub height: u16,
|
//! pub height: u16,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! default_settings!(
|
//! config_defaults!(SETTINGS: Settings => [
|
||||||
//! // [myapp]
|
//! // [myapp]
|
||||||
//! "myapp.name" => "Value Name",
|
//! "myapp.name" => "Value Name",
|
||||||
//! "myapp.width" => 900,
|
//! "myapp.width" => 900,
|
||||||
//! "myapp.height" => 320,
|
//! "myapp.height" => 320,
|
||||||
//! );
|
//! ]);
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! De hecho, así se declaran los ajustes globales de la configuración (ver [`SETTINGS`]).
|
//! De hecho, así se declaran los ajustes globales de la configuración (ver [`SETTINGS`]).
|
||||||
|
|
@ -98,16 +98,17 @@
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use pagetop::prelude::*;
|
//! use pagetop::prelude::*;
|
||||||
|
//! use crate::config;
|
||||||
//!
|
//!
|
||||||
//! fn global_settings() {
|
//! fn global_settings() {
|
||||||
//! println!("App name: {}", &config::SETTINGS.app.name);
|
//! println!("App name: {}", &global::SETTINGS.app.name);
|
||||||
//! println!("App description: {}", &config::SETTINGS.app.description);
|
//! println!("App description: {}", &global::SETTINGS.app.description);
|
||||||
//! println!("Value of PAGETOP_RUN_MODE: {}", &config::SETTINGS.app.run_mode);
|
//! println!("Value of PAGETOP_RUN_MODE: {}", &global::SETTINGS.app.run_mode);
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn package_settings() {
|
//! fn package_settings() {
|
||||||
//! println!("{} - {:?}", &SETTINGS.myapp.name, &SETTINGS.myapp.description);
|
//! println!("{} - {:?}", &config::SETTINGS.myapp.name, &config::SETTINGS.myapp.description);
|
||||||
//! println!("{}", &SETTINGS.myapp.width);
|
//! println!("{}", &config::SETTINGS.myapp.width);
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
|
@ -123,8 +124,6 @@ use crate::concat_string;
|
||||||
use crate::config::data::ConfigData;
|
use crate::config::data::ConfigData;
|
||||||
use crate::config::file::File;
|
use crate::config::file::File;
|
||||||
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
@ -136,7 +135,7 @@ const CONFIG_DIR: &str = "config";
|
||||||
/// archivos de configuración.
|
/// archivos de configuración.
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub static CONFIG: LazyLock<ConfigData> = LazyLock::new(|| {
|
pub static CONFIG_DATA: LazyLock<ConfigData> = LazyLock::new(|| {
|
||||||
// Modo de ejecución según la variable de entorno PAGETOP_RUN_MODE. Por defecto 'default'.
|
// Modo de ejecución según la variable de entorno PAGETOP_RUN_MODE. Por defecto 'default'.
|
||||||
let run_mode = env::var("PAGETOP_RUN_MODE").unwrap_or_else(|_| "default".into());
|
let run_mode = env::var("PAGETOP_RUN_MODE").unwrap_or_else(|_| "default".into());
|
||||||
|
|
||||||
|
|
@ -178,14 +177,14 @@ pub static CONFIG: LazyLock<ConfigData> = LazyLock::new(|| {
|
||||||
/// Detiene la aplicación con un panic! si no pueden asignarse los ajustes de configuración.
|
/// Detiene la aplicación con un panic! si no pueden asignarse los ajustes de configuración.
|
||||||
///
|
///
|
||||||
/// Ver [`Cómo añadir ajustes de configuración`](config/index.html#cómo-añadir-ajustes-de-configuración).
|
/// Ver [`Cómo añadir ajustes de configuración`](config/index.html#cómo-añadir-ajustes-de-configuración).
|
||||||
macro_rules! default_settings {
|
macro_rules! config_defaults {
|
||||||
( $($key:literal => $value:literal),* $(,)? ) => {
|
( $SETTINGS:ident: $Settings:ty => [ $($key:literal => $value:literal),* $(,)? ] ) => {
|
||||||
#[doc = concat!(
|
#[doc = concat!(
|
||||||
"Assigned or predefined values for configuration settings associated to the ",
|
"Assigned or predefined values for configuration settings associated to the ",
|
||||||
"[`Settings`] type."
|
"[`", stringify!($Settings), "`] type."
|
||||||
)]
|
)]
|
||||||
pub static SETTINGS: std::sync::LazyLock<Settings> = std::sync::LazyLock::new(|| {
|
pub static $SETTINGS: std::sync::LazyLock<$Settings> = std::sync::LazyLock::new(|| {
|
||||||
let mut settings = $crate::config::CONFIG.clone();
|
let mut settings = $crate::config::CONFIG_DATA.clone();
|
||||||
$(
|
$(
|
||||||
settings.set_default($key, $value).unwrap();
|
settings.set_default($key, $value).unwrap();
|
||||||
)*
|
)*
|
||||||
|
|
@ -196,120 +195,3 @@ macro_rules! default_settings {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
/// Configuration settings for the [`[app]`](App), [`[dev]`](Dev), [`[log]`](Log), and
|
|
||||||
/// [`[server]`](Server) sections (see [`SETTINGS`]).
|
|
||||||
pub struct Settings {
|
|
||||||
pub app: App,
|
|
||||||
pub dev: Dev,
|
|
||||||
pub log: Log,
|
|
||||||
pub server: Server,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
/// Section `[app]` of the configuration settings.
|
|
||||||
///
|
|
||||||
/// See [`Settings`].
|
|
||||||
pub struct App {
|
|
||||||
/// El nombre de la aplicación.
|
|
||||||
/// Por defecto: *"My App"*.
|
|
||||||
pub name: String,
|
|
||||||
/// Una descripción breve de la aplicación.
|
|
||||||
/// Por defecto: *"Developed with the amazing PageTop framework."*.
|
|
||||||
pub description: String,
|
|
||||||
/// Tema predeterminado.
|
|
||||||
/// Por defecto: *"Default"*.
|
|
||||||
pub theme: String,
|
|
||||||
/// Idioma (localización) predeterminado.
|
|
||||||
/// Por defecto: *"en-US"*.
|
|
||||||
pub language: String,
|
|
||||||
/// Dirección predeterminada para el texto: *"ltr"* (de izquierda a derecha), *"rtl"* (de
|
|
||||||
/// derecha a izquierda) o *"auto"*.
|
|
||||||
/// Por defecto: *"ltr"*.
|
|
||||||
pub direction: String,
|
|
||||||
/// Rótulo de texto ASCII al arrancar: *"Off"*, *"Slant"*, *"Small"*, *"Speed"* o *"Starwars"*.
|
|
||||||
/// Por defecto: *"Slant"*.
|
|
||||||
pub startup_banner: String,
|
|
||||||
/// Por defecto: según variable de entorno `PAGETOP_RUN_MODE`, o *"default"* si no lo está.
|
|
||||||
pub run_mode: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
/// Section `[dev]` of the configuration settings.
|
|
||||||
///
|
|
||||||
/// See [`Settings`].
|
|
||||||
pub struct Dev {
|
|
||||||
/// Los archivos estáticos requeridos por la aplicación se integran de manera predeterminada en
|
|
||||||
/// el binario ejecutable. Sin embargo, durante el desarrollo puede resultar útil servir estos
|
|
||||||
/// archivos desde su propio directorio para evitar recompilar cada vez que se modifican. En
|
|
||||||
/// este caso bastaría con indicar la ruta completa al directorio raíz del proyecto.
|
|
||||||
/// Por defecto: *""*.
|
|
||||||
pub pagetop_project_dir: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
/// Section `[log]` of the configuration settings.
|
|
||||||
///
|
|
||||||
/// See [`Settings`].
|
|
||||||
pub struct Log {
|
|
||||||
/// Filtro, o combinación de filtros separados por coma, para la traza de ejecución: *"Error"*,
|
|
||||||
/// *"Warn"*, *"Info"*, *"Debug"* o *"Trace"*.
|
|
||||||
/// Por ejemplo: "Error,actix_server::builder=Info,tracing_actix_web=Debug".
|
|
||||||
/// Por defecto: *"Info"*.
|
|
||||||
pub tracing: String,
|
|
||||||
/// Muestra la traza en el terminal (*"Stdout"*) o queda registrada en archivos con rotación
|
|
||||||
/// *"Daily"*, *"Hourly"*, *"Minutely"* o *"Endless"*.
|
|
||||||
/// Por defecto: *"Stdout"*.
|
|
||||||
pub rolling: String,
|
|
||||||
/// Directorio para los archivos de traza (si `rolling` != *"Stdout"*).
|
|
||||||
/// Por defecto: *"log"*.
|
|
||||||
pub path: String,
|
|
||||||
/// Prefijo para los archivos de traza (si `rolling` != *"Stdout"*).
|
|
||||||
/// Por defecto: *"tracing.log"*.
|
|
||||||
pub prefix: String,
|
|
||||||
/// Presentación de las trazas. Puede ser *"Full"*, *"Compact"*, *"Pretty"* o *"Json"*.
|
|
||||||
/// Por defecto: *"Full"*.
|
|
||||||
pub format: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
/// Section `[server]` of the configuration settings.
|
|
||||||
///
|
|
||||||
/// See [`Settings`].
|
|
||||||
pub struct Server {
|
|
||||||
/// Dirección del servidor web.
|
|
||||||
/// Por defecto: *"localhost"*.
|
|
||||||
pub bind_address: String,
|
|
||||||
/// Puerto del servidor web.
|
|
||||||
/// Por defecto: *8088*.
|
|
||||||
pub bind_port: u16,
|
|
||||||
/// Duración en segundos para la sesión (0 indica "hasta que se cierre el navegador").
|
|
||||||
/// Por defecto: *604800* (7 días).
|
|
||||||
pub session_lifetime: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
default_settings!(
|
|
||||||
// [app]
|
|
||||||
"app.name" => "My App",
|
|
||||||
"app.description" => "Developed with the amazing PageTop framework.",
|
|
||||||
"app.theme" => "Default",
|
|
||||||
"app.language" => "en-US",
|
|
||||||
"app.direction" => "ltr",
|
|
||||||
"app.startup_banner" => "Slant",
|
|
||||||
|
|
||||||
// [dev]
|
|
||||||
"dev.pagetop_project_dir" => "",
|
|
||||||
|
|
||||||
// [log]
|
|
||||||
"log.tracing" => "Info",
|
|
||||||
"log.rolling" => "Stdout",
|
|
||||||
"log.path" => "log",
|
|
||||||
"log.prefix" => "tracing.log",
|
|
||||||
"log.format" => "Full",
|
|
||||||
|
|
||||||
// [server]
|
|
||||||
"server.bind_address" => "localhost",
|
|
||||||
"server.bind_port" => 8088,
|
|
||||||
"server.session_lifetime" => 604_800,
|
|
||||||
);
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Key types and functions for creating actions, components, packages, and themes.
|
//! Key types and functions for creating actions, components, packages, and themes.
|
||||||
|
|
||||||
use crate::util::TypeInfo;
|
use crate::global::TypeInfo;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ use crate::concat_string;
|
||||||
use crate::core::component::AnyOp;
|
use crate::core::component::AnyOp;
|
||||||
use crate::core::theme::all::{theme_by_short_name, THEME_DEFAULT};
|
use crate::core::theme::all::{theme_by_short_name, THEME_DEFAULT};
|
||||||
use crate::core::theme::{ComponentsInRegions, ThemeRef};
|
use crate::core::theme::{ComponentsInRegions, ThemeRef};
|
||||||
|
use crate::global::TypeInfo;
|
||||||
use crate::html::{html, Markup};
|
use crate::html::{html, Markup};
|
||||||
use crate::html::{Assets, Favicon, JavaScript, StyleSheet};
|
use crate::html::{Assets, Favicon, JavaScript, StyleSheet};
|
||||||
use crate::locale::{LanguageIdentifier, LANGID_DEFAULT};
|
use crate::locale::{LanguageIdentifier, LANGID_DEFAULT};
|
||||||
use crate::service::HttpRequest;
|
use crate::service::HttpRequest;
|
||||||
use crate::util::TypeInfo;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::base::action;
|
use crate::base::action;
|
||||||
use crate::core::component::Context;
|
use crate::core::component::Context;
|
||||||
use crate::core::AnyBase;
|
use crate::core::AnyBase;
|
||||||
|
use crate::global::TypeInfo;
|
||||||
use crate::html::{html, Markup, PrepareMarkup};
|
use crate::html::{html, Markup, PrepareMarkup};
|
||||||
use crate::util::TypeInfo;
|
|
||||||
|
|
||||||
pub trait ComponentBase {
|
pub trait ComponentBase {
|
||||||
fn render(&mut self, cx: &mut Context) -> Markup;
|
fn render(&mut self, cx: &mut Context) -> Markup;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::core::action::add_action;
|
use crate::core::action::add_action;
|
||||||
use crate::core::package::PackageRef;
|
use crate::core::package::PackageRef;
|
||||||
use crate::core::theme::all::THEMES;
|
use crate::core::theme::all::THEMES;
|
||||||
use crate::{config, service, service_for_static_files, static_files, trace};
|
use crate::{global, service, static_files, static_files_service, trace};
|
||||||
|
|
||||||
use std::sync::{LazyLock, RwLock};
|
use std::sync::{LazyLock, RwLock};
|
||||||
|
|
||||||
|
|
@ -130,10 +130,10 @@ pub fn init_packages() {
|
||||||
// CONFIGURE SERVICES ******************************************************************************
|
// CONFIGURE SERVICES ******************************************************************************
|
||||||
|
|
||||||
pub fn configure_services(scfg: &mut service::web::ServiceConfig) {
|
pub fn configure_services(scfg: &mut service::web::ServiceConfig) {
|
||||||
service_for_static_files!(
|
static_files_service!(
|
||||||
scfg,
|
scfg,
|
||||||
base => "/base",
|
base => "/base",
|
||||||
[&config::SETTINGS.dev.pagetop_project_dir, "static/base"]
|
[&global::SETTINGS.dev.pagetop_project_dir, "static/base"]
|
||||||
);
|
);
|
||||||
for m in ENABLED_PACKAGES.read().unwrap().iter() {
|
for m in ENABLED_PACKAGES.read().unwrap().iter() {
|
||||||
m.configure_service(scfg);
|
m.configure_service(scfg);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::config;
|
|
||||||
use crate::core::theme::ThemeRef;
|
use crate::core::theme::ThemeRef;
|
||||||
|
use crate::global;
|
||||||
|
|
||||||
use std::sync::{LazyLock, RwLock};
|
use std::sync::{LazyLock, RwLock};
|
||||||
|
|
||||||
|
|
@ -10,7 +10,7 @@ pub static THEMES: LazyLock<RwLock<Vec<ThemeRef>>> = LazyLock::new(|| RwLock::ne
|
||||||
// DEFAULT THEME ***********************************************************************************
|
// DEFAULT THEME ***********************************************************************************
|
||||||
|
|
||||||
pub static THEME_DEFAULT: LazyLock<ThemeRef> =
|
pub static THEME_DEFAULT: LazyLock<ThemeRef> =
|
||||||
LazyLock::new(|| match theme_by_short_name(&config::SETTINGS.app.theme) {
|
LazyLock::new(|| match theme_by_short_name(&global::SETTINGS.app.theme) {
|
||||||
Some(theme) => theme,
|
Some(theme) => theme,
|
||||||
None => &crate::base::theme::Inception,
|
None => &crate::base::theme::Inception,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::core::package::PackageTrait;
|
||||||
use crate::html::{html, Favicon, PrepareMarkup};
|
use crate::html::{html, Favicon, PrepareMarkup};
|
||||||
use crate::locale::L10n;
|
use crate::locale::L10n;
|
||||||
use crate::response::page::Page;
|
use crate::response::page::Page;
|
||||||
use crate::{concat_string, config};
|
use crate::{concat_string, global};
|
||||||
|
|
||||||
pub type ThemeRef = &'static dyn ThemeTrait;
|
pub type ThemeRef = &'static dyn ThemeTrait;
|
||||||
|
|
||||||
|
|
@ -82,9 +82,9 @@ pub trait ThemeTrait: PackageTrait + Send + Sync {
|
||||||
meta charset="utf-8";
|
meta charset="utf-8";
|
||||||
|
|
||||||
@if let Some(title) = page.title() {
|
@if let Some(title) = page.title() {
|
||||||
title { (config::SETTINGS.app.name) (" - ") (title) }
|
title { (global::SETTINGS.app.name) (" - ") (title) }
|
||||||
} @else {
|
} @else {
|
||||||
title { (config::SETTINGS.app.name) }
|
title { (global::SETTINGS.app.name) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@if let Some(description) = page.description() {
|
@if let Some(description) = page.description() {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,137 @@
|
||||||
//! Functions and macro helpers.
|
//! Global settings, functions and macro helpers.
|
||||||
|
|
||||||
use crate::trace;
|
use crate::{config_defaults, trace};
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
// *************************************************************************************************
|
||||||
|
// SETTINGS.
|
||||||
|
// *************************************************************************************************
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
/// Configuration settings for global [`[app]`](App), [`[dev]`](Dev), [`[log]`](Log), and
|
||||||
|
/// [`[server]`](Server) sections (see [`SETTINGS`]).
|
||||||
|
pub struct Settings {
|
||||||
|
pub app: App,
|
||||||
|
pub dev: Dev,
|
||||||
|
pub log: Log,
|
||||||
|
pub server: Server,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
/// Section `[app]` of the configuration settings.
|
||||||
|
///
|
||||||
|
/// See [`Settings`].
|
||||||
|
pub struct App {
|
||||||
|
/// El nombre de la aplicación.
|
||||||
|
/// Por defecto: *"My App"*.
|
||||||
|
pub name: String,
|
||||||
|
/// Una descripción breve de la aplicación.
|
||||||
|
/// Por defecto: *"Developed with the amazing PageTop framework."*.
|
||||||
|
pub description: String,
|
||||||
|
/// Tema predeterminado.
|
||||||
|
/// Por defecto: *"Default"*.
|
||||||
|
pub theme: String,
|
||||||
|
/// Idioma (localización) predeterminado.
|
||||||
|
/// Por defecto: *"en-US"*.
|
||||||
|
pub language: String,
|
||||||
|
/// Dirección predeterminada para el texto: *"ltr"* (de izquierda a derecha), *"rtl"* (de
|
||||||
|
/// derecha a izquierda) o *"auto"*.
|
||||||
|
/// Por defecto: *"ltr"*.
|
||||||
|
pub direction: String,
|
||||||
|
/// Rótulo de texto ASCII al arrancar: *"Off"*, *"Slant"*, *"Small"*, *"Speed"* o *"Starwars"*.
|
||||||
|
/// Por defecto: *"Slant"*.
|
||||||
|
pub startup_banner: String,
|
||||||
|
/// Por defecto: según variable de entorno `PAGETOP_RUN_MODE`, o *"default"* si no lo está.
|
||||||
|
pub run_mode: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
/// Section `[dev]` of the configuration settings.
|
||||||
|
///
|
||||||
|
/// See [`Settings`].
|
||||||
|
pub struct Dev {
|
||||||
|
/// Los archivos estáticos requeridos por la aplicación se integran de manera predeterminada en
|
||||||
|
/// el binario ejecutable. Sin embargo, durante el desarrollo puede resultar útil servir estos
|
||||||
|
/// archivos desde su propio directorio para evitar recompilar cada vez que se modifican. En
|
||||||
|
/// este caso bastaría con indicar la ruta completa al directorio raíz del proyecto.
|
||||||
|
/// Por defecto: *""*.
|
||||||
|
pub pagetop_project_dir: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
/// Section `[log]` of the configuration settings.
|
||||||
|
///
|
||||||
|
/// See [`Settings`].
|
||||||
|
pub struct Log {
|
||||||
|
/// Filtro, o combinación de filtros separados por coma, para la traza de ejecución: *"Error"*,
|
||||||
|
/// *"Warn"*, *"Info"*, *"Debug"* o *"Trace"*.
|
||||||
|
/// Por ejemplo: "Error,actix_server::builder=Info,tracing_actix_web=Debug".
|
||||||
|
/// Por defecto: *"Info"*.
|
||||||
|
pub tracing: String,
|
||||||
|
/// Muestra la traza en el terminal (*"Stdout"*) o queda registrada en archivos con rotación
|
||||||
|
/// *"Daily"*, *"Hourly"*, *"Minutely"* o *"Endless"*.
|
||||||
|
/// Por defecto: *"Stdout"*.
|
||||||
|
pub rolling: String,
|
||||||
|
/// Directorio para los archivos de traza (si `rolling` != *"Stdout"*).
|
||||||
|
/// Por defecto: *"log"*.
|
||||||
|
pub path: String,
|
||||||
|
/// Prefijo para los archivos de traza (si `rolling` != *"Stdout"*).
|
||||||
|
/// Por defecto: *"tracing.log"*.
|
||||||
|
pub prefix: String,
|
||||||
|
/// Presentación de las trazas. Puede ser *"Full"*, *"Compact"*, *"Pretty"* o *"Json"*.
|
||||||
|
/// Por defecto: *"Full"*.
|
||||||
|
pub format: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
/// Section `[server]` of the configuration settings.
|
||||||
|
///
|
||||||
|
/// See [`Settings`].
|
||||||
|
pub struct Server {
|
||||||
|
/// Dirección del servidor web.
|
||||||
|
/// Por defecto: *"localhost"*.
|
||||||
|
pub bind_address: String,
|
||||||
|
/// Puerto del servidor web.
|
||||||
|
/// Por defecto: *8088*.
|
||||||
|
pub bind_port: u16,
|
||||||
|
/// Duración en segundos para la sesión (0 indica "hasta que se cierre el navegador").
|
||||||
|
/// Por defecto: *604800* (7 días).
|
||||||
|
pub session_lifetime: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
config_defaults!(SETTINGS: Settings => [
|
||||||
|
// [app]
|
||||||
|
"app.name" => "My App",
|
||||||
|
"app.description" => "Developed with the amazing PageTop framework.",
|
||||||
|
"app.theme" => "Default",
|
||||||
|
"app.language" => "en-US",
|
||||||
|
"app.direction" => "ltr",
|
||||||
|
"app.startup_banner" => "Slant",
|
||||||
|
|
||||||
|
// [dev]
|
||||||
|
"dev.pagetop_project_dir" => "",
|
||||||
|
|
||||||
|
// [log]
|
||||||
|
"log.tracing" => "Info",
|
||||||
|
"log.rolling" => "Stdout",
|
||||||
|
"log.path" => "log",
|
||||||
|
"log.prefix" => "tracing.log",
|
||||||
|
"log.format" => "Full",
|
||||||
|
|
||||||
|
// [server]
|
||||||
|
"server.bind_address" => "localhost",
|
||||||
|
"server.bind_port" => 8088,
|
||||||
|
"server.session_lifetime" => 604_800,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// *************************************************************************************************
|
||||||
|
// FUNCTIONS HELPERS.
|
||||||
|
// *************************************************************************************************
|
||||||
|
|
||||||
pub enum TypeInfo {
|
pub enum TypeInfo {
|
||||||
FullName,
|
FullName,
|
||||||
ShortName,
|
ShortName,
|
||||||
|
|
@ -81,10 +208,6 @@ impl TypeInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// *************************************************************************************************
|
|
||||||
// FUNCTIONS HELPERS.
|
|
||||||
// *************************************************************************************************
|
|
||||||
|
|
||||||
/// Calculates the absolute directory given a root path and a relative path.
|
/// Calculates the absolute directory given a root path and a relative path.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
|
@ -95,15 +95,15 @@ pub use std::any::TypeId;
|
||||||
|
|
||||||
pub type Weight = i8;
|
pub type Weight = i8;
|
||||||
|
|
||||||
|
// Global settings, functions and macro helpers.
|
||||||
|
pub mod global;
|
||||||
|
|
||||||
static_locales!(LOCALES_PAGETOP);
|
static_locales!(LOCALES_PAGETOP);
|
||||||
|
|
||||||
// *************************************************************************************************
|
// *************************************************************************************************
|
||||||
// PUBLIC API.
|
// PUBLIC API.
|
||||||
// *************************************************************************************************
|
// *************************************************************************************************
|
||||||
|
|
||||||
// Functions and macro helpers.
|
|
||||||
pub mod util;
|
|
||||||
|
|
||||||
// Retrieve and apply settings values from configuration files.
|
// Retrieve and apply settings values from configuration files.
|
||||||
pub mod config;
|
pub mod config;
|
||||||
// Application tracing and event logging.
|
// Application tracing and event logging.
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use crate::html::{Markup, PreEscaped};
|
use crate::html::{Markup, PreEscaped};
|
||||||
use crate::{config, kv, AutoDefault, LOCALES_PAGETOP};
|
use crate::{global, kv, AutoDefault, LOCALES_PAGETOP};
|
||||||
|
|
||||||
pub use fluent_templates;
|
pub use fluent_templates;
|
||||||
pub use unic_langid::LanguageIdentifier;
|
pub use unic_langid::LanguageIdentifier;
|
||||||
|
|
@ -120,7 +120,7 @@ pub static LANGID_FALLBACK: LazyLock<LanguageIdentifier> = LazyLock::new(|| lang
|
||||||
/// [Unicode Language Identifier](https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier)
|
/// [Unicode Language Identifier](https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier)
|
||||||
/// through `SETTINGS.app.language`.
|
/// through `SETTINGS.app.language`.
|
||||||
pub static LANGID_DEFAULT: LazyLock<&LanguageIdentifier> = LazyLock::new(|| {
|
pub static LANGID_DEFAULT: LazyLock<&LanguageIdentifier> = LazyLock::new(|| {
|
||||||
langid_for(config::SETTINGS.app.language.as_str()).unwrap_or(&LANGID_FALLBACK)
|
langid_for(global::SETTINGS.app.language.as_str()).unwrap_or(&LANGID_FALLBACK)
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn langid_for(language: impl Into<String>) -> Result<&'static LanguageIdentifier, String> {
|
pub fn langid_for(language: impl Into<String>) -> Result<&'static LanguageIdentifier, String> {
|
||||||
|
|
|
||||||
|
|
@ -5,29 +5,25 @@ pub use crate::{concat_string, fn_builder, main, paste, test};
|
||||||
pub use crate::{AutoDefault, ComponentClasses};
|
pub use crate::{AutoDefault, ComponentClasses};
|
||||||
|
|
||||||
// GLOBAL.
|
// GLOBAL.
|
||||||
pub use crate::{HashMapResources, TypeId, Weight};
|
pub use crate::{global, HashMapResources, TypeId, Weight};
|
||||||
|
|
||||||
// MACROS.
|
// MACROS.
|
||||||
|
|
||||||
|
// crate::global
|
||||||
|
pub use crate::kv;
|
||||||
// crate::config
|
// crate::config
|
||||||
pub use crate::default_settings;
|
pub use crate::config_defaults;
|
||||||
// crate::html
|
// crate::html
|
||||||
pub use crate::html;
|
pub use crate::html;
|
||||||
// crate::locale
|
// crate::locale
|
||||||
pub use crate::static_locales;
|
pub use crate::static_locales;
|
||||||
// crate::service
|
// crate::service
|
||||||
pub use crate::{service_for_static_files, static_files};
|
pub use crate::{static_files, static_files_service};
|
||||||
// crate::core::action
|
// crate::core::action
|
||||||
pub use crate::actions;
|
pub use crate::actions;
|
||||||
// crate::util
|
|
||||||
pub use crate::kv;
|
|
||||||
|
|
||||||
// API.
|
// API.
|
||||||
|
|
||||||
pub use crate::util;
|
|
||||||
|
|
||||||
pub use crate::config;
|
|
||||||
|
|
||||||
pub use crate::trace;
|
pub use crate::trace;
|
||||||
|
|
||||||
pub use crate::html::*;
|
pub use crate::html::*;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ macro_rules! static_files {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! service_for_static_files {
|
macro_rules! static_files_service {
|
||||||
( $scfg:ident, $bundle:ident => $path:expr $(, [$root:expr, $relative:expr])? ) => {{
|
( $scfg:ident, $bundle:ident => $path:expr $(, [$root:expr, $relative:expr])? ) => {{
|
||||||
$crate::paste! {
|
$crate::paste! {
|
||||||
let span = $crate::trace::debug_span!("Configuring static files ", path = $path);
|
let span = $crate::trace::debug_span!("Configuring static files ", path = $path);
|
||||||
|
|
@ -42,7 +42,7 @@ macro_rules! service_for_static_files {
|
||||||
let mut serve_embedded:bool = true;
|
let mut serve_embedded:bool = true;
|
||||||
$(
|
$(
|
||||||
if !$root.is_empty() && !$relative.is_empty() {
|
if !$root.is_empty() && !$relative.is_empty() {
|
||||||
if let Ok(absolute) = $crate::util::absolute_dir($root, $relative) {
|
if let Ok(absolute) = $crate::global::absolute_dir($root, $relative) {
|
||||||
$scfg.service($crate::service::ActixFiles::new(
|
$scfg.service($crate::service::ActixFiles::new(
|
||||||
$path,
|
$path,
|
||||||
absolute,
|
absolute,
|
||||||
|
|
|
||||||
16
src/trace.rs
16
src/trace.rs
|
|
@ -12,7 +12,7 @@
|
||||||
//! within a nested tree of similar spans. Additionally, these spans are *structured*, with the
|
//! within a nested tree of similar spans. Additionally, these spans are *structured*, with the
|
||||||
//! ability to record data types and text messages.
|
//! ability to record data types and text messages.
|
||||||
|
|
||||||
use crate::config;
|
use crate::global;
|
||||||
|
|
||||||
pub use tracing::{debug, error, info, trace, warn};
|
pub use tracing::{debug, error, info, trace, warn};
|
||||||
pub use tracing::{debug_span, error_span, info_span, trace_span, warn_span};
|
pub use tracing::{debug_span, error_span, info_span, trace_span, warn_span};
|
||||||
|
|
@ -35,16 +35,16 @@ use std::sync::LazyLock;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub(crate) static TRACING: LazyLock<WorkerGuard> = LazyLock::new(|| {
|
pub(crate) static TRACING: LazyLock<WorkerGuard> = LazyLock::new(|| {
|
||||||
let env_filter = EnvFilter::try_new(&config::SETTINGS.log.tracing)
|
let env_filter = EnvFilter::try_new(&global::SETTINGS.log.tracing)
|
||||||
.unwrap_or_else(|_| EnvFilter::new("Info"));
|
.unwrap_or_else(|_| EnvFilter::new("Info"));
|
||||||
|
|
||||||
let rolling = config::SETTINGS.log.rolling.to_lowercase();
|
let rolling = global::SETTINGS.log.rolling.to_lowercase();
|
||||||
|
|
||||||
let (non_blocking, guard) = match rolling.as_str() {
|
let (non_blocking, guard) = match rolling.as_str() {
|
||||||
"stdout" => tracing_appender::non_blocking(std::io::stdout()),
|
"stdout" => tracing_appender::non_blocking(std::io::stdout()),
|
||||||
_ => tracing_appender::non_blocking({
|
_ => tracing_appender::non_blocking({
|
||||||
let path = &config::SETTINGS.log.path;
|
let path = &global::SETTINGS.log.path;
|
||||||
let prefix = &config::SETTINGS.log.prefix;
|
let prefix = &global::SETTINGS.log.prefix;
|
||||||
match rolling.as_str() {
|
match rolling.as_str() {
|
||||||
"daily" => tracing_appender::rolling::daily(path, prefix),
|
"daily" => tracing_appender::rolling::daily(path, prefix),
|
||||||
"hourly" => tracing_appender::rolling::hourly(path, prefix),
|
"hourly" => tracing_appender::rolling::hourly(path, prefix),
|
||||||
|
|
@ -53,7 +53,7 @@ pub(crate) static TRACING: LazyLock<WorkerGuard> = LazyLock::new(|| {
|
||||||
_ => {
|
_ => {
|
||||||
println!(
|
println!(
|
||||||
"Rolling value \"{}\" not valid. Using \"daily\". Check the settings file.",
|
"Rolling value \"{}\" not valid. Using \"daily\". Check the settings file.",
|
||||||
config::SETTINGS.log.rolling,
|
global::SETTINGS.log.rolling,
|
||||||
);
|
);
|
||||||
tracing_appender::rolling::daily(path, prefix)
|
tracing_appender::rolling::daily(path, prefix)
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +66,7 @@ pub(crate) static TRACING: LazyLock<WorkerGuard> = LazyLock::new(|| {
|
||||||
.with_writer(non_blocking)
|
.with_writer(non_blocking)
|
||||||
.with_ansi(rolling.as_str() == "stdout");
|
.with_ansi(rolling.as_str() == "stdout");
|
||||||
|
|
||||||
match config::SETTINGS.log.format.to_lowercase().as_str() {
|
match global::SETTINGS.log.format.to_lowercase().as_str() {
|
||||||
"json" => subscriber.json().init(),
|
"json" => subscriber.json().init(),
|
||||||
"full" => subscriber.init(),
|
"full" => subscriber.init(),
|
||||||
"compact" => subscriber.compact().init(),
|
"compact" => subscriber.compact().init(),
|
||||||
|
|
@ -74,7 +74,7 @@ pub(crate) static TRACING: LazyLock<WorkerGuard> = LazyLock::new(|| {
|
||||||
_ => {
|
_ => {
|
||||||
println!(
|
println!(
|
||||||
"Tracing format \"{}\" not valid. Using \"Full\". Check the settings file.",
|
"Tracing format \"{}\" not valid. Using \"Full\". Check the settings file.",
|
||||||
config::SETTINGS.log.format,
|
global::SETTINGS.log.format,
|
||||||
);
|
);
|
||||||
subscriber.init();
|
subscriber.init();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue