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![FieldErrorSchema {
69                    field: "email".to_string(),
70                    code: "email".to_string(),
71                    message: "Invalid email format".to_string(),
72                }],
73            },
74        }
75    }
76}
77
78impl ErrorSchema {
79    /// Create a sample not found error
80    pub fn not_found_example() -> Self {
81        Self {
82            error: ErrorBodySchema {
83                error_type: "not_found".to_string(),
84                message: "Resource not found".to_string(),
85                fields: None,
86            },
87            request_id: None,
88        }
89    }
90
91    /// Create a sample internal error
92    pub fn internal_error_example() -> Self {
93        Self {
94            error: ErrorBodySchema {
95                error_type: "internal_error".to_string(),
96                message: "An internal error occurred".to_string(),
97                fields: None,
98            },
99            request_id: None,
100        }
101    }
102
103    /// Create a sample bad request error
104    pub fn bad_request_example() -> Self {
105        Self {
106            error: ErrorBodySchema {
107                error_type: "bad_request".to_string(),
108                message: "Invalid request".to_string(),
109                fields: None,
110            },
111            request_id: None,
112        }
113    }
114}