use std::{env, path::Path};
use fraiseql_error::ConfigError;
use crate::config::{RuntimeConfig, validation::ConfigValidator};
impl RuntimeConfig {
pub fn from_file(path: impl AsRef<Path>) -> Result<Self, ConfigError> {
let path = path.as_ref();
let content = std::fs::read_to_string(path).map_err(|e| ConfigError::ReadError {
path: path.to_path_buf(),
source: e,
})?;
let config: RuntimeConfig =
toml::from_str(&content).map_err(|e| ConfigError::ParseError { source: e })?;
let validation = ConfigValidator::new(&config).validate();
let warnings = validation.into_result()?;
for warning in warnings {
tracing::warn!("Configuration warning: {}", warning);
}
Ok(config)
}
pub fn load() -> Result<Self, ConfigError> {
if let Ok(path) = env::var("FRAISEQL_CONFIG") {
return Self::from_file(&path);
}
let local_config = Path::new("./fraiseql.toml");
if local_config.exists() {
return Self::from_file(local_config);
}
if let Some(config_dir) = dirs::config_dir() {
let user_config = config_dir.join("fraiseql/config.toml");
if user_config.exists() {
return Self::from_file(&user_config);
}
}
Err(ConfigError::NotFound)
}
pub fn load_with_path(path: Option<&Path>) -> Result<Self, ConfigError> {
match path {
Some(p) => Self::from_file(p),
None => Self::load(),
}
}
pub fn validate_syntax(content: &str) -> Result<(), ConfigError> {
let _config: RuntimeConfig =
toml::from_str(content).map_err(|e| ConfigError::ParseError { source: e })?;
Ok(())
}
}