use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
#[error("HTTP request failed: {0}")]
Http(#[from] reqwest::Error),
#[error("Failed to parse JSON: {0}")]
Json(#[from] serde_json::Error),
#[error("API error: {message} (status: {status})")]
Api { status: u16, message: String },
#[error("API key not found. Please set FMP_API_KEY environment variable")]
MissingApiKey,
#[error("Invalid API key format")]
InvalidApiKey,
#[error("Invalid parameter: {0}")]
InvalidParameter(String),
#[error("Rate limit exceeded. Please try again later")]
RateLimitExceeded,
#[error("Resource not found: {0}")]
NotFound(String),
#[error("Failed to parse URL: {0}")]
UrlParse(#[from] url::ParseError),
#[error("{0}")]
Custom(String),
}
impl Error {
pub fn api(status: u16, message: impl Into<String>) -> Self {
Self::Api {
status,
message: message.into(),
}
}
pub fn custom(message: impl Into<String>) -> Self {
Self::Custom(message.into())
}
pub fn is_rate_limit(&self) -> bool {
matches!(self, Error::RateLimitExceeded)
|| matches!(self, Error::Api { status, .. } if *status == 429)
}
pub fn is_not_found(&self) -> bool {
matches!(self, Error::NotFound(_))
|| matches!(self, Error::Api { status, .. } if *status == 404)
}
}