feat: init
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
use crate::error::{AppError, AppResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
pub static GLOBAL_CONFIG: OnceCell<AppConfig> = OnceCell::const_new();
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct AppConfig {
|
||||
pub env: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl AppConfig {
|
||||
pub fn main_domain(&self) -> AppResult<String> {
|
||||
self.get_env::<String>("APP_MAIN_DOMAIN")?
|
||||
.filter(|s| !s.is_empty())
|
||||
.ok_or_else(|| AppError::Config("APP_MAIN_DOMAIN is not set".into()))
|
||||
}
|
||||
|
||||
pub const ENV_FILES: &'static [&'static str] = &[
|
||||
".env",
|
||||
".env.local",
|
||||
".env.development",
|
||||
".env.development.local",
|
||||
".env.test",
|
||||
".env.test.local",
|
||||
".env.production",
|
||||
".env.production.local",
|
||||
];
|
||||
pub fn get_env<T: FromStr>(&self, key: &str) -> AppResult<Option<T>>
|
||||
where
|
||||
<T as FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
match self.env.get(key) {
|
||||
Some(v) if !v.is_empty() => Ok(Some(
|
||||
v.parse::<T>().map_err(|e| AppError::Parse(e.to_string()))?,
|
||||
)),
|
||||
Some(_) => Ok(None),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_env_or<T: FromStr>(&self, key: &str, default: T) -> AppResult<T>
|
||||
where
|
||||
<T as FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
Ok(self.get_env(key)?.unwrap_or(default))
|
||||
}
|
||||
|
||||
pub fn load() -> AppConfig {
|
||||
let mut env = HashMap::new();
|
||||
for env_file in AppConfig::ENV_FILES {
|
||||
if let Err(e) = dotenvy::from_path(env_file) {
|
||||
tracing::debug!(file = %env_file, error = %e, "dotenv load skipped");
|
||||
}
|
||||
if let Ok(env_file_content) = std::fs::read_to_string(env_file) {
|
||||
for line in env_file_content.lines() {
|
||||
if let Some((key, value)) = line.split_once('=') {
|
||||
env.insert(key.to_string(), value.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
env = env.into_iter().chain(std::env::vars()).collect();
|
||||
let this = AppConfig { env };
|
||||
if let Some(config) = GLOBAL_CONFIG.get() {
|
||||
config.clone()
|
||||
} else {
|
||||
let _ = GLOBAL_CONFIG.set(this);
|
||||
GLOBAL_CONFIG
|
||||
.get()
|
||||
.expect("global config should be set after load")
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod aiprovider;
|
||||
pub mod app;
|
||||
pub mod channelaiprovider;
|
||||
pub mod database;
|
||||
pub mod embedaiprovider;
|
||||
pub mod etcd;
|
||||
pub mod lru;
|
||||
pub mod nats;
|
||||
pub mod qdrant;
|
||||
pub mod redis;
|
||||
pub mod rpc;
|
||||
pub mod s3;
|
||||
Reference in New Issue
Block a user