supabase/
error.rs

1//! Error handling for the Supabase client
2
3use thiserror::Error;
4
5/// Result type alias for Supabase operations
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// Main error type for Supabase operations
9#[derive(Error, Debug)]
10pub enum Error {
11    /// HTTP request errors
12    #[error("HTTP request failed: {0}")]
13    Http(#[from] reqwest::Error),
14
15    /// JSON serialization/deserialization errors
16    #[error("JSON error: {0}")]
17    Json(#[from] serde_json::Error),
18
19    /// URL parsing errors
20    #[error("URL parse error: {0}")]
21    UrlParse(#[from] url::ParseError),
22
23    /// JWT token errors
24    #[cfg(feature = "auth")]
25    #[error("JWT error: {0}")]
26    Jwt(#[from] jsonwebtoken::errors::Error),
27
28    /// Authentication errors
29    #[error("Authentication error: {message}")]
30    Auth { message: String },
31
32    /// Database operation errors
33    #[error("Database error: {message}")]
34    Database { message: String },
35
36    /// Storage operation errors
37    #[error("Storage error: {message}")]
38    Storage { message: String },
39
40    /// Realtime connection errors
41    #[error("Realtime error: {message}")]
42    Realtime { message: String },
43
44    /// Configuration errors
45    #[error("Configuration error: {message}")]
46    Config { message: String },
47
48    /// Invalid input errors
49    #[error("Invalid input: {message}")]
50    InvalidInput { message: String },
51
52    /// Network errors
53    #[error("Network error: {message}")]
54    Network { message: String },
55
56    /// Rate limiting errors
57    #[error("Rate limit exceeded: {message}")]
58    RateLimit { message: String },
59
60    /// Permission denied errors
61    #[error("Permission denied: {message}")]
62    PermissionDenied { message: String },
63
64    /// Resource not found errors
65    #[error("Not found: {message}")]
66    NotFound { message: String },
67
68    /// Generic errors
69    #[error("{message}")]
70    Generic { message: String },
71
72    /// Functions errors
73    #[error("Functions error: {message}")]
74    Functions { message: String },
75}
76
77impl Error {
78    /// Create an authentication error
79    pub fn auth<S: Into<String>>(message: S) -> Self {
80        Self::Auth {
81            message: message.into(),
82        }
83    }
84
85    /// Create a database error
86    pub fn database<S: Into<String>>(message: S) -> Self {
87        Self::Database {
88            message: message.into(),
89        }
90    }
91
92    /// Create a storage error
93    pub fn storage<S: Into<String>>(message: S) -> Self {
94        Self::Storage {
95            message: message.into(),
96        }
97    }
98
99    /// Create a realtime error
100    pub fn realtime<S: Into<String>>(message: S) -> Self {
101        Self::Realtime {
102            message: message.into(),
103        }
104    }
105
106    /// Create a configuration error
107    pub fn config<S: Into<String>>(message: S) -> Self {
108        Self::Config {
109            message: message.into(),
110        }
111    }
112
113    /// Create an invalid input error
114    pub fn invalid_input<S: Into<String>>(message: S) -> Self {
115        Self::InvalidInput {
116            message: message.into(),
117        }
118    }
119
120    /// Create a network error
121    pub fn network<S: Into<String>>(message: S) -> Self {
122        Self::Network {
123            message: message.into(),
124        }
125    }
126
127    /// Create a rate limit error
128    pub fn rate_limit<S: Into<String>>(message: S) -> Self {
129        Self::RateLimit {
130            message: message.into(),
131        }
132    }
133
134    /// Create a permission denied error
135    pub fn permission_denied<S: Into<String>>(message: S) -> Self {
136        Self::PermissionDenied {
137            message: message.into(),
138        }
139    }
140
141    /// Create a not found error
142    pub fn not_found<S: Into<String>>(message: S) -> Self {
143        Self::NotFound {
144            message: message.into(),
145        }
146    }
147
148    /// Create a generic error
149    pub fn generic<S: Into<String>>(message: S) -> Self {
150        Self::Generic {
151            message: message.into(),
152        }
153    }
154
155    /// Create a functions error
156    pub fn functions<T: Into<String>>(message: T) -> Self {
157        Self::Functions {
158            message: message.into(),
159        }
160    }
161}
162
163/// Handle HTTP status codes and convert to appropriate errors
164impl From<reqwest::StatusCode> for Error {
165    fn from(status: reqwest::StatusCode) -> Self {
166        match status {
167            reqwest::StatusCode::UNAUTHORIZED => Self::auth("Unauthorized"),
168            reqwest::StatusCode::FORBIDDEN => Self::permission_denied("Forbidden"),
169            reqwest::StatusCode::NOT_FOUND => Self::not_found("Resource not found"),
170            reqwest::StatusCode::TOO_MANY_REQUESTS => Self::rate_limit("Too many requests"),
171            reqwest::StatusCode::INTERNAL_SERVER_ERROR => Self::network("Internal server error"),
172            reqwest::StatusCode::BAD_GATEWAY => Self::network("Bad gateway"),
173            reqwest::StatusCode::SERVICE_UNAVAILABLE => Self::network("Service unavailable"),
174            reqwest::StatusCode::GATEWAY_TIMEOUT => Self::network("Gateway timeout"),
175            _ => Self::network(format!("HTTP error: {}", status)),
176        }
177    }
178}
179
180#[cfg(test)]
181mod tests {
182    use super::*;
183
184    #[test]
185    fn test_error_creation() {
186        let error = Error::auth("test message");
187        assert_eq!(error.to_string(), "Authentication error: test message");
188    }
189
190    #[test]
191    fn test_database_error() {
192        let error = Error::database("query failed");
193        assert_eq!(error.to_string(), "Database error: query failed");
194    }
195
196    #[test]
197    fn test_from_status_code() {
198        let error = Error::from(reqwest::StatusCode::NOT_FOUND);
199        assert_eq!(error.to_string(), "Not found: Resource not found");
200    }
201}