Initial
This commit is contained in:
15
crates/erplt-config/Cargo.toml
Normal file
15
crates/erplt-config/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "erplt-config"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
camino.workspace = true
|
||||
clap.workspace = true
|
||||
serde.workspace = true
|
||||
toml.workspace = true
|
||||
anyhow.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
tracing.workspace = true
|
||||
humantime.workspace = true
|
||||
humantime-serde.workspace = true
|
||||
18
crates/erplt-config/src/config/cli.rs
Normal file
18
crates/erplt-config/src/config/cli.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use camino::Utf8PathBuf;
|
||||
|
||||
|
||||
#[derive(Debug, Clone, clap::Parser)]
|
||||
#[command(
|
||||
name = "erplt",
|
||||
about = "ERP system for European businesses",
|
||||
long_about = "ERPLT is a lightweight ERP system built for the European market.",
|
||||
)]
|
||||
pub struct Cli {
|
||||
/// Config path
|
||||
#[arg(long, short='c', default_value="config.toml")]
|
||||
pub config: Utf8PathBuf,
|
||||
|
||||
/// Debug output
|
||||
#[arg(long, short='d', default_value_t=false)]
|
||||
pub debug: bool,
|
||||
}
|
||||
107
crates/erplt-config/src/config/mod.rs
Normal file
107
crates/erplt-config/src/config/mod.rs
Normal file
@@ -0,0 +1,107 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Context;
|
||||
use camino::Utf8PathBuf;
|
||||
use serde::de;
|
||||
|
||||
pub mod cli;
|
||||
|
||||
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
|
||||
pub struct Config {
|
||||
#[serde(skip)]
|
||||
pub config_path: Utf8PathBuf,
|
||||
pub core: ConfigCore,
|
||||
pub database: ConfigDatabase,
|
||||
pub web: ConfigWeb,
|
||||
}
|
||||
|
||||
|
||||
impl Config {
|
||||
pub(crate) fn parse() -> anyhow::Result<Self> {
|
||||
if !crate::CLI.config.exists() {
|
||||
tracing::warn!("Configuration does not exist, creating at {}", crate::CLI.config.canonicalize_utf8()?);
|
||||
let tml = toml::to_string_pretty(&Config::default()).context("Invalid default config????")?;
|
||||
std::fs::write(&crate::CLI.config, tml).context("Failed to write default config, check permissions?")?;
|
||||
}
|
||||
let text = std::fs::read_to_string(&crate::CLI.config).context("Failed to read config, check permissions?")?;
|
||||
let mut tml: Self = toml::from_str(&text)?;
|
||||
|
||||
|
||||
tml.config_path = crate::CLI.config.clone();
|
||||
tml.core.debug = tml.core.debug || crate::CLI.debug;
|
||||
|
||||
|
||||
tracing::info!("Read config at {}", crate::CLI.config.canonicalize_utf8()?);
|
||||
Ok(tml)
|
||||
}
|
||||
pub fn get() -> &'static Self {
|
||||
crate::CONFIG.get().expect("Config hasnt been read and initialised yet")
|
||||
}
|
||||
pub(crate) fn load_to_global(self) {
|
||||
crate::CONFIG.set(self).expect("Config was already set globaly")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
|
||||
pub struct ConfigCore {
|
||||
pub debug: bool,
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum DatabaseType {
|
||||
#[default]
|
||||
Postgresql,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
|
||||
pub struct ConfigDatabase {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
pub database: String,
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
#[serde(rename="type")]
|
||||
pub db_type: DatabaseType,
|
||||
|
||||
pub max_pool_size: u32,
|
||||
pub min_idle: u32,
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub connection_timeout: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub idle_timeout: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub max_lifetime: Duration,
|
||||
pub test_on_check_out: bool
|
||||
}
|
||||
|
||||
impl ConfigDatabase {
|
||||
pub fn connect_url(&self) -> String {
|
||||
format!(
|
||||
"postgres://{}:{}@{}:{}/{}",
|
||||
self.username,
|
||||
self.password,
|
||||
self.host,
|
||||
self.port,
|
||||
self.database,
|
||||
)
|
||||
}
|
||||
pub fn connect_url_redacted(&self) -> String {
|
||||
format!(
|
||||
"postgres://{}:***@{}:{}/{}",
|
||||
self.username,
|
||||
self.host,
|
||||
self.port,
|
||||
self.database,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
|
||||
pub struct ConfigWeb {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
}
|
||||
20
crates/erplt-config/src/lib.rs
Normal file
20
crates/erplt-config/src/lib.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use std::sync::{LazyLock, OnceLock};
|
||||
use clap::Parser;
|
||||
mod config;
|
||||
|
||||
pub use config::Config;
|
||||
|
||||
|
||||
static CLI: LazyLock<config::cli::Cli> = LazyLock::new(config::cli::Cli::parse);
|
||||
static CONFIG: OnceLock<config::Config> = OnceLock::new();
|
||||
|
||||
pub fn init() -> anyhow::Result<()> {
|
||||
let _ = &*CLI;
|
||||
config::Config::parse()?.load_to_global();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// helper function for faster access
|
||||
pub fn get() -> &'static Config {
|
||||
Config::get()
|
||||
}
|
||||
Reference in New Issue
Block a user