mod api; mod auth; mod error; mod extract; mod models; mod response; mod routers; mod state; mod util; pub use api::{AppOpenApi, tags}; pub use auth::{JwtClaims, create_jwt, create_password, validate_jwt, validate_password}; pub use error::{ApiError, ClientError, ServerError}; pub use response::{ApiResult, ErrorResponse, GlobalResponses, SuccessResponse}; pub use state::AppState; use axum::Router; use sea_orm::Database; use tokio::net::TcpListener; use tower_http::trace::TraceLayer; use tracing::info; use tracing_subscriber::EnvFilter; use utoipa_scalar::{Scalar, Servable}; fn env(name: &str) -> String { std::env::var(name).expect(format!("{} must be set", name).as_str()) } async fn listener() -> TcpListener { TcpListener::bind(env("SERVER_BIND")).await.unwrap() } async fn router() -> Router { let db = Database::connect(env("DATABASE_URL")).await.unwrap(); let secret = env("SECRET"); let (router, api) = routers::router().split_for_parts(); router .layer(TraceLayer::new_for_http()) .with_state(AppState { db, secret }) .merge(Scalar::with_url("/docs", api)) .fallback(routers::not_found) .method_not_allowed_fallback(routers::method_not_allowed) } #[tokio::main] async fn main() { tracing_subscriber::fmt() .with_env_filter(EnvFilter::new("info,sqlx=warn,tower_http=debug")) .init(); let listener = listener().await; let router = router().await; info!( "Start listening server on http://{:?}", listener.local_addr().unwrap() ); axum::serve(listener, router).await.unwrap(); }