Files
k-photos/crates/bootstrap/src/factory.rs

71 lines
2.5 KiB
Rust

use anyhow::Result;
use axum::Router;
use axum::http::HeaderValue;
use std::sync::Arc;
use tower_http::{
cors::{Any, CorsLayer},
trace::TraceLayer,
};
use adapters_postgres::{connect, run_migrations};
use adapters_storage::LocalFileStorage;
use presentation::{routes::app_router, state::AppState};
use crate::config::Config;
use crate::services;
pub async fn build_app(config: &Config) -> Result<Router> {
let pool = connect(&config.database_url).await?;
run_migrations(&pool).await?;
let nats_client = async_nats::connect(&config.nats_url).await?;
adapters_nats::ensure_stream(&nats_client).await?;
let transport = adapters_nats::NatsTransport::new(nats_client);
let nats_publisher: Arc<dyn domain::ports::EventPublisher> =
Arc::new(event_transport::EventPublisherAdapter::new(transport));
let event_store: Arc<dyn domain::ports::EventStore> =
Arc::new(adapters_postgres::PostgresEventStore::new(pool.clone()));
let event_publisher: Arc<dyn domain::ports::EventPublisher> =
Arc::new(event_transport::CompositeEventPublisher::new(nats_publisher, event_store));
let storage_path = std::env::var("STORAGE_PATH").unwrap_or_else(|_| "./data/media".to_string());
let file_storage: Arc<LocalFileStorage> = Arc::new(LocalFileStorage::new(&storage_path));
// Build per-context services
let identity = services::identity::build(&pool, &config.jwt_secret);
let (storage_repos, storage) = services::storage::build(&pool);
let catalog = services::catalog::build(&pool, &storage_repos, file_storage, event_publisher.clone());
let organization = services::organization::build(&pool);
let sidecar = services::sidecar::build(&pool);
let processing = services::processing::build(&pool, event_publisher.clone());
let sharing = services::sharing::build(&pool, event_publisher);
let state = AppState {
identity: identity.handlers,
catalog,
organization,
storage,
sharing,
sidecar,
processing,
token_issuer: identity.token_issuer,
};
let cors = CorsLayer::new()
.allow_origin(
config
.cors_allowed_origins
.iter()
.filter_map(|o| o.parse::<HeaderValue>().ok())
.collect::<Vec<_>>(),
)
.allow_methods(Any)
.allow_headers(Any);
Ok(app_router()
.with_state(state)
.layer(TraceLayer::new_for_http())
.layer(cors))
}