r2_data2/
config.rs

1use std::{fmt, str::FromStr};
2
3use config::{Config, Environment, File};
4use serde::{Deserialize, Serialize};
5
6use crate::DatabaseType;
7
8#[derive(Serialize, Deserialize, Debug, Clone)]
9pub struct DatabaseConfig {
10    pub name: String,
11    #[serde(rename = "type")]
12    pub db_type: DatabaseType,
13    pub conn_string: String,
14}
15
16#[derive(Serialize, Deserialize, Debug, Clone)]
17pub struct AppConfig {
18    pub server_addr: String,
19    #[serde(default)] // Provide default empty vec if missing
20    pub databases: Vec<DatabaseConfig>,
21    pub jwt_secret: String,
22    pub allowed_origin: String,
23}
24
25impl AppConfig {
26    pub fn load() -> Result<Self, anyhow::Error> {
27        // Load configuration
28        let config = Config::builder()
29            .add_source(File::with_name("config/default"))
30            .add_source(File::with_name("config/development").required(false))
31            .add_source(Environment::with_prefix("APP").separator("__"))
32            .build()?;
33
34        let app_config: AppConfig = config.try_deserialize()?;
35        Ok(app_config)
36    }
37}
38
39impl fmt::Display for DatabaseType {
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41        match self {
42            DatabaseType::Postgres => write!(f, "postgres"),
43            DatabaseType::Mysql => write!(f, "mysql"),
44        }
45    }
46}
47
48impl FromStr for DatabaseType {
49    type Err = anyhow::Error;
50
51    fn from_str(s: &str) -> Result<Self, Self::Err> {
52        match s.to_lowercase().as_str() {
53            "postgres" | "postgresql" => Ok(DatabaseType::Postgres),
54            "mysql" | "mariadb" => Ok(DatabaseType::Mysql),
55            _ => Err(anyhow::anyhow!("Invalid database type: {}", s)),
56        }
57    }
58}