Actualiza y afina las dependencias de paquetes

También normaliza los "traits" para definir temas y módulos usando el
mismo criterio visto en SeaORM.
This commit is contained in:
Manuel Cillero 2022-03-16 20:45:49 +01:00
parent 1102a76e47
commit 2167ab9417
26 changed files with 100 additions and 100 deletions

View file

@ -1,4 +1,6 @@
use pagetop::prelude::*;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
pagetop::Application::build(None).await?.run()?.await
Application::prepare(essence).await?.run()?.await
}

View file

@ -27,16 +27,16 @@ categories = [
doc-comment = "0.3.3"
downcast-rs = "1.2.0"
figlet-rs = "0.1.3"
futures = "0.3"
once_cell = "1.9.0"
futures = "0.3.21"
once_cell = "1.10.0"
url = "2.2.2"
config_rs = { package = "config", version = "0.11.0", features = ["toml"] }
tracing = "0.1"
tracing-appender = "0.2"
tracing-subscriber = { version = "0.3", features = ["json", "env-filter"] }
tracing-unwrap = { version = "0.9", default-features = false }
tracing = "0.1.32"
tracing-appender = "0.2.1"
tracing-subscriber = { version = "0.3.9", features = ["json", "env-filter"] }
tracing-unwrap = { version = "0.9.2", default-features = false }
tracing-actix-web = "0.2"
fluent-templates = "0.6.1"
@ -51,17 +51,20 @@ sycamore = { version = "0.7.1", features = ["ssr"] }
serde = { version = "1.0", features = ["derive"] }
[dependencies.sea-orm]
version = "0.6"
version = "0.6.0"
features = ["debug-print", "macros", "runtime-async-std-native-tls"]
default-features = false
optional = true
[dependencies.sea-schema]
version = "0.5"
version = "0.6.0"
features = ["debug-print", "migration"]
default-features = false
optional = true
[dev-dependencies]
tokio = { version = "1.17.0", features = ["macros", "rt-multi-thread"] }
[features]
default = []
mysql = ["sea-orm", "sea-schema", "sea-orm/sqlx-mysql"]

View file

@ -6,7 +6,7 @@ mod summary;
pub struct AdminModule;
impl Module for AdminModule {
impl ModuleTrait for AdminModule {
fn name(&self) -> &'static str {
"admin"
}

View file

@ -4,7 +4,7 @@ localize!("en-US", "src/base/module/homepage/locales");
pub struct HomepageModule;
impl Module for HomepageModule {
impl ModuleTrait for HomepageModule {
fn name(&self) -> &'static str {
"homepage"
}

View file

@ -7,7 +7,7 @@ mod migration;
pub struct UserModule;
impl Module for UserModule {
impl ModuleTrait for UserModule {
fn name(&self) -> &'static str {
"user"
}

View file

@ -4,7 +4,7 @@ include!(concat!(env!("OUT_DIR"), "/aliner.rs"));
pub struct AlinerTheme;
impl Theme for AlinerTheme {
impl ThemeTrait for AlinerTheme {
fn name(&self) -> &'static str {
"aliner"
}

View file

@ -6,7 +6,7 @@ localize!("en-US", "src/base/theme/bootsier/locales");
pub struct BootsierTheme;
impl Theme for BootsierTheme {
impl ThemeTrait for BootsierTheme {
fn name(&self) -> &'static str {
"bootsier"
}

View file

@ -2,7 +2,7 @@ use crate::prelude::*;
pub struct MinimalTheme;
impl Theme for MinimalTheme {
impl ThemeTrait for MinimalTheme {
fn name(&self) -> &'static str {
"minimal"
}

View file

@ -1,21 +1,19 @@
use crate::{Lazy, trace};
use crate::core::theme::Theme;
use crate::core::module::Module;
use crate::core::response::page::PageContainer;
use crate::core::theme::ThemeTrait;
use crate::core::module::ModuleTrait;
use crate::core::server;
use std::sync::RwLock;
use std::collections::HashMap;
include!(concat!(env!("OUT_DIR"), "/theme.rs"));
// -----------------------------------------------------------------------------
// Temas registrados y tema por defecto.
// Temas registrados y tema predeterminado.
// -----------------------------------------------------------------------------
pub static THEMES: Lazy<RwLock<Vec<&dyn Theme>>> = Lazy::new(|| {
RwLock::new(Vec::new())
});
pub static THEMES: Lazy<RwLock<Vec<&dyn ThemeTrait>>> = Lazy::new(
|| { RwLock::new(Vec::new()) }
);
pub fn themes(cfg: &mut server::web::ServiceConfig) {
cfg.service(actix_web_static_files::ResourceFiles::new(
@ -32,9 +30,9 @@ pub fn themes(cfg: &mut server::web::ServiceConfig) {
// Módulos registrados.
// -----------------------------------------------------------------------------
pub static MODULES: Lazy<RwLock<Vec<&dyn Module>>> = Lazy::new(|| {
RwLock::new(Vec::new())
});
pub static MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(
|| { RwLock::new(Vec::new()) }
);
pub fn modules(cfg: &mut server::web::ServiceConfig) {
for m in MODULES.read().unwrap().iter() {
@ -43,19 +41,9 @@ pub fn modules(cfg: &mut server::web::ServiceConfig) {
}
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
pub fn run_migrations() {
trace::info!("Checking migrations.");
pub fn migrations() {
trace::info!("Checking migrations");
for m in MODULES.read().unwrap().iter() {
m.migrations(
&*server::db::DBCONN.read().unwrap()
).expect("Failed to run migrations");
m.migrations(&*server::db::DBCONN).expect("Failed to run migrations");
}
}
// -----------------------------------------------------------------------------
// Componentes globales.
// -----------------------------------------------------------------------------
pub static COMPONENTS: Lazy<RwLock<HashMap<&str, PageContainer>>> = Lazy::new(
|| { RwLock::new(HashMap::new()) }
);

1
pagetop/src/core/html.rs Normal file
View file

@ -0,0 +1 @@
pub use maud::{DOCTYPE, Markup, PreEscaped, html};

View file

@ -1,7 +1,8 @@
pub use actix_web::dev::Server;
mod global;
mod all;
pub mod html;
pub mod theme;
pub mod module;
pub mod response;

View file

@ -4,7 +4,7 @@ use crate::core::server;
use crate::db;
/// Los módulos deben implementar este *trait*.
pub trait Module: Send + Sync {
pub trait ModuleTrait: Send + Sync {
fn name(&self) -> &'static str;
fn fullname(&self) -> String;

View file

@ -1,14 +1,14 @@
use crate::core::global;
use crate::core::all;
mod definition;
pub use definition::Module;
pub use definition::ModuleTrait;
pub fn register_module(m: &'static (dyn Module + 'static)) {
global::MODULES.write().unwrap().push(m);
pub fn register_module(m: &'static (dyn ModuleTrait + 'static)) {
all::MODULES.write().unwrap().push(m);
}
pub fn find_module(name: &str) -> Option<&'static (dyn Module + 'static)> {
let modules = global::MODULES.write().unwrap();
pub fn find_module(name: &str) -> Option<&'static (dyn ModuleTrait + 'static)> {
let modules = all::MODULES.write().unwrap();
match modules.iter().find(|t| t.name() == name) {
Some(module) => Some(*module),
_ => None,

View file

@ -1,10 +1,11 @@
use crate::{Lazy, base};
use crate::config::SETTINGS;
use crate::core::global;
use crate::core::theme::{Markup, PreEscaped, Theme, find_theme, html};
use crate::core::all;
use crate::core::html::{Markup, PreEscaped, html};
use crate::core::theme::*;
static DEFAULT_THEME: Lazy<&dyn Theme> = Lazy::new(|| {
for t in global::THEMES.read().unwrap().iter() {
static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| {
for t in all::THEMES.read().unwrap().iter() {
if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() {
return *t;
}
@ -184,7 +185,7 @@ impl JavaScript {
// -----------------------------------------------------------------------------
pub struct PageAssets {
theme : &'static dyn Theme,
theme : &'static dyn ThemeTrait,
favicon : Option<Favicon>,
metadata : Vec<(String, String)>,
stylesheets: Vec<StyleSheet>,
@ -259,7 +260,7 @@ impl PageAssets {
/// Assets GETTERS.
pub fn theme(&mut self) -> &'static dyn Theme {
pub fn theme(&mut self) -> &'static dyn ThemeTrait {
self.theme
}

View file

@ -1,4 +1,4 @@
use crate::core::theme::{Markup, html};
use crate::core::html::{Markup, html};
use crate::core::response::page::PageAssets;
use downcast_rs::{Downcast, impl_downcast};

View file

@ -1,4 +1,4 @@
use crate::core::theme::{Markup, html};
use crate::core::html::{Markup, html};
use crate::core::response::page::{PageAssets, PageComponent, render_component};
use std::sync::Arc;

View file

@ -1,12 +1,17 @@
use crate::{Lazy, trace, util};
use crate::config::SETTINGS;
use crate::core::{global, server};
use crate::core::theme::{DOCTYPE, Markup, html};
use crate::core::html::{DOCTYPE, Markup, html};
use crate::core::response::page::{PageAssets, PageComponent, PageContainer};
use crate::core::server;
use std::borrow::Cow;
use std::sync::RwLock;
use std::collections::HashMap;
static COMPONENTS: Lazy<RwLock<HashMap<&str, PageContainer>>> = Lazy::new(|| {
RwLock::new(HashMap::new())
});
static DEFAULT_LANGUAGE: Lazy<Option<String>> = Lazy::new(|| {
let language = SETTINGS.app.language[..2].to_lowercase();
if !language.is_empty() {
@ -25,9 +30,9 @@ static DEFAULT_DIRECTION: Lazy<Option<String>> = Lazy::new(|| {
"" => None,
_ => {
trace::warn!(
"Text direction \"{}\" not valid. {}.",
"Text direction \"{}\" not valid, {}",
SETTINGS.app.direction,
"Check the settings file"
"check the settings file"
);
None
}
@ -63,7 +68,7 @@ impl<'a> Page<'a> {
description : None,
body_classes: "body".into(),
assets : PageAssets::new(),
regions : global::COMPONENTS.read().unwrap().clone(),
regions : COMPONENTS.read().unwrap().clone(),
template : "default".to_owned(),
}
}
@ -208,7 +213,7 @@ pub fn render_component(
}
pub fn add_component_to(region: &'static str, component: impl PageComponent) {
let mut hmap = global::COMPONENTS.write().unwrap();
let mut hmap = COMPONENTS.write().unwrap();
if let Some(regions) = hmap.get_mut(region) {
regions.add(component);
} else {

View file

@ -1,6 +1,6 @@
use crate::{Lazy, base, trace};
use crate::config::SETTINGS;
use crate::core::{Server, global, server};
use crate::core::{Server, all, server};
use crate::core::theme::register_theme;
use crate::core::module::register_module;
@ -11,8 +11,12 @@ pub struct Application {
server: Server,
}
pub fn essence() {
trace::info!("No bootstrap configured");
}
impl Application {
pub async fn build(bootstrap: Option<fn()>) -> Result<Self, Error> {
pub async fn prepare(bootstrap: fn()) -> Result<Self, Error> {
// Imprime un rótulo de presentación (opcional).
if SETTINGS.app.startup_banner.to_lowercase() != "off" {
let figfont = figlet_rs::FIGfont::from_content(
@ -61,10 +65,8 @@ impl Application {
register_module(&base::module::user::UserModule);
// Ejecuta la función de inicio de la aplicación.
if bootstrap != None {
trace::info!("Calling application bootstrap.");
let _ = &(bootstrap.unwrap())();
}
trace::info!("Calling application bootstrap");
let _ = &bootstrap();
// Registra el módulo para la página de inicio de PageTop.
// Al ser el último, puede sobrecargarse con la función de inicio.
@ -72,15 +74,15 @@ impl Application {
// Comprueba actualizaciones pendientes de la base de datos (opcional).
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
global::run_migrations();
all::migrations();
// Prepara el servidor web.
let server = server::HttpServer::new(move || {
server::App::new()
.wrap(tracing_actix_web::TracingLogger)
.wrap(NormalizePath::new(TrailingSlash::Trim))
.configure(&global::themes)
.configure(&global::modules)
.configure(&all::themes)
.configure(&all::modules)
})
.bind(format!("{}:{}",
&SETTINGS.webserver.bind_address,

View file

@ -1,13 +1,12 @@
use crate::{Lazy, db, run_now, trace};
use crate::config::SETTINGS;
use std::sync::RwLock;
use sea_orm::{ConnectOptions, Database};
use tracing_unwrap::ResultExt;
pub static DBCONN: Lazy<RwLock<db::DbConn>> = Lazy::new(|| {
pub static DBCONN: Lazy<db::DbConn> = Lazy::new(|| {
trace::info!(
"Connecting to database \"{}\" using a pool of {} connections.",
"Connecting to database \"{}\" using a pool of {} connections",
&SETTINGS.database.db_name,
&SETTINGS.database.max_pool_size
);
@ -41,20 +40,18 @@ pub static DBCONN: Lazy<RwLock<db::DbConn>> = Lazy::new(|| {
).as_str()).unwrap(),
_ => {
trace::error!(
"Unrecognized database type \"{}\".",
"Unrecognized database type \"{}\"",
&SETTINGS.database.db_type
);
db::DbUri::parse("").unwrap()
}
};
let db_conn = run_now(
run_now(
Database::connect::<ConnectOptions>({
let mut db_opt = ConnectOptions::new(db_uri.to_string());
db_opt.max_connections(SETTINGS.database.max_pool_size);
db_opt.into()
})
).expect_or_log("Failed to connect to database");
RwLock::new(db_conn)
).expect_or_log("Failed to connect to database")
});

View file

@ -11,11 +11,12 @@ pub static LANGID: Lazy<LanguageIdentifier> = Lazy::new(|| {
Ok(language) => language,
Err(_) => {
trace::warn!(
"Failed to parse language \"{}\". {}. {}. {}.",
"{}, {} \"{}\"! {}, {}",
"Failed to parse language",
"unrecognized Unicode Language Identifier",
SETTINGS.app.language,
"Unrecognized Unicode Language Identifier",
"Using \"en-US\"",
"Check the settings file",
"check the settings file",
);
"en-US".parse().unwrap()
}

View file

@ -1,11 +1,11 @@
use crate::config::SETTINGS;
use crate::core::server;
use crate::core::theme::{Markup, html};
use crate::core::html::{Markup, html};
use crate::core::response::page::{Page, PageAssets, PageComponent};
use crate::core::server;
use crate::base::component::Chunck;
/// Los temas deben implementar este "trait".
pub trait Theme: Send + Sync {
pub trait ThemeTrait: Send + Sync {
fn name(&self) -> &'static str;
fn fullname(&self) -> String;

View file

@ -1,16 +1,14 @@
use crate::core::global;
pub use maud::{DOCTYPE, Markup, PreEscaped, html};
use crate::core::all;
mod definition;
pub use definition::Theme;
pub use definition::ThemeTrait;
pub fn register_theme(t: &'static (dyn Theme + 'static)) {
global::THEMES.write().unwrap().push(t);
pub fn register_theme(t: &'static (dyn ThemeTrait + 'static)) {
all::THEMES.write().unwrap().push(t);
}
pub fn find_theme(name: &str) -> Option<&'static (dyn Theme + 'static)> {
let themes = global::THEMES.write().unwrap();
pub fn find_theme(name: &str) -> Option<&'static (dyn ThemeTrait + 'static)> {
let themes = all::THEMES.write().unwrap();
match themes.iter().find(|t| t.name() == name) {
Some(theme) => Some(*theme),
_ => None,

View file

@ -20,5 +20,3 @@ pub mod base; // Temas, Módulos y Componentes base.
pub mod util; // Macros y funciones útiles.
pub mod prelude; // Re-exporta recursos comunes.
pub use crate::core::server::app::Application;

View file

@ -37,8 +37,8 @@ macro_rules! localize {
fn e(
key: &str,
args: &std::collections::HashMap<String, FluentValue>
) -> crate::core::theme::PreEscaped<String> {
crate::core::theme::PreEscaped(
) -> crate::core::html::PreEscaped<String> {
crate::core::html::PreEscaped(
LOCALES.lookup_with_args(&LANGID, key, args)
)
}

View file

@ -8,10 +8,12 @@ pub use crate::localize;
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
pub use crate::{db, db_migrations};
pub use crate::core::html::*;
pub use crate::core::theme::*;
pub use crate::core::module::*;
pub use crate::core::response::page::*;
pub use crate::core::server;
pub use crate::core::server::app::{Application, essence};
pub use crate::base::component::*;

View file

@ -1,7 +1,8 @@
use pagetop::core::server;
fn spawn_app() {
let server = server::run(None).expect("Failed to bind address");
async fn spawn_app() {
let server = pagetop::Application::prepare(None)
.await?
.run()?
.expect("Failed to prepare server");
let _ = tokio::spawn(server);
}