use figment::{
providers::{Env, Format, Serialized, Toml},
Figment,
};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use crate::error::{Error, Result};
pub const DEFAULT_MIGRATIONS_DIR: &str = "migrations";
pub const DEFAULT_URL: &str = "http://localhost:6334";
pub const DEFAULT_TRACKING_COLLECTION: &str = "_revector_migrations";
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
#[serde(default = "default_url")]
pub url: String,
#[serde(default)]
pub api_key: Option<String>,
#[serde(default = "default_migrations_dir")]
pub migrations_dir: PathBuf,
#[serde(default = "default_tracking_collection")]
pub tracking_collection: String,
#[serde(default = "default_timeout_secs")]
pub timeout_secs: u64,
}
fn default_url() -> String {
DEFAULT_URL.to_string()
}
fn default_migrations_dir() -> PathBuf {
PathBuf::from(DEFAULT_MIGRATIONS_DIR)
}
fn default_tracking_collection() -> String {
DEFAULT_TRACKING_COLLECTION.to_string()
}
fn default_timeout_secs() -> u64 {
30
}
impl Default for Config {
fn default() -> Self {
Config {
url: default_url(),
api_key: None,
migrations_dir: default_migrations_dir(),
tracking_collection: default_tracking_collection(),
timeout_secs: default_timeout_secs(),
}
}
}
impl Config {
pub fn load(config_path: Option<&Path>) -> Result<Self> {
let mut figment = Figment::from(Serialized::defaults(Config::default()));
match config_path {
Some(path) => {
if !path.exists() {
return Err(Error::Config(format!(
"config file not found: {}",
path.display()
)));
}
figment = figment.merge(Toml::file(path));
}
None => {
let default = Path::new("revector.toml");
if default.exists() {
figment = figment.merge(Toml::file(default));
}
}
}
figment = figment.merge(Env::prefixed("REVECTOR_"));
figment.extract().map_err(|e| Error::Config(e.to_string()))
}
}