use super::{
card::{CardRepository, HttpCardRepository, MockCardRepository},
collection::{CollectionRepository, HttpCollectionRepository, MockCollectionRepository},
dashboard::{DashboardRepository, HttpDashboardRepository, MockDashboardRepository},
query::{HttpQueryRepository, MockQueryRepository, QueryRepository},
};
use crate::transport::http_provider_safe::HttpProviderSafe;
use std::sync::Arc;
#[derive(Clone, Default)]
pub struct RepositoryConfig {
pub use_mocks: bool,
pub http_provider: Option<Arc<dyn HttpProviderSafe>>,
}
impl std::fmt::Debug for RepositoryConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RepositoryConfig")
.field("use_mocks", &self.use_mocks)
.field(
"http_provider",
&self.http_provider.as_ref().map(|_| "Arc<HttpProviderSafe>"),
)
.finish()
}
}
impl RepositoryConfig {
pub fn production(http_provider: Arc<dyn HttpProviderSafe>) -> Self {
Self {
use_mocks: false,
http_provider: Some(http_provider),
}
}
pub fn testing() -> Self {
Self {
use_mocks: true,
http_provider: None,
}
}
}
pub struct RepositoryFactory {
config: RepositoryConfig,
}
impl RepositoryFactory {
pub fn new(config: RepositoryConfig) -> Self {
Self { config }
}
pub fn create_card_repository(&self) -> Arc<dyn CardRepository> {
if self.config.use_mocks {
Arc::new(MockCardRepository::new())
} else {
let http_provider = self
.config
.http_provider
.as_ref()
.expect("HTTP provider required for non-mock repositories")
.clone();
Arc::new(HttpCardRepository::new(http_provider))
}
}
pub fn create_collection_repository(&self) -> Arc<dyn CollectionRepository> {
if self.config.use_mocks {
Arc::new(MockCollectionRepository::new())
} else {
let http_provider = self
.config
.http_provider
.as_ref()
.expect("HTTP provider required for non-mock repositories")
.clone();
Arc::new(HttpCollectionRepository::new(http_provider))
}
}
pub fn create_dashboard_repository(&self) -> Arc<dyn DashboardRepository> {
if self.config.use_mocks {
Arc::new(MockDashboardRepository::new())
} else {
let http_provider = self
.config
.http_provider
.as_ref()
.expect("HTTP provider required for non-mock repositories")
.clone();
Arc::new(HttpDashboardRepository::new(http_provider))
}
}
pub fn create_query_repository(&self) -> Arc<dyn QueryRepository> {
if self.config.use_mocks {
Arc::new(MockQueryRepository::new())
} else {
let http_provider = self
.config
.http_provider
.as_ref()
.expect("HTTP provider required for non-mock repositories")
.clone();
Arc::new(HttpQueryRepository::new(http_provider))
}
}
pub fn create_all(&self) -> RepositorySet {
RepositorySet {
card: self.create_card_repository(),
collection: self.create_collection_repository(),
dashboard: self.create_dashboard_repository(),
query: self.create_query_repository(),
}
}
}
pub struct RepositorySet {
pub card: Arc<dyn CardRepository>,
pub collection: Arc<dyn CollectionRepository>,
pub dashboard: Arc<dyn DashboardRepository>,
pub query: Arc<dyn QueryRepository>,
}
pub struct RepositoryFactoryBuilder {
use_mocks: bool,
http_provider: Option<Arc<dyn HttpProviderSafe>>,
}
impl Default for RepositoryFactoryBuilder {
fn default() -> Self {
Self::new()
}
}
impl RepositoryFactoryBuilder {
pub fn new() -> Self {
Self {
use_mocks: false,
http_provider: None,
}
}
pub fn with_mocks(mut self) -> Self {
self.use_mocks = true;
self
}
pub fn with_http_provider(mut self, provider: Arc<dyn HttpProviderSafe>) -> Self {
self.http_provider = Some(provider);
self.use_mocks = false;
self
}
pub fn build(self) -> RepositoryFactory {
let config = RepositoryConfig {
use_mocks: self.use_mocks,
http_provider: self.http_provider,
};
RepositoryFactory::new(config)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_factory_with_mocks() {
let factory = RepositoryFactoryBuilder::new().with_mocks().build();
let repos = factory.create_all();
let _ = repos.card;
let _ = repos.collection;
let _ = repos.dashboard;
let _ = repos.query;
}
#[test]
fn test_config_presets() {
let test_config = RepositoryConfig::testing();
assert!(test_config.use_mocks);
assert!(test_config.http_provider.is_none());
}
}