kindling_service/error.rs
1//! Service-layer error type.
2
3use kindling_provider::ProviderError;
4use kindling_store::StoreError;
5use kindling_types::{Id, ValidationError};
6
7/// Errors produced by [`KindlingService`](crate::KindlingService).
8///
9/// Mirrors the Result-type error surface of the TS service, which throws
10/// `Error` for validation failures and lifecycle violations. Here those become
11/// structured variants so callers can branch on them.
12#[derive(Debug, thiserror::Error)]
13pub enum ServiceError {
14 /// Underlying store failure (sqlite, JSON, IO, or a store lifecycle error
15 /// not otherwise specialised by the service).
16 #[error(transparent)]
17 Store(#[from] StoreError),
18
19 /// Retrieval/provider failure.
20 #[error(transparent)]
21 Provider(#[from] ProviderError),
22
23 /// JSON (de)serialization failure (export/import bundle handling).
24 #[error("json (de)serialization error: {0}")]
25 Json(#[from] serde_json::Error),
26
27 /// Input validation failed. Carries every field error, matching the TS
28 /// validators which collect all problems before returning.
29 #[error("validation failed: {}", format_validation(.0))]
30 Validation(Vec<ValidationError>),
31
32 /// A session already has an open capsule (open lifecycle invariant).
33 #[error("conflict: {0}")]
34 Conflict(String),
35
36 /// The referenced capsule does not exist.
37 #[error("capsule {0} not found")]
38 NotFound(Id),
39
40 /// The capsule exists but is already closed.
41 #[error("capsule {0} is already closed")]
42 AlreadyClosed(Id),
43}
44
45/// Result alias for service operations.
46pub type ServiceResult<T> = Result<T, ServiceError>;
47
48fn format_validation(errors: &[ValidationError]) -> String {
49 errors
50 .iter()
51 .map(|e| e.message.as_str())
52 .collect::<Vec<_>>()
53 .join(", ")
54}