confine_builder/
lib.rs

1use std::path::PathBuf;
2use config::Config;
3use serde::Deserialize;
4
5#[derive(thiserror::Error, Debug)]
6pub enum ConfineBuilderError {
7    #[error("Error with the config file.")]
8    ConfigError(#[from] config::ConfigError),
9
10    #[error("Environment variable not set correctly.")]
11    EnvVarError(#[from] std::env::VarError),
12}
13
14pub struct ConfineConfigBuilder {
15    config_path: PathBuf,
16    env_var: String,
17    prefix: String,
18}
19
20impl Default for ConfineConfigBuilder {
21    fn default() -> Self {
22        Self {
23            config_path: "config".into(),
24            env_var: "CONFINE_ENV".into(),
25            prefix: "application".into(),
26        }
27    }
28}
29
30impl ConfineConfigBuilder {
31    pub fn config_path(mut self, path: PathBuf) -> Self {
32        self.config_path = path;
33        self
34    }
35
36    pub fn env_var(mut self, env_var: String) -> Self {
37        self.env_var = env_var;
38        self
39    }
40
41    pub fn prefix(mut self, prefix: String) -> Self {
42        self.prefix = prefix;
43        self
44    }
45
46    pub fn try_load<'de, T>(self) -> Result<T, ConfineBuilderError> where T: Deserialize<'de> {
47        let local_config = self.config_path.join(format!("{}.toml", self.prefix));
48        let env = std::env::var(&self.env_var)?;
49        let env_config = self.config_path.join(format!("{}-{}.toml", self.prefix, env));
50
51        let builder = Config::builder()
52            .add_source(config::File::from(local_config))
53            .add_source(config::File::from(env_config).required(false))
54            .add_source(config::Environment::default())
55            .build()?;
56        Ok(builder.try_deserialize()?)
57    }
58}