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}