use thiserror::Error;
pub type Result<T> = std::result::Result<T, VaultmuxError>;
#[derive(Debug, Error)]
pub enum VaultmuxError {
#[error("item not found: {0}")]
NotFound(String),
#[error("item already exists: {0}")]
AlreadyExists(String),
#[error("not authenticated")]
NotAuthenticated,
#[error("session expired")]
SessionExpired,
#[error("backend CLI not installed: {0}")]
BackendNotInstalled(String),
#[error("vault is locked")]
BackendLocked,
#[error("permission denied: {0}")]
PermissionDenied(String),
#[error("operation not supported by backend: {0}")]
NotSupported(String),
#[error("invalid item name: {0}")]
InvalidItemName(String),
#[error("{backend}: {operation} {item}: {source}")]
BackendOperation {
backend: String,
operation: String,
item: String,
#[source]
source: Box<VaultmuxError>,
},
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("command execution failed: {0}")]
CommandFailed(String),
#[error(transparent)]
Other(#[from] anyhow::Error),
}
impl VaultmuxError {
pub fn backend_op(
backend: impl Into<String>,
operation: impl Into<String>,
item: impl Into<String>,
err: VaultmuxError,
) -> Self {
Self::BackendOperation {
backend: backend.into(),
operation: operation.into(),
item: item.into(),
source: Box::new(err),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::error::Error;
#[test]
fn test_error_display() {
let err = VaultmuxError::NotFound("test-item".to_string());
assert_eq!(err.to_string(), "item not found: test-item");
}
#[test]
fn test_backend_operation_error() {
let inner = VaultmuxError::NotFound("api-key".to_string());
let err = VaultmuxError::backend_op("bitwarden", "get", "api-key", inner);
let error_string = err.to_string();
assert!(error_string.contains("bitwarden"));
assert!(error_string.contains("get"));
assert!(error_string.contains("api-key"));
}
#[test]
fn test_error_source_chain() {
let inner = VaultmuxError::NotFound("test".to_string());
let outer = VaultmuxError::backend_op("pass", "get", "test", inner);
assert!(outer.source().is_some());
}
}