systemprompt_models/config/
mod.rs1use 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}