@fogpipe/forma-core 0.11.2 → 0.12.0-alpha.2
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/dist/{chunk-XS3BLVIZ.js → chunk-ZSW7NIMY.js} +127 -22
- package/dist/chunk-ZSW7NIMY.js.map +1 -0
- package/dist/engine/enabled.d.ts.map +1 -1
- package/dist/engine/index.cjs +105 -21
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.ts +2 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +5 -1
- package/dist/engine/readonly.d.ts +44 -0
- package/dist/engine/readonly.d.ts.map +1 -0
- package/dist/engine/validate.d.ts.map +1 -1
- package/dist/engine/visibility.d.ts.map +1 -1
- package/dist/index.cjs +133 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/types.d.ts +128 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/validate.test.ts +1 -0
- package/src/engine/enabled.ts +34 -16
- package/src/engine/index.ts +10 -0
- package/src/engine/readonly.ts +169 -0
- package/src/engine/required.ts +1 -1
- package/src/engine/validate.ts +9 -3
- package/src/engine/visibility.ts +8 -6
- package/src/index.ts +20 -2
- package/src/types.ts +181 -12
- package/dist/chunk-XS3BLVIZ.js.map +0 -1
package/dist/engine/index.cjs
CHANGED
|
@@ -30,11 +30,13 @@ __export(engine_exports, {
|
|
|
30
30
|
getFormattedValue: () => getFormattedValue,
|
|
31
31
|
getOptionsVisibility: () => getOptionsVisibility,
|
|
32
32
|
getPageVisibility: () => getPageVisibility,
|
|
33
|
+
getReadonly: () => getReadonly,
|
|
33
34
|
getRequired: () => getRequired,
|
|
34
35
|
getVisibility: () => getVisibility,
|
|
35
36
|
getVisibleOptions: () => getVisibleOptions,
|
|
36
37
|
isEnabled: () => isEnabled,
|
|
37
38
|
isFieldVisible: () => isFieldVisible,
|
|
39
|
+
isReadonly: () => isReadonly,
|
|
38
40
|
isRequired: () => isRequired,
|
|
39
41
|
isValidFormat: () => isValidFormat,
|
|
40
42
|
parseDecimalFormat: () => parseDecimalFormat,
|
|
@@ -315,6 +317,14 @@ function calculateField(fieldName, data, spec) {
|
|
|
315
317
|
return computed[fieldName] ?? null;
|
|
316
318
|
}
|
|
317
319
|
|
|
320
|
+
// src/types.ts
|
|
321
|
+
function isSelectionField(field) {
|
|
322
|
+
return field.type === "select" || field.type === "multiselect";
|
|
323
|
+
}
|
|
324
|
+
function isArrayField(field) {
|
|
325
|
+
return field.type === "array";
|
|
326
|
+
}
|
|
327
|
+
|
|
318
328
|
// src/engine/visibility.ts
|
|
319
329
|
function filterOptionsByContext(options, context) {
|
|
320
330
|
return options.filter((option) => {
|
|
@@ -336,7 +346,7 @@ function processArrayItemOptions(arrayPath, fieldDef, arrayData, baseContext, re
|
|
|
336
346
|
itemIndex: i
|
|
337
347
|
};
|
|
338
348
|
for (const [itemFieldName, itemFieldDef] of Object.entries(fieldDef.itemFields)) {
|
|
339
|
-
if (itemFieldDef.options && itemFieldDef.options.length > 0) {
|
|
349
|
+
if (isSelectionField(itemFieldDef) && itemFieldDef.options && itemFieldDef.options.length > 0) {
|
|
340
350
|
const itemFieldPath = `${arrayPath}[${i}].${itemFieldName}`;
|
|
341
351
|
result[itemFieldPath] = filterOptionsByContext(itemFieldDef.options, itemContext);
|
|
342
352
|
}
|
|
@@ -368,7 +378,7 @@ function evaluateFieldVisibility(path, fieldDef, data, context, result) {
|
|
|
368
378
|
if (!result[path]) {
|
|
369
379
|
return;
|
|
370
380
|
}
|
|
371
|
-
if (fieldDef.itemFields) {
|
|
381
|
+
if (isArrayField(fieldDef) && fieldDef.itemFields) {
|
|
372
382
|
const arrayData = data[path];
|
|
373
383
|
if (Array.isArray(arrayData)) {
|
|
374
384
|
evaluateArrayItemVisibility(path, fieldDef, arrayData, context, result);
|
|
@@ -441,10 +451,10 @@ function getOptionsVisibility(data, spec, options = {}) {
|
|
|
441
451
|
for (const fieldPath of spec.fieldOrder) {
|
|
442
452
|
const fieldDef = spec.fields[fieldPath];
|
|
443
453
|
if (!fieldDef) continue;
|
|
444
|
-
if (fieldDef.options && fieldDef.options.length > 0) {
|
|
454
|
+
if (isSelectionField(fieldDef) && fieldDef.options && fieldDef.options.length > 0) {
|
|
445
455
|
result[fieldPath] = filterOptionsByContext(fieldDef.options, baseContext);
|
|
446
456
|
}
|
|
447
|
-
if (fieldDef.itemFields) {
|
|
457
|
+
if (isArrayField(fieldDef) && fieldDef.itemFields) {
|
|
448
458
|
const arrayData = data[fieldPath];
|
|
449
459
|
if (Array.isArray(arrayData)) {
|
|
450
460
|
processArrayItemOptions(fieldPath, fieldDef, arrayData, baseContext, result);
|
|
@@ -482,7 +492,7 @@ function getRequired(data, spec, options = {}) {
|
|
|
482
492
|
}
|
|
483
493
|
}
|
|
484
494
|
for (const [fieldPath, fieldDef] of Object.entries(spec.fields)) {
|
|
485
|
-
if (fieldDef.itemFields) {
|
|
495
|
+
if (fieldDef.type === "array" && fieldDef.itemFields) {
|
|
486
496
|
const arrayData = data[fieldPath];
|
|
487
497
|
if (Array.isArray(arrayData)) {
|
|
488
498
|
for (let i = 0; i < arrayData.length; i++) {
|
|
@@ -547,23 +557,10 @@ function getEnabled(data, spec, options = {}) {
|
|
|
547
557
|
}
|
|
548
558
|
}
|
|
549
559
|
for (const [fieldPath, fieldDef] of Object.entries(spec.fields)) {
|
|
550
|
-
if (fieldDef.itemFields) {
|
|
560
|
+
if (fieldDef.type === "array" && fieldDef.itemFields) {
|
|
551
561
|
const arrayData = data[fieldPath];
|
|
552
562
|
if (Array.isArray(arrayData)) {
|
|
553
|
-
|
|
554
|
-
const item = arrayData[i];
|
|
555
|
-
const itemContext = {
|
|
556
|
-
data,
|
|
557
|
-
computed,
|
|
558
|
-
referenceData: spec.referenceData,
|
|
559
|
-
item,
|
|
560
|
-
itemIndex: i
|
|
561
|
-
};
|
|
562
|
-
for (const [itemFieldName, itemFieldDef] of Object.entries(fieldDef.itemFields)) {
|
|
563
|
-
const itemFieldPath = `${fieldPath}[${i}].${itemFieldName}`;
|
|
564
|
-
result[itemFieldPath] = isFieldEnabled(itemFieldDef, itemContext);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
563
|
+
evaluateArrayItemEnabled(fieldPath, fieldDef, arrayData, data, computed, spec, result);
|
|
567
564
|
}
|
|
568
565
|
}
|
|
569
566
|
}
|
|
@@ -575,6 +572,23 @@ function isFieldEnabled(fieldDef, context) {
|
|
|
575
572
|
}
|
|
576
573
|
return true;
|
|
577
574
|
}
|
|
575
|
+
function evaluateArrayItemEnabled(arrayPath, fieldDef, arrayData, data, computed, spec, result) {
|
|
576
|
+
if (!fieldDef.itemFields) return;
|
|
577
|
+
for (let i = 0; i < arrayData.length; i++) {
|
|
578
|
+
const item = arrayData[i];
|
|
579
|
+
const itemContext = {
|
|
580
|
+
data,
|
|
581
|
+
computed,
|
|
582
|
+
referenceData: spec.referenceData,
|
|
583
|
+
item,
|
|
584
|
+
itemIndex: i
|
|
585
|
+
};
|
|
586
|
+
for (const [itemFieldName, itemFieldDef] of Object.entries(fieldDef.itemFields)) {
|
|
587
|
+
const itemFieldPath = `${arrayPath}[${i}].${itemFieldName}`;
|
|
588
|
+
result[itemFieldPath] = isFieldEnabled(itemFieldDef, itemContext);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
578
592
|
function isEnabled(fieldPath, data, spec) {
|
|
579
593
|
const fieldDef = spec.fields[fieldPath];
|
|
580
594
|
if (!fieldDef) {
|
|
@@ -592,6 +606,71 @@ function isEnabled(fieldPath, data, spec) {
|
|
|
592
606
|
return evaluateBoolean(fieldDef.enabledWhen, context);
|
|
593
607
|
}
|
|
594
608
|
|
|
609
|
+
// src/engine/readonly.ts
|
|
610
|
+
function getReadonly(data, spec, options = {}) {
|
|
611
|
+
const computed = options.computed ?? calculate(data, spec);
|
|
612
|
+
const context = {
|
|
613
|
+
data,
|
|
614
|
+
computed,
|
|
615
|
+
referenceData: spec.referenceData
|
|
616
|
+
};
|
|
617
|
+
const result = {};
|
|
618
|
+
for (const fieldPath of spec.fieldOrder) {
|
|
619
|
+
const fieldDef = spec.fields[fieldPath];
|
|
620
|
+
if (fieldDef) {
|
|
621
|
+
result[fieldPath] = isFieldReadonly(fieldDef, context);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
for (const [fieldPath, fieldDef] of Object.entries(spec.fields)) {
|
|
625
|
+
if (fieldDef.type === "array" && fieldDef.itemFields) {
|
|
626
|
+
const arrayData = data[fieldPath];
|
|
627
|
+
if (Array.isArray(arrayData)) {
|
|
628
|
+
evaluateArrayItemReadonly(fieldPath, fieldDef, arrayData, data, computed, spec, result);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
return result;
|
|
633
|
+
}
|
|
634
|
+
function isFieldReadonly(fieldDef, context) {
|
|
635
|
+
if (fieldDef.readonlyWhen) {
|
|
636
|
+
return evaluateBoolean(fieldDef.readonlyWhen, context);
|
|
637
|
+
}
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
function evaluateArrayItemReadonly(arrayPath, fieldDef, arrayData, data, computed, spec, result) {
|
|
641
|
+
if (!fieldDef.itemFields) return;
|
|
642
|
+
for (let i = 0; i < arrayData.length; i++) {
|
|
643
|
+
const item = arrayData[i];
|
|
644
|
+
const itemContext = {
|
|
645
|
+
data,
|
|
646
|
+
computed,
|
|
647
|
+
referenceData: spec.referenceData,
|
|
648
|
+
item,
|
|
649
|
+
itemIndex: i
|
|
650
|
+
};
|
|
651
|
+
for (const [itemFieldName, itemFieldDef] of Object.entries(fieldDef.itemFields)) {
|
|
652
|
+
const itemFieldPath = `${arrayPath}[${i}].${itemFieldName}`;
|
|
653
|
+
result[itemFieldPath] = isFieldReadonly(itemFieldDef, itemContext);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
function isReadonly(fieldPath, data, spec) {
|
|
658
|
+
const fieldDef = spec.fields[fieldPath];
|
|
659
|
+
if (!fieldDef) {
|
|
660
|
+
return false;
|
|
661
|
+
}
|
|
662
|
+
if (!fieldDef.readonlyWhen) {
|
|
663
|
+
return false;
|
|
664
|
+
}
|
|
665
|
+
const computed = calculate(data, spec);
|
|
666
|
+
const context = {
|
|
667
|
+
data,
|
|
668
|
+
computed,
|
|
669
|
+
referenceData: spec.referenceData
|
|
670
|
+
};
|
|
671
|
+
return evaluateBoolean(fieldDef.readonlyWhen, context);
|
|
672
|
+
}
|
|
673
|
+
|
|
595
674
|
// src/engine/validate.ts
|
|
596
675
|
function validate(data, spec, options = {}) {
|
|
597
676
|
const { onlyVisible = true } = options;
|
|
@@ -604,6 +683,9 @@ function validate(data, spec, options = {}) {
|
|
|
604
683
|
if (onlyVisible && visibility[fieldPath] === false) {
|
|
605
684
|
continue;
|
|
606
685
|
}
|
|
686
|
+
if (fieldDef.type === "display") {
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
607
689
|
const schemaProperty = spec.schema.properties[fieldPath];
|
|
608
690
|
const fieldErrors = validateField(
|
|
609
691
|
fieldPath,
|
|
@@ -649,7 +731,7 @@ function validateField(path, value, fieldDef, schemaProperty, spec, data, comput
|
|
|
649
731
|
const customErrors = validateCustomRules(path, fieldDef.validations, context);
|
|
650
732
|
errors.push(...customErrors);
|
|
651
733
|
}
|
|
652
|
-
if (Array.isArray(value)) {
|
|
734
|
+
if (Array.isArray(value) && fieldDef.type === "array") {
|
|
653
735
|
const arrayErrors = validateArray(
|
|
654
736
|
path,
|
|
655
737
|
value,
|
|
@@ -1032,11 +1114,13 @@ function validateSingleField(fieldPath, data, spec) {
|
|
|
1032
1114
|
getFormattedValue,
|
|
1033
1115
|
getOptionsVisibility,
|
|
1034
1116
|
getPageVisibility,
|
|
1117
|
+
getReadonly,
|
|
1035
1118
|
getRequired,
|
|
1036
1119
|
getVisibility,
|
|
1037
1120
|
getVisibleOptions,
|
|
1038
1121
|
isEnabled,
|
|
1039
1122
|
isFieldVisible,
|
|
1123
|
+
isReadonly,
|
|
1040
1124
|
isRequired,
|
|
1041
1125
|
isValidFormat,
|
|
1042
1126
|
parseDecimalFormat,
|