use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::Json;
use kindling_service::ServiceError;
use serde_json::json;
#[derive(Debug, thiserror::Error)]
pub enum ServerError {
#[error("a kindling daemon is already running (pid {0})")]
AlreadyRunning(i32),
#[error("pid file error: {0}")]
Pid(String),
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
Service(#[from] ServiceError),
}
#[derive(Debug)]
pub enum ApiError {
BadRequest(String),
NotFound(String),
Conflict(String),
Internal(String),
}
impl ApiError {
fn parts(&self) -> (StatusCode, &str) {
match self {
ApiError::BadRequest(m) => (StatusCode::BAD_REQUEST, m),
ApiError::NotFound(m) => (StatusCode::NOT_FOUND, m),
ApiError::Conflict(m) => (StatusCode::CONFLICT, m),
ApiError::Internal(m) => (StatusCode::INTERNAL_SERVER_ERROR, m),
}
}
}
impl From<ServiceError> for ApiError {
fn from(err: ServiceError) -> Self {
match err {
ServiceError::Validation(_) => ApiError::BadRequest(err.to_string()),
ServiceError::NotFound(_) => ApiError::NotFound(err.to_string()),
ServiceError::Conflict(_) | ServiceError::AlreadyClosed(_) => {
ApiError::Conflict(err.to_string())
}
ServiceError::Store(_) | ServiceError::Provider(_) | ServiceError::Json(_) => {
ApiError::Internal(err.to_string())
}
}
}
}
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
let (status, message) = self.parts();
(status, Json(json!({ "error": message }))).into_response()
}
}