mod adapters;
mod config;
mod error;
mod features;
mod state;
use axum::{
middleware,
routing::get,
Router,
};
use lmrc_http_common::middleware::{add_request_id, cors_with_origins, log_request};
use sea_orm::Database;
use state::AppState;
use std::net::SocketAddr;
use tower_http::trace::TraceLayer;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::registry()
.with(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "{{app_name}}=debug,tower_http=debug".into()),
)
.with(tracing_subscriber::fmt::layer())
.init();
dotenvy::dotenv().ok();
let config = config::Config::from_env()?;
tracing::info!("Starting {{app_name}} on {}:{}", config.server.host, config.server.port);
tracing::info!("Connecting to database...");
let db = Database::connect(&config.database.url).await?;
tracing::info!("Database connected successfully");
let state = AppState::new(config.clone(), db);
let app = create_router(state);
let addr = SocketAddr::from(([0, 0, 0, 0], config.server.port));
tracing::info!("Listening on {}", addr);
let listener = tokio::net::TcpListener::bind(addr).await?;
axum::serve(listener, app).await?;
Ok(())
}
fn create_router(state: AppState) -> Router {
use axum::routing::{delete, post};
Router::new()
.route("/health", get(features::health::health_check))
.route(
"/api/users",
get(features::examples::handler::list_users)
.post(features::examples::handler::create_user),
)
.route(
"/api/users/search",
get(features::examples::handler::search_users),
)
.route(
"/api/users/:id",
get(features::examples::handler::get_user)
.put(features::examples::handler::update_user)
.delete(features::examples::handler::delete_user),
)
.layer(TraceLayer::new_for_http())
.layer(middleware::from_fn(log_request))
.layer(middleware::from_fn(add_request_id))
.layer(cors_with_origins(state.config.server.cors_origins.clone()))
.with_state(state)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_router_compiles() {
let config = config::Config {
server: config::ServerConfig {
host: "localhost".to_string(),
port: 8080,
cors_origins: vec!["http://localhost:3000".to_string()],
},
database: config::DatabaseConfig {
url: "postgres://test:test@localhost/test".to_string(),
max_connections: 5,
},
};
}
}