Skip to main content

systemprompt_models/config/
mod.rs

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