supabase_client_functions/
error.rs1use serde::Deserialize;
2use supabase_client_core::SupabaseError;
3
4#[derive(Debug, Clone, Deserialize)]
6pub struct FunctionsApiErrorResponse {
7 #[serde(default)]
8 pub error: Option<String>,
9 #[serde(default)]
10 pub message: Option<String>,
11}
12
13impl FunctionsApiErrorResponse {
14 pub fn error_message(&self) -> String {
16 self.message
17 .as_deref()
18 .or(self.error.as_deref())
19 .unwrap_or("Unknown error")
20 .to_string()
21 }
22}
23
24#[derive(Debug, thiserror::Error)]
26pub enum FunctionsError {
27 #[error("HTTP error: {0}")]
29 Http(#[from] reqwest::Error),
30
31 #[error("Functions HTTP error ({status}): {message}")]
33 HttpError { status: u16, message: String },
34
35 #[error("Functions relay error ({status}): {message}")]
37 RelayError { status: u16, message: String },
38
39 #[error("Invalid functions configuration: {0}")]
41 InvalidConfig(String),
42
43 #[error("Serialization error: {0}")]
45 Serialization(#[from] serde_json::Error),
46
47 #[error("URL parse error: {0}")]
49 UrlParse(#[from] url::ParseError),
50}
51
52impl From<FunctionsError> for SupabaseError {
53 fn from(err: FunctionsError) -> Self {
54 SupabaseError::Functions(err.to_string())
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn error_display_http_error() {
64 let err = FunctionsError::HttpError {
65 status: 400,
66 message: "Bad Request".into(),
67 };
68 assert_eq!(err.to_string(), "Functions HTTP error (400): Bad Request");
69 }
70
71 #[test]
72 fn error_display_relay_error() {
73 let err = FunctionsError::RelayError {
74 status: 502,
75 message: "Function not found".into(),
76 };
77 assert_eq!(
78 err.to_string(),
79 "Functions relay error (502): Function not found"
80 );
81 }
82
83 #[test]
84 fn error_display_invalid_config() {
85 let err = FunctionsError::InvalidConfig("missing url".into());
86 assert_eq!(
87 err.to_string(),
88 "Invalid functions configuration: missing url"
89 );
90 }
91
92 #[test]
93 fn error_converts_to_supabase_error() {
94 let err = FunctionsError::HttpError {
95 status: 500,
96 message: "Internal".into(),
97 };
98 let supa: SupabaseError = err.into();
99 match supa {
100 SupabaseError::Functions(msg) => assert!(msg.contains("Internal")),
101 other => panic!("Expected Functions variant, got: {:?}", other),
102 }
103 }
104
105 #[test]
106 fn api_error_response_deserialization() {
107 let json = r#"{"error":"not_found","message":"Function not found"}"#;
108 let resp: FunctionsApiErrorResponse = serde_json::from_str(json).unwrap();
109 assert_eq!(resp.error.as_deref(), Some("not_found"));
110 assert_eq!(resp.message.as_deref(), Some("Function not found"));
111 assert_eq!(resp.error_message(), "Function not found");
112 }
113
114 #[test]
115 fn api_error_response_fallback_to_error() {
116 let json = r#"{"error":"Something went wrong"}"#;
117 let resp: FunctionsApiErrorResponse = serde_json::from_str(json).unwrap();
118 assert_eq!(resp.error_message(), "Something went wrong");
119 }
120
121 #[test]
122 fn api_error_response_unknown() {
123 let json = r#"{}"#;
124 let resp: FunctionsApiErrorResponse = serde_json::from_str(json).unwrap();
125 assert_eq!(resp.error_message(), "Unknown error");
126 }
127}