use axum::{http::StatusCode, response::{IntoResponse, Response}, Json}; use serde_json::json; use thiserror::Error; #[derive(Debug, Error)] pub enum AppError { #[error("database error: {0}")] Db(#[from] sqlx::Error), #[error("not found")] NotFound, #[error("conflict: {0}")] Conflict(String), #[error("unauthorized")] Unauthorized, #[error("bad request: {0}")] BadRequest(String), } impl IntoResponse for AppError { fn into_response(self) -> Response { let (status, msg) = match &self { AppError::Db(e) => { tracing::error!(error = %e, "database error"); (StatusCode::INTERNAL_SERVER_ERROR, "internal error".into()) } AppError::NotFound => (StatusCode::NOT_FOUND, "not found".into()), AppError::Conflict(m) => (StatusCode::CONFLICT, m.clone()), AppError::Unauthorized => (StatusCode::UNAUTHORIZED, "unauthorized".into()), AppError::BadRequest(m) => (StatusCode::BAD_REQUEST, m.clone()), }; (status, Json(json!({"error": msg}))).into_response() } }