use std::sync::Arc; use crate::{DatabaseConfig, db::DatabasePool}; #[cfg(feature = "sqlite")] use crate::{SqliteNoteRepository, SqliteTagRepository, SqliteUserRepository}; use notes_domain::{NoteRepository, TagRepository, 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] notes_domain::DomainError), } pub type FactoryResult = Result; #[cfg(feature = "smart-features")] #[derive(Debug, Clone)] pub enum EmbeddingProvider { FastEmbed, // Ollama(String), // Url // OpenAI(String), // ApiKey } #[cfg(feature = "smart-features")] #[derive(Debug, Clone)] pub enum VectorProvider { Qdrant { url: String, collection: String }, // InMemory, } #[cfg(feature = "smart-features")] pub async fn build_embedding_generator( provider: &EmbeddingProvider, ) -> FactoryResult> { match provider { EmbeddingProvider::FastEmbed => { let adapter = crate::embeddings::fastembed::FastEmbedAdapter::new()?; Ok(Arc::new(adapter)) } } } #[cfg(feature = "smart-features")] pub async fn build_vector_store( provider: &VectorProvider, ) -> FactoryResult> { match provider { VectorProvider::Qdrant { url, collection } => { let adapter = crate::vector::qdrant::QdrantVectorAdapter::new(url, collection)?; adapter.create_collection_if_not_exists().await?; Ok(Arc::new(adapter)) } } } #[cfg(feature = "sqlite")] pub async fn build_link_repository( pool: &DatabasePool, ) -> FactoryResult> { match pool { DatabasePool::Sqlite(pool) => Ok(Arc::new( crate::link_repository::SqliteLinkRepository::new(pool.clone()), )), _ => Err(FactoryError::NotImplemented( "LinkRepostiory for non-sqlite".to_string(), )), } } pub async fn build_database_pool(db_config: &DatabaseConfig) -> FactoryResult { if db_config.url.starts_with("sqlite:") { #[cfg(feature = "sqlite")] { let pool = sqlx::sqlite::SqlitePoolOptions::new() .max_connections(5) .connect(&db_config.url) .await?; Ok(DatabasePool::Sqlite(pool)) } #[cfg(not(feature = "sqlite"))] Err(FactoryError::NotImplemented( "SQLite feature not enabled".to_string(), )) } else if db_config.url.starts_with("postgres:") { #[cfg(feature = "postgres")] { let pool = sqlx::postgres::PgPoolOptions::new() .max_connections(5) .connect(&db_config.url) .await?; Ok(DatabasePool::Postgres(pool)) } #[cfg(not(feature = "postgres"))] Err(FactoryError::NotImplemented( "Postgres feature not enabled".to_string(), )) } else { Err(FactoryError::NotImplemented(format!( "Unsupported database URL scheme in: {}", db_config.url ))) } } pub async fn build_note_repository(pool: &DatabasePool) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new(SqliteNoteRepository::new(pool.clone()))), #[cfg(feature = "postgres")] DatabasePool::Postgres(_) => Err(FactoryError::NotImplemented( "Postgres NoteRepository".to_string(), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "No database feature enabled".to_string(), )), } } pub async fn build_tag_repository(pool: &DatabasePool) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new(SqliteTagRepository::new(pool.clone()))), #[cfg(feature = "postgres")] DatabasePool::Postgres(_) => Err(FactoryError::NotImplemented( "Postgres TagRepository".to_string(), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "No database feature enabled".to_string(), )), } } pub async fn build_user_repository(pool: &DatabasePool) -> FactoryResult> { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => Ok(Arc::new(SqliteUserRepository::new(pool.clone()))), #[cfg(feature = "postgres")] DatabasePool::Postgres(_) => Err(FactoryError::NotImplemented( "Postgres UserRepository".to_string(), )), #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "No database feature enabled".to_string(), )), } } pub async fn build_session_store( pool: &DatabasePool, ) -> FactoryResult { match pool { #[cfg(feature = "sqlite")] DatabasePool::Sqlite(pool) => { let store = tower_sessions_sqlx_store::SqliteStore::new(pool.clone()); Ok(crate::session_store::InfraSessionStore::Sqlite(store)) } #[cfg(feature = "postgres")] DatabasePool::Postgres(pool) => { let store = tower_sessions_sqlx_store::PostgresStore::new(pool.clone()); Ok(crate::session_store::InfraSessionStore::Postgres(store)) } #[allow(unreachable_patterns)] _ => Err(FactoryError::NotImplemented( "No database feature enabled".to_string(), )), } }