1use axum::http::StatusCode;
4use axum::response::{IntoResponse, Response};
5use axum::Json;
6use serde::Serialize;
7
8#[derive(Debug, Serialize)]
10pub struct ErrorResponse {
11 pub error: String,
12 pub message: String,
13}
14
15#[derive(Debug, thiserror::Error)]
17pub enum ApiError {
18 #[error("not found: {0}")]
19 NotFound(String),
20
21 #[error("bad request: {0}")]
22 BadRequest(String),
23
24 #[error("database not initialized")]
25 NotInitialized,
26
27 #[error("internal error: {0}")]
28 Internal(String),
29}
30
31impl From<uls_query::QueryError> for ApiError {
32 fn from(err: uls_query::QueryError) -> Self {
33 match err {
34 uls_query::QueryError::NotInitialized => ApiError::NotInitialized,
35 other => ApiError::Internal(other.to_string()),
36 }
37 }
38}
39
40impl IntoResponse for ApiError {
41 fn into_response(self) -> Response {
42 let (status, error_key, message) = match &self {
43 ApiError::NotFound(msg) => (StatusCode::NOT_FOUND, "not_found", msg.clone()),
44 ApiError::BadRequest(msg) => (StatusCode::BAD_REQUEST, "bad_request", msg.clone()),
45 ApiError::NotInitialized => (
46 StatusCode::SERVICE_UNAVAILABLE,
47 "not_initialized",
48 "Database not initialized. Run 'uls update' first.".to_string(),
49 ),
50 ApiError::Internal(msg) => (
51 StatusCode::INTERNAL_SERVER_ERROR,
52 "internal_error",
53 msg.clone(),
54 ),
55 };
56
57 let body = ErrorResponse {
58 error: error_key.to_string(),
59 message,
60 };
61
62 (status, Json(body)).into_response()
63 }
64}