Skip to main content

systemprompt_database/
error.rs

1//! Typed error boundary for the database crate.
2//!
3//! `RepositoryError` is the canonical error returned from the crate's
4//! database-facing public signatures, including the dyn-safe
5//! `DatabaseProvider` / `DatabaseTransaction` trait surfaces. It composes
6//! `sqlx::Error` and `serde_json::Error` via `#[from]`; runtime invariant
7//! failures are routed through `RepositoryError::InvalidState`. The
8//! filesystem-only [`crate::squash_baseline`] module carries its own error
9//! type.
10//!
11//! Copyright (c) systemprompt.io — Business Source License 1.1.
12//! See <https://systemprompt.io> for licensing details.
13
14use thiserror::Error;
15
16#[derive(Debug, Error)]
17pub enum RepositoryError {
18    #[error("Entity not found: {0}")]
19    NotFound(String),
20
21    #[error("Constraint violation: {0}")]
22    Constraint(String),
23
24    #[error("Database error: {0}")]
25    Database(#[from] sqlx::Error),
26
27    #[error("Serialization error: {0}")]
28    Serialization(#[from] serde_json::Error),
29
30    #[error("Invalid argument: {0}")]
31    InvalidArgument(String),
32
33    #[error("Invalid state: {0}")]
34    InvalidState(String),
35
36    #[error("Internal error: {0}")]
37    Internal(String),
38
39    #[error("Failed to execute query")]
40    QueryExecution(#[source] Box<Self>),
41}
42
43pub type DatabaseResult<T> = Result<T, RepositoryError>;
44
45impl RepositoryError {
46    pub fn not_found<T: std::fmt::Display>(id: T) -> Self {
47        Self::NotFound(id.to_string())
48    }
49
50    pub fn constraint<T: Into<String>>(message: T) -> Self {
51        Self::Constraint(message.into())
52    }
53
54    pub fn invalid_argument<T: Into<String>>(message: T) -> Self {
55        Self::InvalidArgument(message.into())
56    }
57
58    pub fn internal<T: Into<String>>(message: T) -> Self {
59        Self::Internal(message.into())
60    }
61
62    pub fn invalid_state<T: Into<String>>(message: T) -> Self {
63        Self::InvalidState(message.into())
64    }
65
66    #[must_use]
67    pub const fn is_not_found(&self) -> bool {
68        matches!(self, Self::NotFound(_))
69    }
70
71    #[must_use]
72    pub const fn is_constraint(&self) -> bool {
73        matches!(self, Self::Constraint(_))
74    }
75}
76
77impl From<RepositoryError> for systemprompt_traits::RepositoryError {
78    fn from(err: RepositoryError) -> Self {
79        Self::Database(Box::new(err))
80    }
81}