103 lines
2.4 KiB
Rust
103 lines
2.4 KiB
Rust
use anyhow::Result;
|
|
use axum::{
|
|
extract::State,
|
|
http::StatusCode,
|
|
response::Json,
|
|
routing::{get, post},
|
|
Router,
|
|
};
|
|
use serde_json::{json, Value};
|
|
use std::net::SocketAddr;
|
|
use tower_http::cors::CorsLayer;
|
|
use tracing::{info, warn};
|
|
|
|
mod config;
|
|
mod database;
|
|
mod models;
|
|
mod handlers;
|
|
mod services;
|
|
mod auth;
|
|
mod error;
|
|
|
|
use config::Settings;
|
|
use database::Database;
|
|
use error::AppError;
|
|
|
|
#[derive(Clone)]
|
|
pub struct AppState {
|
|
pub db: Database,
|
|
pub settings: Settings,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
// Initialize tracing
|
|
tracing_subscriber::fmt::init();
|
|
|
|
// Load configuration
|
|
let settings = Settings::new()
|
|
.map_err(|e| anyhow::anyhow!("Failed to load configuration: {}", e))?;
|
|
|
|
info!("Starting ai.card API server v{}", env!("CARGO_PKG_VERSION"));
|
|
info!("Configuration loaded from: {}", settings.config_dir.display());
|
|
|
|
// Initialize database
|
|
let database = Database::connect(&settings.database_url).await?;
|
|
|
|
// Run migrations
|
|
database.migrate().await?;
|
|
info!("Database migrations completed");
|
|
|
|
let app_state = AppState {
|
|
db: database,
|
|
settings: settings.clone(),
|
|
};
|
|
|
|
// Build application routes
|
|
let app = create_app(app_state).await;
|
|
|
|
// Start server
|
|
let addr = SocketAddr::from(([0, 0, 0, 0], settings.port));
|
|
info!("ai.card API server listening on {}", addr);
|
|
|
|
let listener = tokio::net::TcpListener::bind(addr).await?;
|
|
axum::serve(listener, app).await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn create_app(state: AppState) -> Router {
|
|
Router::new()
|
|
// Health check
|
|
.route("/health", get(health_check))
|
|
|
|
// API v1 routes
|
|
.nest("/api/v1", create_api_routes())
|
|
|
|
// CORS middleware
|
|
.layer(CorsLayer::permissive())
|
|
|
|
// Application state
|
|
.with_state(state)
|
|
}
|
|
|
|
fn create_api_routes() -> Router<AppState> {
|
|
Router::new()
|
|
// Authentication routes
|
|
.nest("/auth", handlers::auth::create_routes())
|
|
|
|
// Card routes
|
|
.nest("/cards", handlers::cards::create_routes())
|
|
|
|
// Sync routes
|
|
.nest("/sync", handlers::sync::create_routes())
|
|
}
|
|
|
|
async fn health_check() -> Result<Json<Value>, AppError> {
|
|
Ok(Json(json!({
|
|
"status": "healthy",
|
|
"service": "ai.card",
|
|
"version": env!("CARGO_PKG_VERSION"),
|
|
"timestamp": chrono::Utc::now().to_rfc3339()
|
|
})))
|
|
} |