use figment::Figment;
use figment::providers::{Env, Format, Serialized, Toml};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
#[serde(default)]
pub issuer: Option<String>,
#[serde(default = "default_format")]
pub format: String,
}
fn default_format() -> String {
"human".into()
}
impl Default for Config {
fn default() -> Self {
Config {
issuer: None,
format: default_format(),
}
}
}
fn user_home_dir() -> Option<PathBuf> {
std::env::var_os("HOME")
.or_else(|| std::env::var_os("USERPROFILE"))
.map(PathBuf::from)
}
pub fn load(project_root: Option<&Path>) -> crate::Result<Config> {
let mut figment = Figment::new().merge(Serialized::defaults(Config::default()));
if let Some(home) = user_home_dir() {
let user_config = home.join(".config").join("qualifier").join("config.toml");
figment = figment.merge(Toml::file(user_config));
}
if let Some(root) = project_root {
let project_config = root.join(".qualifier.toml");
figment = figment.merge(Toml::file(project_config));
}
figment = figment.merge(Env::prefixed("QUALIFIER_"));
figment
.extract()
.map_err(|e| crate::Error::Validation(format!("invalid configuration: {e}")))
}