/// Cookie and JWT authentication utilities mod cookie; /// Environment configuration loading mod env; /// HTTP request handlers for all endpoints mod handlers; /// Data structures for request/response serialization mod models; /// Axum router configuration with all routes and middleware mod router; use std::sync::Arc; use axum::http::{ HeaderValue, Method, header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE}, }; use dotenv::dotenv; use router::create_router; use sqlx::{PgPool, postgres::PgPoolOptions}; use tower_http::cors::CorsLayer; use crate::env::Env; /// Shared application state passed to all route handlers. /// /// Contains the database connection pool and environment configuration. /// This is wrapped in Arc for thread-safe sharing across async tasks and cloned into each route /// via `with_state`. /// /// # Fields /// - `db`: PostgreSQL connection pool for database access (via `sqlx::PgPool`) /// - `env`: [`Env`] configuration loaded from environment variables pub struct AppState { db: PgPool, env: Env, } /// Main application entry point. /// /// Initializes the server by: /// 1. Loading environment variables from `.env` file /// 2. Establishing database connection pool to PostgreSQL /// 3. Configuring CORS policy for cross-origin requests /// 4. Creating the router with [`create_router`] containing all endpoints /// 5. Starting HTTP server on port 8001 /// /// # Server Configuration /// - Binds to `0.0.0.0:8001` (all network interfaces) /// - Allows: GET, POST, PATCH, DELETE methods /// - Allows credentials and custom headers /// - CORS origin configured from [`Env`] /// /// # State Setup /// Creates shared [`AppState`] wrapped in `Arc` and passes to all routes /// /// # Panics /// - If environment loading fails /// - If database connection fails #[tokio::main] async fn main() { dotenv().ok(); let env = Env::load(); let database_url = &env.db_url; // Establish connection pool to PostgreSQL let pool = match PgPoolOptions::new().connect(database_url).await { Ok(pool) => { println!("Database connection successful"); pool } Err(err) => { println!("Failed to connect to database: {:?}", err); std::process::exit(1); } }; // Configure CORS to allow requests from frontend let cors = CorsLayer::new() .allow_origin(env.origin.parse::().unwrap()) .allow_methods([Method::GET, Method::POST, Method::PATCH, Method::DELETE]) .allow_credentials(true) .allow_headers([AUTHORIZATION, ACCEPT, CONTENT_TYPE]); // Build router with all endpoints and apply CORS middleware let app = create_router(Arc::new(AppState { db: pool.clone(), env: env.clone(), })) .layer(cors); // Start listening for incoming connections let uri = format!("0.0.0.0:{}", env.backend_port); let listener = tokio::net::TcpListener::bind(&uri).await.unwrap(); let _ = axum::serve(listener, app).await; }