174 lines
5.7 KiB
Rust
174 lines
5.7 KiB
Rust
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<T> = Result<T, FactoryError>;
|
|
|
|
#[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<Arc<dyn notes_domain::ports::EmbeddingGenerator>> {
|
|
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<Arc<dyn notes_domain::ports::VectorStore>> {
|
|
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<Arc<dyn notes_domain::ports::LinkRepository>> {
|
|
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<DatabasePool> {
|
|
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<Arc<dyn NoteRepository>> {
|
|
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<Arc<dyn TagRepository>> {
|
|
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<Arc<dyn UserRepository>> {
|
|
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<crate::session_store::InfraSessionStore> {
|
|
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(),
|
|
)),
|
|
}
|
|
}
|