1use std::sync::Arc;
4use tracing::info;
5
6use axum::{middleware as mw, routing::get, Json, Router};
7use config::load_config;
8use middleware::log::layer::log_middleware;
9use serde_json::json;
10use service::api_v1_routes;
11use sqlx::{postgres::PgPoolOptions, PgPool};
12use tracing_subscriber::EnvFilter;
13
14pub use self::error::{Error, PayloadJson, Result};
15
16mod config;
17mod error;
18mod middleware;
19mod service;
20
21#[derive(Clone)]
26struct AppState {
27 db: Arc<PgPool>,
30}
31
32#[tokio::main]
41pub async fn main() -> Result<()> {
42 #[cfg(debug_assertions)]
43 tracing_subscriber::fmt()
44 .with_target(false)
45 .with_env_filter(EnvFilter::new("debug"))
46 .init();
47
48 #[cfg(not(debug_assertions))]
49 tracing_subscriber::fmt()
50 .json()
51 .with_target(false)
52 .with_env_filter(EnvFilter::new("info"))
53 .init();
54
55 info!("Starting Server");
56
57 let config = load_config();
59
60 info!("Connecting to database...");
61 let pool = PgPoolOptions::new()
62 .max_connections(10)
63 .connect(&config.DATABASE_URL)
64 .await
65 .expect("Failed to create PgPool.");
66 info!("Connected to database.");
67
68 let shared_state = AppState { db: Arc::new(pool) };
71
72 let app = Router::new()
73 .route(
74 "/",
75 get(|| async { Json(json!({ "message": "Welcome to Dogy API" })) }),
76 )
77 .nest("/api/v1", api_v1_routes(shared_state.clone()).await)
78 .layer(mw::map_response(log_middleware));
79
80 let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", config.PORT))
82 .await
83 .unwrap();
84 axum::serve(listener, app).await.unwrap();
85
86 Ok(())
87}