-
-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathmod.rs
More file actions
134 lines (115 loc) · 2.95 KB
/
mod.rs
File metadata and controls
134 lines (115 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::{env, fmt::Display, fs, ops::Deref, path::Path, sync::OnceLock};
use auth::AuthConfig;
use serde::Deserialize;
use aiscript_vm::AiConfig;
use db::DatabaseConfig;
pub use sso::{SsoConfig, get_sso_fields};
mod auth;
mod db;
mod sso;
#[cfg(test)]
mod tests;
static CONFIG: OnceLock<Config> = OnceLock::new();
// Custom string type that handles environment variable substitution
#[derive(Debug, Clone, Deserialize)]
#[serde(from = "String")]
pub struct EnvString(String);
impl From<String> for EnvString {
fn from(s: String) -> Self {
if let Some(env_key) = s.strip_prefix('$') {
match env::var(env_key) {
Ok(val) => EnvString(val),
Err(_) => {
// If env var is not found, use the original string
// This allows for better error handling at runtime
EnvString(s)
}
}
} else {
EnvString(s)
}
}
}
impl Display for EnvString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<EnvString> for String {
fn from(s: EnvString) -> Self {
s.0
}
}
impl Deref for EnvString {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<str> for EnvString {
fn as_ref(&self) -> &str {
&self.0
}
}
#[derive(Debug, Deserialize, Default)]
pub struct Config {
#[serde(default)]
pub ai: AiConfig,
#[serde(default)]
pub database: DatabaseConfig,
#[serde(default)]
pub apidoc: ApiDocConfig,
#[serde(default)]
pub auth: AuthConfig,
#[serde(default)]
pub sso: SsoConfig,
}
#[derive(Debug, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum ApiDocType {
Swagger,
#[default]
Redoc,
}
#[derive(Debug, Deserialize)]
pub struct ApiDocConfig {
pub enabled: bool,
#[serde(rename = "type", default)]
pub doc_type: ApiDocType,
#[serde(default = "default_path")]
pub path: String,
}
fn default_path() -> String {
"/doc".to_string()
}
impl Default for ApiDocConfig {
fn default() -> Self {
Self {
enabled: true,
doc_type: ApiDocType::default(),
path: default_path(),
}
}
}
impl Config {
fn new(source: impl AsRef<Path>) -> Result<Self, Box<dyn std::error::Error>> {
let path = source.as_ref();
if path.exists() {
let content = fs::read_to_string(path)?;
Ok(toml::from_str(&content)?)
} else {
Ok(Config::default())
}
}
pub fn load() -> &'static Config {
CONFIG.get_or_init(|| {
Config::new("project.toml").unwrap_or_else(|e| {
eprintln!("Error loading config file: {}", e);
Config::default()
})
})
}
pub fn get() -> &'static Config {
CONFIG.get().expect("Config not initialized")
}
}