rustapi_openapi/
schemas.rs

1//! Standard error schemas for OpenAPI documentation
2//!
3//! These schemas match the error response format used by RustAPI.
4
5use serde::{Deserialize, Serialize};
6use utoipa::ToSchema;
7
8/// Standard error response body
9#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
10pub struct ErrorSchema {
11    /// The error details
12    pub error: ErrorBodySchema,
13    /// Optional request ID for tracing
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub request_id: Option<String>,
16}
17
18/// Error body details
19#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
20pub struct ErrorBodySchema {
21    /// Error type identifier (e.g., "validation_error", "not_found")
22    #[serde(rename = "type")]
23    pub error_type: String,
24    /// Human-readable error message
25    pub message: String,
26    /// Field-level errors (for validation errors)
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub fields: Option<Vec<FieldErrorSchema>>,
29}
30
31/// Field-level validation error
32#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
33pub struct FieldErrorSchema {
34    /// Field name (supports nested paths like "address.city")
35    pub field: String,
36    /// Error code (e.g., "email", "length", "required")
37    pub code: String,
38    /// Human-readable error message
39    pub message: String,
40}
41
42/// Validation error response (422)
43#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
44pub struct ValidationErrorSchema {
45    /// Error wrapper
46    pub error: ValidationErrorBodySchema,
47}
48
49/// Validation error body
50#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
51pub struct ValidationErrorBodySchema {
52    /// Always "validation_error" for validation errors
53    #[serde(rename = "type")]
54    pub error_type: String,
55    /// Always "Request validation failed"
56    pub message: String,
57    /// List of field-level errors
58    pub fields: Vec<FieldErrorSchema>,
59}
60
61impl ValidationErrorSchema {
62    /// Create a sample validation error for documentation
63    pub fn example() -> Self {
64        Self {
65            error: ValidationErrorBodySchema {
66                error_type: "validation_error".to_string(),
67                message: "Request validation failed".to_string(),
68                fields: vec![
69                    FieldErrorSchema {
70                        field: "email".to_string(),
71                        code: "email".to_string(),
72                        message: "Invalid email format".to_string(),
73                    },
74                ],
75            },
76        }
77    }
78}
79
80impl ErrorSchema {
81    /// Create a sample not found error
82    pub fn not_found_example() -> Self {
83        Self {
84            error: ErrorBodySchema {
85                error_type: "not_found".to_string(),
86                message: "Resource not found".to_string(),
87                fields: None,
88            },
89            request_id: None,
90        }
91    }
92    
93    /// Create a sample internal error
94    pub fn internal_error_example() -> Self {
95        Self {
96            error: ErrorBodySchema {
97                error_type: "internal_error".to_string(),
98                message: "An internal error occurred".to_string(),
99                fields: None,
100            },
101            request_id: None,
102        }
103    }
104    
105    /// Create a sample bad request error
106    pub fn bad_request_example() -> Self {
107        Self {
108            error: ErrorBodySchema {
109                error_type: "bad_request".to_string(),
110                message: "Invalid request".to_string(),
111                fields: None,
112            },
113            request_id: None,
114        }
115    }
116}