use std::sync::Arc; use anyhow::Result; use axum::Router; use axum::http::HeaderValue; use tower_http::{cors::{Any, CorsLayer}, trace::TraceLayer}; use adapters_auth::{BcryptPasswordHasher, JwtTokenIssuer}; use adapters_postgres::{connect, run_migrations, PostgresUserRepository}; use adapters_storage::{ObjectStorageAdapter, StorageConfig, build_store}; use application::identity::{RegisterUserHandler, LoginUserHandler, GetProfileHandler}; use presentation::{routes::app_router, state::AppState}; use crate::config::Config; pub async fn build_app(config: &Config) -> Result { let pool = connect(&config.database_url).await?; run_migrations(&pool).await?; let user_repo = Arc::new(PostgresUserRepository::new(pool)); let hasher = Arc::new(BcryptPasswordHasher); let issuer = Arc::new(JwtTokenIssuer::new(&config.jwt_secret)); let register_handler = Arc::new(RegisterUserHandler::new(user_repo.clone(), hasher.clone())); let login_handler = Arc::new(LoginUserHandler::new(user_repo.clone(), hasher, issuer.clone())); let get_profile_handler = Arc::new(GetProfileHandler::new(user_repo)); let storage_cfg = StorageConfig::from_env()?; let store = build_store(&storage_cfg)?; let storage = Arc::new(ObjectStorageAdapter::new(store, &storage_cfg.prefix)?); let state = AppState::new(register_handler, login_handler, get_profile_handler, issuer, storage); let cors = CorsLayer::new() .allow_origin( config.cors_allowed_origins.iter() .filter_map(|o| o.parse::().ok()) .collect::>(), ) .allow_methods(Any) .allow_headers(Any); Ok(app_router() .with_state(state) .layer(TraceLayer::new_for_http()) .layer(cors)) }