systemprompt_models/config/
mod.rs1use std::sync::OnceLock;
10use systemprompt_traits::ConfigProvider;
11
12use crate::auth::JwtAudience;
13use crate::profile::{ContentNegotiationConfig, SecurityHeadersConfig};
14
15mod environment;
16mod paths;
17mod rate_limits;
18mod validation;
19mod verbosity;
20
21pub use environment::Environment;
22pub use paths::PathNotConfiguredError;
23pub use rate_limits::RateLimitConfig;
24pub use validation::{
25 format_path_errors, validate_optional_path, validate_postgres_url, validate_profile_paths,
26 validate_required_optional_path, validate_required_path,
27};
28pub use verbosity::VerbosityLevel;
29
30static CONFIG: OnceLock<Config> = OnceLock::new();
31
32#[derive(Debug, Clone)]
33pub struct Config {
34 pub sitename: String,
35 pub database_type: String,
36 pub database_url: String,
37 pub database_write_url: Option<String>,
38 pub github_link: String,
39 pub github_token: Option<String>,
40 pub system_path: String,
41 pub services_path: String,
42 pub bin_path: String,
43 pub skills_path: String,
44 pub settings_path: String,
45 pub content_config_path: String,
46 pub geoip_database_path: Option<String>,
47 pub web_path: String,
48 pub web_config_path: String,
49 pub web_metadata_path: String,
50 pub host: String,
51 pub port: u16,
52 pub api_server_url: String,
53 pub api_internal_url: String,
54 pub api_external_url: String,
55 pub jwt_issuer: String,
56 pub jwt_access_token_expiration: i64,
57 pub jwt_refresh_token_expiration: i64,
58 pub jwt_audiences: Vec<JwtAudience>,
59 pub use_https: bool,
60 pub rate_limits: RateLimitConfig,
61 pub cors_allowed_origins: Vec<String>,
62 pub is_cloud: bool,
63 pub content_negotiation: ContentNegotiationConfig,
64 pub security_headers: SecurityHeadersConfig,
65 pub allow_registration: bool,
66}
67
68impl Config {
69 pub fn is_initialized() -> bool {
70 CONFIG.get().is_some()
71 }
72
73 pub fn get() -> Result<&'static Self, crate::errors::ConfigError> {
74 CONFIG
75 .get()
76 .ok_or(crate::errors::ConfigError::NotInitialized)
77 }
78
79 pub fn install(config: Self) -> Result<(), Box<Self>> {
80 CONFIG.set(config).map_err(Box::new)
81 }
82}
83
84impl ConfigProvider for Config {
85 fn get(&self, key: &str) -> Option<String> {
86 match key {
87 "database_type" => Some(self.database_type.clone()),
88 "database_url" => Some(self.database_url.clone()),
89 "database_write_url" => self.database_write_url.clone(),
90 "host" => Some(self.host.clone()),
91 "port" => Some(self.port.to_string()),
92 "system_path" => Some(self.system_path.clone()),
93 "services_path" => Some(self.services_path.clone()),
94 "bin_path" => Some(self.bin_path.clone()),
95 "skills_path" => Some(self.skills_path.clone()),
96 "settings_path" => Some(self.settings_path.clone()),
97 "content_config_path" => Some(self.content_config_path.clone()),
98 "web_path" => Some(self.web_path.clone()),
99 "web_config_path" => Some(self.web_config_path.clone()),
100 "web_metadata_path" => Some(self.web_metadata_path.clone()),
101 "sitename" => Some(self.sitename.clone()),
102 "github_link" => Some(self.github_link.clone()),
103 "github_token" => self.github_token.clone(),
104 "api_server_url" => Some(self.api_server_url.clone()),
105 "api_external_url" => Some(self.api_external_url.clone()),
106 "jwt_issuer" => Some(self.jwt_issuer.clone()),
107 "is_cloud" => Some(self.is_cloud.to_string()),
108 _ => None,
109 }
110 }
111
112 fn database_url(&self) -> &str {
113 &self.database_url
114 }
115
116 fn database_write_url(&self) -> Option<&str> {
117 self.database_write_url.as_deref()
118 }
119
120 fn system_path(&self) -> &str {
121 &self.system_path
122 }
123
124 fn api_port(&self) -> u16 {
125 self.port
126 }
127
128 fn as_any(&self) -> &dyn std::any::Any {
129 self
130 }
131}