1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//! WASM validation functions
use super::core::console_log;
use super::types::{
create_validation_error, create_validation_result, JSONEvalWasm, ValidationError,
ValidationResult,
};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
impl JSONEvalWasm {
/// Validate data against schema rules
///
/// @param data - JSON data string
/// @param context - Optional context data JSON string
/// @param validate_readonly - Optional flag to also validate readonly fields
/// @param include_subforms - Optional flag to also validate array subforms
/// @returns ValidationResult
#[wasm_bindgen]
pub fn validate(
&mut self,
data: &str,
context: Option<String>,
validate_readonly: Option<bool>,
include_subforms: Option<bool>,
) -> Result<ValidationResult, JsValue> {
let ctx = context.as_deref();
let token = self.reset_token();
match self.inner.validate(
data,
ctx,
None,
token.as_ref(),
validate_readonly,
include_subforms,
) {
Ok(result) => {
let mut errors: std::collections::HashMap<String, ValidationError> =
std::collections::HashMap::new();
for (path, error) in result.errors {
errors.insert(path.clone(), create_validation_error(path.clone(), &error));
}
Ok(create_validation_result(result.has_error, errors))
}
Err(e) => {
let error_msg = format!("Validation failed: {}", e);
console_log(&format!("[WASM ERROR] {}", error_msg));
Err(JsValue::from_str(&error_msg))
}
}
}
/// Validate data and return as plain JavaScript object (Worker-safe)
///
/// @param data - JSON data string
/// @param context - Optional context data JSON string
/// @param validate_readonly - Optional flag to also validate readonly fields
/// @param include_subforms - Optional flag to also validate array subforms
/// @returns Plain JavaScript object with validation result
#[wasm_bindgen(js_name = validateJS)]
pub fn validate_js(
&mut self,
data: &str,
context: Option<String>,
validate_readonly: Option<bool>,
include_subforms: Option<bool>,
) -> Result<JsValue, JsValue> {
match self.validate_to_value(data, context, None, validate_readonly, include_subforms) {
Ok(validation_result) => super::to_value(&validation_result).map_err(|e| {
let error_msg = format!("Failed to serialize validation result: {}", e);
console_log(&format!("[WASM ERROR] {}", error_msg));
JsValue::from_str(&error_msg)
}),
Err(e) => {
let error_msg = format!("Validation failed: {}", e);
console_log(&format!("[WASM ERROR] {}", error_msg));
Err(JsValue::from_str(&error_msg))
}
}
}
}
impl JSONEvalWasm {
/// Internal helper to validate and return serde_json::Value (testable)
/// This is not exposed to JS directly, but used by validate_js and tests
pub fn validate_to_value(
&mut self,
data: &str,
context: Option<String>,
paths: Option<Vec<String>>,
validate_readonly: Option<bool>,
include_subforms: Option<bool>,
) -> Result<serde_json::Value, String> {
let ctx = context.as_deref();
let paths_ref = paths.as_ref().map(|v| v.as_slice());
let token = self.reset_token();
match self.inner.validate(
data,
ctx,
paths_ref,
token.as_ref(),
validate_readonly,
include_subforms,
) {
Ok(result) => {
let mut errors_map = serde_json::Map::new();
for (path, error) in result.errors {
errors_map.insert(
path.clone(),
serde_json::json!({
"path": path,
"type": error.rule_type,
"message": error.message,
"code": error.code,
"pattern": error.pattern,
"fieldValue": error.field_value,
"data": error.data,
}),
);
}
Ok(serde_json::json!({
"has_error": result.has_error,
"hasError": result.has_error,
"error": errors_map,
"errors": errors_map,
}))
}
Err(e) => Err(e.to_string()),
}
}
}
#[wasm_bindgen]
impl JSONEvalWasm {
/// Validate data against schema rules with optional path filtering
///
/// @param data - JSON data string
/// @param context - Optional context data JSON string
/// @param paths - Optional array of paths to validate (null for all)
/// @param validate_readonly - Optional flag to also validate readonly fields
/// @param include_subforms - Optional flag to also validate array subforms
/// @returns ValidationResult
#[wasm_bindgen(js_name = validatePaths)]
pub fn validate_paths(
&mut self,
data: &str,
context: Option<String>,
paths: Option<Vec<String>>,
validate_readonly: Option<bool>,
include_subforms: Option<bool>,
) -> Result<ValidationResult, JsValue> {
let ctx = context.as_deref();
let paths_ref = paths.as_ref().map(|v| v.as_slice());
let token = self.reset_token();
match self.inner.validate(
data,
ctx,
paths_ref,
token.as_ref(),
validate_readonly,
include_subforms,
) {
Ok(result) => {
let mut errors: std::collections::HashMap<String, ValidationError> =
std::collections::HashMap::new();
for (path, error) in result.errors {
errors.insert(path.clone(), create_validation_error(path.clone(), &error));
}
Ok(create_validation_result(result.has_error, errors))
}
Err(e) => {
let error_msg = format!("Validation failed: {}", e);
console_log(&format!("[WASM ERROR] {}", error_msg));
Err(JsValue::from_str(&error_msg))
}
}
}
/// Validate with path filtering and return as plain JavaScript object (Worker-safe)
///
/// @param data - JSON data string
/// @param context - Optional context data JSON string
/// @param paths - Optional array of paths to validate (null for all)
/// @param validate_readonly - Optional flag to also validate readonly fields
/// @param include_subforms - Optional flag to also validate array subforms
/// @returns Plain JavaScript object with validation result
#[wasm_bindgen(js_name = validatePathsJS)]
pub fn validate_paths_js(
&mut self,
data: &str,
context: Option<String>,
paths: Option<Vec<String>>,
validate_readonly: Option<bool>,
include_subforms: Option<bool>,
) -> Result<JsValue, JsValue> {
match self.validate_to_value(data, context, paths, validate_readonly, include_subforms) {
Ok(validation_result) => super::to_value(&validation_result).map_err(|e| {
let error_msg = format!("Failed to serialize validation result: {}", e);
console_log(&format!("[WASM ERROR] {}", error_msg));
JsValue::from_str(&error_msg)
}),
Err(e) => {
let error_msg = format!("Validation failed: {}", e);
console_log(&format!("[WASM ERROR] {}", error_msg));
Err(JsValue::from_str(&error_msg))
}
}
}
}