@json-eval-rs/react-native 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,778 @@
1
+ import React from 'react';
2
+ import { NativeModules, Platform } from 'react-native';
3
+ const LINKING_ERROR = `The package '@json-eval-rs/react-native' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
4
+ ios: "- You have run 'pod install'\n",
5
+ default: ''
6
+ }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n';
7
+ const JsonEvalRs = NativeModules.JsonEvalRs ? NativeModules.JsonEvalRs : new Proxy({}, {
8
+ get() {
9
+ throw new Error(LINKING_ERROR);
10
+ }
11
+ });
12
+
13
+ /**
14
+ * Validation error for a specific field
15
+ */
16
+
17
+ /**
18
+ * Result of validation operation
19
+ */
20
+
21
+ /**
22
+ * Dependent field change from evaluateDependents
23
+ */
24
+
25
+ /**
26
+ * Options for creating a JSONEval instance
27
+ */
28
+
29
+ /**
30
+ * Options for evaluation
31
+ */
32
+
33
+ /**
34
+ * Options for validation with path filtering
35
+ */
36
+
37
+ /**
38
+ * Cache statistics
39
+ */
40
+
41
+ /**
42
+ * Options for evaluating dependents
43
+ */
44
+
45
+ /**
46
+ * Options for evaluating a subform
47
+ */
48
+
49
+ /**
50
+ * Options for validating a subform
51
+ */
52
+
53
+ /**
54
+ * Options for evaluating dependents in a subform
55
+ */
56
+
57
+ /**
58
+ * Options for resolving layout in a subform
59
+ */
60
+
61
+ /**
62
+ * Options for getting evaluated schema from a subform
63
+ */
64
+
65
+ /**
66
+ * Options for getting schema value from a subform
67
+ */
68
+
69
+ /**
70
+ * Options for getting evaluated schema by path from a subform
71
+ */
72
+
73
+ /**
74
+ * Options for getting evaluated schema by multiple paths from a subform
75
+ */
76
+
77
+ /**
78
+ * Options for getting schema by path from a subform
79
+ */
80
+
81
+ /**
82
+ * Options for getting schema by multiple paths from a subform
83
+ */
84
+
85
+ /**
86
+ * High-performance JSON Logic evaluator with schema validation for React Native
87
+ *
88
+ * ## Zero-Copy Architecture
89
+ *
90
+ * This binding is optimized for minimal memory copies:
91
+ * - **Rust FFI Layer**: Returns raw pointers (zero-copy)
92
+ * - **C++ Bridge**: Uses direct pointer access with single-copy string construction
93
+ * - **Native Platform**: Minimizes intermediate conversions
94
+ * - **JS Bridge**: React Native's architecture requires serialization (unavoidable)
95
+ *
96
+ * While true zero-copy across JS/Native boundary is not possible due to React Native's
97
+ * architecture, we minimize copies within the native layer to maximize performance.
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * import { JSONEval } from '@json-eval-rs/react-native';
102
+ *
103
+ * const schema = {
104
+ * type: 'object',
105
+ * properties: {
106
+ * user: {
107
+ * type: 'object',
108
+ * properties: {
109
+ * name: {
110
+ * type: 'string',
111
+ * rules: {
112
+ * required: { value: true, message: 'Name is required' }
113
+ * }
114
+ * }
115
+ * }
116
+ * }
117
+ * }
118
+ * };
119
+ *
120
+ * const eval = new JSONEval({ schema });
121
+ *
122
+ * const data = { user: { name: 'John' } };
123
+ * const result = await eval.evaluate({ data });
124
+ * console.log(result);
125
+ *
126
+ * const validation = await eval.validate({ data });
127
+ * if (validation.hasError) {
128
+ * console.error('Validation errors:', validation.errors);
129
+ * }
130
+ *
131
+ * await eval.dispose();
132
+ * ```
133
+ */
134
+ export class JSONEval {
135
+ disposed = false;
136
+
137
+ /**
138
+ * Creates a new JSON evaluator instance from a cached ParsedSchema
139
+ * @param cacheKey - Cache key to lookup in the global ParsedSchemaCache
140
+ * @param context - Optional context data
141
+ * @param data - Optional initial data
142
+ * @returns New JSONEval instance
143
+ * @throws {Error} If schema not found in cache or creation fails
144
+ */
145
+ static fromCache(cacheKey, context, data) {
146
+ const contextStr = context ? typeof context === 'string' ? context : JSON.stringify(context) : null;
147
+ const dataStr = data ? typeof data === 'string' ? data : JSON.stringify(data) : null;
148
+ const handle = JsonEvalRs.createFromCache(cacheKey, contextStr, dataStr);
149
+ return new JSONEval({
150
+ schema: {},
151
+ _handle: handle
152
+ });
153
+ }
154
+
155
+ /**
156
+ * Creates a new JSON evaluator instance
157
+ * @param options - Configuration options with schema, context, and data
158
+ * @throws {Error} If creation fails
159
+ */
160
+ constructor(options) {
161
+ // If handle is provided (from static factory), use it directly
162
+ if (options._handle) {
163
+ this.handle = options._handle;
164
+ return;
165
+ }
166
+ const {
167
+ schema,
168
+ context,
169
+ data
170
+ } = options;
171
+ try {
172
+ const schemaStr = typeof schema === 'string' ? schema : JSON.stringify(schema);
173
+ const contextStr = context ? typeof context === 'string' ? context : JSON.stringify(context) : null;
174
+ const dataStr = data ? typeof data === 'string' ? data : JSON.stringify(data) : null;
175
+ this.handle = JsonEvalRs.create(schemaStr, contextStr, dataStr);
176
+ } catch (error) {
177
+ const errorMessage = error instanceof Error ? error.message : String(error);
178
+ throw new Error(`Failed to create JSONEval instance: ${errorMessage}`);
179
+ }
180
+ }
181
+ throwIfDisposed() {
182
+ if (this.disposed) {
183
+ throw new Error('JSONEval instance has been disposed');
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Convert value to JSON string
189
+ * Performance note: If you have a pre-serialized JSON string, pass it directly
190
+ * instead of an object to avoid the JSON.stringify overhead
191
+ */
192
+ toJsonString(value) {
193
+ return typeof value === 'string' ? value : JSON.stringify(value);
194
+ }
195
+
196
+ /**
197
+ * Evaluate schema with provided data
198
+ * @param options - Evaluation options
199
+ * @returns Promise resolving to evaluated schema object
200
+ * @throws {Error} If evaluation fails
201
+ */
202
+ async evaluate(options) {
203
+ this.throwIfDisposed();
204
+ try {
205
+ const dataStr = this.toJsonString(options.data);
206
+ const contextStr = options.context ? this.toJsonString(options.context) : null;
207
+ const resultStr = await JsonEvalRs.evaluate(this.handle, dataStr, contextStr);
208
+ return JSON.parse(resultStr);
209
+ } catch (error) {
210
+ const errorMessage = error instanceof Error ? error.message : String(error);
211
+ throw new Error(`Evaluation failed: ${errorMessage}`);
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Validate data against schema rules
217
+ * @param options - Validation options
218
+ * @returns Promise resolving to ValidationResult
219
+ * @throws {Error} If validation operation fails
220
+ */
221
+ async validate(options) {
222
+ this.throwIfDisposed();
223
+ try {
224
+ const dataStr = this.toJsonString(options.data);
225
+ const contextStr = options.context ? this.toJsonString(options.context) : null;
226
+ const resultStr = await JsonEvalRs.validate(this.handle, dataStr, contextStr);
227
+ return JSON.parse(resultStr);
228
+ } catch (error) {
229
+ const errorMessage = error instanceof Error ? error.message : String(error);
230
+ throw new Error(`Validation failed: ${errorMessage}`);
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Re-evaluate fields that depend on a changed path
236
+ * @param options - Dependent evaluation options
237
+ * @returns Promise resolving to array of dependent field changes
238
+ * @throws {Error} If evaluation fails
239
+ */
240
+ async evaluateDependents(options) {
241
+ this.throwIfDisposed();
242
+ try {
243
+ const {
244
+ changedPaths,
245
+ data,
246
+ context,
247
+ reEvaluate = false
248
+ } = options;
249
+ const changedPathsJson = JSON.stringify(changedPaths);
250
+ const dataStr = data ? this.toJsonString(data) : null;
251
+ const contextStr = context ? this.toJsonString(context) : null;
252
+ const resultStr = await JsonEvalRs.evaluateDependents(this.handle, changedPathsJson, dataStr, contextStr, reEvaluate);
253
+ return JSON.parse(resultStr);
254
+ } catch (error) {
255
+ const errorMessage = error instanceof Error ? error.message : String(error);
256
+ throw new Error(`Dependent evaluation failed: ${errorMessage}`);
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Get the evaluated schema with optional layout resolution
262
+ * @param skipLayout - Whether to skip layout resolution (default: false)
263
+ * @returns Promise resolving to evaluated schema object
264
+ * @throws {Error} If operation fails
265
+ */
266
+ async getEvaluatedSchema(skipLayout = false) {
267
+ this.throwIfDisposed();
268
+ const resultStr = await JsonEvalRs.getEvaluatedSchema(this.handle, skipLayout);
269
+ return JSON.parse(resultStr);
270
+ }
271
+
272
+ /**
273
+ * Get all schema values (evaluations ending with .value)
274
+ * @returns Promise resolving to map of path -> value
275
+ * @throws {Error} If operation fails
276
+ */
277
+ async getSchemaValue() {
278
+ this.throwIfDisposed();
279
+ const resultStr = await JsonEvalRs.getSchemaValue(this.handle);
280
+ return JSON.parse(resultStr);
281
+ }
282
+
283
+ /**
284
+ * Get the evaluated schema without $params field
285
+ * @param skipLayout - Whether to skip layout resolution (default: false)
286
+ * @returns Promise resolving to evaluated schema object
287
+ * @throws {Error} If operation fails
288
+ */
289
+ async getEvaluatedSchemaWithoutParams(skipLayout = false) {
290
+ this.throwIfDisposed();
291
+ const resultStr = await JsonEvalRs.getEvaluatedSchemaWithoutParams(this.handle, skipLayout);
292
+ return JSON.parse(resultStr);
293
+ }
294
+
295
+ /**
296
+ * Get a value from the evaluated schema using dotted path notation
297
+ * @param path - Dotted path to the value (e.g., "properties.field.value")
298
+ * @param skipLayout - Whether to skip layout resolution
299
+ * @returns Promise resolving to the value at the path, or null if not found
300
+ * @throws {Error} If operation fails
301
+ */
302
+ async getEvaluatedSchemaByPath(path, skipLayout = false) {
303
+ this.throwIfDisposed();
304
+ const resultStr = await JsonEvalRs.getEvaluatedSchemaByPath(this.handle, path, skipLayout);
305
+ return resultStr ? JSON.parse(resultStr) : null;
306
+ }
307
+
308
+ /**
309
+ * Get values from the evaluated schema using multiple dotted path notations
310
+ * Returns a merged object containing all requested paths (skips paths that are not found)
311
+ * @param paths - Array of dotted paths to retrieve
312
+ * @param skipLayout - Whether to skip layout resolution
313
+ * @returns Promise resolving to merged object containing all found paths
314
+ * @throws {Error} If operation fails
315
+ */
316
+ async getEvaluatedSchemaByPaths(paths, skipLayout = false) {
317
+ this.throwIfDisposed();
318
+ const pathsJson = JSON.stringify(paths);
319
+ const resultStr = await JsonEvalRs.getEvaluatedSchemaByPaths(this.handle, pathsJson, skipLayout);
320
+ return JSON.parse(resultStr);
321
+ }
322
+
323
+ /**
324
+ * Get a value from the schema using dotted path notation
325
+ * @param path - Dotted path to the value (e.g., "properties.field.value")
326
+ * @returns Promise resolving to the value at the path, or null if not found
327
+ * @throws {Error} If operation fails
328
+ */
329
+ async getSchemaByPath(path) {
330
+ this.throwIfDisposed();
331
+ const resultStr = await JsonEvalRs.getSchemaByPath(this.handle, path);
332
+ return resultStr ? JSON.parse(resultStr) : null;
333
+ }
334
+
335
+ /**
336
+ * Get values from the schema using multiple dotted path notations
337
+ * Returns a merged object containing all requested paths (skips paths that are not found)
338
+ * @param paths - Array of dotted paths to retrieve
339
+ * @returns Promise resolving to merged object containing all found paths
340
+ * @throws {Error} If operation fails
341
+ */
342
+ async getSchemaByPaths(paths) {
343
+ this.throwIfDisposed();
344
+ const pathsJson = JSON.stringify(paths);
345
+ const resultStr = await JsonEvalRs.getSchemaByPaths(this.handle, pathsJson);
346
+ return JSON.parse(resultStr);
347
+ }
348
+
349
+ /**
350
+ * Reload schema with new data
351
+ * @param options - Configuration options with new schema, context, and data
352
+ * @throws {Error} If reload fails
353
+ */
354
+ async reloadSchema(options) {
355
+ this.throwIfDisposed();
356
+ try {
357
+ const {
358
+ schema,
359
+ context,
360
+ data
361
+ } = options;
362
+ const schemaStr = typeof schema === 'string' ? schema : JSON.stringify(schema);
363
+ const contextStr = context ? typeof context === 'string' ? context : JSON.stringify(context) : null;
364
+ const dataStr = data ? typeof data === 'string' ? data : JSON.stringify(data) : null;
365
+ await JsonEvalRs.reloadSchema(this.handle, schemaStr, contextStr, dataStr);
366
+ } catch (error) {
367
+ const errorMessage = error instanceof Error ? error.message : String(error);
368
+ throw new Error(`Failed to reload schema: ${errorMessage}`);
369
+ }
370
+ }
371
+
372
+ /**
373
+ * Reload schema from MessagePack bytes
374
+ * @param schemaMsgpack - MessagePack-encoded schema bytes (Uint8Array or number array)
375
+ * @param context - Optional context data
376
+ * @param data - Optional initial data
377
+ * @throws {Error} If reload fails
378
+ */
379
+ async reloadSchemaMsgpack(schemaMsgpack, context, data) {
380
+ this.throwIfDisposed();
381
+ try {
382
+ // Convert Uint8Array to number array if needed
383
+ const msgpackArray = schemaMsgpack instanceof Uint8Array ? Array.from(schemaMsgpack) : schemaMsgpack;
384
+ const contextStr = context ? typeof context === 'string' ? context : JSON.stringify(context) : null;
385
+ const dataStr = data ? typeof data === 'string' ? data : JSON.stringify(data) : null;
386
+ await JsonEvalRs.reloadSchemaMsgpack(this.handle, msgpackArray, contextStr, dataStr);
387
+ } catch (error) {
388
+ const errorMessage = error instanceof Error ? error.message : String(error);
389
+ throw new Error(`Failed to reload schema from MessagePack: ${errorMessage}`);
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Reload schema from ParsedSchemaCache using a cache key
395
+ * @param cacheKey - Cache key to lookup in the global ParsedSchemaCache
396
+ * @param context - Optional context data
397
+ * @param data - Optional initial data
398
+ * @throws {Error} If reload fails or schema not found in cache
399
+ */
400
+ async reloadSchemaFromCache(cacheKey, context, data) {
401
+ this.throwIfDisposed();
402
+ try {
403
+ const contextStr = context ? typeof context === 'string' ? context : JSON.stringify(context) : null;
404
+ const dataStr = data ? typeof data === 'string' ? data : JSON.stringify(data) : null;
405
+ await JsonEvalRs.reloadSchemaFromCache(this.handle, cacheKey, contextStr, dataStr);
406
+ } catch (error) {
407
+ const errorMessage = error instanceof Error ? error.message : String(error);
408
+ throw new Error(`Failed to reload schema from cache: ${errorMessage}`);
409
+ }
410
+ }
411
+
412
+ /**
413
+ * Get cache statistics
414
+ * @returns Promise resolving to cache statistics
415
+ * @throws {Error} If operation fails
416
+ */
417
+ async cacheStats() {
418
+ this.throwIfDisposed();
419
+ const resultStr = await JsonEvalRs.cacheStats(this.handle);
420
+ return JSON.parse(resultStr);
421
+ }
422
+
423
+ /**
424
+ * Clear the evaluation cache
425
+ * @returns Promise that resolves when cache is cleared
426
+ * @throws {Error} If operation fails
427
+ */
428
+ async clearCache() {
429
+ this.throwIfDisposed();
430
+ await JsonEvalRs.clearCache(this.handle);
431
+ }
432
+
433
+ /**
434
+ * Get the number of cached entries
435
+ * @returns Promise resolving to number of cached entries
436
+ * @throws {Error} If operation fails
437
+ */
438
+ async cacheLen() {
439
+ this.throwIfDisposed();
440
+ return await JsonEvalRs.cacheLen(this.handle);
441
+ }
442
+
443
+ /**
444
+ * Enable evaluation caching
445
+ * Useful for reusing JSONEval instances with different data
446
+ * @returns Promise that resolves when cache is enabled
447
+ * @throws {Error} If operation fails
448
+ */
449
+ async enableCache() {
450
+ this.throwIfDisposed();
451
+ await JsonEvalRs.enableCache(this.handle);
452
+ }
453
+
454
+ /**
455
+ * Disable evaluation caching
456
+ * Useful for web API usage where each request creates a new JSONEval instance
457
+ * Improves performance by skipping cache operations that have no benefit for single-use instances
458
+ * @returns Promise that resolves when cache is disabled
459
+ * @throws {Error} If operation fails
460
+ */
461
+ async disableCache() {
462
+ this.throwIfDisposed();
463
+ await JsonEvalRs.disableCache(this.handle);
464
+ }
465
+
466
+ /**
467
+ * Check if evaluation caching is enabled
468
+ * @returns Boolean indicating if caching is enabled
469
+ * @throws {Error} If operation fails
470
+ */
471
+ isCacheEnabled() {
472
+ this.throwIfDisposed();
473
+ return JsonEvalRs.isCacheEnabled(this.handle);
474
+ }
475
+
476
+ /**
477
+ * Resolve layout with optional evaluation
478
+ * @param evaluate - If true, runs evaluation before resolving layout (default: false)
479
+ * @returns Promise that resolves when layout resolution is complete
480
+ * @throws {Error} If operation fails
481
+ */
482
+ async resolveLayout(evaluate = false) {
483
+ this.throwIfDisposed();
484
+ await JsonEvalRs.resolveLayout(this.handle, evaluate);
485
+ }
486
+
487
+ /**
488
+ * Compile and run JSON logic from a JSON logic string
489
+ * @param logicStr - JSON logic expression as a string or object
490
+ * @param data - Optional JSON data string or object (null to use existing data)
491
+ * @param context - Optional context data string or object (null to use existing context)
492
+ * @returns Promise resolving to the result of the evaluation
493
+ * @throws {Error} If compilation or evaluation fails
494
+ */
495
+ async compileAndRunLogic(logicStr, data, context) {
496
+ this.throwIfDisposed();
497
+ const logic = this.toJsonString(logicStr);
498
+ const dataStr = data ? this.toJsonString(data) : null;
499
+ const contextStr = context ? this.toJsonString(context) : null;
500
+ const resultStr = await JsonEvalRs.compileAndRunLogic(this.handle, logic, dataStr, contextStr);
501
+ return JSON.parse(resultStr);
502
+ }
503
+
504
+ /**
505
+ * Compile JSON logic and return a global ID
506
+ * @param logicStr - JSON logic expression as a string or object
507
+ * @returns Promise resolving to the compiled logic ID
508
+ * @throws {Error} If compilation fails
509
+ */
510
+ async compileLogic(logicStr) {
511
+ this.throwIfDisposed();
512
+ const logic = this.toJsonString(logicStr);
513
+ return await JsonEvalRs.compileLogic(this.handle, logic);
514
+ }
515
+
516
+ /**
517
+ * Run pre-compiled logic by ID
518
+ * @param logicId - Compiled logic ID from compileLogic
519
+ * @param data - Optional JSON data string or object (null to use existing data)
520
+ * @param context - Optional context data string or object (null to use existing context)
521
+ * @returns Promise resolving to the result of the evaluation
522
+ * @throws {Error} If execution fails
523
+ */
524
+ async runLogic(logicId, data, context) {
525
+ this.throwIfDisposed();
526
+ const dataStr = data ? this.toJsonString(data) : null;
527
+ const contextStr = context ? this.toJsonString(context) : null;
528
+ const resultStr = await JsonEvalRs.runLogic(this.handle, logicId, dataStr, contextStr);
529
+ return JSON.parse(resultStr);
530
+ }
531
+
532
+ /**
533
+ * Validate data against schema rules with optional path filtering
534
+ * @param options - Validation options with optional path filtering
535
+ * @returns Promise resolving to ValidationResult
536
+ * @throws {Error} If validation operation fails
537
+ */
538
+ async validatePaths(options) {
539
+ this.throwIfDisposed();
540
+ const dataStr = this.toJsonString(options.data);
541
+ const contextStr = options.context ? this.toJsonString(options.context) : null;
542
+ const paths = options.paths || null;
543
+ const resultStr = await JsonEvalRs.validatePaths(this.handle, dataStr, contextStr, paths);
544
+ return JSON.parse(resultStr);
545
+ }
546
+
547
+ // ============================================================================
548
+ // Subform Methods
549
+ // ============================================================================
550
+
551
+ /**
552
+ * Evaluate a subform with data
553
+ * @param options - Evaluation options including subform path and data
554
+ * @returns Promise that resolves when evaluation is complete
555
+ * @throws {Error} If evaluation fails
556
+ */
557
+ async evaluateSubform(options) {
558
+ this.throwIfDisposed();
559
+ const dataStr = this.toJsonString(options.data);
560
+ const contextStr = options.context ? this.toJsonString(options.context) : null;
561
+ return JsonEvalRs.evaluateSubform(this.handle, options.subformPath, dataStr, contextStr);
562
+ }
563
+
564
+ /**
565
+ * Validate subform data against its schema rules
566
+ * @param options - Validation options including subform path and data
567
+ * @returns Promise resolving to ValidationResult
568
+ * @throws {Error} If validation fails
569
+ */
570
+ async validateSubform(options) {
571
+ this.throwIfDisposed();
572
+ const dataStr = this.toJsonString(options.data);
573
+ const contextStr = options.context ? this.toJsonString(options.context) : null;
574
+ const resultStr = await JsonEvalRs.validateSubform(this.handle, options.subformPath, dataStr, contextStr);
575
+ return JSON.parse(resultStr);
576
+ }
577
+
578
+ /**
579
+ * Evaluate dependents in a subform when fields change
580
+ * @param options - Options including subform path, changed paths array, and optional data
581
+ * @returns Promise resolving to dependent evaluation results
582
+ * @throws {Error} If evaluation fails
583
+ */
584
+ async evaluateDependentsSubform(options) {
585
+ this.throwIfDisposed();
586
+ const dataStr = options.data ? this.toJsonString(options.data) : null;
587
+ const contextStr = options.context ? this.toJsonString(options.context) : null;
588
+
589
+ // For now, pass the first path since native bridge expects single path (wraps internally)
590
+ const changedPath = options.changedPaths[0] || '';
591
+ const resultStr = await JsonEvalRs.evaluateDependentsSubform(this.handle, options.subformPath, changedPath, dataStr, contextStr);
592
+ return JSON.parse(resultStr);
593
+ }
594
+
595
+ /**
596
+ * Resolve layout for subform
597
+ * @param options - Options including subform path and evaluate flag
598
+ * @returns Promise that resolves when layout is resolved
599
+ * @throws {Error} If layout resolution fails
600
+ */
601
+ async resolveLayoutSubform(options) {
602
+ this.throwIfDisposed();
603
+ return JsonEvalRs.resolveLayoutSubform(this.handle, options.subformPath, options.evaluate || false);
604
+ }
605
+
606
+ /**
607
+ * Get evaluated schema from subform
608
+ * @param options - Options including subform path and resolveLayout flag
609
+ * @returns Promise resolving to evaluated schema
610
+ * @throws {Error} If operation fails
611
+ */
612
+ async getEvaluatedSchemaSubform(options) {
613
+ this.throwIfDisposed();
614
+ const resultStr = await JsonEvalRs.getEvaluatedSchemaSubform(this.handle, options.subformPath, options.resolveLayout || false);
615
+ return JSON.parse(resultStr);
616
+ }
617
+
618
+ /**
619
+ * Get schema value from subform (all .value fields)
620
+ * @param options - Options including subform path
621
+ * @returns Promise resolving to schema values
622
+ * @throws {Error} If operation fails
623
+ */
624
+ async getSchemaValueSubform(options) {
625
+ this.throwIfDisposed();
626
+ const resultStr = await JsonEvalRs.getSchemaValueSubform(this.handle, options.subformPath);
627
+ return JSON.parse(resultStr);
628
+ }
629
+
630
+ /**
631
+ * Get evaluated schema without $params from subform
632
+ * @param options - Options including subform path and resolveLayout flag
633
+ * @returns Promise resolving to evaluated schema without $params
634
+ * @throws {Error} If operation fails
635
+ */
636
+ async getEvaluatedSchemaWithoutParamsSubform(options) {
637
+ this.throwIfDisposed();
638
+ const resultStr = await JsonEvalRs.getEvaluatedSchemaWithoutParamsSubform(this.handle, options.subformPath, options.resolveLayout || false);
639
+ return JSON.parse(resultStr);
640
+ }
641
+
642
+ /**
643
+ * Get evaluated schema by specific path from subform
644
+ * @param options - Options including subform path, schema path, and skipLayout flag
645
+ * @returns Promise resolving to value at path or null if not found
646
+ * @throws {Error} If operation fails
647
+ */
648
+ async getEvaluatedSchemaByPathSubform(options) {
649
+ this.throwIfDisposed();
650
+ const resultStr = await JsonEvalRs.getEvaluatedSchemaByPathSubform(this.handle, options.subformPath, options.schemaPath, options.skipLayout || false);
651
+ return resultStr ? JSON.parse(resultStr) : null;
652
+ }
653
+
654
+ /**
655
+ * Get evaluated schema by multiple paths from subform
656
+ * Returns a merged object containing all requested paths (skips paths that are not found)
657
+ * @param options - Options including subform path, array of schema paths, and skipLayout flag
658
+ * @returns Promise resolving to merged object containing all found paths
659
+ * @throws {Error} If operation fails
660
+ */
661
+ async getEvaluatedSchemaByPathsSubform(options) {
662
+ this.throwIfDisposed();
663
+ const pathsJson = JSON.stringify(options.schemaPaths);
664
+ const resultStr = await JsonEvalRs.getEvaluatedSchemaByPathsSubform(this.handle, options.subformPath, pathsJson, options.skipLayout || false);
665
+ return JSON.parse(resultStr);
666
+ }
667
+
668
+ /**
669
+ * Get list of available subform paths
670
+ * @returns Promise resolving to array of subform paths
671
+ * @throws {Error} If operation fails
672
+ */
673
+ async getSubformPaths() {
674
+ this.throwIfDisposed();
675
+ const resultStr = await JsonEvalRs.getSubformPaths(this.handle);
676
+ return JSON.parse(resultStr);
677
+ }
678
+
679
+ /**
680
+ * Get schema value by specific path from subform
681
+ * @param options - Options including subform path and schema path
682
+ * @returns Promise resolving to value at path or null if not found
683
+ * @throws {Error} If operation fails
684
+ */
685
+ async getSchemaByPathSubform(options) {
686
+ this.throwIfDisposed();
687
+ const resultStr = await JsonEvalRs.getSchemaByPathSubform(this.handle, options.subformPath, options.schemaPath);
688
+ return resultStr ? JSON.parse(resultStr) : null;
689
+ }
690
+
691
+ /**
692
+ * Get schema values by multiple paths from subform
693
+ * Returns a merged object containing all requested paths (skips paths that are not found)
694
+ * @param options - Options including subform path and array of schema paths
695
+ * @returns Promise resolving to merged object containing all found paths
696
+ * @throws {Error} If operation fails
697
+ */
698
+ async getSchemaByPathsSubform(options) {
699
+ this.throwIfDisposed();
700
+ const pathsJson = JSON.stringify(options.schemaPaths);
701
+ const resultStr = await JsonEvalRs.getSchemaByPathsSubform(this.handle, options.subformPath, pathsJson);
702
+ return JSON.parse(resultStr);
703
+ }
704
+
705
+ /**
706
+ * Check if a subform exists at the given path
707
+ * @param subformPath - Path to check
708
+ * @returns Promise resolving to true if subform exists, false otherwise
709
+ * @throws {Error} If operation fails
710
+ */
711
+ async hasSubform(subformPath) {
712
+ this.throwIfDisposed();
713
+ return JsonEvalRs.hasSubform(this.handle, subformPath);
714
+ }
715
+
716
+ /**
717
+ * Dispose of the native resources
718
+ * Must be called when done using the instance
719
+ * @returns Promise that resolves when disposal is complete
720
+ */
721
+ async dispose() {
722
+ if (this.disposed) return;
723
+ await JsonEvalRs.dispose(this.handle);
724
+ this.disposed = true;
725
+ }
726
+
727
+ /**
728
+ * Get the library version
729
+ * @returns Promise resolving to version string
730
+ */
731
+ static async version() {
732
+ return JsonEvalRs.version();
733
+ }
734
+ }
735
+
736
+ /**
737
+ * Hook for using JSONEval in React components with automatic cleanup
738
+ * @param options - Configuration options
739
+ * @returns JSONEval instance or null if not yet initialized
740
+ *
741
+ * @example
742
+ * ```typescript
743
+ * import { useJSONEval } from '@json-eval-rs/react-native';
744
+ *
745
+ * function MyComponent() {
746
+ * const eval = useJSONEval({ schema: mySchema });
747
+ *
748
+ * const handleValidate = async () => {
749
+ * if (!eval) return;
750
+ * const result = await eval.validate({ data: myData });
751
+ * console.log(result);
752
+ * };
753
+ *
754
+ * return <Button onPress={handleValidate} title="Validate" />;
755
+ * }
756
+ * ```
757
+ */
758
+ export function useJSONEval(options) {
759
+ const [evalInstance, setEvalInstance] = React.useState(null);
760
+ React.useEffect(() => {
761
+ const instance = new JSONEval(options);
762
+ setEvalInstance(instance);
763
+ return () => {
764
+ instance.dispose().catch(console.error);
765
+ };
766
+ // eslint-disable-next-line react-hooks/exhaustive-deps
767
+ }, []);
768
+ return evalInstance;
769
+ }
770
+
771
+ // Default export
772
+ export default JSONEval;
773
+
774
+ // For backwards compatibility
775
+ export const multiply = (a, b) => {
776
+ return JsonEvalRs.multiply(a, b);
777
+ };
778
+ //# sourceMappingURL=index.js.map