Axum server entry point, AppConfig, AppState, ApiError, all model structs (auth, license, server, wipe), and the PanelAdapter trait that abstracts AMP/Pterodactyl/companion connections. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
86 lines
2.5 KiB
Rust
86 lines
2.5 KiB
Rust
use std::sync::Arc;
|
|
|
|
use axum::Router;
|
|
use sqlx::postgres::PgPoolOptions;
|
|
use tokio::net::TcpListener;
|
|
use tower_http::cors::CorsLayer;
|
|
use tower_http::trace::TraceLayer;
|
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
|
|
|
mod api;
|
|
mod config;
|
|
mod db;
|
|
mod middleware;
|
|
mod models;
|
|
mod services;
|
|
|
|
use config::AppConfig;
|
|
|
|
/// Shared application state available to all handlers
|
|
pub struct AppState {
|
|
pub db: sqlx::PgPool,
|
|
pub nats: async_nats::Client,
|
|
pub config: AppConfig,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
// Load environment variables
|
|
dotenvy::dotenv().ok();
|
|
|
|
// Initialize tracing
|
|
tracing_subscriber::registry()
|
|
.with(tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
|
|
"corrosion_api=debug,tower_http=debug,axum=trace".into()
|
|
}))
|
|
.with(tracing_subscriber::fmt::layer())
|
|
.init();
|
|
|
|
let config = AppConfig::from_env()?;
|
|
|
|
// Database connection pool
|
|
let db = PgPoolOptions::new()
|
|
.max_connections(config.database_max_connections)
|
|
.connect(&config.database_url)
|
|
.await?;
|
|
|
|
tracing::info!("Connected to PostgreSQL");
|
|
|
|
// Run migrations
|
|
sqlx::migrate!("./migrations").run(&db).await?;
|
|
tracing::info!("Database migrations applied");
|
|
|
|
// NATS connection
|
|
let nats = async_nats::connect(&config.nats_url).await?;
|
|
tracing::info!("Connected to NATS at {}", config.nats_url);
|
|
|
|
let state = Arc::new(AppState { db, nats, config });
|
|
|
|
// Build router
|
|
let app = Router::new()
|
|
.nest("/api/auth", api::auth::router())
|
|
.nest("/api/servers", api::servers::router())
|
|
.nest("/api/wipes", api::wipes::router())
|
|
.nest("/api/maps", api::maps::router())
|
|
.nest("/api/plugins", api::plugins::router())
|
|
.nest("/api/panels", api::panels::router())
|
|
.nest("/api/schedules", api::schedules::router())
|
|
.nest("/api/logs", api::logs::router())
|
|
.nest("/api/public", api::public::router())
|
|
.nest("/api/team", api::team::router())
|
|
.nest("/api/notifications", api::notifications::router())
|
|
.nest("/api/license", api::license::router())
|
|
.nest("/api/store", api::store::router())
|
|
.layer(CorsLayer::permissive()) // TODO: Restrict in production
|
|
.layer(TraceLayer::new_for_http())
|
|
.with_state(state);
|
|
|
|
let bind_addr = "0.0.0.0:3000";
|
|
let listener = TcpListener::bind(bind_addr).await?;
|
|
tracing::info!("Corrosion API listening on {}", bind_addr);
|
|
|
|
axum::serve(listener, app).await?;
|
|
|
|
Ok(())
|
|
}
|