use serde::Deserialize; use crate::error::{CoreError, CoreResult}; #[derive(Deserialize, Clone, Debug)] #[serde(rename_all = "lowercase")] pub enum DatabaseType { Postgres, Sqlite, } #[derive(Deserialize, Clone, Debug)] pub struct DatabaseConfig { pub db_type: DatabaseType, pub url: String, } #[derive(Deserialize, Clone, Debug)] #[serde(rename_all = "lowercase")] pub enum ThumbnailFormat { Jpeg, Webp, } #[derive(Deserialize, Clone, Debug)] pub struct ThumbnailConfig { pub format: ThumbnailFormat, pub quality: u8, pub width: u32, pub height: u32, pub library_path: String, } #[derive(Deserialize, Clone, Debug)] pub struct Config { pub database_url: String, pub database_db_type: DatabaseType, pub server_address: String, pub jwt_secret: String, pub media_library_path: String, pub broker_url: String, #[serde(default = "default_max_upload_size")] pub max_upload_size_mb: u32, #[serde(default = "default_storage_quota")] pub default_storage_quota_gb: u64, #[serde(default = "default_allowed_sort_columns")] pub allowed_sort_columns: Vec, pub thumbnail_config: Option, } fn default_max_upload_size() -> u32 { 100 } fn default_storage_quota() -> u64 { 10 } fn default_allowed_sort_columns() -> Vec { vec!["created_at".to_string(), "original_filename".to_string()] } #[derive(Clone, Debug)] pub struct AppConfig { pub database: DatabaseConfig, pub server_address: String, pub jwt_secret: String, pub media_library_path: String, pub broker_url: String, pub max_upload_size_mb: Option, pub default_storage_quota_gb: Option, pub allowed_sort_columns: Option>, pub thumbnail_config: Option, } pub fn load_config() -> CoreResult { let env_path = dotenvy::dotenv() .map_err(|e| CoreError::Config(format!("Failed to load .env file: {}", e)))?; println!("Loaded config from {}", env_path.display()); let config = config::Config::builder() .add_source( config::Environment::default() .with_list_parse_key("allowed_sort_columns") .list_separator(",") .try_parsing(true) .separator("__"), ) .build() .map_err(|e| CoreError::Config(format!("Failed to build config: {}", e)))?; let config: Config = config .try_deserialize() .map_err(|e| CoreError::Config(format!("Failed to deserialize config: {}", e)))?; Ok(AppConfig { database: DatabaseConfig { db_type: config.database_db_type, url: config.database_url, }, server_address: config.server_address, jwt_secret: config.jwt_secret, media_library_path: config.media_library_path, broker_url: config.broker_url, max_upload_size_mb: Some(config.max_upload_size_mb), default_storage_quota_gb: Some(config.default_storage_quota_gb), allowed_sort_columns: Some(config.allowed_sort_columns), thumbnail_config: config.thumbnail_config, }) }