Skip to main content

shared/config/boot/
database.rs

1use secrecy::{ExposeSecret, SecretString};
2use utoipa::ToSchema;
3
4#[derive(
5    Debug, Default, Clone, Copy, serde::Deserialize, serde::Serialize, Eq, PartialEq, ToSchema,
6)]
7pub enum DatabaseDriver {
8    #[default]
9    SQLite,
10    PostgreSQL,
11    MongoDB,
12}
13
14impl DatabaseDriver {
15    pub fn as_str(&self) -> &'static str {
16        match self {
17            DatabaseDriver::SQLite => "sqlite",
18            DatabaseDriver::MongoDB => "mongodb",
19            DatabaseDriver::PostgreSQL => "postgresql",
20        }
21    }
22    pub fn name(&self) -> &'static str {
23        match self {
24            DatabaseDriver::SQLite => "SQLite",
25            DatabaseDriver::MongoDB => "MongoDB",
26            DatabaseDriver::PostgreSQL => "PostgreSQL",
27        }
28    }
29    pub fn _is_sql(&self) -> bool {
30        matches!(self, DatabaseDriver::SQLite | DatabaseDriver::PostgreSQL)
31    }
32
33    pub fn _is_nosql(&self) -> bool {
34        matches!(self, DatabaseDriver::MongoDB)
35    }
36}
37impl std::fmt::Display for DatabaseDriver {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        write!(f, "{}", self.as_str())
40    }
41}
42impl TryFrom<String> for DatabaseDriver {
43    type Error = String;
44
45    fn try_from(s: String) -> Result<Self, Self::Error> {
46        match s.to_lowercase().as_str() {
47            "sqlite" => Ok(Self::SQLite),
48            "mongodb" => Ok(Self::MongoDB),
49            "postgresql" => Ok(Self::PostgreSQL),
50            other => Err(format!(
51                "{} is not supported database. Use either `sqlite`, `postgresql` or `mongodb`",
52                other
53            )),
54        }
55    }
56}
57
58#[derive(Default, Debug, serde::Deserialize)]
59pub struct DatabaseConfig {
60    pub username: String,
61    pub password: SecretString,
62    pub port: String,
63    pub host: String,
64    pub name: String,
65    pub driver: DatabaseDriver,
66}
67
68impl DatabaseConfig {
69    pub fn connection_string(&self) -> String {
70        match self.driver {
71            DatabaseDriver::MongoDB => {
72                // mongodb+srv://<username>:<password>@<host>:<port>/<db_name>
73                // test: mongodb://localhost:27017/dev
74                // prod: mongodb://db:27017/production
75                format!(
76                    "mongodb://{}:{}@{}:{}/{}?retryWrites=false&authSource=admin",
77                    self.username,
78                    self.password.expose_secret(),
79                    self.host,
80                    self.port,
81                    self.name
82                )
83            }
84            DatabaseDriver::SQLite => self.name.to_string(),
85            DatabaseDriver::PostgreSQL => {
86                format!(
87                    "postgres://{}:{}@{}:{}/{}",
88                    self.username,
89                    self.password.expose_secret(),
90                    self.host,
91                    self.port,
92                    self.name
93                )
94            }
95        }
96    }
97
98    pub fn is_sql(&self) -> bool {
99        matches!(
100            self.driver,
101            DatabaseDriver::SQLite | DatabaseDriver::PostgreSQL
102        )
103    }
104
105    pub fn is_nosql(&self) -> bool {
106        matches!(self.driver, DatabaseDriver::MongoDB)
107    }
108}