use thiserror::Error;
#[derive(Debug, Error)]
pub enum PlatformApiError {
#[error("HTTP request failed: {0}")]
HttpError(#[from] reqwest::Error),
#[error("API error ({status}): {message}")]
ApiError {
status: u16,
message: String,
},
#[error("Failed to parse response: {0}")]
ParseError(String),
#[error("Not authenticated - run `sync-ctl auth login` first")]
Unauthorized,
#[error("Not found: {0}")]
NotFound(String),
#[error("Permission denied: {0}")]
PermissionDenied(String),
#[error("Rate limit exceeded - please try again later")]
RateLimited,
#[error("Server error ({status}): {message}")]
ServerError {
status: u16,
message: String,
},
#[error("Could not connect to Syncable API - check your internet connection")]
ConnectionFailed,
}
impl PlatformApiError {
pub fn suggestion(&self) -> Option<&'static str> {
match self {
Self::Unauthorized => Some("Run `sync-ctl auth login` to authenticate"),
Self::RateLimited => Some("Wait a moment and try again"),
Self::HttpError(_) => Some("Check your internet connection"),
Self::ServerError { .. } => Some("The server is experiencing issues. Try again later"),
Self::PermissionDenied(_) => {
Some("Check your project permissions in the Syncable dashboard")
}
Self::NotFound(_) => Some("Verify the resource ID is correct"),
Self::ParseError(_) => Some("This may be a bug - please report it"),
Self::ApiError { status, .. } if *status >= 400 && *status < 500 => {
Some("Check the request parameters")
}
Self::ConnectionFailed => Some("Check your internet connection and try again"),
_ => None,
}
}
pub fn with_suggestion(&self) -> String {
match self.suggestion() {
Some(suggestion) => format!("{}\n → {}", self, suggestion),
None => self.to_string(),
}
}
}
pub type Result<T> = std::result::Result<T, PlatformApiError>;