use std::path::PathBuf;
fn home() -> PathBuf {
PathBuf::from(std::env::var("HOME").unwrap_or_else(|_| ".".into()))
}
fn base(xdg_env: &str, xdg_default: &str, root_sub: &str) -> PathBuf {
if let Ok(root) = std::env::var("IMPYARD_ROOT") {
return PathBuf::from(root).join(root_sub);
}
std::env::var(xdg_env)
.map(PathBuf::from)
.unwrap_or_else(|_| home().join(xdg_default))
.join("impyard")
}
pub fn config_root() -> PathBuf {
base("XDG_CONFIG_HOME", ".config", "config")
}
pub fn data_root() -> PathBuf {
base("XDG_DATA_HOME", ".local/share", "data")
}
pub fn state_root() -> PathBuf {
base("XDG_STATE_HOME", ".local/state", "state")
}
pub fn short_imp(imp: &str) -> &str {
imp.rsplit('/').next().unwrap_or(imp)
}
pub fn org_file() -> PathBuf {
config_root().join("org.toml")
}
pub fn providers_file() -> PathBuf {
config_root().join("providers.toml")
}
pub fn connections_dir() -> PathBuf {
config_root().join("connections")
}
pub fn imps_dir() -> PathBuf {
config_root().join("imps")
}
pub fn imp_dir(name: &str) -> PathBuf {
imps_dir().join(short_imp(name))
}
pub fn vault_dir() -> PathBuf {
if let Ok(dir) = std::env::var("IMPYARD_VAULT_DIR") {
return PathBuf::from(dir);
}
data_root().join("vault")
}
pub fn ca_dir() -> PathBuf {
if let Ok(dir) = std::env::var("IMPYARD_CA_DIR") {
return PathBuf::from(dir);
}
data_root().join("ca")
}
pub fn imps_data_dir() -> PathBuf {
data_root().join("imps")
}
pub fn imp_data_dir(imp: &str) -> PathBuf {
imps_data_dir().join(short_imp(imp))
}
pub fn imp_queue_dir(imp: &str) -> PathBuf {
imp_data_dir(imp).join("queue")
}
pub fn imp_journal_file(imp: &str) -> PathBuf {
imp_data_dir(imp).join("journal").join("events.jsonl")
}
pub fn imp_memory_file(imp: &str) -> PathBuf {
imp_data_dir(imp).join("memory.jsonl")
}
pub fn imp_notes_legacy_file(imp: &str) -> PathBuf {
imp_data_dir(imp).join("notes-legacy.jsonl")
}
pub fn imp_knowledge_dir(imp: &str) -> PathBuf {
imp_data_dir(imp).join("knowledge")
}
pub fn imp_gates_pending_dir(imp: &str) -> PathBuf {
imp_data_dir(imp).join("gates").join("pending")
}
pub fn imp_gates_resolved_dir(imp: &str) -> PathBuf {
imp_data_dir(imp).join("gates").join("resolved")
}
pub fn channels_dir() -> PathBuf {
data_root().join("channels")
}
pub fn channel_dir(channel_id: &str) -> PathBuf {
channels_dir().join(channel_id)
}
fn audit_dir() -> PathBuf {
data_root().join("audit")
}
pub fn decisions_log() -> PathBuf {
audit_dir().join("decisions.jsonl")
}
#[cfg_attr(test, allow(dead_code))]
pub fn usage_log() -> PathBuf {
audit_dir().join("usage.jsonl")
}
pub fn credentials_log() -> PathBuf {
audit_dir().join("credentials.jsonl")
}
pub fn messages_log() -> PathBuf {
audit_dir().join("messages.jsonl")
}
pub fn runs_dir() -> PathBuf {
state_root().join("runs")
}
pub fn run_dir(run_id: &str) -> PathBuf {
runs_dir().join(run_id)
}
pub fn identity_dir() -> PathBuf {
state_root().join("identity")
}
pub fn locks_dir() -> PathBuf {
state_root().join("locks")
}
pub fn imp_listener_lock(imp: &str) -> PathBuf {
locks_dir().join(format!("{}.lock", short_imp(imp)))
}
pub fn outbox_dir() -> PathBuf {
state_root().join("outbox")
}
pub fn trigger_state_file() -> PathBuf {
state_root().join("trigger-state.json")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn imp_handles_normalize() {
assert_eq!(imp_data_dir("yuko"), imp_data_dir("org/yuko"));
assert_eq!(imp_queue_dir("org/yuko").file_name().unwrap(), "queue");
}
}