1#![allow(missing_docs)]
7
8mod auth;
9mod config;
10mod file;
11mod http;
12mod integration;
13mod notification;
14mod observer;
15mod webhook;
16
17pub use auth::AuthError;
18pub use config::ConfigError;
19pub use file::FileError;
20pub use http::{ErrorResponse, IntoHttpResponse};
22pub use integration::IntegrationError;
23pub use notification::NotificationError;
24pub use observer::ObserverError;
25pub use webhook::WebhookError;
26
27#[derive(Debug, thiserror::Error)]
29pub enum RuntimeError {
30 #[error(transparent)]
31 Config(#[from] ConfigError),
32
33 #[error(transparent)]
34 Auth(#[from] AuthError),
35
36 #[error(transparent)]
37 Webhook(#[from] WebhookError),
38
39 #[error(transparent)]
40 File(#[from] FileError),
41
42 #[error(transparent)]
43 Notification(#[from] NotificationError),
44
45 #[error(transparent)]
46 Observer(#[from] ObserverError),
47
48 #[error(transparent)]
49 Integration(#[from] IntegrationError),
50
51 #[error("Database error: {0}")]
52 Database(#[from] sqlx::Error),
53
54 #[error("Rate limit exceeded")]
55 RateLimited { retry_after: Option<u64> },
56
57 #[error("Service unavailable: {reason}")]
58 ServiceUnavailable {
59 reason: String,
60 retry_after: Option<u64>,
61 },
62
63 #[error("Resource not found: {resource}")]
64 NotFound { resource: String },
65
66 #[error("Internal error: {message}")]
67 Internal {
68 message: String,
69 #[source]
70 source: Option<Box<dyn std::error::Error + Send + Sync>>,
71 },
72}
73
74impl RuntimeError {
75 pub const fn error_code(&self) -> &'static str {
77 match self {
78 Self::Config(e) => e.error_code(),
79 Self::Auth(e) => e.error_code(),
80 Self::Webhook(e) => e.error_code(),
81 Self::File(e) => e.error_code(),
82 Self::Notification(e) => e.error_code(),
83 Self::Observer(e) => e.error_code(),
84 Self::Integration(e) => e.error_code(),
85 Self::Database(_) => "database_error",
86 Self::RateLimited { .. } => "rate_limited",
87 Self::ServiceUnavailable { .. } => "service_unavailable",
88 Self::NotFound { .. } => "not_found",
89 Self::Internal { .. } => "internal_error",
90 }
91 }
92
93 pub fn docs_url(&self) -> String {
95 format!("https://docs.fraiseql.dev/errors#{}", self.error_code())
96 }
97}