use std::{net::SocketAddr, sync::Arc}; use axum::Router; use serde::Deserialize; use sqlx::{postgres::PgPoolOptions, PgPool}; use tracing_subscriber::EnvFilter; fn default_port() -> u16 { 8080 } fn default_address() -> String { "127.0.0.1".into() } #[derive(Deserialize, Debug)] #[serde(rename_all = "UPPERCASE")] struct Settings { #[serde(default = "default_port")] port: u16, #[serde(default = "default_address")] address: String, database_url: String, } impl Settings { fn new() -> color_eyre::Result { envious::Config::default() .with_prefix("MAIL_ADMIN_") .case_sensitive(true) .build_from_env() .map_err(Into::into) } } struct AppState { db: PgPool, } #[tokio::main] async fn main() -> color_eyre::Result<()> { color_eyre::install()?; tracing_subscriber::fmt() .with_max_level(tracing::Level::DEBUG) .with_target(true) .with_env_filter(EnvFilter::from_default_env()) .init(); let config = Settings::new()?; tracing::info!("Settings: {config:#?}"); let addr: SocketAddr = format!("{}:{}", config.address, config.port).parse()?; let db = PgPoolOptions::new() .max_connections(5) .connect(&config.database_url) .await?; sqlx::migrate!().run(&db).await?; tracing::info!("Listening on {addr}"); let router = Router::new().with_state(Arc::new(AppState { db })); Ok(axum::Server::bind(&addr) .serve(router.into_make_service()) .await?) }