Skip to main content

tuitbot_server/
error.rs

1//! API error types for the tuitbot server.
2//!
3//! Maps core domain errors to HTTP status codes and JSON error responses.
4
5use axum::http::StatusCode;
6use axum::response::{IntoResponse, Response};
7use serde_json::json;
8
9/// API error type for route handlers.
10pub enum ApiError {
11    /// Internal storage/database error.
12    Storage(tuitbot_core::error::StorageError),
13    /// Requested resource not found.
14    NotFound(String),
15    /// Bad request (invalid query parameters, etc.).
16    BadRequest(String),
17    /// Conflict (resource already exists, runtime already running, etc.).
18    Conflict(String),
19}
20
21impl From<tuitbot_core::error::StorageError> for ApiError {
22    fn from(err: tuitbot_core::error::StorageError) -> Self {
23        Self::Storage(err)
24    }
25}
26
27impl IntoResponse for ApiError {
28    fn into_response(self) -> Response {
29        let (status, message) = match self {
30            Self::Storage(e) => {
31                tracing::error!("storage error: {e}");
32                (StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
33            }
34            Self::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
35            Self::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg),
36            Self::Conflict(msg) => (StatusCode::CONFLICT, msg),
37        };
38
39        let body = axum::Json(json!({ "error": message }));
40        (status, body).into_response()
41    }
42}