1use crate::error::{Error, Result};
2use std::{
3 collections::HashMap,
4 env,
5 path::{Path, PathBuf},
6};
7
8#[derive(Debug)]
9pub struct Config {
10 pub migrate_dir: PathBuf,
11 pub connection_string: String,
12}
13
14impl Config {
15 pub fn new(migrate_dir: impl AsRef<Path>, connection_string: impl AsRef<str>) -> Config {
16 let migrate_dir = migrate_dir.as_ref().to_path_buf();
17 let connection_string = connection_string.as_ref().to_owned();
18 Config {
19 migrate_dir,
20 connection_string,
21 }
22 }
23
24 pub fn from_env() -> Result<Self> {
25 let env_vars = env::vars().collect::<HashMap<String, String>>();
26 let migrate_dir = get_env("MIGRATE_DIR", &env_vars)?.into();
27 let connection_string = connection_string_from_env(&env_vars)?;
28
29 Ok(Config {
30 migrate_dir,
31 connection_string,
32 })
33 }
34}
35
36fn get_env(key: &str, vars: &HashMap<String, String>) -> Result<String> {
37 vars.get(key)
38 .map(|s| s.to_owned())
39 .ok_or(Error::MissingEnv {
40 name: key.to_owned(),
41 })
42}
43
44fn connection_string_from_env(env_vars: &HashMap<String, String>) -> Result<String> {
45 if let Ok(connection_string) = get_env("PG_CONNECTION_STRING", env_vars) {
46 Ok(connection_string)
47 } else {
48 let pg_user = get_env("PG_USER", env_vars)?;
49 let maybe_pg_password = env_vars.get("PG_PASSWORD").map(|s| s.to_owned());
50 let pg_host = get_env("PG_HOST", env_vars)?;
51 let pg_port_str = get_env("PG_PORT", env_vars)?;
52 let pg_port = pg_port_str
53 .parse::<u16>()
54 .map_err(|_| Error::BadEnvFormat {
55 name: "PG_PORT".to_string(),
56 })?;
57 let pg_db = get_env("PG_DB", env_vars)?;
58
59 let connection_string = if let Some(pg_password) = maybe_pg_password {
60 format!(
61 "postgresql://{}:{}@{}:{}/{}",
62 pg_user, pg_password, pg_host, pg_port, pg_db
63 )
64 } else {
65 format!("postgresql://{}@{}:{}/{}", pg_user, pg_host, pg_port, pg_db)
66 };
67
68 Ok(connection_string)
69 }
70}