use serde::Deserialize; use secrecy::SecretString; #[derive(Debug, Deserialize, Clone)] pub struct AppConfig { pub server_port: u16, pub nats_addr: String, pub data_persistence_service_url: String, pub tushare_api_url: String, pub tushare_api_token: Option, } impl AppConfig { pub fn load() -> Result { let cfg = config::Config::builder() .add_source(config::Environment::default().separator("__")) .build()?; let cfg: Self = cfg.try_deserialize()?; if cfg.server_port == 0 { return Err(config::ConfigError::Message( "SERVER_PORT must be > 0".to_string(), )); } if cfg.nats_addr.trim().is_empty() { return Err(config::ConfigError::Message( "NATS_ADDR must not be empty".to_string(), )); } if cfg.data_persistence_service_url.trim().is_empty() { return Err(config::ConfigError::Message( "DATA_PERSISTENCE_SERVICE_URL must not be empty".to_string(), )); } if cfg.tushare_api_url.trim().is_empty() { return Err(config::ConfigError::Message( "TUSHARE_API_URL must not be empty".to_string(), )); } Ok(cfg) } }