mockforge_core/
runtime_validation.rs1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct RuntimeValidationError {
12 pub schema_path: String,
14 pub expected_type: String,
16 pub actual_value: Option<String>,
18 pub contract_diff_id: Option<String>,
20 pub is_breaking_change: bool,
22 pub message: String,
24 pub details: Option<HashMap<String, serde_json::Value>>,
26}
27
28impl RuntimeValidationError {
29 pub fn new(
31 schema_path: impl Into<String>,
32 expected_type: impl Into<String>,
33 message: impl Into<String>,
34 ) -> Self {
35 Self {
36 schema_path: schema_path.into(),
37 expected_type: expected_type.into(),
38 actual_value: None,
39 contract_diff_id: None,
40 is_breaking_change: false,
41 message: message.into(),
42 details: None,
43 }
44 }
45
46 pub fn with_actual_value(mut self, value: impl Into<String>) -> Self {
48 self.actual_value = Some(value.into());
49 self
50 }
51
52 pub fn with_contract_diff_id(mut self, diff_id: impl Into<String>) -> Self {
54 self.contract_diff_id = Some(diff_id.into());
55 self
56 }
57
58 pub fn as_breaking_change(mut self) -> Self {
60 self.is_breaking_change = true;
61 self
62 }
63
64 pub fn with_details(mut self, details: HashMap<String, serde_json::Value>) -> Self {
66 self.details = Some(details);
67 self
68 }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct RuntimeValidationResult {
74 pub valid: bool,
76 pub errors: Vec<RuntimeValidationError>,
78 pub warnings: Vec<RuntimeValidationError>,
80}
81
82impl RuntimeValidationResult {
83 pub fn success() -> Self {
85 Self {
86 valid: true,
87 errors: Vec::new(),
88 warnings: Vec::new(),
89 }
90 }
91
92 pub fn failure(errors: Vec<RuntimeValidationError>) -> Self {
94 Self {
95 valid: false,
96 errors,
97 warnings: Vec::new(),
98 }
99 }
100
101 pub fn add_error(&mut self, error: RuntimeValidationError) {
103 self.valid = false;
104 self.errors.push(error);
105 }
106
107 pub fn add_warning(&mut self, warning: RuntimeValidationError) {
109 self.warnings.push(warning);
110 }
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct SchemaMetadata {
116 pub id: String,
118 pub schema: serde_json::Value,
120 pub required: bool,
122 pub contract_diff_id: Option<String>,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct RuntimeValidatorConfig {
129 pub validate_requests: bool,
131 pub validate_responses: bool,
133 pub throw_on_error: bool,
135 pub include_contract_diffs: bool,
137 pub schemas: HashMap<String, SchemaMetadata>,
139}
140
141impl Default for RuntimeValidatorConfig {
142 fn default() -> Self {
143 Self {
144 validate_requests: false,
145 validate_responses: false,
146 throw_on_error: false,
147 include_contract_diffs: true,
148 schemas: HashMap::new(),
149 }
150 }
151}
152
153impl RuntimeValidatorConfig {
154 pub fn new() -> Self {
156 Self::default()
157 }
158
159 pub fn with_request_validation(mut self, enabled: bool) -> Self {
161 self.validate_requests = enabled;
162 self
163 }
164
165 pub fn with_response_validation(mut self, enabled: bool) -> Self {
167 self.validate_responses = enabled;
168 self
169 }
170
171 pub fn with_throw_on_error(mut self, throw: bool) -> Self {
173 self.throw_on_error = throw;
174 self
175 }
176
177 pub fn add_schema(&mut self, metadata: SchemaMetadata) {
179 self.schemas.insert(metadata.id.clone(), metadata);
180 }
181}