use std::path::PathBuf;
use axum::async_trait;
use color_eyre::owo_colors::OwoColorize;
use colored::Colorize;
use crate::application::{container, Container};
use crate::contracts::Configuration;
use crate::Result;
use crate::{app, config, env};
#[async_trait]
pub trait Application: Sync + Send {
fn logo() -> &'static str {
r"
░░ ░░░ ░░░░ ░░ ░░░░ ░░ ░░░ ░
▒ ▒▒▒▒ ▒▒▒ ▒▒ ▒▒▒ ▒▒▒▒ ▒▒ ▒▒ ▒
▓ ▓▓▓▓ ▓▓▓▓ ▓▓▓▓ ▓▓▓▓ ▓▓ ▓ ▓ ▓
█ █████ █████ ████ ██ ██ █
█ ████ █████ ██████ ███ ███ █
"
}
fn name() -> &'static str {
env!("CARGO_CRATE_NAME")
}
fn version() -> &'static str {
env!("CARGO_PKG_VERSION")
}
fn base_path() -> PathBuf {
env("CARGO_MANIFEST_DIR")
.map(PathBuf::from)
.unwrap_or_else(|_| {
std::env::current_dir()
.expect("project directory does not exist or permissions are insufficient")
})
}
#[cfg(any(feature = "http1", feature = "http2"))]
fn with_routing() -> axum::Router {
axum::Router::new()
.merge(crate::http::Router::group(Box::new(|mut router| {
router.route("/", axum::routing::get(|| async { "hello,ayun" }));
router
})))
.merge(crate::http::Router::group(Box::new(|mut router| {
router
.with_global_middlewares()
.route("/ping", axum::routing::get(|| async { "pong" }))
.route("/pong", axum::routing::get(|| async { "ping" }));
router
})))
}
#[cfg(feature = "schedule")]
fn with_schedule() -> Result<crate::support::scheduling::Schedule> {
use crate::support::scheduling::Task;
let mut schedule = crate::support::scheduling::Schedule::default();
schedule.add(Task::foreground("0/1 * * * * *", || {
tracing::info!("task: 0/1 * * * * *")
})?);
schedule.add(Task::foreground("0/5 * * * * *", || {
tracing::info!("task: 0/5 * * * * *")
})?);
schedule.add(Task::background("0/10 * * * * *", || {
Box::pin(async { tracing::info!("async task: 0/10 * * * * *") })
})?);
Ok(schedule)
}
fn register() -> Container {
let mut container = Container::default();
container.register::<Self, crate::support::facades::Path>();
container.register::<Self, crate::support::facades::Environment>();
container.register::<Self, crate::support::facades::Config>();
container.register::<Self, crate::support::facades::Logger>();
#[cfg(feature = "metrics")]
container.register::<Self, crate::support::facades::Metrics>();
#[cfg(any(
feature = "http1",
feature = "http2",
feature = "database",
feature = "redis"
))]
container.register::<Self, crate::support::facades::Runtime>();
#[cfg(feature = "database")]
container.register::<Self, crate::support::facades::Database>();
#[cfg(feature = "redis")]
container.register::<Self, crate::support::facades::Redis>();
container
}
fn boot() -> Result<()> {
let _enter = app::<crate::support::facades::Logger>().map(|span| span.enter());
for (scope, name) in container().instances() {
tracing::info!("[{}] `{}` successfully boot.", scope, name);
}
println!("{}", Self::logo().cyan());
let workspace = Self::base_path().to_string_lossy().to_string();
let environment =
app::<crate::support::facades::Environment>().map(|environment| environment.is())?;
let source = app::<crate::support::facades::Config>()?
.source()
.replace(&workspace, "");
let level = config::<crate::enums::config::Logger>("log")
.unwrap_or_default()
.level;
println!("environment: {}", environment.green().bold());
println!(" config: {}", source.yellow());
println!(" logger: {}", level.green());
println!();
#[cfg(feature = "schedule")]
crate::support::scheduling::run::<Self>()?;
#[cfg(any(feature = "http1", feature = "http2"))]
{
let runtime = app::<crate::support::facades::Runtime>()?;
let config = config::<crate::enums::config::Server>("server").unwrap_or_default();
println!("server listening on {}", config.uri.green());
runtime.block_on(crate::http::server::<Self>(config))?;
}
Ok(())
}
}