backend/
main.rs

1/// Cookie and JWT authentication utilities
2mod cookie;
3/// Environment configuration loading
4mod env;
5/// HTTP request handlers for all endpoints
6mod handlers;
7/// Data structures for request/response serialization
8mod models;
9/// Axum router configuration with all routes and middleware
10mod router;
11
12use std::sync::Arc;
13
14use axum::http::{
15    HeaderValue, Method,
16    header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE},
17};
18use dotenv::dotenv;
19use router::create_router;
20use sqlx::{PgPool, postgres::PgPoolOptions};
21use tower_http::cors::CorsLayer;
22
23use crate::env::Env;
24
25/// Shared application state passed to all route handlers.
26///
27/// Contains the database connection pool and environment configuration.
28/// This is wrapped in Arc for thread-safe sharing across async tasks and cloned into each route
29/// via `with_state`.
30///
31/// # Fields
32/// - `db`: PostgreSQL connection pool for database access (via `sqlx::PgPool`)
33/// - `env`: [`Env`] configuration loaded from environment variables
34pub struct AppState {
35    /// PostgreSQL connection pool for all database operations
36    pub db: PgPool,
37    /// Environment configuration with secrets and settings
38    pub env: Env,
39}
40
41/// Main application entry point.
42///
43/// Initializes the server by:
44/// 1. Loading environment variables from `.env` file
45/// 2. Establishing database connection pool to PostgreSQL
46/// 3. Configuring CORS policy for cross-origin requests
47/// 4. Creating the router with [`create_router`] containing all endpoints
48/// 5. Starting HTTP server on port 8001
49///
50/// # Server Configuration
51/// - Binds to `0.0.0.0:8001` (all network interfaces)
52/// - Allows: GET, POST, PATCH, DELETE methods
53/// - Allows credentials and custom headers
54/// - CORS origin configured from [`Env`]
55///
56/// # State Setup
57/// Creates shared [`AppState`] wrapped in `Arc` and passes to all routes
58///
59/// # Panics
60/// - If environment loading fails
61/// - If database connection fails
62#[tokio::main]
63async fn main() {
64    dotenv().ok();
65    let env = Env::load();
66    let database_url = &env.db_url;
67
68    // Establish connection pool to PostgreSQL
69    let pool = match PgPoolOptions::new().connect(&database_url).await {
70        Ok(pool) => {
71            println!("Database connection successful");
72            pool
73        }
74        Err(err) => {
75            println!("Failed to connect to database: {:?}", err);
76            std::process::exit(1);
77        }
78    };
79
80    // Configure CORS to allow requests from frontend
81    let cors = CorsLayer::new()
82        .allow_origin(env.origin.parse::<HeaderValue>().unwrap())
83        .allow_methods([Method::GET, Method::POST, Method::PATCH, Method::DELETE])
84        .allow_credentials(true)
85        .allow_headers([AUTHORIZATION, ACCEPT, CONTENT_TYPE]);
86
87    // Build router with all endpoints and apply CORS middleware
88    let app = create_router(Arc::new(AppState {
89        db: pool.clone(),
90        env: env.clone(),
91    }))
92    .layer(cors);
93
94    // Start listening for incoming connections
95    let listener = tokio::net::TcpListener::bind("0.0.0.0:8001").await.unwrap();
96    let _ = axum::serve(listener, app).await;
97}