fraiseql_core/validation/
error_responses.rs1use serde::{Deserialize, Serialize};
7
8use crate::error::{FraiseQLError, ValidationFieldError};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct GraphQLValidationError {
13 pub message: String,
15
16 #[serde(skip_serializing_if = "Option::is_none")]
18 pub path: Option<Vec<String>>,
19
20 #[serde(skip_serializing_if = "Option::is_none")]
22 pub extensions: Option<ValidationErrorExtensions>,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct ValidationErrorExtensions {
28 pub code: String,
30
31 pub rule_type: String,
33
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub field_path: Option<String>,
37
38 #[serde(skip_serializing_if = "Option::is_none")]
40 pub context: Option<serde_json::Value>,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct GraphQLValidationResponse {
46 pub errors: Vec<GraphQLValidationError>,
48
49 pub error_count: usize,
51}
52
53impl GraphQLValidationResponse {
54 #[must_use]
56 pub const fn new() -> Self {
57 Self {
58 errors: Vec::new(),
59 error_count: 0,
60 }
61 }
62
63 pub fn add_field_error(
65 &mut self,
66 field_error: ValidationFieldError,
67 context: Option<serde_json::Value>,
68 ) {
69 let path = Self::parse_path(&field_error.field);
70 let extensions = ValidationErrorExtensions {
71 code: "VALIDATION_FAILED".to_string(),
72 rule_type: field_error.rule_type,
73 field_path: Some(field_error.field.clone()),
74 context,
75 };
76
77 self.errors.push(GraphQLValidationError {
78 message: format!("Validation failed: {}", field_error.message),
79 path: Some(path),
80 extensions: Some(extensions),
81 });
82
83 self.error_count += 1;
84 }
85
86 pub fn add_errors(&mut self, errors: Vec<ValidationFieldError>) {
88 for error in errors {
89 self.add_field_error(error, None);
90 }
91 }
92
93 #[must_use]
95 pub fn from_error(error: &FraiseQLError) -> Option<Self> {
96 if let FraiseQLError::Validation { message, path } = error {
97 let mut response = Self::new();
98 response.errors.push(GraphQLValidationError {
99 message: message.clone(),
100 path: path.as_ref().map(|p| Self::parse_path(p)),
101 extensions: Some(ValidationErrorExtensions {
102 code: "VALIDATION_FAILED".to_string(),
103 rule_type: "unknown".to_string(),
104 field_path: path.clone(),
105 context: None,
106 }),
107 });
108 response.error_count = 1;
109 Some(response)
110 } else {
111 None
112 }
113 }
114
115 pub(crate) fn parse_path(path: &str) -> Vec<String> {
117 path.split('.').map(|s| s.to_string()).collect()
118 }
119
120 #[must_use]
122 pub const fn has_errors(&self) -> bool {
123 !self.errors.is_empty()
124 }
125
126 #[must_use]
128 pub fn to_graphql_errors(&self) -> serde_json::Value {
129 serde_json::json!({
130 "errors": self.errors,
131 "error_count": self.error_count
132 })
133 }
134}
135
136impl Default for GraphQLValidationResponse {
137 fn default() -> Self {
138 Self::new()
139 }
140}