use crate::environment::Environment;
use serde::Deserialize;
pub use doido_core::logger::LoggerConfig;
#[derive(Debug, Clone, Deserialize)]
pub struct DatabaseConfig {
pub url: String,
}
impl Default for DatabaseConfig {
fn default() -> Self {
Self {
url: "sqlite://db/development.db".to_string(),
}
}
}
pub trait Config: Send + Sync {
fn database(&self) -> &DatabaseConfig;
fn logger(&self) -> &LoggerConfig;
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct YamlConfig {
#[serde(default)]
pub database: DatabaseConfig,
#[serde(default)]
pub logger: LoggerConfig,
}
impl Config for YamlConfig {
fn database(&self) -> &DatabaseConfig {
&self.database
}
fn logger(&self) -> &LoggerConfig {
&self.logger
}
}
impl YamlConfig {
pub fn load() -> std::io::Result<Self> {
Self::load_env(Environment::get_env())
}
pub fn load_env(env: Environment) -> std::io::Result<Self> {
let path = format!("config/{}.yml", env.as_str());
let contents = std::fs::read_to_string(&path)?;
Self::from_yaml(&contents)
}
pub fn from_yaml(yaml: &str) -> std::io::Result<Self> {
serde_norway::from_str(yaml)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
}
}
pub fn load() -> Box<dyn Config> {
Box::new(YamlConfig::load().unwrap_or_default())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_database_url_and_ignores_other_sections() {
let yaml = "server:\n bind: 0.0.0.0\n port: 3000\ndatabase:\n url: postgres://localhost/app_development\n";
let config = YamlConfig::from_yaml(yaml).unwrap();
assert_eq!(
config.database().url,
"postgres://localhost/app_development"
);
}
#[test]
fn defaults_when_database_section_absent() {
let config = YamlConfig::from_yaml("server:\n port: 3000\n").unwrap();
assert_eq!(config.database().url, "sqlite://db/development.db");
}
}