use std::sync::Arc; use crate::db::DatabasePool; use domain::{ActivityLogRepository, ChannelRepository, IAppSettingsRepository, ILibraryRepository, ProviderConfigRepository, ScheduleRepository, TranscodeSettingsRepository, UserRepository}; #[derive(Debug, thiserror::Error)] pub enum FactoryError { #[error("Database error: {0}")] Database(#[from] sqlx::Error), #[error("Not implemented: {0}")] NotImplemented(String), #[error("Infrastructure error: {0}")] Infrastructure(#[from] domain::DomainError), } pub type FactoryResult = Result; pub async fn build_user_repository(pool: &DatabasePool) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new( crate::user_repository::SqliteUserRepository::new(pool.clone()), )), #[cfg(feature = "postgres")] DatabasePool::Postgres(pool) => Ok(Arc::new( crate::user_repository::PostgresUserRepository::new(pool.clone()), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "No database feature enabled".to_string(), )), } } pub async fn build_channel_repository( pool: &DatabasePool, ) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new( crate::channel_repository::SqliteChannelRepository::new(pool.clone()), )), #[cfg(feature = "postgres")] DatabasePool::Postgres(pool) => Ok(Arc::new( crate::channel_repository::PostgresChannelRepository::new(pool.clone()), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "No database feature enabled".to_string(), )), } } pub async fn build_activity_log_repository( pool: &DatabasePool, ) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new( crate::activity_log_repository::SqliteActivityLogRepository::new(pool.clone()), )), #[cfg(feature = "postgres")] DatabasePool::Postgres(_pool) => Err(FactoryError::NotImplemented( "ActivityLogRepository not yet implemented for Postgres".to_string(), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "No database feature enabled".to_string(), )), } } pub async fn build_provider_config_repository( pool: &DatabasePool, ) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new( crate::provider_config_repository::SqliteProviderConfigRepository::new(pool.clone()), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "ProviderConfigRepository not implemented for this database".to_string(), )), } } pub async fn build_schedule_repository( pool: &DatabasePool, ) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new( crate::schedule_repository::SqliteScheduleRepository::new(pool.clone()), )), #[cfg(feature = "postgres")] DatabasePool::Postgres(pool) => Ok(Arc::new( crate::schedule_repository::PostgresScheduleRepository::new(pool.clone()), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "No database feature enabled".to_string(), )), } } pub async fn build_transcode_settings_repository( pool: &DatabasePool, ) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(p) => Ok(Arc::new( crate::transcode_settings_repository::SqliteTranscodeSettingsRepository::new(p.clone()), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "TranscodeSettingsRepository not implemented for this database".to_string(), )), } } pub async fn build_library_repository( pool: &DatabasePool, ) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new( crate::library_repository::SqliteLibraryRepository::new(pool.clone()), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "LibraryRepository not implemented for this database".to_string(), )), } } pub async fn build_app_settings_repository( pool: &DatabasePool, ) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new( crate::app_settings_repository::SqliteAppSettingsRepository::new(pool.clone()), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "AppSettingsRepository not implemented for this database".to_string(), )), } } #[cfg(feature = "local-files")] pub struct LocalFilesBundle { pub provider: Arc, pub local_index: Arc, pub transcode_manager: Option>, } #[cfg(feature = "local-files")] pub async fn build_local_files_bundle( pool: &DatabasePool, root_dir: std::path::PathBuf, transcode_dir: Option, cleanup_ttl_hours: u32, base_url: String, provider_id: &str, ) -> FactoryResult { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(sqlite_pool) => { let cfg = crate::LocalFilesConfig { root_dir, base_url, transcode_dir: transcode_dir.clone(), cleanup_ttl_hours, }; let idx = Arc::new(crate::LocalIndex::new(&cfg, sqlite_pool.clone(), provider_id.to_string()).await); let tm = transcode_dir.as_ref().map(|td| { std::fs::create_dir_all(td).ok(); crate::TranscodeManager::new(td.clone(), cleanup_ttl_hours) }); let provider = Arc::new(crate::LocalFilesProvider::new(Arc::clone(&idx), cfg, tm.clone())); Ok(LocalFilesBundle { provider, local_index: idx, transcode_manager: tm }) } #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "local-files requires SQLite".to_string(), )), } }