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    #[error("JWT error: {0}")]
25    Jwt(#[from] jsonwebtoken::errors::Error),
26
27    /// Authentication errors
28    #[error("Authentication error: {message}")]
29    Auth { message: String },
30
31    /// Database operation errors
32    #[error("Database error: {message}")]
33    Database { message: String },
34
35    /// Storage operation errors
36    #[error("Storage error: {message}")]
37    Storage { message: String },
38
39    /// Realtime connection errors
40    #[error("Realtime error: {message}")]
41    Realtime { message: String },
42
43    /// Configuration errors
44    #[error("Configuration error: {message}")]
45    Config { message: String },
46
47    /// Invalid input errors
48    #[error("Invalid input: {message}")]
49    InvalidInput { message: String },
50
51    /// Network errors
52    #[error("Network error: {message}")]
53    Network { message: String },
54
55    /// Rate limiting errors
56    #[error("Rate limit exceeded: {message}")]
57    RateLimit { message: String },
58
59    /// Permission denied errors
60    #[error("Permission denied: {message}")]
61    PermissionDenied { message: String },
62
63    /// Resource not found errors
64    #[error("Not found: {message}")]
65    NotFound { message: String },
66
67    /// Generic errors
68    #[error("{message}")]
69    Generic { message: String },
70}
71
72impl Error {
73    /// Create an authentication error
74    pub fn auth<S: Into<String>>(message: S) -> Self {
75        Self::Auth {
76            message: message.into(),
77        }
78    }
79
80    /// Create a database error
81    pub fn database<S: Into<String>>(message: S) -> Self {
82        Self::Database {
83            message: message.into(),
84        }
85    }
86
87    /// Create a storage error
88    pub fn storage<S: Into<String>>(message: S) -> Self {
89        Self::Storage {
90            message: message.into(),
91        }
92    }
93
94    /// Create a realtime error
95    pub fn realtime<S: Into<String>>(message: S) -> Self {
96        Self::Realtime {
97            message: message.into(),
98        }
99    }
100
101    /// Create a configuration error
102    pub fn config<S: Into<String>>(message: S) -> Self {
103        Self::Config {
104            message: message.into(),
105        }
106    }
107
108    /// Create an invalid input error
109    pub fn invalid_input<S: Into<String>>(message: S) -> Self {
110        Self::InvalidInput {
111            message: message.into(),
112        }
113    }
114
115    /// Create a network error
116    pub fn network<S: Into<String>>(message: S) -> Self {
117        Self::Network {
118            message: message.into(),
119        }
120    }
121
122    /// Create a rate limit error
123    pub fn rate_limit<S: Into<String>>(message: S) -> Self {
124        Self::RateLimit {
125            message: message.into(),
126        }
127    }
128
129    /// Create a permission denied error
130    pub fn permission_denied<S: Into<String>>(message: S) -> Self {
131        Self::PermissionDenied {
132            message: message.into(),
133        }
134    }
135
136    /// Create a not found error
137    pub fn not_found<S: Into<String>>(message: S) -> Self {
138        Self::NotFound {
139            message: message.into(),
140        }
141    }
142
143    /// Create a generic error
144    pub fn generic<S: Into<String>>(message: S) -> Self {
145        Self::Generic {
146            message: message.into(),
147        }
148    }
149}
150
151/// Handle HTTP status codes and convert to appropriate errors
152impl From<reqwest::StatusCode> for Error {
153    fn from(status: reqwest::StatusCode) -> Self {
154        match status {
155            reqwest::StatusCode::UNAUTHORIZED => Self::auth("Unauthorized"),
156            reqwest::StatusCode::FORBIDDEN => Self::permission_denied("Forbidden"),
157            reqwest::StatusCode::NOT_FOUND => Self::not_found("Resource not found"),
158            reqwest::StatusCode::TOO_MANY_REQUESTS => Self::rate_limit("Too many requests"),
159            reqwest::StatusCode::INTERNAL_SERVER_ERROR => Self::network("Internal server error"),
160            reqwest::StatusCode::BAD_GATEWAY => Self::network("Bad gateway"),
161            reqwest::StatusCode::SERVICE_UNAVAILABLE => Self::network("Service unavailable"),
162            reqwest::StatusCode::GATEWAY_TIMEOUT => Self::network("Gateway timeout"),
163            _ => Self::network(format!("HTTP error: {}", status)),
164        }
165    }
166}