@json-eval-rs/react-native 0.0.54 → 0.0.56
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 +94 -16
- package/android/src/main/java/com/jsonevalrs/JsonEvalRsModule.kt +59 -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 +156 -0
- package/cpp/json-eval-bridge.h +62 -0
- package/ios/JsonEvalRs.mm +99 -0
- package/ios/JsonEvalRs.xcframework/Info.plist +5 -5
- 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 +85 -17
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +86 -17
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +47 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +413 -124
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
|
/**
|
|
@@ -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,13 +334,54 @@ 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
|
}
|
|
333
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Evaluates logic expression without creating an instance
|
|
354
|
+
* @param logicStr - JSON Logic expression as string or object
|
|
355
|
+
* @param data - Optional data as string or object
|
|
356
|
+
* @param context - Optional context as string or object
|
|
357
|
+
* @returns Promise resolving to evaluation result
|
|
358
|
+
*/
|
|
359
|
+
static async evaluateLogic(
|
|
360
|
+
logicStr: string | object,
|
|
361
|
+
data?: string | object | null,
|
|
362
|
+
context?: string | object | null
|
|
363
|
+
): Promise<any> {
|
|
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
|
+
);
|
|
382
|
+
return JSON.parse(resultStr);
|
|
383
|
+
}
|
|
384
|
+
|
|
334
385
|
/**
|
|
335
386
|
* Creates a new JSON evaluator instance
|
|
336
387
|
* @param options - Configuration options with schema, context, and data
|
|
@@ -342,17 +393,27 @@ export class JSONEval {
|
|
|
342
393
|
this.handle = options._handle;
|
|
343
394
|
return;
|
|
344
395
|
}
|
|
345
|
-
|
|
396
|
+
|
|
346
397
|
const { schema, context, data } = options;
|
|
347
|
-
|
|
398
|
+
|
|
348
399
|
try {
|
|
349
|
-
const schemaStr =
|
|
350
|
-
|
|
351
|
-
const
|
|
352
|
-
|
|
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
|
+
|
|
353
413
|
this.handle = JsonEvalRs.create(schemaStr, contextStr, dataStr);
|
|
354
414
|
} catch (error) {
|
|
355
|
-
const errorMessage =
|
|
415
|
+
const errorMessage =
|
|
416
|
+
error instanceof Error ? error.message : String(error);
|
|
356
417
|
throw new Error(`Failed to create JSONEval instance: ${errorMessage}`);
|
|
357
418
|
}
|
|
358
419
|
}
|
|
@@ -374,7 +435,7 @@ export class JSONEval {
|
|
|
374
435
|
|
|
375
436
|
/**
|
|
376
437
|
* Cancel any running evaluation
|
|
377
|
-
* The generic auto-cancellation on new evaluation will still work,
|
|
438
|
+
* The generic auto-cancellation on new evaluation will still work,
|
|
378
439
|
* but this allows manual cancellation.
|
|
379
440
|
*/
|
|
380
441
|
async cancel(): Promise<void> {
|
|
@@ -390,16 +451,24 @@ export class JSONEval {
|
|
|
390
451
|
*/
|
|
391
452
|
async evaluate(options: EvaluateOptions): Promise<any> {
|
|
392
453
|
this.throwIfDisposed();
|
|
393
|
-
|
|
454
|
+
|
|
394
455
|
try {
|
|
395
456
|
const dataStr = this.toJsonString(options.data);
|
|
396
|
-
const contextStr = options.context
|
|
457
|
+
const contextStr = options.context
|
|
458
|
+
? this.toJsonString(options.context)
|
|
459
|
+
: null;
|
|
397
460
|
const pathsJson = options.paths ? JSON.stringify(options.paths) : null;
|
|
398
|
-
|
|
399
|
-
const resultStr = await JsonEvalRs.evaluate(
|
|
461
|
+
|
|
462
|
+
const resultStr = await JsonEvalRs.evaluate(
|
|
463
|
+
this.handle,
|
|
464
|
+
dataStr,
|
|
465
|
+
contextStr,
|
|
466
|
+
pathsJson
|
|
467
|
+
);
|
|
400
468
|
return JSON.parse(resultStr);
|
|
401
469
|
} catch (error) {
|
|
402
|
-
const errorMessage =
|
|
470
|
+
const errorMessage =
|
|
471
|
+
error instanceof Error ? error.message : String(error);
|
|
403
472
|
throw new Error(`Evaluation failed: ${errorMessage}`);
|
|
404
473
|
}
|
|
405
474
|
}
|
|
@@ -412,15 +481,22 @@ export class JSONEval {
|
|
|
412
481
|
*/
|
|
413
482
|
async validate(options: EvaluateOptions): Promise<ValidationResult> {
|
|
414
483
|
this.throwIfDisposed();
|
|
415
|
-
|
|
484
|
+
|
|
416
485
|
try {
|
|
417
486
|
const dataStr = this.toJsonString(options.data);
|
|
418
|
-
const contextStr = options.context
|
|
419
|
-
|
|
420
|
-
|
|
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
|
+
);
|
|
421
496
|
return JSON.parse(resultStr);
|
|
422
497
|
} catch (error) {
|
|
423
|
-
const errorMessage =
|
|
498
|
+
const errorMessage =
|
|
499
|
+
error instanceof Error ? error.message : String(error);
|
|
424
500
|
throw new Error(`Validation failed: ${errorMessage}`);
|
|
425
501
|
}
|
|
426
502
|
}
|
|
@@ -431,15 +507,17 @@ export class JSONEval {
|
|
|
431
507
|
* @returns Promise resolving to array of dependent field changes
|
|
432
508
|
* @throws {Error} If evaluation fails
|
|
433
509
|
*/
|
|
434
|
-
async evaluateDependents(
|
|
510
|
+
async evaluateDependents(
|
|
511
|
+
options: EvaluateDependentsOptions
|
|
512
|
+
): Promise<DependentChange[]> {
|
|
435
513
|
this.throwIfDisposed();
|
|
436
|
-
|
|
514
|
+
|
|
437
515
|
try {
|
|
438
516
|
const { changedPaths, data, context, reEvaluate = true } = options;
|
|
439
517
|
const changedPathsJson = JSON.stringify(changedPaths);
|
|
440
518
|
const dataStr = data ? this.toJsonString(data) : null;
|
|
441
519
|
const contextStr = context ? this.toJsonString(context) : null;
|
|
442
|
-
|
|
520
|
+
|
|
443
521
|
const resultStr = await JsonEvalRs.evaluateDependents(
|
|
444
522
|
this.handle,
|
|
445
523
|
changedPathsJson,
|
|
@@ -449,7 +527,8 @@ export class JSONEval {
|
|
|
449
527
|
);
|
|
450
528
|
return JSON.parse(resultStr);
|
|
451
529
|
} catch (error) {
|
|
452
|
-
const errorMessage =
|
|
530
|
+
const errorMessage =
|
|
531
|
+
error instanceof Error ? error.message : String(error);
|
|
453
532
|
throw new Error(`Dependent evaluation failed: ${errorMessage}`);
|
|
454
533
|
}
|
|
455
534
|
}
|
|
@@ -462,7 +541,10 @@ export class JSONEval {
|
|
|
462
541
|
*/
|
|
463
542
|
async getEvaluatedSchema(skipLayout: boolean = false): Promise<any> {
|
|
464
543
|
this.throwIfDisposed();
|
|
465
|
-
const resultStr = await JsonEvalRs.getEvaluatedSchema(
|
|
544
|
+
const resultStr = await JsonEvalRs.getEvaluatedSchema(
|
|
545
|
+
this.handle,
|
|
546
|
+
skipLayout
|
|
547
|
+
);
|
|
466
548
|
return JSON.parse(resultStr);
|
|
467
549
|
}
|
|
468
550
|
|
|
@@ -477,15 +559,44 @@ export class JSONEval {
|
|
|
477
559
|
return JSON.parse(resultStr);
|
|
478
560
|
}
|
|
479
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
|
+
|
|
480
586
|
/**
|
|
481
587
|
* Get the evaluated schema without $params field
|
|
482
588
|
* @param skipLayout - Whether to skip layout resolution (default: false)
|
|
483
589
|
* @returns Promise resolving to evaluated schema object
|
|
484
590
|
* @throws {Error} If operation fails
|
|
485
591
|
*/
|
|
486
|
-
async getEvaluatedSchemaWithoutParams(
|
|
592
|
+
async getEvaluatedSchemaWithoutParams(
|
|
593
|
+
skipLayout: boolean = false
|
|
594
|
+
): Promise<any> {
|
|
487
595
|
this.throwIfDisposed();
|
|
488
|
-
const resultStr = await JsonEvalRs.getEvaluatedSchemaWithoutParams(
|
|
596
|
+
const resultStr = await JsonEvalRs.getEvaluatedSchemaWithoutParams(
|
|
597
|
+
this.handle,
|
|
598
|
+
skipLayout
|
|
599
|
+
);
|
|
489
600
|
return JSON.parse(resultStr);
|
|
490
601
|
}
|
|
491
602
|
|
|
@@ -496,9 +607,16 @@ export class JSONEval {
|
|
|
496
607
|
* @returns Promise resolving to the value at the path, or null if not found
|
|
497
608
|
* @throws {Error} If operation fails
|
|
498
609
|
*/
|
|
499
|
-
async getEvaluatedSchemaByPath(
|
|
610
|
+
async getEvaluatedSchemaByPath(
|
|
611
|
+
path: string,
|
|
612
|
+
skipLayout: boolean = false
|
|
613
|
+
): Promise<any | null> {
|
|
500
614
|
this.throwIfDisposed();
|
|
501
|
-
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPath(
|
|
615
|
+
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPath(
|
|
616
|
+
this.handle,
|
|
617
|
+
path,
|
|
618
|
+
skipLayout
|
|
619
|
+
);
|
|
502
620
|
return resultStr ? JSON.parse(resultStr) : null;
|
|
503
621
|
}
|
|
504
622
|
|
|
@@ -511,10 +629,19 @@ export class JSONEval {
|
|
|
511
629
|
* @returns Promise resolving to data in the specified format
|
|
512
630
|
* @throws {Error} If operation fails
|
|
513
631
|
*/
|
|
514
|
-
async getEvaluatedSchemaByPaths(
|
|
632
|
+
async getEvaluatedSchemaByPaths(
|
|
633
|
+
paths: string[],
|
|
634
|
+
skipLayout: boolean = false,
|
|
635
|
+
format: ReturnFormat = ReturnFormat.Nested
|
|
636
|
+
): Promise<any> {
|
|
515
637
|
this.throwIfDisposed();
|
|
516
638
|
const pathsJson = JSON.stringify(paths);
|
|
517
|
-
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPaths(
|
|
639
|
+
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPaths(
|
|
640
|
+
this.handle,
|
|
641
|
+
pathsJson,
|
|
642
|
+
skipLayout,
|
|
643
|
+
format
|
|
644
|
+
);
|
|
518
645
|
return JSON.parse(resultStr);
|
|
519
646
|
}
|
|
520
647
|
|
|
@@ -538,10 +665,17 @@ export class JSONEval {
|
|
|
538
665
|
* @returns Promise resolving to data in the specified format
|
|
539
666
|
* @throws {Error} If operation fails
|
|
540
667
|
*/
|
|
541
|
-
async getSchemaByPaths(
|
|
668
|
+
async getSchemaByPaths(
|
|
669
|
+
paths: string[],
|
|
670
|
+
format: ReturnFormat = ReturnFormat.Nested
|
|
671
|
+
): Promise<any> {
|
|
542
672
|
this.throwIfDisposed();
|
|
543
673
|
const pathsJson = JSON.stringify(paths);
|
|
544
|
-
const resultStr = await JsonEvalRs.getSchemaByPaths(
|
|
674
|
+
const resultStr = await JsonEvalRs.getSchemaByPaths(
|
|
675
|
+
this.handle,
|
|
676
|
+
pathsJson,
|
|
677
|
+
format
|
|
678
|
+
);
|
|
545
679
|
return JSON.parse(resultStr);
|
|
546
680
|
}
|
|
547
681
|
|
|
@@ -552,16 +686,31 @@ export class JSONEval {
|
|
|
552
686
|
*/
|
|
553
687
|
async reloadSchema(options: JSONEvalOptions): Promise<void> {
|
|
554
688
|
this.throwIfDisposed();
|
|
555
|
-
|
|
689
|
+
|
|
556
690
|
try {
|
|
557
691
|
const { schema, context, data } = options;
|
|
558
|
-
const schemaStr =
|
|
559
|
-
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
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
|
+
);
|
|
563
711
|
} catch (error) {
|
|
564
|
-
const errorMessage =
|
|
712
|
+
const errorMessage =
|
|
713
|
+
error instanceof Error ? error.message : String(error);
|
|
565
714
|
throw new Error(`Failed to reload schema: ${errorMessage}`);
|
|
566
715
|
}
|
|
567
716
|
}
|
|
@@ -579,20 +728,37 @@ export class JSONEval {
|
|
|
579
728
|
data?: string | object | null
|
|
580
729
|
): Promise<void> {
|
|
581
730
|
this.throwIfDisposed();
|
|
582
|
-
|
|
731
|
+
|
|
583
732
|
try {
|
|
584
733
|
// Convert Uint8Array to number array if needed
|
|
585
|
-
const msgpackArray =
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
const
|
|
591
|
-
|
|
592
|
-
|
|
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
|
+
);
|
|
593
756
|
} catch (error) {
|
|
594
|
-
const errorMessage =
|
|
595
|
-
|
|
757
|
+
const errorMessage =
|
|
758
|
+
error instanceof Error ? error.message : String(error);
|
|
759
|
+
throw new Error(
|
|
760
|
+
`Failed to reload schema from MessagePack: ${errorMessage}`
|
|
761
|
+
);
|
|
596
762
|
}
|
|
597
763
|
}
|
|
598
764
|
|
|
@@ -609,14 +775,28 @@ export class JSONEval {
|
|
|
609
775
|
data?: string | object | null
|
|
610
776
|
): Promise<void> {
|
|
611
777
|
this.throwIfDisposed();
|
|
612
|
-
|
|
778
|
+
|
|
613
779
|
try {
|
|
614
|
-
const contextStr = context
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
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
|
+
);
|
|
618
797
|
} catch (error) {
|
|
619
|
-
const errorMessage =
|
|
798
|
+
const errorMessage =
|
|
799
|
+
error instanceof Error ? error.message : String(error);
|
|
620
800
|
throw new Error(`Failed to reload schema from cache: ${errorMessage}`);
|
|
621
801
|
}
|
|
622
802
|
}
|
|
@@ -702,15 +882,15 @@ export class JSONEval {
|
|
|
702
882
|
* Pass null to reset to UTC
|
|
703
883
|
* @returns Promise that resolves when timezone is set
|
|
704
884
|
* @throws {Error} If operation fails
|
|
705
|
-
*
|
|
885
|
+
*
|
|
706
886
|
* @example
|
|
707
887
|
* ```typescript
|
|
708
888
|
* // Set to UTC+7 (Jakarta, Bangkok)
|
|
709
889
|
* await eval.setTimezoneOffset(420);
|
|
710
|
-
*
|
|
890
|
+
*
|
|
711
891
|
* // Set to UTC-5 (New York, EST)
|
|
712
892
|
* await eval.setTimezoneOffset(-300);
|
|
713
|
-
*
|
|
893
|
+
*
|
|
714
894
|
* // Reset to UTC
|
|
715
895
|
* await eval.setTimezoneOffset(null);
|
|
716
896
|
* ```
|
|
@@ -728,14 +908,23 @@ export class JSONEval {
|
|
|
728
908
|
* @returns Promise resolving to the result of the evaluation
|
|
729
909
|
* @throws {Error} If compilation or evaluation fails
|
|
730
910
|
*/
|
|
731
|
-
async compileAndRunLogic(
|
|
911
|
+
async compileAndRunLogic(
|
|
912
|
+
logicStr: string | object,
|
|
913
|
+
data?: string | object,
|
|
914
|
+
context?: string | object
|
|
915
|
+
): Promise<any> {
|
|
732
916
|
this.throwIfDisposed();
|
|
733
|
-
|
|
917
|
+
|
|
734
918
|
const logic = this.toJsonString(logicStr);
|
|
735
919
|
const dataStr = data ? this.toJsonString(data) : null;
|
|
736
920
|
const contextStr = context ? this.toJsonString(context) : null;
|
|
737
|
-
|
|
738
|
-
const resultStr = await JsonEvalRs.compileAndRunLogic(
|
|
921
|
+
|
|
922
|
+
const resultStr = await JsonEvalRs.compileAndRunLogic(
|
|
923
|
+
this.handle,
|
|
924
|
+
logic,
|
|
925
|
+
dataStr,
|
|
926
|
+
contextStr
|
|
927
|
+
);
|
|
739
928
|
return JSON.parse(resultStr);
|
|
740
929
|
}
|
|
741
930
|
|
|
@@ -747,7 +936,7 @@ export class JSONEval {
|
|
|
747
936
|
*/
|
|
748
937
|
async compileLogic(logicStr: string | object): Promise<number> {
|
|
749
938
|
this.throwIfDisposed();
|
|
750
|
-
|
|
939
|
+
|
|
751
940
|
const logic = this.toJsonString(logicStr);
|
|
752
941
|
return await JsonEvalRs.compileLogic(this.handle, logic);
|
|
753
942
|
}
|
|
@@ -760,13 +949,22 @@ export class JSONEval {
|
|
|
760
949
|
* @returns Promise resolving to the result of the evaluation
|
|
761
950
|
* @throws {Error} If execution fails
|
|
762
951
|
*/
|
|
763
|
-
async runLogic(
|
|
952
|
+
async runLogic(
|
|
953
|
+
logicId: number,
|
|
954
|
+
data?: string | object,
|
|
955
|
+
context?: string | object
|
|
956
|
+
): Promise<any> {
|
|
764
957
|
this.throwIfDisposed();
|
|
765
|
-
|
|
958
|
+
|
|
766
959
|
const dataStr = data ? this.toJsonString(data) : null;
|
|
767
960
|
const contextStr = context ? this.toJsonString(context) : null;
|
|
768
|
-
|
|
769
|
-
const resultStr = await JsonEvalRs.runLogic(
|
|
961
|
+
|
|
962
|
+
const resultStr = await JsonEvalRs.runLogic(
|
|
963
|
+
this.handle,
|
|
964
|
+
logicId,
|
|
965
|
+
dataStr,
|
|
966
|
+
contextStr
|
|
967
|
+
);
|
|
770
968
|
return JSON.parse(resultStr);
|
|
771
969
|
}
|
|
772
970
|
|
|
@@ -776,14 +974,23 @@ export class JSONEval {
|
|
|
776
974
|
* @returns Promise resolving to ValidationResult
|
|
777
975
|
* @throws {Error} If validation operation fails
|
|
778
976
|
*/
|
|
779
|
-
async validatePaths(
|
|
977
|
+
async validatePaths(
|
|
978
|
+
options: ValidatePathsOptions
|
|
979
|
+
): Promise<ValidationResult> {
|
|
780
980
|
this.throwIfDisposed();
|
|
781
|
-
|
|
981
|
+
|
|
782
982
|
const dataStr = this.toJsonString(options.data);
|
|
783
|
-
const contextStr = options.context
|
|
983
|
+
const contextStr = options.context
|
|
984
|
+
? this.toJsonString(options.context)
|
|
985
|
+
: null;
|
|
784
986
|
const paths = options.paths || null;
|
|
785
|
-
|
|
786
|
-
const resultStr = await JsonEvalRs.validatePaths(
|
|
987
|
+
|
|
988
|
+
const resultStr = await JsonEvalRs.validatePaths(
|
|
989
|
+
this.handle,
|
|
990
|
+
dataStr,
|
|
991
|
+
contextStr,
|
|
992
|
+
paths
|
|
993
|
+
);
|
|
787
994
|
return JSON.parse(resultStr);
|
|
788
995
|
}
|
|
789
996
|
|
|
@@ -799,11 +1006,19 @@ export class JSONEval {
|
|
|
799
1006
|
*/
|
|
800
1007
|
async evaluateSubform(options: EvaluateSubformOptions): Promise<void> {
|
|
801
1008
|
this.throwIfDisposed();
|
|
802
|
-
|
|
1009
|
+
|
|
803
1010
|
const dataStr = this.toJsonString(options.data);
|
|
804
|
-
const contextStr = options.context
|
|
805
|
-
|
|
806
|
-
|
|
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
|
+
);
|
|
807
1022
|
}
|
|
808
1023
|
|
|
809
1024
|
/**
|
|
@@ -812,13 +1027,22 @@ export class JSONEval {
|
|
|
812
1027
|
* @returns Promise resolving to ValidationResult
|
|
813
1028
|
* @throws {Error} If validation fails
|
|
814
1029
|
*/
|
|
815
|
-
async validateSubform(
|
|
1030
|
+
async validateSubform(
|
|
1031
|
+
options: ValidateSubformOptions
|
|
1032
|
+
): Promise<ValidationResult> {
|
|
816
1033
|
this.throwIfDisposed();
|
|
817
|
-
|
|
1034
|
+
|
|
818
1035
|
const dataStr = this.toJsonString(options.data);
|
|
819
|
-
const contextStr = options.context
|
|
820
|
-
|
|
821
|
-
|
|
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
|
+
);
|
|
822
1046
|
return JSON.parse(resultStr);
|
|
823
1047
|
}
|
|
824
1048
|
|
|
@@ -828,15 +1052,19 @@ export class JSONEval {
|
|
|
828
1052
|
* @returns Promise resolving to dependent evaluation results
|
|
829
1053
|
* @throws {Error} If evaluation fails
|
|
830
1054
|
*/
|
|
831
|
-
async evaluateDependentsSubform(
|
|
1055
|
+
async evaluateDependentsSubform(
|
|
1056
|
+
options: EvaluateDependentsSubformOptions
|
|
1057
|
+
): Promise<DependentChange[]> {
|
|
832
1058
|
this.throwIfDisposed();
|
|
833
|
-
|
|
1059
|
+
|
|
834
1060
|
const dataStr = options.data ? this.toJsonString(options.data) : null;
|
|
835
|
-
const contextStr = options.context
|
|
836
|
-
|
|
1061
|
+
const contextStr = options.context
|
|
1062
|
+
? this.toJsonString(options.context)
|
|
1063
|
+
: null;
|
|
1064
|
+
|
|
837
1065
|
// For now, pass the first path since native bridge expects single path (wraps internally)
|
|
838
1066
|
const changedPath = options.changedPaths[0] || '';
|
|
839
|
-
|
|
1067
|
+
|
|
840
1068
|
const resultStr = await JsonEvalRs.evaluateDependentsSubform(
|
|
841
1069
|
this.handle,
|
|
842
1070
|
options.subformPath,
|
|
@@ -854,10 +1082,16 @@ export class JSONEval {
|
|
|
854
1082
|
* @returns Promise that resolves when layout is resolved
|
|
855
1083
|
* @throws {Error} If layout resolution fails
|
|
856
1084
|
*/
|
|
857
|
-
async resolveLayoutSubform(
|
|
1085
|
+
async resolveLayoutSubform(
|
|
1086
|
+
options: ResolveLayoutSubformOptions
|
|
1087
|
+
): Promise<void> {
|
|
858
1088
|
this.throwIfDisposed();
|
|
859
|
-
|
|
860
|
-
return JsonEvalRs.resolveLayoutSubform(
|
|
1089
|
+
|
|
1090
|
+
return JsonEvalRs.resolveLayoutSubform(
|
|
1091
|
+
this.handle,
|
|
1092
|
+
options.subformPath,
|
|
1093
|
+
options.evaluate || false
|
|
1094
|
+
);
|
|
861
1095
|
}
|
|
862
1096
|
|
|
863
1097
|
/**
|
|
@@ -866,9 +1100,11 @@ export class JSONEval {
|
|
|
866
1100
|
* @returns Promise resolving to evaluated schema
|
|
867
1101
|
* @throws {Error} If operation fails
|
|
868
1102
|
*/
|
|
869
|
-
async getEvaluatedSchemaSubform(
|
|
1103
|
+
async getEvaluatedSchemaSubform(
|
|
1104
|
+
options: GetEvaluatedSchemaSubformOptions
|
|
1105
|
+
): Promise<any> {
|
|
870
1106
|
this.throwIfDisposed();
|
|
871
|
-
|
|
1107
|
+
|
|
872
1108
|
const resultStr = await JsonEvalRs.getEvaluatedSchemaSubform(
|
|
873
1109
|
this.handle,
|
|
874
1110
|
options.subformPath,
|
|
@@ -883,10 +1119,53 @@ export class JSONEval {
|
|
|
883
1119
|
* @returns Promise resolving to schema values
|
|
884
1120
|
* @throws {Error} If operation fails
|
|
885
1121
|
*/
|
|
886
|
-
async getSchemaValueSubform(
|
|
1122
|
+
async getSchemaValueSubform(
|
|
1123
|
+
options: GetSchemaValueSubformOptions
|
|
1124
|
+
): Promise<any> {
|
|
1125
|
+
this.throwIfDisposed();
|
|
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[]> {
|
|
887
1144
|
this.throwIfDisposed();
|
|
888
|
-
|
|
889
|
-
const resultStr = await JsonEvalRs.
|
|
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
|
+
);
|
|
890
1169
|
return JSON.parse(resultStr);
|
|
891
1170
|
}
|
|
892
1171
|
|
|
@@ -896,9 +1175,11 @@ export class JSONEval {
|
|
|
896
1175
|
* @returns Promise resolving to evaluated schema without $params
|
|
897
1176
|
* @throws {Error} If operation fails
|
|
898
1177
|
*/
|
|
899
|
-
async getEvaluatedSchemaWithoutParamsSubform(
|
|
1178
|
+
async getEvaluatedSchemaWithoutParamsSubform(
|
|
1179
|
+
options: GetEvaluatedSchemaSubformOptions
|
|
1180
|
+
): Promise<any> {
|
|
900
1181
|
this.throwIfDisposed();
|
|
901
|
-
|
|
1182
|
+
|
|
902
1183
|
const resultStr = await JsonEvalRs.getEvaluatedSchemaWithoutParamsSubform(
|
|
903
1184
|
this.handle,
|
|
904
1185
|
options.subformPath,
|
|
@@ -913,9 +1194,11 @@ export class JSONEval {
|
|
|
913
1194
|
* @returns Promise resolving to value at path or null if not found
|
|
914
1195
|
* @throws {Error} If operation fails
|
|
915
1196
|
*/
|
|
916
|
-
async getEvaluatedSchemaByPathSubform(
|
|
1197
|
+
async getEvaluatedSchemaByPathSubform(
|
|
1198
|
+
options: GetEvaluatedSchemaByPathSubformOptions
|
|
1199
|
+
): Promise<any | null> {
|
|
917
1200
|
this.throwIfDisposed();
|
|
918
|
-
|
|
1201
|
+
|
|
919
1202
|
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPathSubform(
|
|
920
1203
|
this.handle,
|
|
921
1204
|
options.subformPath,
|
|
@@ -932,9 +1215,11 @@ export class JSONEval {
|
|
|
932
1215
|
* @returns Promise resolving to data in the specified format
|
|
933
1216
|
* @throws {Error} If operation fails
|
|
934
1217
|
*/
|
|
935
|
-
async getEvaluatedSchemaByPathsSubform(
|
|
1218
|
+
async getEvaluatedSchemaByPathsSubform(
|
|
1219
|
+
options: GetEvaluatedSchemaByPathsSubformOptions
|
|
1220
|
+
): Promise<any> {
|
|
936
1221
|
this.throwIfDisposed();
|
|
937
|
-
|
|
1222
|
+
|
|
938
1223
|
const pathsJson = JSON.stringify(options.schemaPaths);
|
|
939
1224
|
const resultStr = await JsonEvalRs.getEvaluatedSchemaByPathsSubform(
|
|
940
1225
|
this.handle,
|
|
@@ -953,7 +1238,7 @@ export class JSONEval {
|
|
|
953
1238
|
*/
|
|
954
1239
|
async getSubformPaths(): Promise<string[]> {
|
|
955
1240
|
this.throwIfDisposed();
|
|
956
|
-
|
|
1241
|
+
|
|
957
1242
|
const resultStr = await JsonEvalRs.getSubformPaths(this.handle);
|
|
958
1243
|
return JSON.parse(resultStr);
|
|
959
1244
|
}
|
|
@@ -964,9 +1249,11 @@ export class JSONEval {
|
|
|
964
1249
|
* @returns Promise resolving to value at path or null if not found
|
|
965
1250
|
* @throws {Error} If operation fails
|
|
966
1251
|
*/
|
|
967
|
-
async getSchemaByPathSubform(
|
|
1252
|
+
async getSchemaByPathSubform(
|
|
1253
|
+
options: GetSchemaByPathSubformOptions
|
|
1254
|
+
): Promise<any | null> {
|
|
968
1255
|
this.throwIfDisposed();
|
|
969
|
-
|
|
1256
|
+
|
|
970
1257
|
const resultStr = await JsonEvalRs.getSchemaByPathSubform(
|
|
971
1258
|
this.handle,
|
|
972
1259
|
options.subformPath,
|
|
@@ -982,9 +1269,11 @@ export class JSONEval {
|
|
|
982
1269
|
* @returns Promise resolving to data in the specified format
|
|
983
1270
|
* @throws {Error} If operation fails
|
|
984
1271
|
*/
|
|
985
|
-
async getSchemaByPathsSubform(
|
|
1272
|
+
async getSchemaByPathsSubform(
|
|
1273
|
+
options: GetSchemaByPathsSubformOptions
|
|
1274
|
+
): Promise<any> {
|
|
986
1275
|
this.throwIfDisposed();
|
|
987
|
-
|
|
1276
|
+
|
|
988
1277
|
const pathsJson = JSON.stringify(options.schemaPaths);
|
|
989
1278
|
const resultStr = await JsonEvalRs.getSchemaByPathsSubform(
|
|
990
1279
|
this.handle,
|
|
@@ -1003,7 +1292,7 @@ export class JSONEval {
|
|
|
1003
1292
|
*/
|
|
1004
1293
|
async hasSubform(subformPath: string): Promise<boolean> {
|
|
1005
1294
|
this.throwIfDisposed();
|
|
1006
|
-
|
|
1295
|
+
|
|
1007
1296
|
return JsonEvalRs.hasSubform(this.handle, subformPath);
|
|
1008
1297
|
}
|
|
1009
1298
|
|
|
@@ -1014,7 +1303,7 @@ export class JSONEval {
|
|
|
1014
1303
|
*/
|
|
1015
1304
|
async dispose(): Promise<void> {
|
|
1016
1305
|
if (this.disposed) return;
|
|
1017
|
-
|
|
1306
|
+
|
|
1018
1307
|
await JsonEvalRs.dispose(this.handle);
|
|
1019
1308
|
this.disposed = true;
|
|
1020
1309
|
}
|
|
@@ -1032,20 +1321,20 @@ export class JSONEval {
|
|
|
1032
1321
|
* Hook for using JSONEval in React components with automatic cleanup
|
|
1033
1322
|
* @param options - Configuration options
|
|
1034
1323
|
* @returns JSONEval instance or null if not yet initialized
|
|
1035
|
-
*
|
|
1324
|
+
*
|
|
1036
1325
|
* @example
|
|
1037
1326
|
* ```typescript
|
|
1038
1327
|
* import { useJSONEval } from '@json-eval-rs/react-native';
|
|
1039
|
-
*
|
|
1328
|
+
*
|
|
1040
1329
|
* function MyComponent() {
|
|
1041
1330
|
* const eval = useJSONEval({ schema: mySchema });
|
|
1042
|
-
*
|
|
1331
|
+
*
|
|
1043
1332
|
* const handleValidate = async () => {
|
|
1044
1333
|
* if (!eval) return;
|
|
1045
1334
|
* const result = await eval.validate({ data: myData });
|
|
1046
1335
|
* console.log(result);
|
|
1047
1336
|
* };
|
|
1048
|
-
*
|
|
1337
|
+
*
|
|
1049
1338
|
* return <Button onPress={handleValidate} title="Validate" />;
|
|
1050
1339
|
* }
|
|
1051
1340
|
* ```
|