use thiserror::Error;
#[derive(Debug, Error)]
pub enum ZoeyError {
#[error("Database error: {0}")]
DatabaseSqlx(#[from] sqlx::Error),
#[error("Database error: {0}")]
Database(String),
#[error("Plugin error: {0}")]
Plugin(String),
#[error("Runtime error: {0}")]
Runtime(String),
#[error("Model error: {0}")]
Model(String),
#[error("Memory error: {0}")]
Memory(String),
#[error("Serialization error: {0}")]
Serialization(#[from] serde_json::Error),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Configuration error: {0}")]
Config(String),
#[error("Validation error: {0}")]
Validation(String),
#[error("Network error: {0}")]
Network(#[from] reqwest::Error),
#[error("Template error: {0}")]
Template(String),
#[error("Service error: {0}")]
Service(String),
#[error("Event error: {0}")]
Event(String),
#[error("Action error: {0}")]
Action(String),
#[error("Provider error: {0}")]
Provider(String),
#[error("Evaluator error: {0}")]
Evaluator(String),
#[error("Not found: {0}")]
NotFound(String),
#[error("Auth error: {0}")]
Auth(String),
#[error("Rate limit exceeded: {0}")]
RateLimit(String),
#[error("Timeout: {0}")]
Timeout(String),
#[error("{0}")]
Other(String),
#[error(
"Database constraint violation in table '{table}': {constraint} = '{value}'. {suggestion}"
)]
DatabaseConstraintViolation {
table: String,
constraint: String,
value: String,
suggestion: String,
},
#[error(
"Vector search error: {message}. Dimension: {dimension}, Expected: {expected_dimension}"
)]
VectorSearch {
message: String,
dimension: usize,
expected_dimension: usize,
},
#[error("Missing required field '{field}' in {context}. {suggestion}")]
MissingField {
field: String,
context: String,
suggestion: String,
},
#[error("Resource '{resource}' exhausted: {message}. Current: {current}, Limit: {limit}")]
ResourceExhausted {
resource: String,
message: String,
current: usize,
limit: usize,
},
}
pub type Result<T> = std::result::Result<T, ZoeyError>;
impl ZoeyError {
pub fn database(msg: impl Into<String>) -> Self {
ZoeyError::Database(msg.into())
}
pub fn plugin(msg: impl Into<String>) -> Self {
ZoeyError::Plugin(msg.into())
}
pub fn runtime(msg: impl Into<String>) -> Self {
ZoeyError::Runtime(msg.into())
}
pub fn model(msg: impl Into<String>) -> Self {
ZoeyError::Model(msg.into())
}
pub fn memory(msg: impl Into<String>) -> Self {
ZoeyError::Memory(msg.into())
}
pub fn config(msg: impl Into<String>) -> Self {
ZoeyError::Config(msg.into())
}
pub fn validation(msg: impl Into<String>) -> Self {
ZoeyError::Validation(msg.into())
}
pub fn service(msg: impl Into<String>) -> Self {
ZoeyError::Service(msg.into())
}
pub fn event(msg: impl Into<String>) -> Self {
ZoeyError::Event(msg.into())
}
pub fn action(msg: impl Into<String>) -> Self {
ZoeyError::Action(msg.into())
}
pub fn provider(msg: impl Into<String>) -> Self {
ZoeyError::Provider(msg.into())
}
pub fn evaluator(msg: impl Into<String>) -> Self {
ZoeyError::Evaluator(msg.into())
}
pub fn not_found(msg: impl Into<String>) -> Self {
ZoeyError::NotFound(msg.into())
}
pub fn auth(msg: impl Into<String>) -> Self {
ZoeyError::Auth(msg.into())
}
pub fn rate_limit(msg: impl Into<String>) -> Self {
ZoeyError::RateLimit(msg.into())
}
pub fn timeout(msg: impl Into<String>) -> Self {
ZoeyError::Timeout(msg.into())
}
pub fn other(msg: impl Into<String>) -> Self {
ZoeyError::Other(msg.into())
}
pub fn template(msg: impl Into<String>) -> Self {
ZoeyError::Template(msg.into())
}
pub fn constraint_violation(
table: impl Into<String>,
constraint: impl Into<String>,
value: impl Into<String>,
suggestion: impl Into<String>,
) -> Self {
ZoeyError::DatabaseConstraintViolation {
table: table.into(),
constraint: constraint.into(),
value: value.into(),
suggestion: suggestion.into(),
}
}
pub fn vector_search(
message: impl Into<String>,
dimension: usize,
expected_dimension: usize,
) -> Self {
ZoeyError::VectorSearch {
message: message.into(),
dimension,
expected_dimension,
}
}
pub fn missing_field(
field: impl Into<String>,
context: impl Into<String>,
suggestion: impl Into<String>,
) -> Self {
ZoeyError::MissingField {
field: field.into(),
context: context.into(),
suggestion: suggestion.into(),
}
}
pub fn resource_exhausted(
resource: impl Into<String>,
message: impl Into<String>,
current: usize,
limit: usize,
) -> Self {
ZoeyError::ResourceExhausted {
resource: resource.into(),
message: message.into(),
current,
limit,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_creation() {
let err = ZoeyError::plugin("test plugin error");
assert_eq!(err.to_string(), "Plugin error: test plugin error");
let err = ZoeyError::runtime("test runtime error");
assert_eq!(err.to_string(), "Runtime error: test runtime error");
}
#[test]
fn test_result_type() {
fn returns_result() -> Result<i32> {
Ok(42)
}
assert_eq!(returns_result().unwrap(), 42);
}
}