84 lines
2.4 KiB
Rust
84 lines
2.4 KiB
Rust
|
|
use std::path::Path;
|
||
|
|
|
||
|
|
use serde_json::Value;
|
||
|
|
|
||
|
|
use crate::error::{ConfigError, Result};
|
||
|
|
use crate::format::{self, ConfigLoader};
|
||
|
|
|
||
|
|
/// Extensiones adicionales para ConfigLoader
|
||
|
|
pub trait ConfigLoaderExt: ConfigLoader {
|
||
|
|
/// Carga la configuración como JSON genérico (sin deserializar a tipo
|
||
|
|
/// específico)
|
||
|
|
fn load_as_json() -> Result<Value> {
|
||
|
|
let service = Self::service_name();
|
||
|
|
|
||
|
|
// Intenta cargar desde la jerarquía
|
||
|
|
if let Some(path) = crate::hierarchy::resolve_config_path(service) {
|
||
|
|
return format::load_config(&path);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fallback a defaults
|
||
|
|
tracing::debug!("No config file found for {} - using empty object", service);
|
||
|
|
Ok(Value::Object(serde_json::Map::new()))
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Valida si la configuración está disponible
|
||
|
|
fn is_available() -> bool {
|
||
|
|
crate::hierarchy::resolve_config_path(Self::service_name()).is_some()
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Obtiene el archivo de configuración que se usaría
|
||
|
|
fn config_path() -> Option<std::path::PathBuf> {
|
||
|
|
crate::hierarchy::resolve_config_path(Self::service_name())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Implementa ConfigLoaderExt automáticamente para todos los ConfigLoader
|
||
|
|
impl<T: ConfigLoader> ConfigLoaderExt for T {}
|
||
|
|
|
||
|
|
/// Utilidad para cargar y validar configuraciones genéricamente
|
||
|
|
pub struct ConfigValidator;
|
||
|
|
|
||
|
|
impl ConfigValidator {
|
||
|
|
/// Valida que un archivo de configuración sea válido
|
||
|
|
pub fn validate_file<P: AsRef<Path>>(path: P) -> Result<()> {
|
||
|
|
let _ = format::load_config(path)?;
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Valida que el servicio tenga una configuración disponible
|
||
|
|
pub fn validate_service<T: ConfigLoader>() -> Result<()> {
|
||
|
|
T::load().map(|_| ()).map_err(|e| {
|
||
|
|
ConfigError::validation_failed(format!(
|
||
|
|
"Service {} validation failed: {}",
|
||
|
|
T::service_name(),
|
||
|
|
e
|
||
|
|
))
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Valida múltiples servicios en paralelo
|
||
|
|
pub fn validate_services(
|
||
|
|
services: Vec<(&'static str, fn() -> Result<()>)>,
|
||
|
|
) -> Result<Vec<(String, Result<()>)>> {
|
||
|
|
let mut results = Vec::new();
|
||
|
|
|
||
|
|
for (service_name, validator) in services {
|
||
|
|
let result = validator();
|
||
|
|
results.push((service_name.to_string(), result));
|
||
|
|
}
|
||
|
|
|
||
|
|
Ok(results)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use super::*;
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_config_validator_creates() {
|
||
|
|
let _ = ConfigValidator;
|
||
|
|
}
|
||
|
|
}
|