use crate::core::action::add_action; use crate::core::package::PackageRef; use crate::core::theme::all::THEMES; use crate::{config, service, service_for_static_files, static_files, trace, LazyStatic}; #[cfg(feature = "database")] use crate::db::*; use std::sync::RwLock; static_files!(base); // PACKAGES **************************************************************************************** static ENABLED_PACKAGES: LazyStatic>> = LazyStatic::new(|| RwLock::new(Vec::new())); static DROPPED_PACKAGES: LazyStatic>> = LazyStatic::new(|| RwLock::new(Vec::new())); // REGISTER PACKAGES ******************************************************************************* pub fn register_packages(app: PackageRef) { // List of packages to drop. let mut list: Vec = Vec::new(); add_to_dropped(&mut list, app); DROPPED_PACKAGES.write().unwrap().append(&mut list); // List of packages to enable. let mut list: Vec = Vec::new(); // Enable default welcome page. add_to_enabled(&mut list, &crate::base::package::Welcome); // Enable default themes. add_to_enabled(&mut list, &crate::base::theme::Basic); add_to_enabled(&mut list, &crate::base::theme::Chassis); add_to_enabled(&mut list, &crate::base::theme::Inception); // Enable application packages. add_to_enabled(&mut list, app); list.reverse(); ENABLED_PACKAGES.write().unwrap().append(&mut list); } fn add_to_dropped(list: &mut Vec, package: PackageRef) { for d in package.drop_packages().iter() { if !list.iter().any(|p| p.type_id() == d.type_id()) { list.push(*d); trace::debug!("Package \"{}\" dropped", d.single_name()); } } for d in package.dependencies().iter() { add_to_dropped(list, *d); } } fn add_to_enabled(list: &mut Vec, package: PackageRef) { if !list.iter().any(|p| p.type_id() == package.type_id()) { if DROPPED_PACKAGES .read() .unwrap() .iter() .any(|p| p.type_id() == package.type_id()) { panic!( "Trying to enable \"{}\" package which is dropped", package.single_name() ); } else { list.push(package); let mut dependencies = package.dependencies(); dependencies.reverse(); for d in dependencies.iter() { add_to_enabled(list, *d); } if let Some(theme) = package.theme() { let mut registered_themes = THEMES.write().unwrap(); if !registered_themes .iter() .any(|t| t.type_id() == theme.type_id()) { registered_themes.push(theme); trace::debug!("Enabling \"{}\" theme", theme.single_name()); } } else { trace::debug!("Enabling \"{}\" package", package.single_name()); } } } } // REGISTER ACTIONS ******************************************************************************** pub fn register_actions() { for m in ENABLED_PACKAGES.read().unwrap().iter() { for a in m.actions().into_iter() { add_action(a); } } } // INIT PACKAGES *********************************************************************************** pub fn init_packages() { trace::info!("Calling application bootstrap"); for m in ENABLED_PACKAGES.read().unwrap().iter() { m.init(); } } // RUN MIGRATIONS ********************************************************************************** #[cfg(feature = "database")] pub fn run_migrations() { if let Some(dbconn) = &*DBCONN { if let Err(e) = run_now({ struct Migrator; impl MigratorTrait for Migrator { fn migrations() -> Vec { let mut migrations = vec![]; for m in ENABLED_PACKAGES.read().unwrap().iter() { migrations.append(&mut m.migrations()); } migrations } } Migrator::up(SchemaManagerConnection::Connection(dbconn), None) }) { trace::error!("Database upgrade failed ({})", e); }; if let Err(e) = run_now({ struct Migrator; impl MigratorTrait for Migrator { fn migrations() -> Vec { let mut migrations = vec![]; for m in DROPPED_PACKAGES.read().unwrap().iter() { migrations.append(&mut m.migrations()); } migrations } } Migrator::down(SchemaManagerConnection::Connection(dbconn), None) }) { trace::error!("Database downgrade failed ({})", e); }; } } // CONFIGURE SERVICES ****************************************************************************** pub fn configure_services(scfg: &mut service::web::ServiceConfig) { service_for_static_files!( scfg, base => "/base", [&config::SETTINGS.dev.pagetop_project_dir, "static/base"] ); for m in ENABLED_PACKAGES.read().unwrap().iter() { m.configure_service(scfg); } }