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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
//! WASM schema getter functions
use super::core::console_log;
use super::types::JSONEvalWasm;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
impl JSONEvalWasm {
/// Get the evaluated schema (compact, without $layout resolution)
///
/// @returns Evaluated schema as JSON string
#[wasm_bindgen(js_name = getEvaluatedSchema)]
pub fn get_evaluated_schema(&mut self) -> String {
let result = self.inner.get_evaluated_schema();
serde_json::to_string(&result).unwrap_or_else(|_| "{}".to_string())
}
/// Get the evaluated schema as JavaScript object
///
/// @returns Evaluated schema as JavaScript object
#[wasm_bindgen(js_name = getEvaluatedSchemaJS)]
pub fn get_evaluated_schema_js(&mut self) -> Result<JsValue, JsValue> {
let result = self.inner.get_evaluated_schema();
super::to_value(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get the evaluated schema in MessagePack format
///
/// @returns Evaluated schema as MessagePack bytes (Uint8Array)
///
/// # Zero-Copy Optimization
///
/// This method returns MessagePack binary data with minimal copying:
/// 1. Serializes schema to Vec<u8> in Rust (unavoidable)
/// 2. wasm-bindgen transfers Vec<u8> to JS as Uint8Array (optimized)
/// 3. Result is a Uint8Array view (minimal overhead)
///
/// MessagePack format is 20-50% smaller than JSON, ideal for web/WASM.
#[wasm_bindgen(js_name = getEvaluatedSchemaMsgpack)]
pub fn get_evaluated_schema_msgpack(&mut self) -> Result<Vec<u8>, JsValue> {
self.inner
.get_evaluated_schema_msgpack()
.map_err(|e| JsValue::from_str(&e))
}
/// Get all schema values (evaluations ending with .value)
/// Mutates internal data by overriding with values from value evaluations
///
/// @returns Modified data as JavaScript object
#[wasm_bindgen(js_name = getSchemaValue)]
pub fn get_schema_value(&mut self) -> Result<JsValue, JsValue> {
let result = self.inner.get_schema_value();
super::to_value(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get all schema values as array of path-value pairs
/// Returns [{path: "", value: ""}, ...]
///
/// @returns Array of {path, value} objects as JavaScript array
#[wasm_bindgen(js_name = getSchemaValueArray)]
pub fn get_schema_value_array(&self) -> Result<JsValue, JsValue> {
let result = self.inner.get_schema_value_array();
super::to_value(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get all schema values as object with dotted path keys
/// Returns {path: value, ...}
///
/// @returns Flat object with dotted paths as keys
#[wasm_bindgen(js_name = getSchemaValueObject)]
pub fn get_schema_value_object(&self) -> Result<JsValue, JsValue> {
let result = self.inner.get_schema_value_object();
super::to_value(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get the evaluated schema without $params field (compact)
///
/// @returns Evaluated schema as JSON string
#[wasm_bindgen(js_name = getEvaluatedSchemaWithoutParams)]
pub fn get_evaluated_schema_without_params(&mut self) -> String {
let result = self.inner.get_evaluated_schema_without_params();
serde_json::to_string(&result).unwrap_or_else(|_| "{}".to_string())
}
/// Get the evaluated schema without $params as JavaScript object
///
/// @returns Evaluated schema as JavaScript object
#[wasm_bindgen(js_name = getEvaluatedSchemaWithoutParamsJS)]
pub fn get_evaluated_schema_without_params_js(&mut self) -> Result<JsValue, JsValue> {
let result = self.inner.get_evaluated_schema_without_params();
super::to_value(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get a value from the evaluated schema using dotted path notation
///
/// @param path - Dotted path to the value (e.g., "properties.field.value")
/// @returns Value as JSON string or null if not found
#[wasm_bindgen(js_name = getEvaluatedSchemaByPath)]
pub fn get_evaluated_schema_by_path(&mut self, path: &str) -> Option<String> {
self.inner
.get_evaluated_schema_by_path(path)
.map(|v| serde_json::to_string(&v).unwrap_or_else(|_| "null".to_string()))
}
/// Get a value from the evaluated schema using dotted path notation as JavaScript object
///
/// @param path - Dotted path to the value (e.g., "properties.field.value")
/// @returns Value as JavaScript object or null if not found
#[wasm_bindgen(js_name = getEvaluatedSchemaByPathJS)]
pub fn get_evaluated_schema_by_path_js(&mut self, path: &str) -> Result<JsValue, JsValue> {
match self.inner.get_evaluated_schema_by_path(path) {
Some(value) => super::to_value(&value).map_err(|e| JsValue::from_str(&e.to_string())),
None => Ok(JsValue::NULL),
}
}
/// Get values from evaluated schema using multiple dotted paths
/// @param pathsJson - JSON array of dotted paths
/// @param format - Return format (0=Nested, 1=Flat, 2=Array)
/// @returns Data in specified format as JSON string
#[wasm_bindgen(js_name = getEvaluatedSchemaByPaths)]
pub fn get_evaluated_schema_by_paths(
&mut self,
paths_json: &str,
format: u8,
) -> Result<String, JsValue> {
// Parse JSON array of paths
let paths: Vec<String> = serde_json::from_str(paths_json)
.map_err(|e| JsValue::from_str(&format!("Failed to parse paths JSON: {}", e)))?;
let return_format = match format {
1 => crate::ReturnFormat::Flat,
2 => crate::ReturnFormat::Array,
_ => crate::ReturnFormat::Nested,
};
let result = self
.inner
.get_evaluated_schema_by_paths(&paths, Some(return_format));
serde_json::to_string(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get values from evaluated schema using multiple dotted paths (JS object)
/// @param pathsJson - JSON array of dotted paths
/// @param format - Return format (0=Nested, 1=Flat, 2=Array)
/// @returns Data in specified format as JavaScript object
#[wasm_bindgen(js_name = getEvaluatedSchemaByPathsJS)]
pub fn get_evaluated_schema_by_paths_js(
&mut self,
paths_json: &str,
format: u8,
) -> Result<JsValue, JsValue> {
// Parse JSON array of paths
let paths: Vec<String> = serde_json::from_str(paths_json)
.map_err(|e| JsValue::from_str(&format!("Failed to parse paths JSON: {}", e)))?;
let return_format = match format {
1 => crate::ReturnFormat::Flat,
2 => crate::ReturnFormat::Array,
_ => crate::ReturnFormat::Nested,
};
let result = self
.inner
.get_evaluated_schema_by_paths(&paths, Some(return_format));
super::to_value(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get a value from the schema using dotted path notation
///
/// @param path - Dotted path to the value (e.g., "properties.field.value")
/// @returns Value as JSON string or null if not found
#[wasm_bindgen(js_name = getSchemaByPath)]
pub fn get_schema_by_path(&self, path: &str) -> Option<String> {
self.inner
.get_schema_by_path(path)
.map(|v| serde_json::to_string(&v).unwrap_or_else(|_| "null".to_string()))
}
/// Get a value from the schema using dotted path notation as JavaScript object
///
/// @param path - Dotted path to the value (e.g., "properties.field.value")
/// @returns Value as JavaScript object or null if not found
#[wasm_bindgen(js_name = getSchemaByPathJS)]
pub fn get_schema_by_path_js(&self, path: &str) -> Result<JsValue, JsValue> {
match self.inner.get_schema_by_path(path) {
Some(value) => super::to_value(&value).map_err(|e| JsValue::from_str(&e.to_string())),
None => Ok(JsValue::NULL),
}
}
/// Get values from schema using multiple dotted paths
/// @param pathsJson - JSON array of dotted paths
/// @param format - Return format (0=Nested, 1=Flat, 2=Array)
/// @returns Data in specified format as JSON string
#[wasm_bindgen(js_name = getSchemaByPaths)]
pub fn get_schema_by_paths(&self, paths_json: &str, format: u8) -> Result<String, JsValue> {
// Parse JSON array of paths
let paths: Vec<String> = serde_json::from_str(paths_json)
.map_err(|e| JsValue::from_str(&format!("Failed to parse paths JSON: {}", e)))?;
let return_format = match format {
1 => crate::ReturnFormat::Flat,
2 => crate::ReturnFormat::Array,
_ => crate::ReturnFormat::Nested,
};
let result = self.inner.get_schema_by_paths(&paths, Some(return_format));
serde_json::to_string(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get values from schema using multiple dotted paths (JS object)
/// @param pathsJson - JSON array of dotted paths
/// @param format - Return format (0=Nested, 1=Flat, 2=Array)
/// @returns Data in specified format as JavaScript object
#[wasm_bindgen(js_name = getSchemaByPathsJS)]
pub fn get_schema_by_paths_js(&self, paths_json: &str, format: u8) -> Result<JsValue, JsValue> {
// Parse JSON array of paths
let paths: Vec<String> = serde_json::from_str(paths_json)
.map_err(|e| JsValue::from_str(&format!("Failed to parse paths JSON: {}", e)))?;
let return_format = match format {
1 => crate::ReturnFormat::Flat,
2 => crate::ReturnFormat::Array,
_ => crate::ReturnFormat::Nested,
};
let result = self.inner.get_schema_by_paths(&paths, Some(return_format));
super::to_value(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Reload schema with new data
///
/// @param schema - New JSON schema string
/// @param context - Optional context data JSON string
/// @param data - Optional initial data JSON string
#[wasm_bindgen(js_name = reloadSchema)]
pub fn reload_schema(
&mut self,
schema: &str,
context: Option<String>,
data: Option<String>,
) -> Result<(), JsValue> {
let ctx = context.as_deref();
let dt = data.as_deref();
self.inner.reload_schema(schema, ctx, dt).map_err(|e| {
let error_msg = format!("Failed to reload schema: {}", e);
console_log(&format!("[WASM ERROR] {}", error_msg));
JsValue::from_str(&error_msg)
})
}
/// Reload schema from MessagePack-encoded bytes
///
/// @param schemaMsgpack - MessagePack-encoded schema bytes (Uint8Array)
/// @param context - Optional context data JSON string
/// @param data - Optional initial data JSON string
#[wasm_bindgen(js_name = reloadSchemaMsgpack)]
pub fn reload_schema_msgpack(
&mut self,
schema_msgpack: &[u8],
context: Option<String>,
data: Option<String>,
) -> Result<(), JsValue> {
let ctx = context.as_deref();
let dt = data.as_deref();
self.inner
.reload_schema_msgpack(schema_msgpack, ctx, dt)
.map_err(|e| {
let error_msg = format!("Failed to reload schema from MessagePack: {}", e);
console_log(&format!("[WASM ERROR] {}", error_msg));
JsValue::from_str(&error_msg)
})
}
/// Reload schema from ParsedSchemaCache using a cache key
///
/// @param cacheKey - Cache key to lookup in the global ParsedSchemaCache
/// @param context - Optional context data JSON string
/// @param data - Optional initial data JSON string
#[wasm_bindgen(js_name = reloadSchemaFromCache)]
pub fn reload_schema_from_cache(
&mut self,
cache_key: &str,
context: Option<String>,
data: Option<String>,
) -> Result<(), JsValue> {
let ctx = context.as_deref();
let dt = data.as_deref();
self.inner
.reload_schema_from_cache(cache_key, ctx, dt)
.map_err(|e| {
let error_msg = format!("Failed to reload schema from cache: {}", e);
console_log(&format!("[WASM ERROR] {}", error_msg));
JsValue::from_str(&error_msg)
})
}
/// Get the resolved layout overlays (separate from evaluated schema)
///
/// @returns LayoutOverlayEntry array as JavaScript object
#[wasm_bindgen(js_name = getResolvedLayout)]
pub fn get_resolved_layout(&mut self) -> Result<JsValue, JsValue> {
let result = self.inner.get_resolved_layout();
super::to_value(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get the evaluated schema with $layout resolution merged in
/// Convenience method — equivalent to compact schema + overlay merge
///
/// @returns Fully resolved evaluated schema as JavaScript object
#[wasm_bindgen(js_name = getEvaluatedSchemaResolved)]
pub fn get_evaluated_schema_resolved(&mut self) -> Result<JsValue, JsValue> {
let result = self.inner.get_evaluated_schema_resolved();
super::to_value(&result).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Evaluate and return the options for a specific field on demand.
///
/// Accepts dotted notation (`form.occupation`), JSON pointer
/// (`/properties/form/properties/occupation`), or schema ref
/// (`#/properties/form/properties/occupation`).
///
/// @param fieldPath - Field path in dotted, pointer, or ref notation
/// @returns Options as JSON string, or null if the field has no options
#[wasm_bindgen(js_name = getFieldOptions)]
pub fn get_field_options(&mut self, field_path: &str) -> Option<String> {
self.inner
.get_field_options(field_path)
.map(|v| serde_json::to_string(&v).unwrap_or_else(|_| "null".to_string()))
}
/// Evaluate and return the options for a specific field on demand (as JavaScript object).
///
/// Accepts dotted notation (`form.occupation`), JSON pointer
/// (`/properties/form/properties/occupation`), or schema ref
/// (`#/properties/form/properties/occupation`).
///
/// @param fieldPath - Field path in dotted, pointer, or ref notation
/// @returns Options as JavaScript value, or null if the field has no options
#[wasm_bindgen(js_name = getFieldOptionsJS)]
pub fn get_field_options_js(&mut self, field_path: &str) -> Result<JsValue, JsValue> {
match self.inner.get_field_options(field_path) {
Some(value) => super::to_value(&value).map_err(|e| JsValue::from_str(&e.to_string())),
None => Ok(JsValue::NULL),
}
}
}
impl JSONEvalWasm {
/// Rust-only helper to get resolved schema (testable)
pub fn get_evaluated_schema_resolved_to_value(&mut self) -> serde_json::Value {
self.inner.get_evaluated_schema_resolved()
}
}