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