use serde::{Deserialize, Serialize};
use crate::cache_constants::CACHE_MANAGER;
use crate::cache_providers::createCacheManager;
use crate::interfaces::{CacheModuleAsyncOptions, CacheModuleOptions, CacheOptions};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ProviderKind {
Class,
Value,
Factory,
Existing,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Provider {
pub provide: String,
pub kind: ProviderKind,
pub use_value: Option<serde_json::Value>,
pub inject: Vec<String>,
pub use_existing: Option<String>,
}
impl Provider {
pub fn class(provide: impl Into<String>) -> Self {
Self {
provide: provide.into(),
kind: ProviderKind::Class,
use_value: None,
inject: Vec::new(),
use_existing: None,
}
}
pub fn value<T: Serialize>(provide: impl Into<String>, value: T) -> Self {
Self {
provide: provide.into(),
kind: ProviderKind::Value,
use_value: serde_json::to_value(value).ok(),
inject: Vec::new(),
use_existing: None,
}
}
pub fn factory(provide: impl Into<String>, inject: Vec<String>) -> Self {
Self {
provide: provide.into(),
kind: ProviderKind::Factory,
use_value: None,
inject,
use_existing: None,
}
}
pub fn existing(provide: impl Into<String>, use_existing: impl Into<String>) -> Self {
Self {
provide: provide.into(),
kind: ProviderKind::Existing,
use_value: None,
inject: Vec::new(),
use_existing: Some(use_existing.into()),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DynamicModule {
pub global: bool,
pub module: String,
pub imports: Vec<String>,
pub providers: Vec<Provider>,
pub exports: Vec<String>,
}
impl DynamicModule {
pub fn cache_options(&self) -> Option<CacheOptions> {
self.providers
.iter()
.find(|provider| provider.provide == crate::cache_constants::CACHE_MODULE_OPTIONS)
.and_then(|provider| provider.use_value.as_ref())
.and_then(|value| serde_json::from_value(value.clone()).ok())
}
}
pub struct Cache;
pub struct CacheModule;
impl CacheModule {
pub fn register(options: CacheModuleOptions) -> DynamicModule {
DynamicModule {
global: options.isGlobal.unwrap_or(false),
module: "CacheModule".to_string(),
imports: Vec::new(),
providers: vec![
Provider::value(
crate::cache_constants::CACHE_MODULE_OPTIONS,
&options.cache_options,
),
createCacheManager(),
Provider::existing("Cache", CACHE_MANAGER),
],
exports: vec![CACHE_MANAGER.to_string(), "Cache".to_string()],
}
}
pub fn registerAsync(options: CacheModuleAsyncOptions) -> DynamicModule {
let mut providers = Self::createAsyncProviders(options.clone());
providers.push(createCacheManager());
providers.push(Provider::existing("Cache", CACHE_MANAGER));
providers.extend(options.extraProviders.iter().map(Provider::class));
DynamicModule {
global: options.isGlobal.unwrap_or(false),
module: "CacheModule".to_string(),
imports: options.imports,
providers,
exports: vec![CACHE_MANAGER.to_string(), "Cache".to_string()],
}
}
pub fn register_async(options: CacheModuleAsyncOptions) -> DynamicModule {
Self::registerAsync(options)
}
fn createAsyncProviders(options: CacheModuleAsyncOptions) -> Vec<Provider> {
if options.useExisting.is_some() || options.useFactory {
return vec![Self::createAsyncOptionsProvider(options)];
}
let use_class = options.useClass.clone().unwrap_or_default();
vec![
Self::createAsyncOptionsProvider(options),
Provider::class(use_class),
]
}
fn createAsyncOptionsProvider(options: CacheModuleAsyncOptions) -> Provider {
if options.useFactory {
return Provider::factory(crate::cache_constants::CACHE_MODULE_OPTIONS, options.inject);
}
Provider::factory(
crate::cache_constants::CACHE_MODULE_OPTIONS,
vec![
options
.useExisting
.unwrap_or_else(|| options.useClass.unwrap_or_default()),
],
)
}
}