1#[derive(Debug, Clone)]
24pub struct DbkitConfig {
25 pub url: String,
27 pub pool_size: usize,
29 pub connect_timeout_secs: u64,
31 pub idle_timeout_secs: u64,
33 pub auto_create_db: bool,
35}
36
37impl DbkitConfig {
38 pub fn from_url(url: &str) -> Self {
40 Self {
41 url: url.to_string(),
42 pool_size: 16,
43 connect_timeout_secs: 30,
44 idle_timeout_secs: 300,
45 auto_create_db: true,
46 }
47 }
48
49 pub fn builder() -> ConfigBuilder {
51 ConfigBuilder::default()
52 }
53}
54
55pub struct ConfigBuilder {
57 host: String,
58 port: u16,
59 database: String,
60 user: Option<String>,
61 password: Option<String>,
62 pool_size: usize,
63 connect_timeout_secs: u64,
64 idle_timeout_secs: u64,
65 auto_create_db: bool,
66 ssl_mode: SslMode,
67}
68
69#[derive(Debug, Clone, Copy, Default)]
71pub enum SslMode {
72 #[default]
74 Disable,
75 Prefer,
77 Require,
79}
80
81impl Default for ConfigBuilder {
82 fn default() -> Self {
83 Self {
84 host: "localhost".into(),
85 port: 5432,
86 database: "postgres".into(),
87 user: None,
88 password: None,
89 pool_size: 16,
90 connect_timeout_secs: 30,
91 idle_timeout_secs: 300,
92 auto_create_db: true,
93 ssl_mode: SslMode::default(),
94 }
95 }
96}
97
98impl ConfigBuilder {
99 pub fn host(mut self, host: &str) -> Self {
100 self.host = host.to_string();
101 self
102 }
103
104 pub fn port(mut self, port: u16) -> Self {
105 self.port = port;
106 self
107 }
108
109 pub fn database(mut self, database: &str) -> Self {
110 self.database = database.to_string();
111 self
112 }
113
114 pub fn user(mut self, user: &str) -> Self {
115 self.user = Some(user.to_string());
116 self
117 }
118
119 pub fn password(mut self, password: &str) -> Self {
120 self.password = Some(password.to_string());
121 self
122 }
123
124 pub fn pool_size(mut self, size: usize) -> Self {
125 self.pool_size = size;
126 self
127 }
128
129 pub fn connect_timeout_secs(mut self, secs: u64) -> Self {
130 self.connect_timeout_secs = secs;
131 self
132 }
133
134 pub fn idle_timeout_secs(mut self, secs: u64) -> Self {
135 self.idle_timeout_secs = secs;
136 self
137 }
138
139 pub fn auto_create_db(mut self, enabled: bool) -> Self {
140 self.auto_create_db = enabled;
141 self
142 }
143
144 pub fn ssl_mode(mut self, mode: SslMode) -> Self {
145 self.ssl_mode = mode;
146 self
147 }
148
149 pub fn build(self) -> DbkitConfig {
151 let auth = match (&self.user, &self.password) {
152 (Some(u), Some(p)) => format!("{}:{}@", u, p),
153 (Some(u), None) => format!("{}@", u),
154 _ => String::new(),
155 };
156
157 let ssl_param = match self.ssl_mode {
158 SslMode::Disable => "",
159 SslMode::Prefer => "?sslmode=prefer",
160 SslMode::Require => "?sslmode=require",
161 };
162
163 let url = format!(
164 "postgres://{}{}:{}/{}{}",
165 auth, self.host, self.port, self.database, ssl_param
166 );
167
168 DbkitConfig {
169 url,
170 pool_size: self.pool_size,
171 connect_timeout_secs: self.connect_timeout_secs,
172 idle_timeout_secs: self.idle_timeout_secs,
173 auto_create_db: self.auto_create_db,
174 }
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn test_from_url() {
184 let config = DbkitConfig::from_url("postgres://localhost/mydb");
185 assert_eq!(config.url, "postgres://localhost/mydb");
186 assert_eq!(config.pool_size, 16);
187 assert!(config.auto_create_db);
188 }
189
190 #[test]
191 fn test_builder_full() {
192 let config = DbkitConfig::builder()
193 .host("db.example.com")
194 .port(5433)
195 .database("myapp")
196 .user("admin")
197 .password("secret")
198 .pool_size(32)
199 .connect_timeout_secs(10)
200 .ssl_mode(SslMode::Require)
201 .build();
202
203 assert_eq!(
204 config.url,
205 "postgres://admin:secret@db.example.com:5433/myapp?sslmode=require"
206 );
207 assert_eq!(config.pool_size, 32);
208 assert_eq!(config.connect_timeout_secs, 10);
209 }
210
211 #[test]
212 fn test_builder_minimal() {
213 let config = DbkitConfig::builder().database("test").build();
214 assert_eq!(config.url, "postgres://localhost:5432/test");
215 }
216
217 #[test]
218 fn test_builder_user_no_password() {
219 let config = DbkitConfig::builder()
220 .user("readonly")
221 .database("prod")
222 .build();
223 assert_eq!(config.url, "postgres://readonly@localhost:5432/prod");
224 }
225}