use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
const DEFAULT_API_URL: &str = "https://api.harmont.dev";
pub fn user_config_dir() -> Result<PathBuf> {
hm_util::dirs::harmont_config_dir().context("could not determine home directory")
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Preferences {
pub format: Option<String>,
pub auto_watch: Option<bool>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Config {
pub api_url: Option<String>,
pub org: Option<String>,
#[serde(default)]
pub preferences: Preferences,
}
impl Config {
pub fn path() -> Result<PathBuf> {
Ok(user_config_dir()?.join("config.toml"))
}
pub fn load() -> Result<Self> {
let path = Self::path()?;
if !path.exists() {
return Ok(Self::default());
}
let contents = std::fs::read_to_string(&path)
.with_context(|| format!("reading {}", path.display()))?;
let config: Self =
toml::from_str(&contents).with_context(|| format!("parsing {}", path.display()))?;
Ok(config)
}
pub fn save(&self) -> Result<()> {
let path = Self::path()?;
let serialized = toml::to_string_pretty(self).context("serializing config")?;
hm_util::os::fs::blocking::write_atomic_restricted(
&path,
serialized.as_bytes(),
0o644,
0o700,
)
.with_context(|| format!("writing {}", path.display()))?;
Ok(())
}
#[must_use]
pub fn api_url(&self) -> &str {
self.api_url.as_deref().unwrap_or(DEFAULT_API_URL)
}
}