use crate::errors::XrpcCliError;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Serialize, Deserialize, Default)]
pub struct Config {
pub accounts: Vec<Account>,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct Account {
pub handle: String,
pub did: String,
pub pds_endpoint: String,
pub app_password: String,
pub access_jwt: String,
pub refresh_jwt: String,
}
pub fn config_path() -> Result<PathBuf> {
if let Ok(path) = std::env::var("ATPXRPC_CONFIG") {
return Ok(PathBuf::from(path));
}
let config_dir = dirs::config_dir().ok_or(XrpcCliError::ConfigDirNotFound)?;
Ok(config_dir.join("atpxrpc").join("config.json"))
}
pub fn load_config() -> Result<Config> {
let path = config_path()?;
if !path.exists() {
return Ok(Config::default());
}
let content = std::fs::read_to_string(&path).map_err(|_| XrpcCliError::ConfigReadFailed {
path: path.display().to_string(),
})?;
let config: Config =
serde_json::from_str(&content).map_err(|_| XrpcCliError::ConfigReadFailed {
path: path.display().to_string(),
})?;
Ok(config)
}
pub fn save_config(config: &Config) -> Result<()> {
let path = config_path()?;
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).map_err(|_| XrpcCliError::ConfigWriteFailed {
path: path.display().to_string(),
})?;
}
let content =
serde_json::to_string_pretty(config).map_err(|_| XrpcCliError::ConfigWriteFailed {
path: path.display().to_string(),
})?;
std::fs::write(&path, content).map_err(|_| XrpcCliError::ConfigWriteFailed {
path: path.display().to_string(),
})?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o600)).map_err(|_| {
XrpcCliError::ConfigWriteFailed {
path: path.display().to_string(),
}
})?;
}
Ok(())
}