rskit_config/app.rs
1//! Service-application config convenience trait.
2
3use crate::ServiceConfig;
4
5/// Trait that every application config struct must implement.
6///
7/// Typically implemented by a struct that embeds [`ServiceConfig`] and adds service-specific fields.
8///
9/// ```no_run
10/// use rskit_config::{AppConfig, ConfigLoader, SecretString, ServiceConfig};
11/// use rskit_validation::Validate;
12///
13/// #[derive(serde::Deserialize)]
14/// struct MyConfig {
15/// #[serde(flatten)]
16/// service: ServiceConfig,
17/// grpc_port: u16,
18/// api_token: SecretString,
19/// }
20///
21/// impl Validate for MyConfig {
22/// fn validate(&self) -> Result<(), validator::ValidationErrors> {
23/// self.service.validate()?;
24/// if self.grpc_port == 0 {
25/// let mut errors = validator::ValidationErrors::new();
26/// errors.add("grpc_port", validator::ValidationError::new("range"));
27/// return Err(errors);
28/// }
29/// Ok(())
30/// }
31/// }
32///
33/// impl AppConfig for MyConfig {
34/// fn apply_defaults(&mut self) {
35/// if self.grpc_port == 0 { self.grpc_port = 50051; }
36/// }
37/// fn service_config(&self) -> &ServiceConfig { &self.service }
38/// }
39///
40/// # fn main() -> rskit_errors::AppResult<()> {
41/// let cfg: MyConfig = ConfigLoader::app().load_app()?;
42/// assert_eq!(cfg.api_token.to_string(), "***");
43/// # Ok(())
44/// # }
45/// ```
46pub trait AppConfig:
47 serde::de::DeserializeOwned + rskit_validation::Validate + Send + Sync + 'static
48{
49 /// Apply any programmatic defaults after deserialization.
50 fn apply_defaults(&mut self);
51 /// Return a reference to the embedded [`ServiceConfig`].
52 fn service_config(&self) -> &ServiceConfig;
53}