1use axum::{
8 Json,
9 http::StatusCode,
10 response::{IntoResponse, Response},
11};
12use molten_config::ConfigError;
13use molten_service::ServiceError;
14use serde_json::json;
15use thiserror::Error;
16
17#[derive(Error, Debug)]
19pub enum ApiError {
20 #[error("molten-service error: {0:?}")]
22 Service(#[from] ServiceError),
23 #[error("molten-config error: {0:?}")]
25 Config(#[from] ConfigError),
26}
27
28impl IntoResponse for ApiError {
29 fn into_response(self) -> Response {
30 let (status, message) = match &self {
31 ApiError::Service(ServiceError::FormNotFound(id)) => {
33 (StatusCode::NOT_FOUND, format!("Form '{}' not found", id))
34 }
35 ApiError::Service(ServiceError::WorkflowNotFound(id)) => (
36 StatusCode::NOT_FOUND,
37 format!("Workflow '{}' not found", id),
38 ),
39
40 ApiError::Service(ServiceError::DocumentValidationErrors(errs)) => {
42 return (
44 StatusCode::BAD_REQUEST,
45 Json(json!({ "error": "Document Validation Failed", "details": errs })),
46 )
47 .into_response();
48 }
49 ApiError::Service(ServiceError::FormValidationErrors(e)) => {
50 (StatusCode::BAD_REQUEST, e.to_string())
51 }
52 ApiError::Service(ServiceError::WorkflowValidationErrors(e)) => {
53 (StatusCode::BAD_REQUEST, e.to_string())
54 }
55 ApiError::Config(ConfigError::ValidationErrors(e)) => {
56 (StatusCode::BAD_REQUEST, e.to_string())
57 }
58 ApiError::Service(ServiceError::WorkflowRuleViolation(e)) => {
59 (StatusCode::BAD_REQUEST, e.to_string())
60 }
61 ApiError::Config(ConfigError::JsonError(e)) => (StatusCode::BAD_REQUEST, e.to_string()),
62
63 ApiError::Service(ServiceError::DatabaseError(e)) => {
65 (StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
66 }
67 ApiError::Service(ServiceError::Internal(e)) => {
68 (StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
69 }
70 ApiError::Config(e) => {
71 tracing::error!("Unhandled ConfigError in API layer: {:?}", e);
72 return (
73 StatusCode::INTERNAL_SERVER_ERROR,
74 Json(json!({ "error": "Internal server error" })),
75 )
76 .into_response();
77 }
78 };
79
80 (status, Json(json!({ "error": message }))).into_response()
81 }
82}
83
84#[derive(Debug, Error)]
88pub enum BuildError {
89 #[error("database error during startup")]
91 Database(#[from] sea_orm::DbErr),
92
93 #[error("I/O error during startup")]
95 Io(#[from] std::io::Error),
96}