use figment::{ providers::{Format, Json, Yaml}, Figment, }; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use crate::{ auth::AppAuthConfig, dal::config::AppDalConfig, extract::mikan::AppMikanConfig, graphql::config::AppGraphQLConfig, }; const DEFAULT_APP_SETTINGS_MIXIN: &str = include_str!("./settings_mixin.yaml"); #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct AppConfig { pub auth: AppAuthConfig, pub dal: AppDalConfig, pub mikan: AppMikanConfig, pub graphql: AppGraphQLConfig, } pub fn deserialize_key_path_from_json_value( value: &serde_json::Value, key_path: &[&str], ) -> Result, loco_rs::Error> { let mut stack = vec![("", value)]; for key in key_path { let current = stack.last().unwrap().1; if let Some(v) = current.get(key) { stack.push((key, v)); } else { return Ok(None); } } let result: T = serde_json::from_value(stack.pop().unwrap().1.clone())?; Ok(Some(result)) } pub fn deserialize_key_path_from_app_config( app_config: &loco_rs::config::Config, key_path: &[&str], ) -> Result, loco_rs::Error> { let settings = app_config.settings.as_ref(); if let Some(settings) = settings { deserialize_key_path_from_json_value(settings, key_path) } else { Ok(None) } } pub trait AppConfigExt { fn get_root_conf(&self) -> &loco_rs::config::Config; fn get_app_conf(&self) -> loco_rs::Result { let settings_str = self .get_root_conf() .settings .as_ref() .map(serde_json::to_string) .unwrap_or_else(|| Ok(String::new()))?; let app_config = Figment::from(Json::string(&settings_str)) .merge(Yaml::string(DEFAULT_APP_SETTINGS_MIXIN)) .extract() .map_err(loco_rs::Error::wrap)?; Ok(app_config) } } impl AppConfigExt for loco_rs::config::Config { fn get_root_conf(&self) -> &loco_rs::config::Config { self } }