use config::{Config, Environment};
use lazy_static::{__Deref, lazy_static};
use serde::{Deserialize, Serialize};
use std::path::Path;
use std::sync::RwLock;
use super::error::Result;
use crate::types::LogLevel;
lazy_static! {
pub static ref CONFIG: RwLock<Config> = RwLock::new(Config::builder().build().unwrap());
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AppConfig {
pub debug: bool,
pub log_level: LogLevel,
pub openai_key: String,
}
impl AppConfig {
pub fn init(default_config: Option<&str>) -> Result<()> {
let mut settings = Config::builder().build()?;
if let Some(config_contents) = default_config {
settings.merge(config::File::from_str(
config_contents,
config::FileFormat::Toml,
))?;
}
settings.merge(Environment::with_prefix("APP"))?; {
let mut w = CONFIG.write()?;
*w = settings;
}
Ok(())
}
pub fn merge_args(args: clap::ArgMatches) -> Result<()> {
if args.contains_id("debug") {
let value: &str = *args.get_one("debug").unwrap();
AppConfig::set("debug", &value.to_string())?;
}
if args.contains_id("log_level") {
let value: &str = *args.get_one("log_level").unwrap();
AppConfig::set("log_level", &value.to_string())?;
}
Ok(())
}
pub fn merge_config(config_file: Option<&Path>) -> Result<()> {
if let Some(config_file_path) = config_file {
{
CONFIG
.write()?
.merge(config::File::with_name(config_file_path.to_str().unwrap()))?;
}
}
Ok(())
}
pub fn set(key: &str, value: &str) -> Result<()> {
{
CONFIG.write()?.set(key, value)?;
}
Ok(())
}
pub fn get<'de, T>(key: &'de str) -> Result<T>
where
T: serde::Deserialize<'de>,
{
Ok(CONFIG.read()?.get::<T>(key)?)
}
pub fn fetch() -> Result<AppConfig> {
let r = CONFIG.read()?;
let config_clone = r.deref().clone();
let app_config: AppConfig = config_clone.into();
Ok(app_config)
}
}
impl From<Config> for AppConfig {
fn from(config: Config) -> Self {
AppConfig {
debug: config.get_bool("debug").unwrap(),
log_level: config.get::<LogLevel>("log_level").unwrap(),
openai_key: config.get::<String>("openai_key").unwrap().to_string(),
}
}
}