Skip to main content

siderite_config/
settings.rs

1//! Strongly typed configuration sections.
2
3use crate::secret::Secret;
4use serde::Deserialize;
5use std::collections::BTreeMap;
6
7/// Default bind address used when no file, env, or override sets `server.addr`.
8pub const DEFAULT_SERVER_ADDR: &str = "127.0.0.1:8000";
9
10/// Default application name.
11pub const DEFAULT_APP_NAME: &str = "siderite";
12
13/// Default tracing filter when `RUST_LOG` is unset.
14pub const DEFAULT_LOG_LEVEL: &str = "info";
15
16/// Default in-memory cache capacity.
17pub const DEFAULT_CACHE_MAX_ENTRIES: usize = 1024;
18
19/// Complete application settings, produced by [`crate::ConfigBuilder`] or
20/// [`crate::load`].
21#[derive(Debug, Clone, Default, PartialEq, Deserialize)]
22pub struct Settings {
23    /// Application identity.
24    #[serde(default)]
25    pub app: AppSettings,
26    /// HTTP bind address.
27    #[serde(default)]
28    pub server: ServerSettings,
29    /// Named database connections. The `"default"` alias is the conventional
30    /// primary database.
31    #[serde(default)]
32    pub databases: BTreeMap<String, DatabaseSettings>,
33    /// Cache backend.
34    #[serde(default)]
35    pub cache: CacheSettings,
36    /// Tracing / logging.
37    #[serde(default)]
38    pub log: LogSettings,
39    /// Signing / session key, if the application uses one.
40    #[serde(default)]
41    pub secret_key: Option<Secret<String>>,
42}
43
44/// Application identity and debug flag.
45#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
46pub struct AppSettings {
47    /// Application name. Defaults to [`DEFAULT_APP_NAME`].
48    #[serde(default = "default_app_name")]
49    pub name: String,
50    /// When `true`, applications may enable extra diagnostics. Defaults to
51    /// `false`.
52    #[serde(default)]
53    pub debug: bool,
54}
55
56impl Default for AppSettings {
57    fn default() -> Self {
58        Self {
59            name: default_app_name(),
60            debug: false,
61        }
62    }
63}
64
65fn default_app_name() -> String {
66    DEFAULT_APP_NAME.to_owned()
67}
68
69/// HTTP server bind settings.
70#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
71pub struct ServerSettings {
72    /// Address passed to the listener, for example `"127.0.0.1:8000"`.
73    #[serde(default = "default_server_addr")]
74    pub addr: String,
75}
76
77impl Default for ServerSettings {
78    fn default() -> Self {
79        Self {
80            addr: default_server_addr(),
81        }
82    }
83}
84
85fn default_server_addr() -> String {
86    DEFAULT_SERVER_ADDR.to_owned()
87}
88
89/// Connection settings for one database alias.
90#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
91pub struct DatabaseSettings {
92    /// Connection URL. Never printed by [`std::fmt::Debug`].
93    pub url: Secret<String>,
94    /// Optional pool size. `None` leaves the backend default in place.
95    #[serde(default)]
96    pub max_connections: Option<u32>,
97}
98
99/// Cache backend settings.
100#[derive(Debug, Clone, PartialEq, Deserialize)]
101pub struct CacheSettings {
102    /// Optional cache URL (for example a Redis URL). Never printed by [`std::fmt::Debug`].
103    #[serde(default)]
104    pub url: Option<Secret<String>>,
105    /// Maximum in-memory entries. Defaults to [`DEFAULT_CACHE_MAX_ENTRIES`].
106    #[serde(default = "default_cache_max_entries")]
107    pub max_entries: usize,
108}
109
110impl Default for CacheSettings {
111    fn default() -> Self {
112        Self {
113            url: None,
114            max_entries: DEFAULT_CACHE_MAX_ENTRIES,
115        }
116    }
117}
118
119fn default_cache_max_entries() -> usize {
120    DEFAULT_CACHE_MAX_ENTRIES
121}
122
123/// Tracing subscriber settings.
124#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
125pub struct LogSettings {
126    /// Filter directive used when `RUST_LOG` is unset. Defaults to
127    /// [`DEFAULT_LOG_LEVEL`].
128    #[serde(default = "default_log_level")]
129    pub level: String,
130    /// When `true`, events are formatted as JSON. Defaults to `false`.
131    #[serde(default)]
132    pub json: bool,
133}
134
135impl Default for LogSettings {
136    fn default() -> Self {
137        Self {
138            level: default_log_level(),
139            json: false,
140        }
141    }
142}
143
144fn default_log_level() -> String {
145    DEFAULT_LOG_LEVEL.to_owned()
146}
147
148/// JSON object merged as the lowest-precedence provider.
149pub(crate) fn default_values() -> serde_json::Value {
150    serde_json::json!({
151        "app": {
152            "name": DEFAULT_APP_NAME,
153            "debug": false,
154        },
155        "server": {
156            "addr": DEFAULT_SERVER_ADDR,
157        },
158        "databases": {},
159        "cache": {
160            "max_entries": DEFAULT_CACHE_MAX_ENTRIES,
161        },
162        "log": {
163            "level": DEFAULT_LOG_LEVEL,
164            "json": false,
165        },
166    })
167}