systemprompt_loader/
services_bootstrap.rs1use std::path::Path;
14use std::sync::OnceLock;
15
16use systemprompt_models::services::{GatewayConfig, ProviderRegistry, ServicesConfig};
17
18use crate::config_loader::ConfigLoader;
19use crate::error::{ConfigLoadError, ConfigLoadResult};
20
21static SERVICES: OnceLock<ServicesConfig> = OnceLock::new();
22
23#[derive(Debug, Clone, Copy)]
24pub struct ServicesBootstrap;
25
26impl ServicesBootstrap {
27 pub fn init() -> ConfigLoadResult<&'static ServicesConfig> {
28 if SERVICES.get().is_some() {
29 return Err(ConfigLoadError::AlreadyInitialized);
30 }
31 let services = ConfigLoader::load()?;
32 Self::install(services)
33 }
34
35 pub fn init_from_path(path: &Path) -> ConfigLoadResult<&'static ServicesConfig> {
36 if SERVICES.get().is_some() {
37 return Err(ConfigLoadError::AlreadyInitialized);
38 }
39 let services = ConfigLoader::load_from_path(path)?;
40 Self::install(services)
41 }
42
43 pub fn try_init() -> ConfigLoadResult<&'static ServicesConfig> {
44 if let Some(services) = SERVICES.get() {
45 return Ok(services);
46 }
47 Self::init()
48 }
49
50 pub fn get() -> ConfigLoadResult<&'static ServicesConfig> {
51 SERVICES.get().ok_or(ConfigLoadError::NotInitialized)
52 }
53
54 pub fn providers() -> ConfigLoadResult<&'static ProviderRegistry> {
55 Self::get().map(|s| &s.providers)
56 }
57
58 pub fn gateway() -> ConfigLoadResult<Option<&'static GatewayConfig>> {
59 Self::get().map(ServicesConfig::gateway_config)
60 }
61
62 #[must_use]
63 pub fn is_initialized() -> bool {
64 SERVICES.get().is_some()
65 }
66
67 fn install(services: ServicesConfig) -> ConfigLoadResult<&'static ServicesConfig> {
68 SERVICES
69 .set(services)
70 .map_err(|_already| ConfigLoadError::AlreadyInitialized)?;
71 SERVICES.get().ok_or(ConfigLoadError::NotInitialized)
72 }
73}