use std::env;
pub const VITE_IPC_ENV: &str = "ARCATURE_VITE_IPC";
pub const APP_IPC_ENV: &str = "ARCATURE_APP_IPC";
#[must_use]
pub fn env_or(key: &str, default: &str) -> String {
env::var(key)
.ok()
.filter(|v| !v.is_empty())
.unwrap_or_else(|| default.to_string())
}
pub fn env_required(key: &str) -> crate::Result<String> {
env::var(key)
.ok()
.filter(|v| !v.is_empty())
.ok_or_else(|| crate::Error::Config(format!("{key} is required but not set")))
}
pub fn env_parsed<T>(key: &str, default: T) -> T
where
T: std::str::FromStr,
T::Err: std::fmt::Display,
{
env::var(key)
.ok()
.filter(|v| !v.is_empty())
.and_then(|v| v.parse().ok())
.unwrap_or(default)
}
#[derive(Debug, Clone)]
pub struct AppConfig {
pub name: String,
pub url: String,
pub env: AppEnvironment,
pub port: u16,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AppEnvironment {
Development,
Production,
Test,
}
impl AppEnvironment {
#[must_use]
pub fn parse(value: &str) -> Self {
match value.to_ascii_lowercase().as_str() {
"production" | "prod" => AppEnvironment::Production,
"test" => AppEnvironment::Test,
_ => AppEnvironment::Development,
}
}
#[must_use]
pub fn is_production(self) -> bool {
matches!(self, AppEnvironment::Production)
}
#[must_use]
pub fn is_development(self) -> bool {
matches!(self, AppEnvironment::Development)
}
}
impl Default for AppConfig {
fn default() -> Self {
Self::new()
}
}
impl AppConfig {
#[must_use]
pub fn new() -> Self {
AppConfig {
name: "Arcature".to_string(),
url: "http://localhost:3000".to_string(),
env: AppEnvironment::Development,
port: 3000,
}
}
#[must_use]
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = name.into();
self
}
#[must_use]
pub fn url(mut self, url: impl Into<String>) -> Self {
self.url = url.into();
self
}
#[must_use]
pub fn environment(mut self, env: AppEnvironment) -> Self {
self.env = env;
self
}
#[must_use]
pub fn port(mut self, port: u16) -> Self {
self.port = port;
self
}
#[must_use]
pub fn from_env() -> Self {
AppConfig::new()
.name(env_or("APP_NAME", "Arcature"))
.url(env_or("APP_URL", "http://localhost:3000"))
.environment(AppEnvironment::parse(&env_or("APP_ENV", "development")))
.port(env_parsed("APP_PORT", 3000))
}
}