use axum::{ response::Json, routing::{delete, get, post}, Router, }; use std::sync::Arc; use tower_http::cors::{Any, CorsLayer}; pub mod auth; pub mod calendar; pub mod config; pub mod db; pub mod handlers; pub mod models; use auth::AuthService; use db::Database; #[derive(Clone)] pub struct AppState { pub auth_service: AuthService, pub db: Database, } pub async fn run_server() -> Result<(), Box> { // Initialize logging println!("🚀 Starting Calendar Backend Server"); // Initialize database let database_url = std::env::var("DATABASE_URL") .unwrap_or_else(|_| "sqlite:calendar.db".to_string()); let db = Database::new(&database_url).await?; println!("✅ Database initialized"); // Create auth service let jwt_secret = std::env::var("JWT_SECRET") .unwrap_or_else(|_| "your-super-secret-jwt-key-change-in-production".to_string()); let auth_service = AuthService::new(jwt_secret, db.clone()); let app_state = AppState { auth_service, db }; // Build our application with routes let app = Router::new() .route("/", get(root)) .route("/api/health", get(health_check)) .route("/api/auth/login", post(handlers::login)) .route("/api/auth/verify", get(handlers::verify_token)) .route("/api/user/info", get(handlers::get_user_info)) .route("/api/calendar/create", post(handlers::create_calendar)) .route("/api/calendar/delete", post(handlers::delete_calendar)) .route("/api/calendar/events", get(handlers::get_calendar_events)) .route("/api/calendar/events/create", post(handlers::create_event)) .route("/api/calendar/events/update", post(handlers::update_event)) .route("/api/calendar/events/delete", post(handlers::delete_event)) .route("/api/calendar/events/:uid", get(handlers::refresh_event)) // Event series-specific endpoints .route( "/api/calendar/events/series/create", post(handlers::create_event_series), ) .route( "/api/calendar/events/series/update", post(handlers::update_event_series), ) .route( "/api/calendar/events/series/delete", post(handlers::delete_event_series), ) // User preferences endpoints .route("/api/preferences", get(handlers::get_preferences)) .route("/api/preferences", post(handlers::update_preferences)) .route("/api/auth/logout", post(handlers::logout)) // External calendars endpoints .route("/api/external-calendars", get(handlers::get_external_calendars)) .route("/api/external-calendars", post(handlers::create_external_calendar)) .route("/api/external-calendars/:id", post(handlers::update_external_calendar)) .route("/api/external-calendars/:id", delete(handlers::delete_external_calendar)) .route("/api/external-calendars/:id/events", get(handlers::fetch_external_calendar_events)) .layer( CorsLayer::new() .allow_origin(Any) .allow_methods(Any) .allow_headers(Any), ) .with_state(Arc::new(app_state)); // Start server let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?; println!("📡 Server listening on http://0.0.0.0:3000"); axum::serve(listener, app).await?; Ok(()) } async fn root() -> &'static str { "Calendar Backend API v0.1.0" } async fn health_check() -> Json { Json(serde_json::json!({ "status": "healthy", "service": "calendar-backend", "version": "0.1.0" })) }