Transform the single binary crate into a 9-crate workspace monorepo: - Root Cargo.toml as [workspace] manager with resolver = "2" - zesdex-entities: Domain entity types (session, settings, store, message, etc.) - zesdex-utils: Pure utility functions (error, logger, pagination, slug, clipboard) - zesdex-dto: Data Transfer Objects for LLM provider API communication - zesdex-ipc: Unix-socket IPC layer (client/server/framing/protocol) - zesdex-iam: Identity & Access Management (Clean Architecture: domain/application/infrastructure) - zesdex-cms: Content Management (Clean Architecture: domain/application/infrastructure) - zesdex-middleware: HTTP middleware (Auth, CORS, Rate Limiting) - zesdex-libs: Composition root (AppContext, DB init, JWT, Argon2) - zesdex-backend: Main binary entry point + seed/migrate binaries - DevOps: Dockerfile, docker-compose, Nix (flake/shell/default), CI/CD updates - Remove dead root src/ and src-misc/ directories All crate re-exports maintain backward compatibility with original crate::model::*, crate::dto::*, crate::ipc::* module paths. Feature crates enforce strict layer separation: domain -> application -> infrastructure with generic trait-based dependency injection.
98 lines
2.9 KiB
Rust
98 lines
2.9 KiB
Rust
#![allow(
|
|
clippy::cast_possible_truncation,
|
|
clippy::cast_sign_loss,
|
|
clippy::cast_precision_loss,
|
|
clippy::cast_possible_wrap
|
|
)]
|
|
|
|
use std::fmt;
|
|
|
|
/// Unified error type for the zesdex codebase.
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
/// Wraps an I/O error.
|
|
Io(std::io::Error),
|
|
/// Wraps a JSON serialization/deserialization error.
|
|
Serde(serde_json::Error),
|
|
/// A generic parse failure with a message.
|
|
Parse(String),
|
|
/// A resource was not found.
|
|
NotFound(String),
|
|
/// Invalid input was provided.
|
|
InvalidInput(String),
|
|
/// The session is locked and cannot be accessed.
|
|
SessionLocked,
|
|
}
|
|
|
|
impl fmt::Display for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Self::Io(e) => write!(f, "I/O error: {e}"),
|
|
Self::Serde(e) => write!(f, "serialization error: {e}"),
|
|
Self::Parse(msg) => write!(f, "parse error: {msg}"),
|
|
Self::NotFound(resource) => write!(f, "not found: {resource}"),
|
|
Self::InvalidInput(msg) => write!(f, "invalid input: {msg}"),
|
|
Self::SessionLocked => write!(f, "session is locked"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for Error {
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
match self {
|
|
Self::Io(e) => Some(e),
|
|
Self::Serde(e) => Some(e),
|
|
Self::Parse(_) | Self::NotFound(_) | Self::InvalidInput(_) | Self::SessionLocked => {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// From conversions
|
|
// ---------------------------------------------------------------------------
|
|
|
|
impl From<std::io::Error> for Error {
|
|
fn from(e: std::io::Error) -> Self {
|
|
Self::Io(e)
|
|
}
|
|
}
|
|
|
|
impl From<serde_json::Error> for Error {
|
|
fn from(e: serde_json::Error) -> Self {
|
|
Self::Serde(e)
|
|
}
|
|
}
|
|
|
|
// Note: anyhow already provides `From<E> for anyhow::Error` for all
|
|
// `E: std::error::Error + Send + Sync + 'static`, which our `Error` satisfies.
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Type alias
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Convenience alias for `Result<T, zesdex_utils::Error>`.
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Additional impls
|
|
// ---------------------------------------------------------------------------
|
|
|
|
impl Error {
|
|
/// Create a `Parse` error.
|
|
pub fn parse(msg: impl Into<String>) -> Self {
|
|
Self::Parse(msg.into())
|
|
}
|
|
|
|
/// Create a `NotFound` error.
|
|
pub fn not_found(resource: impl Into<String>) -> Self {
|
|
Self::NotFound(resource.into())
|
|
}
|
|
|
|
/// Create an `InvalidInput` error.
|
|
pub fn invalid_input(msg: impl Into<String>) -> Self {
|
|
Self::InvalidInput(msg.into())
|
|
}
|
|
}
|