use std::env;
#[derive(Debug, Clone)]
pub struct Config {
pub server: ServerConfig,
pub database: DatabaseConfig,
pub hetzner_api_token: String,
pub vault_addr: String,
pub vault_token: String,
pub jwt_secret: String,
pub jwt_expiration_hours: u64,
}
#[derive(Debug, Clone)]
pub struct ServerConfig {
pub host: String,
pub port: u16,
pub cors_origins: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct DatabaseConfig {
pub url: String,
pub max_connections: u32,
}
impl Config {
pub fn from_env() -> Result<Self, ConfigError> {
Ok(Self {
server: ServerConfig {
host: env::var("SERVER_HOST").unwrap_or_else(|_| "0.0.0.0".to_string()),
port: env::var("SERVER_PORT")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(8081),
cors_origins: env::var("CORS_ORIGINS")
.unwrap_or_else(|_| "http://localhost:3000".to_string())
.split(',')
.map(|s| s.trim().to_string())
.collect(),
},
database: DatabaseConfig {
url: env::var("INFRA_DATABASE_URL")
.map_err(|_| ConfigError::MissingEnvVar("INFRA_DATABASE_URL".to_string()))?,
max_connections: env::var("DATABASE_MAX_CONNECTIONS")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(10),
},
hetzner_api_token: env::var("HETZNER_API_TOKEN")
.map_err(|_| ConfigError::MissingEnvVar("HETZNER_API_TOKEN".to_string()))?,
vault_addr: env::var("VAULT_ADDR")
.map_err(|_| ConfigError::MissingEnvVar("VAULT_ADDR".to_string()))?,
vault_token: env::var("VAULT_TOKEN")
.map_err(|_| ConfigError::MissingEnvVar("VAULT_TOKEN".to_string()))?,
jwt_secret: env::var("JWT_SECRET")
.map_err(|_| ConfigError::MissingEnvVar("JWT_SECRET".to_string()))?,
jwt_expiration_hours: env::var("JWT_EXPIRATION_HOURS")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(24),
})
}
}
#[derive(Debug, thiserror::Error)]
pub enum ConfigError {
#[error("Missing required environment variable: {0}")]
MissingEnvVar(String),
#[error("Invalid configuration value: {0}")]
InvalidValue(String),
}