use serde::Deserialize;
use supabase_client_core::SupabaseError;
#[derive(Debug, Clone, Deserialize)]
pub struct FunctionsApiErrorResponse {
#[serde(default)]
pub error: Option<String>,
#[serde(default)]
pub message: Option<String>,
}
impl FunctionsApiErrorResponse {
pub fn error_message(&self) -> String {
self.message
.as_deref()
.or(self.error.as_deref())
.unwrap_or("Unknown error")
.to_string()
}
}
#[derive(Debug, thiserror::Error)]
pub enum FunctionsError {
#[error("HTTP error: {0}")]
Http(#[from] reqwest::Error),
#[error("Functions HTTP error ({status}): {message}")]
HttpError { status: u16, message: String },
#[error("Functions relay error ({status}): {message}")]
RelayError { status: u16, message: String },
#[error("Invalid functions configuration: {0}")]
InvalidConfig(String),
#[error("Serialization error: {0}")]
Serialization(#[from] serde_json::Error),
#[error("URL parse error: {0}")]
UrlParse(#[from] url::ParseError),
}
impl From<FunctionsError> for SupabaseError {
fn from(err: FunctionsError) -> Self {
SupabaseError::Functions(err.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_display_http_error() {
let err = FunctionsError::HttpError {
status: 400,
message: "Bad Request".into(),
};
assert_eq!(err.to_string(), "Functions HTTP error (400): Bad Request");
}
#[test]
fn error_display_relay_error() {
let err = FunctionsError::RelayError {
status: 502,
message: "Function not found".into(),
};
assert_eq!(
err.to_string(),
"Functions relay error (502): Function not found"
);
}
#[test]
fn error_display_invalid_config() {
let err = FunctionsError::InvalidConfig("missing url".into());
assert_eq!(
err.to_string(),
"Invalid functions configuration: missing url"
);
}
#[test]
fn error_converts_to_supabase_error() {
let err = FunctionsError::HttpError {
status: 500,
message: "Internal".into(),
};
let supa: SupabaseError = err.into();
match supa {
SupabaseError::Functions(msg) => assert!(msg.contains("Internal")),
other => panic!("Expected Functions variant, got: {:?}", other),
}
}
#[test]
fn api_error_response_deserialization() {
let json = r#"{"error":"not_found","message":"Function not found"}"#;
let resp: FunctionsApiErrorResponse = serde_json::from_str(json).unwrap();
assert_eq!(resp.error.as_deref(), Some("not_found"));
assert_eq!(resp.message.as_deref(), Some("Function not found"));
assert_eq!(resp.error_message(), "Function not found");
}
#[test]
fn api_error_response_fallback_to_error() {
let json = r#"{"error":"Something went wrong"}"#;
let resp: FunctionsApiErrorResponse = serde_json::from_str(json).unwrap();
assert_eq!(resp.error_message(), "Something went wrong");
}
#[test]
fn api_error_response_unknown() {
let json = r#"{}"#;
let resp: FunctionsApiErrorResponse = serde_json::from_str(json).unwrap();
assert_eq!(resp.error_message(), "Unknown error");
}
}