From 934fb31059da10fa843d96a10c37f181eaa89456 Mon Sep 17 00:00:00 2001 From: Dawid Rycerz Date: Mon, 21 Jul 2025 21:10:22 +0300 Subject: feat: add weather pooler and config --- src/config.rs | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/config.rs (limited to 'src/config.rs') diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..186ef82 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,160 @@ +use std::env; +use std::path::PathBuf; + +#[derive(Debug, Clone)] +pub struct Config { + pub database_url: String, + #[allow(dead_code)] + pub openweathermap_api_key: Option, + pub admin_token: Option, + pub server_port: u16, + pub server_host: String, + pub log_level: String, +} + +impl Config { + pub fn from_env() -> Self { + let database_url = Self::get_database_url(); + let openweathermap_api_key = env::var("OPENWEATHERMAP_API_KEY").ok(); + let admin_token = env::var("ADMIN_TOKEN").ok(); + let server_port = env::var("PORT") + .unwrap_or_else(|_| "4000".to_string()) + .parse() + .unwrap_or(4000); + let server_host = env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string()); + let log_level = env::var("LOG_LEVEL").unwrap_or_else(|_| "info".to_string()); + + Self { + database_url, + openweathermap_api_key, + admin_token, + server_port, + server_host, + log_level, + } + } + + fn get_database_url() -> String { + // First, check if DATABASE_URL is explicitly set + if let Ok(url) = env::var("DATABASE_URL") { + return url; + } + + // If not set, construct the path using XDG_DATA_HOME or fallback + let data_dir = if let Ok(xdg_data_home) = env::var("XDG_DATA_HOME") { + PathBuf::from(xdg_data_home) + } else { + // Fallback to ~/.local/share + let home = env::var("HOME") + .unwrap_or_else(|_| env::var("USERPROFILE").unwrap_or_else(|_| "/tmp".to_string())); + PathBuf::from(home).join(".local").join("share") + }; + + let db_path = data_dir.join("silmataivas").join("silmataivas.db"); + + // Ensure the directory exists + if let Some(parent) = db_path.parent() { + let _ = std::fs::create_dir_all(parent); + } + + format!("sqlite://{}", db_path.display()) + } + + #[allow(dead_code)] + pub fn validate(&self) -> Result<(), String> { + if self.openweathermap_api_key.is_none() { + return Err("OPENWEATHERMAP_API_KEY environment variable is required".to_string()); + } + Ok(()) + } + + #[allow(dead_code)] + pub fn validate_optional(&self) -> Result<(), String> { + // For optional validation (e.g., during development) + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::env; + use std::sync::Once; + + static INIT: Once = Once::new(); + + fn setup() { + INIT.call_once(|| { + // Clear all environment variables that might interfere with tests + unsafe { + env::remove_var("DATABASE_URL"); + env::remove_var("XDG_DATA_HOME"); + env::remove_var("PORT"); + env::remove_var("HOST"); + env::remove_var("LOG_LEVEL"); + } + }); + + // Clear environment variables before each test + unsafe { + env::remove_var("DATABASE_URL"); + env::remove_var("XDG_DATA_HOME"); + env::remove_var("PORT"); + env::remove_var("HOST"); + env::remove_var("LOG_LEVEL"); + } + } + + #[test] + fn test_database_url_fallback() { + setup(); + + let home = env::var("HOME").unwrap_or_else(|_| "/tmp".to_string()); + let expected_path = format!("sqlite://{home}/.local/share/silmataivas/silmataivas.db"); + + let config = Config::from_env(); + assert_eq!(config.database_url, expected_path); + } + + #[test] + fn test_database_url_xdg_data_home() { + setup(); + + unsafe { + env::set_var("XDG_DATA_HOME", "/custom/data/path"); + } + + let expected_path = "sqlite:///custom/data/path/silmataivas/silmataivas.db"; + + let config = Config::from_env(); + assert_eq!(config.database_url, expected_path); + } + + #[test] + fn test_database_url_explicit() { + setup(); + + unsafe { + env::set_var("DATABASE_URL", "sqlite:///explicit/path.db"); + } + + let config = Config::from_env(); + assert_eq!(config.database_url, "sqlite:///explicit/path.db"); + } + + #[test] + fn test_server_config() { + setup(); + + unsafe { + env::set_var("PORT", "8080"); + env::set_var("HOST", "127.0.0.1"); + env::set_var("LOG_LEVEL", "debug"); + } + + let config = Config::from_env(); + assert_eq!(config.server_port, 8080); + assert_eq!(config.server_host, "127.0.0.1"); + assert_eq!(config.log_level, "debug"); + } +} -- cgit v1.2.3