1
0
card/src/main.rs
2025-06-08 06:42:03 +09:00

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()
})))
}