@json-eval-rs/react-native 0.0.55 → 0.0.57
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.
- package/android/src/main/cpp/json-eval-rn.cpp +76 -16
- package/android/src/main/java/com/jsonevalrs/JsonEvalRsModule.kt +48 -0
- package/android/src/main/jniLibs/arm64-v8a/libjson_eval_rs.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libjson_eval_rs.so +0 -0
- package/android/src/main/jniLibs/x86/libjson_eval_rs.so +0 -0
- package/android/src/main/jniLibs/x86_64/libjson_eval_rs.so +0 -0
- package/cpp/json-eval-bridge.cpp +126 -0
- package/cpp/json-eval-bridge.h +48 -0
- package/ios/JsonEvalRs.mm +78 -0
- package/ios/JsonEvalRs.xcframework/ios-arm64/libjson_eval_rs.a +0 -0
- package/ios/JsonEvalRs.xcframework/ios-arm64_x86_64-simulator/libjson_eval_rs.a +0 -0
- package/lib/commonjs/index.js +70 -17
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +71 -17
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +41 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +400 -131
package/src/index.tsx
CHANGED
|
@@ -18,6 +18,16 @@ const JsonEvalRs = NativeModules.JsonEvalRs
|
|
|
18
18
|
}
|
|
19
19
|
);
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Item for get schema value array results
|
|
23
|
+
*/
|
|
24
|
+
export interface SchemaValueItem {
|
|
25
|
+
/** Dotted path (e.g., "field1.field2") */
|
|
26
|
+
path: string;
|
|
27
|
+
/** Value at this path */
|
|
28
|
+
value: any;
|
|
29
|
+
}
|
|
30
|
+
|
|
21
31
|
/**
|
|
22
32
|
* Return format for path-based methods
|
|
23
33
|
*/
|
|
@@ -27,7 +37,7 @@ export enum ReturnFormat {
|
|
|
27
37
|
/** Flat object with dotted keys */
|
|
28
38
|
Flat = 1,
|
|
29
39
|
/** Array of values in the order of requested paths */
|
|
30
|
-
Array = 2
|
|
40
|
+
Array = 2,
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
/**
|
|
@@ -56,8 +66,8 @@ export interface ValidationError {
|
|
|
56
66
|
export interface ValidationResult {
|
|
57
67
|
/** Whether any validation errors occurred */
|
|
58
68
|
hasError: boolean;
|
|
59
|
-
/**
|
|
60
|
-
|
|
69
|
+
/** Map of validation errors keyed by field path */
|
|
70
|
+
error: Record<string, ValidationError>;
|
|
61
71
|
}
|
|
62
72
|
|
|
63
73
|
/**
|
|
@@ -260,22 +270,22 @@ export interface GetSchemaByPathsSubformOptions {
|
|
|
260
270
|
|
|
261
271
|
/**
|
|
262
272
|
* High-performance JSON Logic evaluator with schema validation for React Native
|
|
263
|
-
*
|
|
273
|
+
*
|
|
264
274
|
* ## Zero-Copy Architecture
|
|
265
|
-
*
|
|
275
|
+
*
|
|
266
276
|
* This binding is optimized for minimal memory copies:
|
|
267
277
|
* - **Rust FFI Layer**: Returns raw pointers (zero-copy)
|
|
268
278
|
* - **C++ Bridge**: Uses direct pointer access with single-copy string construction
|
|
269
279
|
* - **Native Platform**: Minimizes intermediate conversions
|
|
270
280
|
* - **JS Bridge**: React Native's architecture requires serialization (unavoidable)
|
|
271
|
-
*
|
|
281
|
+
*
|
|
272
282
|
* While true zero-copy across JS/Native boundary is not possible due to React Native's
|
|
273
283
|
* architecture, we minimize copies within the native layer to maximize performance.
|
|
274
|
-
*
|
|
284
|
+
*
|
|
275
285
|
* @example
|
|
276
286
|
* ```typescript
|
|
277
287
|
* import { JSONEval } from '@json-eval-rs/react-native';
|
|
278
|
-
*
|
|
288
|
+
*
|
|
279
289
|
* const schema = {
|
|
280
290
|
* type: 'object',
|
|
281
291
|
* properties: {
|
|
@@ -292,18 +302,18 @@ export interface GetSchemaByPathsSubformOptions {
|
|
|
292
302
|
* }
|
|
293
303
|
* }
|
|
294
304
|
* };
|
|
295
|
-
*
|
|
305
|
+
*
|
|
296
306
|
* const eval = new JSONEval({ schema });
|
|
297
|
-
*
|
|
307
|
+
*
|
|
298
308
|
* const data = { user: { name: 'John' } };
|
|
299
309
|
* const result = await eval.evaluate({ data });
|
|
300
310
|
* console.log(result);
|
|
301
|
-
*
|
|
311
|
+
*
|
|
302
312
|
* const validation = await eval.validate({ data });
|
|
303
313
|
* if (validation.hasError) {
|
|
304
314
|
* console.error('Validation errors:', validation.errors);
|
|
305
315
|
* }
|
|
306
|
-
*
|
|
316
|
+
*
|
|
307
317
|
* await eval.dispose();
|
|
308
318
|
* ```
|
|
309
319
|
*/
|
|
@@ -324,9 +334,17 @@ export class JSONEval {
|
|
|
324
334
|
context?: string | object | null,
|
|
325
335
|
data?: string | object | null
|
|
326
336
|
): JSONEval {
|
|
327
|
-
const contextStr = context
|
|
328
|
-
|
|
329
|
-
|
|
337
|
+
const contextStr = context
|
|
338
|
+
? typeof context === 'string'
|
|
339
|
+
? context
|
|
340
|
+
: JSON.stringify(context)
|
|
341
|
+
: null;
|
|
342
|
+
const dataStr = data
|
|
343
|
+
? typeof data === 'string'
|
|
344
|
+
? data
|
|
345
|
+
: JSON.stringify(data)
|
|
346
|
+
: null;
|
|
347
|
+
|
|
330
348
|
const handle = JsonEvalRs.createFromCache(cacheKey, contextStr, dataStr);
|
|
331
349
|
return new JSONEval({ schema: {}, _handle: handle });
|
|
332
350
|
}
|
|
@@ -343,11 +361,24 @@ export class JSONEval {
|
|
|
343
361
|
data?: string | object | null,
|
|
344
362
|
context?: string | object | null
|
|
345
363
|
): Promise<any> {
|
|
346
|
-
const logic =
|
|
347
|
-
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
364
|
+
const logic =
|
|
365
|
+
typeof logicStr === 'string' ? logicStr : JSON.stringify(logicStr);
|
|
366
|
+
const dataStr = data
|
|
367
|
+
? typeof data === 'string'
|
|
368
|
+
? data
|
|
369
|
+
: JSON.stringify(data)
|
|
370
|
+
: null;
|
|
371
|
+
const contextStr = context
|
|
372
|
+
? typeof context === 'string'
|
|
373
|
+
? context
|
|
374
|
+
: JSON.stringify(context)
|
|
375
|
+
: null;
|
|
376
|
+
|
|
377
|
+
const resultStr = await JsonEvalRs.evaluateLogic(
|
|
378
|
+
logic,
|
|
379
|
+
dataStr,
|
|
380
|
+
contextStr
|
|
381
|
+
);
|
|
351
382
|
return JSON.parse(resultStr);
|
|
352
383
|
}
|
|
353
384
|
|
|
@@ -362,17 +393,27 @@ export class JSONEval {
|
|
|
362
393
|
this.handle = options._handle;
|
|
363
394
|
return;
|
|
364
395
|
}
|
|
365
|
-
|
|
396
|
+
|
|
366
397
|
const { schema, context, data } = options;
|
|
367
|
-
|
|
398
|
+
|
|
368
399
|
try {
|
|
369
|
-
const schemaStr =
|
|
370
|
-
|
|
371
|
-
const
|
|
372
|
-
|
|
400
|
+
const schemaStr =
|
|
401
|
+
typeof schema === 'string' ? schema : JSON.stringify(schema);
|
|
402
|
+
const contextStr = context
|
|
403
|
+
? typeof context === 'string'
|
|
404
|
+
? context
|
|
405
|
+
: JSON.stringify(context)
|
|
406
|
+
: null;
|
|
407
|
+
const dataStr = data
|
|
408
|
+
? typeof data === 'string'
|
|
409
|
+
? data
|
|
410
|
+
: JSON.stringify(data)
|
|
411
|
+
: null;
|
|
412
|
+
|
|
373
413
|
this.handle = JsonEvalRs.create(schemaStr, contextStr, dataStr);
|
|
374
414
|
} catch (error) {
|
|
375
|
-
const errorMessage =
|
|
415
|
+
const errorMessage =
|
|
416
|
+
error instanceof Error ? error.message : String(error);
|
|
376
417
|
throw new Error(`Failed to create JSONEval instance: ${errorMessage}`);
|
|
377
418
|
}
|
|
378
419
|
}
|
|
@@ -394,7 +435,7 @@ export class JSONEval {
|
|
|
394
435
|
|
|
395
436
|
/**
|
|
396
437
|
* Cancel any running evaluation
|
|
397
|
-
* The generic auto-cancellation on new evaluation will still work,
|
|
438
|
+
* The generic auto-cancellation on new evaluation will still work,
|
|
398
439
|
* but this allows manual cancellation.
|
|
399
440
|
*/
|
|
400
441
|
async cancel(): Promise<void> {
|
|
@@ -410,16 +451,24 @@ export class JSONEval {
|
|
|
410
451
|
*/
|
|
411
452
|
async evaluate(options: EvaluateOptions): Promise<any> {
|
|
412
453
|
this.throwIfDisposed();
|
|
413
|
-
|
|
454
|
+
|
|
414
455
|
try {
|
|
415
456
|
const dataStr = this.toJsonString(options.data);
|
|
416
|
-
const contextStr = options.context
|
|
457
|
+
const contextStr = options.context
|
|
458
|
+
? this.toJsonString(options.context)
|
|
459
|
+
: null;
|
|
417
460
|
const pathsJson = options.paths ? JSON.stringify(options.paths) : null;
|
|
418
|
-
|
|
419
|
-
const resultStr = await JsonEvalRs.evaluate(
|
|
461
|
+
|
|
462
|
+
const resultStr = await JsonEvalRs.evaluate(
|
|
463
|
+
this.handle,
|
|
464
|
+
dataStr,
|
|
465
|
+
contextStr,
|
|
466
|
+
pathsJson
|
|
467
|
+
);
|
|
420
468
|
return JSON.parse(resultStr);
|
|
421
469
|
} catch (error) {
|
|
422
|
-
const errorMessage =
|
|
470
|
+
const errorMessage =
|
|
471
|
+
error instanceof Error ? error.message : String(error);
|
|
423
472
|
throw new Error(`Evaluation failed: ${errorMessage}`);
|
|
424
473
|
}
|
|
425
474
|
}
|
|
@@ -432,15 +481,22 @@ export class JSONEval {
|
|
|
432
481
|
*/
|
|
433
482
|
async validate(options: EvaluateOptions): Promise<ValidationResult> {
|
|
434
483
|
this.throwIfDisposed();
|
|
435
|
-
|
|
484
|
+
|
|
436
485
|
try {
|
|
437
486
|
const dataStr = this.toJsonString(options.data);
|
|
438
|
-
const contextStr = options.context
|
|
439
|
-
|
|
440
|
-
|
|
487
|
+
const contextStr = options.context
|
|
488
|
+
? this.toJsonString(options.context)
|
|
489
|
+
: null;
|
|
490
|
+
|
|
491
|
+
const resultStr = await JsonEvalRs.validate(
|
|
492
|
+
this.handle,
|
|
493
|
+
dataStr,
|
|
494
|
+
contextStr
|
|
495
|
+
);
|
|
441
496
|
return JSON.parse(resultStr);
|
|
442
497
|
} catch (error) {
|
|
443
|
-
const errorMessage =
|
|
498
|
+
const errorMessage =
|
|
499
|
+
error instanceof Error ? error.message : String(error);
|
|
444
500
|
throw new Error(`Validation failed: ${errorMessage}`);
|
|
445
501
|
}
|
|
446
502
|
}
|
|
@@ -451,15 +507,17 @@ export class JSONEval {
|
|
|
451
507
|
* @returns Promise resolving to array of dependent field changes
|
|
452
508
|
* @throws {Error} If evaluation fails
|
|
453
509
|
*/
|
|
454
|
-
async evaluateDependents(
|
|
510
|
+
async evaluateDependents(
|
|
511
|
+
options: EvaluateDependentsOptions
|
|
512
|
+
): Promise<DependentChange[]> {
|
|
455
513
|
this.throwIfDisposed();
|
|
456
|
-
|
|
514
|
+
|
|
457
515
|
try {
|
|
458
516
|
const { changedPaths, data, context, reEvaluate = true } = options;
|
|
459
517
|
const changedPathsJson = JSON.stringify(changedPaths);
|
|
460
518
|
const dataStr = data ? this.toJsonString(data) : null;
|
|
461
519
|
const contextStr = context ? this.toJsonString(context) : null;
|
|
462
|
-
|
|
520
|
+
|
|
463
521
|
const resultStr = await JsonEvalRs.evaluateDependents(
|
|
464
522
|
this.handle,
|
|
465
523
|
changedPathsJson,
|
|
@@ -469,7 +527,8 @@ export class JSONEval {
|
|
|
469
527
|
);
|
|
470
528
|
return JSON.parse(resultStr);
|
|
471
529
|
} catch (error) {
|
|
472
|
-
const errorMessage =
|
|
530
|
+
const errorMessage =
|
|
531
|
+
error instanceof Error ? error.message : String(error);
|
|
473
532
|
throw new Error(`Dependent evaluation failed: ${errorMessage}`);
|
|
474
533
|
}
|
|
475
534
|
}
|
|
@@ -482,7 +541,10 @@ export class JSONEval {
|
|
|
482
541
|
*/
|
|
483
542
|
async getEvaluatedSchema(skipLayout: boolean = false): Promise<any> {
|
|
484
543
|
this.throwIfDisposed();
|
|
485
|
-
const resultStr = await JsonEvalRs.getEvaluatedSchema(
|
|
544
|
+
const resultStr = await JsonEvalRs.getEvaluatedSchema(
|
|
545
|
+
this.handle,
|
|
546
|
+
skipLayout
|
|
547
|
+
);
|
|
486
548
|
return JSON.parse(resultStr);
|
|
487
549
|
}
|
|
488
550
|
|
|
@@ -497,15 +559,44 @@ export class JSONEval {
|
|
|
497
559
|
return JSON.parse(resultStr);
|
|
498
560
|
}
|
|
499
561
|
|
|
562
|
+
/**
|
|
563
|
+
* Get all schema values as array of path-value pairs
|
|
564
|
+
* Returns [{path: "", value: ""}, ...]
|
|
565
|
+
* @returns Promise resolving to array of SchemaValueItem objects
|
|
566
|
+
* @throws {Error} If operation fails
|
|
567
|
+
*/
|
|
568
|
+
async getSchemaValueArray(): Promise<SchemaValueItem[]> {
|
|
569
|
+
this.throwIfDisposed();
|
|
570
|
+
const resultStr = await JsonEvalRs.getSchemaValueArray(this.handle);
|
|
571
|
+
return JSON.parse(resultStr);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Get all schema values as object with dotted path keys
|
|
576
|
+
* Returns {path: value, ...}
|
|
577
|
+
* @returns Promise resolving to flat object with dotted paths as keys
|
|
578
|
+
* @throws {Error} If operation fails
|
|
579
|
+
*/
|
|
580
|
+
async getSchemaValueObject(): Promise<Record<string, any>> {
|
|
581
|
+
this.throwIfDisposed();
|
|
582
|
+
const resultStr = await JsonEvalRs.getSchemaValueObject(this.handle);
|
|
583
|
+
return JSON.parse(resultStr);
|
|
584
|
+
}
|
|
585
|
+
|
|
500
586
|
/**
|
|
501
587
|
* Get the evaluated schema without $params field
|
|
502
588
|
* @param skipLayout - Whether to skip layout resolution (default: false)
|
|
503
589
|
* @returns Promise resolving to evaluated schema object
|
|
504
590
|
* @throws {Error} If operation fails
|
|
505
591
|
*/
|
|
506
|
-
async getEvaluatedSchemaWithoutParams(
|
|
592
|
+
async getEvaluatedSchemaWithoutParams(
|
|
593
|
+
skipLayout: boolean = false
|
|
594
|
+
): Promise<any> {
|
|
507
595
|
this.throwIfDisposed();
|
|
508
|
-
const resultStr = await JsonEvalRs.getEvaluatedSchemaWithoutParams(
|
|
596
|
+
const resultStr = await JsonEvalRs.getEvaluatedSchemaWithoutParams(
|
|
597
|
+
this.handle,
|
|
598
|
+
skipLayout
|
|
599
|
+
);
|
|
509
600
|
return JSON.parse(resultStr);
|
|
510
601
|
}
|
|
511
602
|
|
|
@@ -516,9 +607,16 @@ export class JSONEval {
|
|
|
516
607
|
* @returns Promise resolving to the value at the path, or null if not found
|
|
517
608
|
* @throws {Error} If operation fails
|
|
518
609
|
*/
|
|
519
|
-
async getEvaluatedSchemaByPath(
|
|
610
|
+
async getEvaluatedSchemaByPath(
|
|
611
|
+
path: string,
|
|
612
|
+
skipLayout: boolean = false
|
|
613
|
+
): Promise<any | null> {
|
|
520
614
|
this.throwIfDisposed();
|
|
521
|
-
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPath(
|
|
615
|
+
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPath(
|
|
616
|
+
this.handle,
|
|
617
|
+
path,
|
|
618
|
+
skipLayout
|
|
619
|
+
);
|
|
522
620
|
return resultStr ? JSON.parse(resultStr) : null;
|
|
523
621
|
}
|
|
524
622
|
|
|
@@ -531,10 +629,19 @@ export class JSONEval {
|
|
|
531
629
|
* @returns Promise resolving to data in the specified format
|
|
532
630
|
* @throws {Error} If operation fails
|
|
533
631
|
*/
|
|
534
|
-
async getEvaluatedSchemaByPaths(
|
|
632
|
+
async getEvaluatedSchemaByPaths(
|
|
633
|
+
paths: string[],
|
|
634
|
+
skipLayout: boolean = false,
|
|
635
|
+
format: ReturnFormat = ReturnFormat.Nested
|
|
636
|
+
): Promise<any> {
|
|
535
637
|
this.throwIfDisposed();
|
|
536
638
|
const pathsJson = JSON.stringify(paths);
|
|
537
|
-
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPaths(
|
|
639
|
+
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPaths(
|
|
640
|
+
this.handle,
|
|
641
|
+
pathsJson,
|
|
642
|
+
skipLayout,
|
|
643
|
+
format
|
|
644
|
+
);
|
|
538
645
|
return JSON.parse(resultStr);
|
|
539
646
|
}
|
|
540
647
|
|
|
@@ -558,10 +665,17 @@ export class JSONEval {
|
|
|
558
665
|
* @returns Promise resolving to data in the specified format
|
|
559
666
|
* @throws {Error} If operation fails
|
|
560
667
|
*/
|
|
561
|
-
async getSchemaByPaths(
|
|
668
|
+
async getSchemaByPaths(
|
|
669
|
+
paths: string[],
|
|
670
|
+
format: ReturnFormat = ReturnFormat.Nested
|
|
671
|
+
): Promise<any> {
|
|
562
672
|
this.throwIfDisposed();
|
|
563
673
|
const pathsJson = JSON.stringify(paths);
|
|
564
|
-
const resultStr = await JsonEvalRs.getSchemaByPaths(
|
|
674
|
+
const resultStr = await JsonEvalRs.getSchemaByPaths(
|
|
675
|
+
this.handle,
|
|
676
|
+
pathsJson,
|
|
677
|
+
format
|
|
678
|
+
);
|
|
565
679
|
return JSON.parse(resultStr);
|
|
566
680
|
}
|
|
567
681
|
|
|
@@ -572,16 +686,31 @@ export class JSONEval {
|
|
|
572
686
|
*/
|
|
573
687
|
async reloadSchema(options: JSONEvalOptions): Promise<void> {
|
|
574
688
|
this.throwIfDisposed();
|
|
575
|
-
|
|
689
|
+
|
|
576
690
|
try {
|
|
577
691
|
const { schema, context, data } = options;
|
|
578
|
-
const schemaStr =
|
|
579
|
-
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
|
|
692
|
+
const schemaStr =
|
|
693
|
+
typeof schema === 'string' ? schema : JSON.stringify(schema);
|
|
694
|
+
const contextStr = context
|
|
695
|
+
? typeof context === 'string'
|
|
696
|
+
? context
|
|
697
|
+
: JSON.stringify(context)
|
|
698
|
+
: null;
|
|
699
|
+
const dataStr = data
|
|
700
|
+
? typeof data === 'string'
|
|
701
|
+
? data
|
|
702
|
+
: JSON.stringify(data)
|
|
703
|
+
: null;
|
|
704
|
+
|
|
705
|
+
await JsonEvalRs.reloadSchema(
|
|
706
|
+
this.handle,
|
|
707
|
+
schemaStr,
|
|
708
|
+
contextStr,
|
|
709
|
+
dataStr
|
|
710
|
+
);
|
|
583
711
|
} catch (error) {
|
|
584
|
-
const errorMessage =
|
|
712
|
+
const errorMessage =
|
|
713
|
+
error instanceof Error ? error.message : String(error);
|
|
585
714
|
throw new Error(`Failed to reload schema: ${errorMessage}`);
|
|
586
715
|
}
|
|
587
716
|
}
|
|
@@ -599,20 +728,37 @@ export class JSONEval {
|
|
|
599
728
|
data?: string | object | null
|
|
600
729
|
): Promise<void> {
|
|
601
730
|
this.throwIfDisposed();
|
|
602
|
-
|
|
731
|
+
|
|
603
732
|
try {
|
|
604
733
|
// Convert Uint8Array to number array if needed
|
|
605
|
-
const msgpackArray =
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
|
|
734
|
+
const msgpackArray =
|
|
735
|
+
schemaMsgpack instanceof Uint8Array
|
|
736
|
+
? Array.from(schemaMsgpack)
|
|
737
|
+
: schemaMsgpack;
|
|
738
|
+
|
|
739
|
+
const contextStr = context
|
|
740
|
+
? typeof context === 'string'
|
|
741
|
+
? context
|
|
742
|
+
: JSON.stringify(context)
|
|
743
|
+
: null;
|
|
744
|
+
const dataStr = data
|
|
745
|
+
? typeof data === 'string'
|
|
746
|
+
? data
|
|
747
|
+
: JSON.stringify(data)
|
|
748
|
+
: null;
|
|
749
|
+
|
|
750
|
+
await JsonEvalRs.reloadSchemaMsgpack(
|
|
751
|
+
this.handle,
|
|
752
|
+
msgpackArray,
|
|
753
|
+
contextStr,
|
|
754
|
+
dataStr
|
|
755
|
+
);
|
|
613
756
|
} catch (error) {
|
|
614
|
-
const errorMessage =
|
|
615
|
-
|
|
757
|
+
const errorMessage =
|
|
758
|
+
error instanceof Error ? error.message : String(error);
|
|
759
|
+
throw new Error(
|
|
760
|
+
`Failed to reload schema from MessagePack: ${errorMessage}`
|
|
761
|
+
);
|
|
616
762
|
}
|
|
617
763
|
}
|
|
618
764
|
|
|
@@ -629,14 +775,28 @@ export class JSONEval {
|
|
|
629
775
|
data?: string | object | null
|
|
630
776
|
): Promise<void> {
|
|
631
777
|
this.throwIfDisposed();
|
|
632
|
-
|
|
778
|
+
|
|
633
779
|
try {
|
|
634
|
-
const contextStr = context
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
780
|
+
const contextStr = context
|
|
781
|
+
? typeof context === 'string'
|
|
782
|
+
? context
|
|
783
|
+
: JSON.stringify(context)
|
|
784
|
+
: null;
|
|
785
|
+
const dataStr = data
|
|
786
|
+
? typeof data === 'string'
|
|
787
|
+
? data
|
|
788
|
+
: JSON.stringify(data)
|
|
789
|
+
: null;
|
|
790
|
+
|
|
791
|
+
await JsonEvalRs.reloadSchemaFromCache(
|
|
792
|
+
this.handle,
|
|
793
|
+
cacheKey,
|
|
794
|
+
contextStr,
|
|
795
|
+
dataStr
|
|
796
|
+
);
|
|
638
797
|
} catch (error) {
|
|
639
|
-
const errorMessage =
|
|
798
|
+
const errorMessage =
|
|
799
|
+
error instanceof Error ? error.message : String(error);
|
|
640
800
|
throw new Error(`Failed to reload schema from cache: ${errorMessage}`);
|
|
641
801
|
}
|
|
642
802
|
}
|
|
@@ -722,15 +882,15 @@ export class JSONEval {
|
|
|
722
882
|
* Pass null to reset to UTC
|
|
723
883
|
* @returns Promise that resolves when timezone is set
|
|
724
884
|
* @throws {Error} If operation fails
|
|
725
|
-
*
|
|
885
|
+
*
|
|
726
886
|
* @example
|
|
727
887
|
* ```typescript
|
|
728
888
|
* // Set to UTC+7 (Jakarta, Bangkok)
|
|
729
889
|
* await eval.setTimezoneOffset(420);
|
|
730
|
-
*
|
|
890
|
+
*
|
|
731
891
|
* // Set to UTC-5 (New York, EST)
|
|
732
892
|
* await eval.setTimezoneOffset(-300);
|
|
733
|
-
*
|
|
893
|
+
*
|
|
734
894
|
* // Reset to UTC
|
|
735
895
|
* await eval.setTimezoneOffset(null);
|
|
736
896
|
* ```
|
|
@@ -748,14 +908,23 @@ export class JSONEval {
|
|
|
748
908
|
* @returns Promise resolving to the result of the evaluation
|
|
749
909
|
* @throws {Error} If compilation or evaluation fails
|
|
750
910
|
*/
|
|
751
|
-
async compileAndRunLogic(
|
|
911
|
+
async compileAndRunLogic(
|
|
912
|
+
logicStr: string | object,
|
|
913
|
+
data?: string | object,
|
|
914
|
+
context?: string | object
|
|
915
|
+
): Promise<any> {
|
|
752
916
|
this.throwIfDisposed();
|
|
753
|
-
|
|
917
|
+
|
|
754
918
|
const logic = this.toJsonString(logicStr);
|
|
755
919
|
const dataStr = data ? this.toJsonString(data) : null;
|
|
756
920
|
const contextStr = context ? this.toJsonString(context) : null;
|
|
757
|
-
|
|
758
|
-
const resultStr = await JsonEvalRs.compileAndRunLogic(
|
|
921
|
+
|
|
922
|
+
const resultStr = await JsonEvalRs.compileAndRunLogic(
|
|
923
|
+
this.handle,
|
|
924
|
+
logic,
|
|
925
|
+
dataStr,
|
|
926
|
+
contextStr
|
|
927
|
+
);
|
|
759
928
|
return JSON.parse(resultStr);
|
|
760
929
|
}
|
|
761
930
|
|
|
@@ -767,7 +936,7 @@ export class JSONEval {
|
|
|
767
936
|
*/
|
|
768
937
|
async compileLogic(logicStr: string | object): Promise<number> {
|
|
769
938
|
this.throwIfDisposed();
|
|
770
|
-
|
|
939
|
+
|
|
771
940
|
const logic = this.toJsonString(logicStr);
|
|
772
941
|
return await JsonEvalRs.compileLogic(this.handle, logic);
|
|
773
942
|
}
|
|
@@ -780,13 +949,22 @@ export class JSONEval {
|
|
|
780
949
|
* @returns Promise resolving to the result of the evaluation
|
|
781
950
|
* @throws {Error} If execution fails
|
|
782
951
|
*/
|
|
783
|
-
async runLogic(
|
|
952
|
+
async runLogic(
|
|
953
|
+
logicId: number,
|
|
954
|
+
data?: string | object,
|
|
955
|
+
context?: string | object
|
|
956
|
+
): Promise<any> {
|
|
784
957
|
this.throwIfDisposed();
|
|
785
|
-
|
|
958
|
+
|
|
786
959
|
const dataStr = data ? this.toJsonString(data) : null;
|
|
787
960
|
const contextStr = context ? this.toJsonString(context) : null;
|
|
788
|
-
|
|
789
|
-
const resultStr = await JsonEvalRs.runLogic(
|
|
961
|
+
|
|
962
|
+
const resultStr = await JsonEvalRs.runLogic(
|
|
963
|
+
this.handle,
|
|
964
|
+
logicId,
|
|
965
|
+
dataStr,
|
|
966
|
+
contextStr
|
|
967
|
+
);
|
|
790
968
|
return JSON.parse(resultStr);
|
|
791
969
|
}
|
|
792
970
|
|
|
@@ -796,14 +974,23 @@ export class JSONEval {
|
|
|
796
974
|
* @returns Promise resolving to ValidationResult
|
|
797
975
|
* @throws {Error} If validation operation fails
|
|
798
976
|
*/
|
|
799
|
-
async validatePaths(
|
|
977
|
+
async validatePaths(
|
|
978
|
+
options: ValidatePathsOptions
|
|
979
|
+
): Promise<ValidationResult> {
|
|
800
980
|
this.throwIfDisposed();
|
|
801
|
-
|
|
981
|
+
|
|
802
982
|
const dataStr = this.toJsonString(options.data);
|
|
803
|
-
const contextStr = options.context
|
|
983
|
+
const contextStr = options.context
|
|
984
|
+
? this.toJsonString(options.context)
|
|
985
|
+
: null;
|
|
804
986
|
const paths = options.paths || null;
|
|
805
|
-
|
|
806
|
-
const resultStr = await JsonEvalRs.validatePaths(
|
|
987
|
+
|
|
988
|
+
const resultStr = await JsonEvalRs.validatePaths(
|
|
989
|
+
this.handle,
|
|
990
|
+
dataStr,
|
|
991
|
+
contextStr,
|
|
992
|
+
paths
|
|
993
|
+
);
|
|
807
994
|
return JSON.parse(resultStr);
|
|
808
995
|
}
|
|
809
996
|
|
|
@@ -819,11 +1006,19 @@ export class JSONEval {
|
|
|
819
1006
|
*/
|
|
820
1007
|
async evaluateSubform(options: EvaluateSubformOptions): Promise<void> {
|
|
821
1008
|
this.throwIfDisposed();
|
|
822
|
-
|
|
1009
|
+
|
|
823
1010
|
const dataStr = this.toJsonString(options.data);
|
|
824
|
-
const contextStr = options.context
|
|
825
|
-
|
|
826
|
-
|
|
1011
|
+
const contextStr = options.context
|
|
1012
|
+
? this.toJsonString(options.context)
|
|
1013
|
+
: null;
|
|
1014
|
+
|
|
1015
|
+
return JsonEvalRs.evaluateSubform(
|
|
1016
|
+
this.handle,
|
|
1017
|
+
options.subformPath,
|
|
1018
|
+
dataStr,
|
|
1019
|
+
contextStr,
|
|
1020
|
+
options.paths
|
|
1021
|
+
);
|
|
827
1022
|
}
|
|
828
1023
|
|
|
829
1024
|
/**
|
|
@@ -832,13 +1027,22 @@ export class JSONEval {
|
|
|
832
1027
|
* @returns Promise resolving to ValidationResult
|
|
833
1028
|
* @throws {Error} If validation fails
|
|
834
1029
|
*/
|
|
835
|
-
async validateSubform(
|
|
1030
|
+
async validateSubform(
|
|
1031
|
+
options: ValidateSubformOptions
|
|
1032
|
+
): Promise<ValidationResult> {
|
|
836
1033
|
this.throwIfDisposed();
|
|
837
|
-
|
|
1034
|
+
|
|
838
1035
|
const dataStr = this.toJsonString(options.data);
|
|
839
|
-
const contextStr = options.context
|
|
840
|
-
|
|
841
|
-
|
|
1036
|
+
const contextStr = options.context
|
|
1037
|
+
? this.toJsonString(options.context)
|
|
1038
|
+
: null;
|
|
1039
|
+
|
|
1040
|
+
const resultStr = await JsonEvalRs.validateSubform(
|
|
1041
|
+
this.handle,
|
|
1042
|
+
options.subformPath,
|
|
1043
|
+
dataStr,
|
|
1044
|
+
contextStr
|
|
1045
|
+
);
|
|
842
1046
|
return JSON.parse(resultStr);
|
|
843
1047
|
}
|
|
844
1048
|
|
|
@@ -848,15 +1052,19 @@ export class JSONEval {
|
|
|
848
1052
|
* @returns Promise resolving to dependent evaluation results
|
|
849
1053
|
* @throws {Error} If evaluation fails
|
|
850
1054
|
*/
|
|
851
|
-
async evaluateDependentsSubform(
|
|
1055
|
+
async evaluateDependentsSubform(
|
|
1056
|
+
options: EvaluateDependentsSubformOptions
|
|
1057
|
+
): Promise<DependentChange[]> {
|
|
852
1058
|
this.throwIfDisposed();
|
|
853
|
-
|
|
1059
|
+
|
|
854
1060
|
const dataStr = options.data ? this.toJsonString(options.data) : null;
|
|
855
|
-
const contextStr = options.context
|
|
856
|
-
|
|
1061
|
+
const contextStr = options.context
|
|
1062
|
+
? this.toJsonString(options.context)
|
|
1063
|
+
: null;
|
|
1064
|
+
|
|
857
1065
|
// For now, pass the first path since native bridge expects single path (wraps internally)
|
|
858
1066
|
const changedPath = options.changedPaths[0] || '';
|
|
859
|
-
|
|
1067
|
+
|
|
860
1068
|
const resultStr = await JsonEvalRs.evaluateDependentsSubform(
|
|
861
1069
|
this.handle,
|
|
862
1070
|
options.subformPath,
|
|
@@ -874,10 +1082,16 @@ export class JSONEval {
|
|
|
874
1082
|
* @returns Promise that resolves when layout is resolved
|
|
875
1083
|
* @throws {Error} If layout resolution fails
|
|
876
1084
|
*/
|
|
877
|
-
async resolveLayoutSubform(
|
|
1085
|
+
async resolveLayoutSubform(
|
|
1086
|
+
options: ResolveLayoutSubformOptions
|
|
1087
|
+
): Promise<void> {
|
|
878
1088
|
this.throwIfDisposed();
|
|
879
|
-
|
|
880
|
-
return JsonEvalRs.resolveLayoutSubform(
|
|
1089
|
+
|
|
1090
|
+
return JsonEvalRs.resolveLayoutSubform(
|
|
1091
|
+
this.handle,
|
|
1092
|
+
options.subformPath,
|
|
1093
|
+
options.evaluate || false
|
|
1094
|
+
);
|
|
881
1095
|
}
|
|
882
1096
|
|
|
883
1097
|
/**
|
|
@@ -886,9 +1100,11 @@ export class JSONEval {
|
|
|
886
1100
|
* @returns Promise resolving to evaluated schema
|
|
887
1101
|
* @throws {Error} If operation fails
|
|
888
1102
|
*/
|
|
889
|
-
async getEvaluatedSchemaSubform(
|
|
1103
|
+
async getEvaluatedSchemaSubform(
|
|
1104
|
+
options: GetEvaluatedSchemaSubformOptions
|
|
1105
|
+
): Promise<any> {
|
|
890
1106
|
this.throwIfDisposed();
|
|
891
|
-
|
|
1107
|
+
|
|
892
1108
|
const resultStr = await JsonEvalRs.getEvaluatedSchemaSubform(
|
|
893
1109
|
this.handle,
|
|
894
1110
|
options.subformPath,
|
|
@@ -903,10 +1119,53 @@ export class JSONEval {
|
|
|
903
1119
|
* @returns Promise resolving to schema values
|
|
904
1120
|
* @throws {Error} If operation fails
|
|
905
1121
|
*/
|
|
906
|
-
async getSchemaValueSubform(
|
|
1122
|
+
async getSchemaValueSubform(
|
|
1123
|
+
options: GetSchemaValueSubformOptions
|
|
1124
|
+
): Promise<any> {
|
|
907
1125
|
this.throwIfDisposed();
|
|
908
|
-
|
|
909
|
-
const resultStr = await JsonEvalRs.getSchemaValueSubform(
|
|
1126
|
+
|
|
1127
|
+
const resultStr = await JsonEvalRs.getSchemaValueSubform(
|
|
1128
|
+
this.handle,
|
|
1129
|
+
options.subformPath
|
|
1130
|
+
);
|
|
1131
|
+
return JSON.parse(resultStr);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/**
|
|
1135
|
+
* Get schema values from subform as a flat array of path-value pairs.
|
|
1136
|
+
* Returns an array like `[{path: "field.sub", value: 123}, ...]`.
|
|
1137
|
+
* @param options - Options including subform path
|
|
1138
|
+
* @returns Promise resolving to array of SchemaValueItem objects
|
|
1139
|
+
* @throws {Error} If operation fails
|
|
1140
|
+
*/
|
|
1141
|
+
async getSchemaValueArraySubform(
|
|
1142
|
+
options: GetSchemaValueSubformOptions
|
|
1143
|
+
): Promise<SchemaValueItem[]> {
|
|
1144
|
+
this.throwIfDisposed();
|
|
1145
|
+
|
|
1146
|
+
const resultStr = await JsonEvalRs.getSchemaValueArraySubform(
|
|
1147
|
+
this.handle,
|
|
1148
|
+
options.subformPath
|
|
1149
|
+
);
|
|
1150
|
+
return JSON.parse(resultStr);
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
/**
|
|
1154
|
+
* Get schema values from subform as a flat object with dotted path keys.
|
|
1155
|
+
* Returns an object like `{"field.sub": 123, ...}`.
|
|
1156
|
+
* @param options - Options including subform path
|
|
1157
|
+
* @returns Promise resolving to flat object with dotted paths
|
|
1158
|
+
* @throws {Error} If operation fails
|
|
1159
|
+
*/
|
|
1160
|
+
async getSchemaValueObjectSubform(
|
|
1161
|
+
options: GetSchemaValueSubformOptions
|
|
1162
|
+
): Promise<Record<string, any>> {
|
|
1163
|
+
this.throwIfDisposed();
|
|
1164
|
+
|
|
1165
|
+
const resultStr = await JsonEvalRs.getSchemaValueObjectSubform(
|
|
1166
|
+
this.handle,
|
|
1167
|
+
options.subformPath
|
|
1168
|
+
);
|
|
910
1169
|
return JSON.parse(resultStr);
|
|
911
1170
|
}
|
|
912
1171
|
|
|
@@ -916,9 +1175,11 @@ export class JSONEval {
|
|
|
916
1175
|
* @returns Promise resolving to evaluated schema without $params
|
|
917
1176
|
* @throws {Error} If operation fails
|
|
918
1177
|
*/
|
|
919
|
-
async getEvaluatedSchemaWithoutParamsSubform(
|
|
1178
|
+
async getEvaluatedSchemaWithoutParamsSubform(
|
|
1179
|
+
options: GetEvaluatedSchemaSubformOptions
|
|
1180
|
+
): Promise<any> {
|
|
920
1181
|
this.throwIfDisposed();
|
|
921
|
-
|
|
1182
|
+
|
|
922
1183
|
const resultStr = await JsonEvalRs.getEvaluatedSchemaWithoutParamsSubform(
|
|
923
1184
|
this.handle,
|
|
924
1185
|
options.subformPath,
|
|
@@ -933,9 +1194,11 @@ export class JSONEval {
|
|
|
933
1194
|
* @returns Promise resolving to value at path or null if not found
|
|
934
1195
|
* @throws {Error} If operation fails
|
|
935
1196
|
*/
|
|
936
|
-
async getEvaluatedSchemaByPathSubform(
|
|
1197
|
+
async getEvaluatedSchemaByPathSubform(
|
|
1198
|
+
options: GetEvaluatedSchemaByPathSubformOptions
|
|
1199
|
+
): Promise<any | null> {
|
|
937
1200
|
this.throwIfDisposed();
|
|
938
|
-
|
|
1201
|
+
|
|
939
1202
|
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPathSubform(
|
|
940
1203
|
this.handle,
|
|
941
1204
|
options.subformPath,
|
|
@@ -952,9 +1215,11 @@ export class JSONEval {
|
|
|
952
1215
|
* @returns Promise resolving to data in the specified format
|
|
953
1216
|
* @throws {Error} If operation fails
|
|
954
1217
|
*/
|
|
955
|
-
async getEvaluatedSchemaByPathsSubform(
|
|
1218
|
+
async getEvaluatedSchemaByPathsSubform(
|
|
1219
|
+
options: GetEvaluatedSchemaByPathsSubformOptions
|
|
1220
|
+
): Promise<any> {
|
|
956
1221
|
this.throwIfDisposed();
|
|
957
|
-
|
|
1222
|
+
|
|
958
1223
|
const pathsJson = JSON.stringify(options.schemaPaths);
|
|
959
1224
|
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPathsSubform(
|
|
960
1225
|
this.handle,
|
|
@@ -973,7 +1238,7 @@ export class JSONEval {
|
|
|
973
1238
|
*/
|
|
974
1239
|
async getSubformPaths(): Promise<string[]> {
|
|
975
1240
|
this.throwIfDisposed();
|
|
976
|
-
|
|
1241
|
+
|
|
977
1242
|
const resultStr = await JsonEvalRs.getSubformPaths(this.handle);
|
|
978
1243
|
return JSON.parse(resultStr);
|
|
979
1244
|
}
|
|
@@ -984,9 +1249,11 @@ export class JSONEval {
|
|
|
984
1249
|
* @returns Promise resolving to value at path or null if not found
|
|
985
1250
|
* @throws {Error} If operation fails
|
|
986
1251
|
*/
|
|
987
|
-
async getSchemaByPathSubform(
|
|
1252
|
+
async getSchemaByPathSubform(
|
|
1253
|
+
options: GetSchemaByPathSubformOptions
|
|
1254
|
+
): Promise<any | null> {
|
|
988
1255
|
this.throwIfDisposed();
|
|
989
|
-
|
|
1256
|
+
|
|
990
1257
|
const resultStr = await JsonEvalRs.getSchemaByPathSubform(
|
|
991
1258
|
this.handle,
|
|
992
1259
|
options.subformPath,
|
|
@@ -1002,9 +1269,11 @@ export class JSONEval {
|
|
|
1002
1269
|
* @returns Promise resolving to data in the specified format
|
|
1003
1270
|
* @throws {Error} If operation fails
|
|
1004
1271
|
*/
|
|
1005
|
-
async getSchemaByPathsSubform(
|
|
1272
|
+
async getSchemaByPathsSubform(
|
|
1273
|
+
options: GetSchemaByPathsSubformOptions
|
|
1274
|
+
): Promise<any> {
|
|
1006
1275
|
this.throwIfDisposed();
|
|
1007
|
-
|
|
1276
|
+
|
|
1008
1277
|
const pathsJson = JSON.stringify(options.schemaPaths);
|
|
1009
1278
|
const resultStr = await JsonEvalRs.getSchemaByPathsSubform(
|
|
1010
1279
|
this.handle,
|
|
@@ -1023,7 +1292,7 @@ export class JSONEval {
|
|
|
1023
1292
|
*/
|
|
1024
1293
|
async hasSubform(subformPath: string): Promise<boolean> {
|
|
1025
1294
|
this.throwIfDisposed();
|
|
1026
|
-
|
|
1295
|
+
|
|
1027
1296
|
return JsonEvalRs.hasSubform(this.handle, subformPath);
|
|
1028
1297
|
}
|
|
1029
1298
|
|
|
@@ -1034,7 +1303,7 @@ export class JSONEval {
|
|
|
1034
1303
|
*/
|
|
1035
1304
|
async dispose(): Promise<void> {
|
|
1036
1305
|
if (this.disposed) return;
|
|
1037
|
-
|
|
1306
|
+
|
|
1038
1307
|
await JsonEvalRs.dispose(this.handle);
|
|
1039
1308
|
this.disposed = true;
|
|
1040
1309
|
}
|
|
@@ -1052,20 +1321,20 @@ export class JSONEval {
|
|
|
1052
1321
|
* Hook for using JSONEval in React components with automatic cleanup
|
|
1053
1322
|
* @param options - Configuration options
|
|
1054
1323
|
* @returns JSONEval instance or null if not yet initialized
|
|
1055
|
-
*
|
|
1324
|
+
*
|
|
1056
1325
|
* @example
|
|
1057
1326
|
* ```typescript
|
|
1058
1327
|
* import { useJSONEval } from '@json-eval-rs/react-native';
|
|
1059
|
-
*
|
|
1328
|
+
*
|
|
1060
1329
|
* function MyComponent() {
|
|
1061
1330
|
* const eval = useJSONEval({ schema: mySchema });
|
|
1062
|
-
*
|
|
1331
|
+
*
|
|
1063
1332
|
* const handleValidate = async () => {
|
|
1064
1333
|
* if (!eval) return;
|
|
1065
1334
|
* const result = await eval.validate({ data: myData });
|
|
1066
1335
|
* console.log(result);
|
|
1067
1336
|
* };
|
|
1068
|
-
*
|
|
1337
|
+
*
|
|
1069
1338
|
* return <Button onPress={handleValidate} title="Validate" />;
|
|
1070
1339
|
* }
|
|
1071
1340
|
* ```
|