@remoteoss/json-schema-form 0.4.4-dev.20230829101351 → 0.4.4-dev.20230829102031
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/index.cjs +62 -489
- package/dist/index.js +62 -489
- package/dist/standalone.js +62 -867
- package/package.json +1 -2
- package/src/tests/const.test.js +78 -0
- package/src/tests/jsonLogic.test.js +0 -814
- package/src/tests/jsonLogicFixtures.js +0 -1489
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2023 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.4.4-dev.
|
|
5
|
-
Generated: Tue, 29 Aug 2023 10:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.4.4-dev.20230829102031
|
|
5
|
+
Generated: Tue, 29 Aug 2023 10:20:47 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -67,8 +67,8 @@ function hasProperty(object2, propertyName) {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// src/checkIfConditionMatches.js
|
|
70
|
-
function checkIfConditionMatches(node, formValues, formFields
|
|
71
|
-
return Object.keys(node.if.properties
|
|
70
|
+
function checkIfConditionMatches(node, formValues, formFields) {
|
|
71
|
+
return Object.keys(node.if.properties).every((name) => {
|
|
72
72
|
const currentProperty = node.if.properties[name];
|
|
73
73
|
const value = formValues[name];
|
|
74
74
|
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
@@ -94,8 +94,7 @@ function checkIfConditionMatches(node, formValues, formFields, validations) {
|
|
|
94
94
|
return checkIfConditionMatches(
|
|
95
95
|
{ if: currentProperty },
|
|
96
96
|
formValues[name],
|
|
97
|
-
getField(name, formFields).fields
|
|
98
|
-
validations
|
|
97
|
+
getField(name, formFields).fields
|
|
99
98
|
);
|
|
100
99
|
}
|
|
101
100
|
const field = getField(name, formFields);
|
|
@@ -111,23 +110,6 @@ function checkIfConditionMatches(node, formValues, formFields, validations) {
|
|
|
111
110
|
);
|
|
112
111
|
});
|
|
113
112
|
}
|
|
114
|
-
function checkIfMatchesValidationsAndComputedValues(node, formValues, validations, parentID) {
|
|
115
|
-
const validationsMatch = Object.entries(node.if.validations ?? {}).every(([name, property]) => {
|
|
116
|
-
const currentValue = validations.getScope(parentID).evaluateValidationRuleInCondition(name, formValues);
|
|
117
|
-
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
118
|
-
return true;
|
|
119
|
-
return false;
|
|
120
|
-
});
|
|
121
|
-
const computedValuesMatch = Object.entries(node.if.computedValues ?? {}).every(
|
|
122
|
-
([name, property]) => {
|
|
123
|
-
const currentValue = validations.getScope(parentID).evaluateComputedValueRuleInCondition(name, formValues);
|
|
124
|
-
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
125
|
-
return true;
|
|
126
|
-
return false;
|
|
127
|
-
}
|
|
128
|
-
);
|
|
129
|
-
return computedValuesMatch && validationsMatch;
|
|
130
|
-
}
|
|
131
113
|
|
|
132
114
|
// src/internals/helpers.js
|
|
133
115
|
import merge from "lodash/fp/merge";
|
|
@@ -388,9 +370,6 @@ function _composeFieldCustomClosure(defaultComposeFn) {
|
|
|
388
370
|
};
|
|
389
371
|
}
|
|
390
372
|
|
|
391
|
-
// src/jsonLogic.js
|
|
392
|
-
import jsonLogic from "json-logic-js";
|
|
393
|
-
|
|
394
373
|
// src/yupSchema.js
|
|
395
374
|
import flow from "lodash/flow";
|
|
396
375
|
import noop from "lodash/noop";
|
|
@@ -518,7 +497,7 @@ var getYupSchema = ({ inputType, ...field }) => {
|
|
|
518
497
|
}
|
|
519
498
|
return yupSchemas[inputType] || yupSchemasToJsonTypes[jsonType];
|
|
520
499
|
};
|
|
521
|
-
function buildYupSchema(field, config
|
|
500
|
+
function buildYupSchema(field, config) {
|
|
522
501
|
const { inputType, jsonType: jsonTypeValue, errorMessage = {}, ...propertyFields } = field;
|
|
523
502
|
const isCheckboxBoolean = typeof propertyFields.checkboxValue === "boolean";
|
|
524
503
|
let baseSchema;
|
|
@@ -618,8 +597,7 @@ function buildYupSchema(field, config, validations) {
|
|
|
618
597
|
...fieldSetfield,
|
|
619
598
|
inputType: fieldSetfield.type
|
|
620
599
|
},
|
|
621
|
-
|
|
622
|
-
validations
|
|
600
|
+
config
|
|
623
601
|
)();
|
|
624
602
|
}
|
|
625
603
|
});
|
|
@@ -630,11 +608,7 @@ function buildYupSchema(field, config, validations) {
|
|
|
630
608
|
propertyFields.nthFieldGroup.fields().reduce(
|
|
631
609
|
(schema, groupArrayField) => ({
|
|
632
610
|
...schema,
|
|
633
|
-
[groupArrayField.name]: buildYupSchema(
|
|
634
|
-
groupArrayField,
|
|
635
|
-
{ ...config, parentID: `${propertyFields.nthFieldGroup.name}[]` },
|
|
636
|
-
validations
|
|
637
|
-
)()
|
|
611
|
+
[groupArrayField.name]: buildYupSchema(groupArrayField, config)()
|
|
638
612
|
}),
|
|
639
613
|
{}
|
|
640
614
|
)
|
|
@@ -673,11 +647,6 @@ function buildYupSchema(field, config, validations) {
|
|
|
673
647
|
if (propertyFields.const) {
|
|
674
648
|
validators.push(withConst);
|
|
675
649
|
}
|
|
676
|
-
if (propertyFields.requiredValidations) {
|
|
677
|
-
propertyFields.requiredValidations.forEach(
|
|
678
|
-
(id) => validators.push(yupSchemaWithCustomJSONLogic({ field, id, validations, config }))
|
|
679
|
-
);
|
|
680
|
-
}
|
|
681
650
|
return flow(validators);
|
|
682
651
|
}
|
|
683
652
|
function getNoSortEdges(fields = []) {
|
|
@@ -688,322 +657,26 @@ function getNoSortEdges(fields = []) {
|
|
|
688
657
|
return list;
|
|
689
658
|
}, []);
|
|
690
659
|
}
|
|
691
|
-
function getSchema(fields = [], config
|
|
660
|
+
function getSchema(fields = [], config) {
|
|
692
661
|
const newSchema = {};
|
|
693
662
|
fields.forEach((field) => {
|
|
694
663
|
if (field.schema) {
|
|
695
664
|
if (field.name) {
|
|
696
665
|
if (field.inputType === supportedTypes.FIELDSET) {
|
|
697
|
-
const fieldsetSchema = buildYupSchema(
|
|
698
|
-
field,
|
|
699
|
-
{ ...config, parentID: field.name },
|
|
700
|
-
validations
|
|
701
|
-
)();
|
|
666
|
+
const fieldsetSchema = buildYupSchema(field, config)();
|
|
702
667
|
newSchema[field.name] = fieldsetSchema;
|
|
703
668
|
} else {
|
|
704
669
|
newSchema[field.name] = field.schema;
|
|
705
670
|
}
|
|
706
671
|
} else {
|
|
707
|
-
Object.assign(newSchema, getSchema(field.fields, config
|
|
672
|
+
Object.assign(newSchema, getSchema(field.fields, config));
|
|
708
673
|
}
|
|
709
674
|
}
|
|
710
675
|
});
|
|
711
676
|
return newSchema;
|
|
712
677
|
}
|
|
713
|
-
function buildCompleteYupSchema(fields, config
|
|
714
|
-
return object().shape(getSchema(fields, config
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
// src/jsonLogic.js
|
|
718
|
-
function createValidationChecker(schema) {
|
|
719
|
-
const scopes = /* @__PURE__ */ new Map();
|
|
720
|
-
function createScopes(jsonSchema, key = "root") {
|
|
721
|
-
const sampleEmptyObject = buildSampleEmptyObject(schema);
|
|
722
|
-
scopes.set(key, createValidationsScope(jsonSchema));
|
|
723
|
-
Object.entries(jsonSchema?.properties ?? {}).filter(([, property]) => property.type === "object" || property.type === "array").forEach(([key2, property]) => {
|
|
724
|
-
if (property.type === "array") {
|
|
725
|
-
createScopes(property.items, `${key2}[]`);
|
|
726
|
-
}
|
|
727
|
-
createScopes(property, key2);
|
|
728
|
-
});
|
|
729
|
-
validateInlineRules(jsonSchema, sampleEmptyObject);
|
|
730
|
-
}
|
|
731
|
-
createScopes(schema);
|
|
732
|
-
return {
|
|
733
|
-
scopes,
|
|
734
|
-
getScope(name = "root") {
|
|
735
|
-
return scopes.get(name);
|
|
736
|
-
}
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
function createValidationsScope(schema) {
|
|
740
|
-
const validationMap = /* @__PURE__ */ new Map();
|
|
741
|
-
const computedValuesMap = /* @__PURE__ */ new Map();
|
|
742
|
-
const logic = schema?.["x-jsf-logic"] ?? {
|
|
743
|
-
validations: {},
|
|
744
|
-
computedValues: {}
|
|
745
|
-
};
|
|
746
|
-
const validations = Object.entries(logic.validations ?? {});
|
|
747
|
-
const computedValues = Object.entries(logic.computedValues ?? {});
|
|
748
|
-
const sampleEmptyObject = buildSampleEmptyObject(schema);
|
|
749
|
-
validations.forEach(([id, validation]) => {
|
|
750
|
-
if (!validation.rule) {
|
|
751
|
-
throw Error(`Missing rule for validation with id of: "${id}".`);
|
|
752
|
-
}
|
|
753
|
-
checkRuleIntegrity(validation.rule, id, sampleEmptyObject);
|
|
754
|
-
validationMap.set(id, validation);
|
|
755
|
-
});
|
|
756
|
-
computedValues.forEach(([id, computedValue]) => {
|
|
757
|
-
if (!computedValue.rule) {
|
|
758
|
-
throw Error(`Missing rule for computedValue with id of: "${id}".`);
|
|
759
|
-
}
|
|
760
|
-
checkRuleIntegrity(computedValue.rule, id, sampleEmptyObject);
|
|
761
|
-
computedValuesMap.set(id, computedValue);
|
|
762
|
-
});
|
|
763
|
-
function evaluateValidation(rule, values) {
|
|
764
|
-
return jsonLogic.apply(rule, clean(values));
|
|
765
|
-
}
|
|
766
|
-
return {
|
|
767
|
-
validationMap,
|
|
768
|
-
computedValuesMap,
|
|
769
|
-
evaluateValidation,
|
|
770
|
-
evaluateValidationRuleInCondition(id, values) {
|
|
771
|
-
const validation = validationMap.get(id);
|
|
772
|
-
if (validation === void 0)
|
|
773
|
-
throw Error(`"${id}" validation in if condition doesn't exist.`);
|
|
774
|
-
return evaluateValidation(validation.rule, values);
|
|
775
|
-
},
|
|
776
|
-
evaluateComputedValueRuleForField(id, values, fieldName) {
|
|
777
|
-
const validation = computedValuesMap.get(id);
|
|
778
|
-
if (validation === void 0)
|
|
779
|
-
throw Error(`"${id}" computedValue in field "${fieldName}" doesn't exist.`);
|
|
780
|
-
return evaluateValidation(validation.rule, values);
|
|
781
|
-
},
|
|
782
|
-
evaluateComputedValueRuleInCondition(id, values) {
|
|
783
|
-
const validation = computedValuesMap.get(id);
|
|
784
|
-
if (validation === void 0)
|
|
785
|
-
throw Error(`"${id}" computedValue in if condition doesn't exist.`);
|
|
786
|
-
return evaluateValidation(validation.rule, values);
|
|
787
|
-
}
|
|
788
|
-
};
|
|
789
|
-
}
|
|
790
|
-
function clean(values = {}) {
|
|
791
|
-
return Object.entries(values).reduce((prev, [key, value]) => {
|
|
792
|
-
return { ...prev, [key]: value === void 0 ? null : value };
|
|
793
|
-
}, {});
|
|
794
|
-
}
|
|
795
|
-
function yupSchemaWithCustomJSONLogic({ field, validations, config, id }) {
|
|
796
|
-
const { parentID = "root" } = config;
|
|
797
|
-
const validation = validations.getScope(parentID).validationMap.get(id);
|
|
798
|
-
if (validation === void 0) {
|
|
799
|
-
throw Error(`Validation "${id}" required for "${field.name}" doesn't exist.`);
|
|
800
|
-
}
|
|
801
|
-
return (yupSchema) => yupSchema.test(
|
|
802
|
-
`${field.name}-validation-${id}`,
|
|
803
|
-
validation?.errorMessage ?? "This field is invalid.",
|
|
804
|
-
(value, { parent }) => {
|
|
805
|
-
if (value === void 0 && !field.required)
|
|
806
|
-
return true;
|
|
807
|
-
return jsonLogic.apply(validation.rule, parent);
|
|
808
|
-
}
|
|
809
|
-
);
|
|
810
|
-
}
|
|
811
|
-
function replaceHandlebarsTemplates({
|
|
812
|
-
value: toReplace,
|
|
813
|
-
validations,
|
|
814
|
-
formValues,
|
|
815
|
-
parentID,
|
|
816
|
-
name: fieldName
|
|
817
|
-
}) {
|
|
818
|
-
if (typeof toReplace === "string") {
|
|
819
|
-
return toReplace.replace(/\{\{([^{}]+)\}\}/g, (match, key) => {
|
|
820
|
-
return validations.getScope(parentID).evaluateComputedValueRuleForField(key.trim(), formValues, fieldName);
|
|
821
|
-
});
|
|
822
|
-
} else if (typeof toReplace === "object") {
|
|
823
|
-
const { value, ...rules } = toReplace;
|
|
824
|
-
if (Object.keys(rules).length > 1 && !value)
|
|
825
|
-
throw Error("Cannot define multiple rules without a template string with key `value`.");
|
|
826
|
-
const computedTemplateValue = Object.entries(rules).reduce((prev, [key, rule]) => {
|
|
827
|
-
const computedValue = validations.getScope(parentID).evaluateValidation(rule, formValues);
|
|
828
|
-
return prev.replaceAll(`{{${key}}}`, computedValue);
|
|
829
|
-
}, value);
|
|
830
|
-
return computedTemplateValue.replace(/\{\{([^{}]+)\}\}/g, (match, key) => {
|
|
831
|
-
return validations.getScope(parentID).evaluateComputedValueRuleForField(key.trim(), formValues, fieldName);
|
|
832
|
-
});
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
function calculateComputedAttributes(fieldParams, { parentID = "root" } = {}) {
|
|
836
|
-
return ({ validations, isRequired, config, formValues }) => {
|
|
837
|
-
const { name, computedAttributes } = fieldParams;
|
|
838
|
-
const attributes = Object.fromEntries(
|
|
839
|
-
Object.entries(computedAttributes).map(handleComputedAttribute(validations, formValues, parentID, name)).filter(([, value]) => value !== null)
|
|
840
|
-
);
|
|
841
|
-
return {
|
|
842
|
-
...attributes,
|
|
843
|
-
schema: buildYupSchema(
|
|
844
|
-
{ ...fieldParams, ...attributes, required: isRequired },
|
|
845
|
-
config,
|
|
846
|
-
validations
|
|
847
|
-
)
|
|
848
|
-
};
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
function handleComputedAttribute(validations, formValues, parentID, name) {
|
|
852
|
-
return ([key, value]) => {
|
|
853
|
-
if (key === "description")
|
|
854
|
-
return [key, replaceHandlebarsTemplates({ value, validations, formValues, parentID, name })];
|
|
855
|
-
if (key === "title") {
|
|
856
|
-
return [
|
|
857
|
-
"label",
|
|
858
|
-
replaceHandlebarsTemplates({ value, validations, formValues, parentID, name })
|
|
859
|
-
];
|
|
860
|
-
}
|
|
861
|
-
if (key === "const")
|
|
862
|
-
return [
|
|
863
|
-
key,
|
|
864
|
-
validations.getScope(parentID).evaluateComputedValueRuleForField(value, formValues, name)
|
|
865
|
-
];
|
|
866
|
-
if (key === "x-jsf-errorMessage") {
|
|
867
|
-
return [
|
|
868
|
-
"errorMessage",
|
|
869
|
-
handleNestedObjectForComputedValues(value, formValues, parentID, validations, name)
|
|
870
|
-
];
|
|
871
|
-
}
|
|
872
|
-
if (typeof value === "string") {
|
|
873
|
-
return [
|
|
874
|
-
key,
|
|
875
|
-
validations.getScope(parentID).evaluateComputedValueRuleForField(value, formValues, name)
|
|
876
|
-
];
|
|
877
|
-
}
|
|
878
|
-
if (key === "x-jsf-presentation" && value.statement) {
|
|
879
|
-
return [
|
|
880
|
-
"statement",
|
|
881
|
-
handleNestedObjectForComputedValues(
|
|
882
|
-
value.statement,
|
|
883
|
-
formValues,
|
|
884
|
-
parentID,
|
|
885
|
-
validations,
|
|
886
|
-
name
|
|
887
|
-
)
|
|
888
|
-
];
|
|
889
|
-
}
|
|
890
|
-
if (typeof value === "object" && value.rule) {
|
|
891
|
-
return [key, validations.getScope(parentID).evaluateValidation(value.rule, formValues)];
|
|
892
|
-
}
|
|
893
|
-
};
|
|
894
|
-
}
|
|
895
|
-
function handleNestedObjectForComputedValues(values, formValues, parentID, validations, name) {
|
|
896
|
-
return Object.fromEntries(
|
|
897
|
-
Object.entries(values).map(([key, value]) => {
|
|
898
|
-
return [key, replaceHandlebarsTemplates({ value, validations, formValues, parentID, name })];
|
|
899
|
-
})
|
|
900
|
-
);
|
|
901
|
-
}
|
|
902
|
-
function processJSONLogicNode({
|
|
903
|
-
node,
|
|
904
|
-
formFields,
|
|
905
|
-
formValues,
|
|
906
|
-
accRequired,
|
|
907
|
-
parentID,
|
|
908
|
-
validations
|
|
909
|
-
}) {
|
|
910
|
-
const requiredFields = new Set(accRequired);
|
|
911
|
-
if (node.allOf) {
|
|
912
|
-
node.allOf.map(
|
|
913
|
-
(allOfNode) => processJSONLogicNode({ node: allOfNode, formValues, formFields, validations, parentID })
|
|
914
|
-
).forEach(({ required: allOfItemRequired }) => {
|
|
915
|
-
allOfItemRequired.forEach(requiredFields.add, requiredFields);
|
|
916
|
-
});
|
|
917
|
-
}
|
|
918
|
-
if (node.if) {
|
|
919
|
-
const matchesPropertyCondition = checkIfConditionMatches(
|
|
920
|
-
node,
|
|
921
|
-
formValues,
|
|
922
|
-
formFields,
|
|
923
|
-
validations
|
|
924
|
-
);
|
|
925
|
-
const matchesValidationsAndComputedValues = checkIfMatchesValidationsAndComputedValues(
|
|
926
|
-
node,
|
|
927
|
-
formValues,
|
|
928
|
-
validations,
|
|
929
|
-
parentID
|
|
930
|
-
);
|
|
931
|
-
const isConditionMatch = matchesPropertyCondition && matchesValidationsAndComputedValues;
|
|
932
|
-
if (isConditionMatch && node.then) {
|
|
933
|
-
const { required: branchRequired } = processNode({
|
|
934
|
-
node: node.then,
|
|
935
|
-
formValues,
|
|
936
|
-
formFields,
|
|
937
|
-
accRequired,
|
|
938
|
-
validations
|
|
939
|
-
});
|
|
940
|
-
branchRequired.forEach((field) => requiredFields.add(field));
|
|
941
|
-
}
|
|
942
|
-
if (!isConditionMatch && node.else) {
|
|
943
|
-
const { required: branchRequired } = processNode({
|
|
944
|
-
node: node.else,
|
|
945
|
-
formValues,
|
|
946
|
-
formFields,
|
|
947
|
-
accRequired: requiredFields,
|
|
948
|
-
validations
|
|
949
|
-
});
|
|
950
|
-
branchRequired.forEach((field) => requiredFields.add(field));
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
return { required: requiredFields };
|
|
954
|
-
}
|
|
955
|
-
function buildSampleEmptyObject(schema = {}) {
|
|
956
|
-
const sample = {};
|
|
957
|
-
if (typeof schema !== "object" || !schema.properties) {
|
|
958
|
-
return schema;
|
|
959
|
-
}
|
|
960
|
-
for (const key in schema.properties) {
|
|
961
|
-
if (schema.properties[key].type === "object") {
|
|
962
|
-
sample[key] = buildSampleEmptyObject(schema.properties[key]);
|
|
963
|
-
} else if (schema.properties[key].type === "array") {
|
|
964
|
-
const itemSchema = schema.properties[key].items;
|
|
965
|
-
sample[key] = buildSampleEmptyObject(itemSchema);
|
|
966
|
-
} else {
|
|
967
|
-
sample[key] = true;
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
return sample;
|
|
971
|
-
}
|
|
972
|
-
function validateInlineRules(jsonSchema, sampleEmptyObject) {
|
|
973
|
-
const properties = (jsonSchema?.properties || jsonSchema?.items?.properties) ?? {};
|
|
974
|
-
Object.entries(properties).filter(([, property]) => property["x-jsf-logic-computedAttrs"] !== void 0).forEach(([fieldName, property]) => {
|
|
975
|
-
Object.entries(property["x-jsf-logic-computedAttrs"]).filter(([, value]) => typeof value === "object").forEach(([key, item]) => {
|
|
976
|
-
Object.values(item).forEach((rule) => {
|
|
977
|
-
checkRuleIntegrity(
|
|
978
|
-
rule,
|
|
979
|
-
fieldName,
|
|
980
|
-
sampleEmptyObject,
|
|
981
|
-
(item2) => `"${item2.var}" in inline rule in property "${fieldName}.x-jsf-logic-computedAttrs.${key}" does not exist as a JSON schema property.`
|
|
982
|
-
);
|
|
983
|
-
});
|
|
984
|
-
});
|
|
985
|
-
});
|
|
986
|
-
}
|
|
987
|
-
function checkRuleIntegrity(rule, id, data, errorMessage = (item) => `"${item.var}" in rule "${id}" does not exist as a JSON schema property.`) {
|
|
988
|
-
Object.values(rule ?? {}).map((subRule) => {
|
|
989
|
-
if (!Array.isArray(subRule) && subRule !== null && subRule !== void 0)
|
|
990
|
-
return;
|
|
991
|
-
subRule.map((item) => {
|
|
992
|
-
const isVar = item !== null && typeof item === "object" && Object.hasOwn(item, "var");
|
|
993
|
-
if (isVar) {
|
|
994
|
-
const exists = jsonLogic.apply({ var: removeIndicesFromPath(item.var) }, data);
|
|
995
|
-
if (exists === null) {
|
|
996
|
-
throw Error(errorMessage(item));
|
|
997
|
-
}
|
|
998
|
-
} else {
|
|
999
|
-
checkRuleIntegrity(item, id, data);
|
|
1000
|
-
}
|
|
1001
|
-
});
|
|
1002
|
-
});
|
|
1003
|
-
}
|
|
1004
|
-
function removeIndicesFromPath(path) {
|
|
1005
|
-
const intermediatePath = path.replace(/\.\d+\./g, ".");
|
|
1006
|
-
return intermediatePath.replace(/\.\d+$/, "");
|
|
678
|
+
function buildCompleteYupSchema(fields, config) {
|
|
679
|
+
return object().shape(getSchema(fields, config), getNoSortEdges(fields));
|
|
1007
680
|
}
|
|
1008
681
|
|
|
1009
682
|
// src/helpers.js
|
|
@@ -1013,8 +686,8 @@ function hasType(type, typeName) {
|
|
|
1013
686
|
function getField(fieldName, fields) {
|
|
1014
687
|
return fields.find(({ name }) => name === fieldName);
|
|
1015
688
|
}
|
|
1016
|
-
function validateFieldSchema(field, value
|
|
1017
|
-
const validator = buildYupSchema(field
|
|
689
|
+
function validateFieldSchema(field, value) {
|
|
690
|
+
const validator = buildYupSchema(field);
|
|
1018
691
|
return validator().isValidSync(value);
|
|
1019
692
|
}
|
|
1020
693
|
function compareFormValueWithSchemaValue(formValue, schemaValue) {
|
|
@@ -1079,7 +752,7 @@ function getPrefillValues(fields, initialValues = {}) {
|
|
|
1079
752
|
});
|
|
1080
753
|
return initialValues;
|
|
1081
754
|
}
|
|
1082
|
-
function updateField(field, requiredFields, node, formValues
|
|
755
|
+
function updateField(field, requiredFields, node, formValues) {
|
|
1083
756
|
if (!field) {
|
|
1084
757
|
return;
|
|
1085
758
|
}
|
|
@@ -1101,25 +774,8 @@ function updateField(field, requiredFields, node, formValues, validations, confi
|
|
|
1101
774
|
}
|
|
1102
775
|
}
|
|
1103
776
|
});
|
|
1104
|
-
if (field.getComputedAttributes) {
|
|
1105
|
-
const computedFieldValues = field.getComputedAttributes({
|
|
1106
|
-
field,
|
|
1107
|
-
isRequired: fieldIsRequired,
|
|
1108
|
-
node,
|
|
1109
|
-
formValues,
|
|
1110
|
-
config,
|
|
1111
|
-
validations
|
|
1112
|
-
});
|
|
1113
|
-
updateValues(computedFieldValues);
|
|
1114
|
-
}
|
|
1115
777
|
if (field.calculateConditionalProperties) {
|
|
1116
|
-
const newFieldValues = field.calculateConditionalProperties(
|
|
1117
|
-
fieldIsRequired,
|
|
1118
|
-
node,
|
|
1119
|
-
validations,
|
|
1120
|
-
config,
|
|
1121
|
-
formValues
|
|
1122
|
-
);
|
|
778
|
+
const newFieldValues = field.calculateConditionalProperties(fieldIsRequired, node);
|
|
1123
779
|
updateValues(newFieldValues);
|
|
1124
780
|
}
|
|
1125
781
|
if (field.calculateCustomValidationProperties) {
|
|
@@ -1131,46 +787,33 @@ function updateField(field, requiredFields, node, formValues, validations, confi
|
|
|
1131
787
|
updateValues(newFieldValues);
|
|
1132
788
|
}
|
|
1133
789
|
}
|
|
1134
|
-
function processNode({
|
|
1135
|
-
node,
|
|
1136
|
-
formValues,
|
|
1137
|
-
formFields,
|
|
1138
|
-
accRequired = /* @__PURE__ */ new Set(),
|
|
1139
|
-
parentID = "root",
|
|
1140
|
-
validations
|
|
1141
|
-
}) {
|
|
790
|
+
function processNode(node, formValues, formFields, accRequired = /* @__PURE__ */ new Set()) {
|
|
1142
791
|
const requiredFields = new Set(accRequired);
|
|
1143
792
|
Object.keys(node.properties ?? []).forEach((fieldName) => {
|
|
1144
793
|
const field = getField(fieldName, formFields);
|
|
1145
|
-
updateField(field, requiredFields, node, formValues
|
|
794
|
+
updateField(field, requiredFields, node, formValues);
|
|
1146
795
|
});
|
|
1147
796
|
node.required?.forEach((fieldName) => {
|
|
1148
797
|
requiredFields.add(fieldName);
|
|
1149
|
-
updateField(getField(fieldName, formFields), requiredFields, node, formValues
|
|
1150
|
-
parentID
|
|
1151
|
-
});
|
|
798
|
+
updateField(getField(fieldName, formFields), requiredFields, node, formValues);
|
|
1152
799
|
});
|
|
1153
800
|
if (node.if) {
|
|
1154
|
-
const matchesCondition = checkIfConditionMatches(node, formValues, formFields
|
|
801
|
+
const matchesCondition = checkIfConditionMatches(node, formValues, formFields);
|
|
1155
802
|
if (matchesCondition && node.then) {
|
|
1156
|
-
const { required: branchRequired } = processNode(
|
|
1157
|
-
node
|
|
803
|
+
const { required: branchRequired } = processNode(
|
|
804
|
+
node.then,
|
|
1158
805
|
formValues,
|
|
1159
806
|
formFields,
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
validations
|
|
1163
|
-
});
|
|
807
|
+
requiredFields
|
|
808
|
+
);
|
|
1164
809
|
branchRequired.forEach((field) => requiredFields.add(field));
|
|
1165
810
|
} else if (node.else) {
|
|
1166
|
-
const { required: branchRequired } = processNode(
|
|
1167
|
-
node
|
|
811
|
+
const { required: branchRequired } = processNode(
|
|
812
|
+
node.else,
|
|
1168
813
|
formValues,
|
|
1169
814
|
formFields,
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
validations
|
|
1173
|
-
});
|
|
815
|
+
requiredFields
|
|
816
|
+
);
|
|
1174
817
|
branchRequired.forEach((field) => requiredFields.add(field));
|
|
1175
818
|
}
|
|
1176
819
|
}
|
|
@@ -1182,21 +825,12 @@ function processNode({
|
|
|
1182
825
|
node.anyOf.forEach(({ required = [] }) => {
|
|
1183
826
|
required.forEach((fieldName) => {
|
|
1184
827
|
const field = getField(fieldName, formFields);
|
|
1185
|
-
updateField(field, requiredFields, node, formValues
|
|
828
|
+
updateField(field, requiredFields, node, formValues);
|
|
1186
829
|
});
|
|
1187
830
|
});
|
|
1188
831
|
}
|
|
1189
832
|
if (node.allOf) {
|
|
1190
|
-
node.allOf.map(
|
|
1191
|
-
(allOfNode) => processNode({
|
|
1192
|
-
node: allOfNode,
|
|
1193
|
-
formValues,
|
|
1194
|
-
formFields,
|
|
1195
|
-
accRequired: requiredFields,
|
|
1196
|
-
parentID,
|
|
1197
|
-
validations
|
|
1198
|
-
})
|
|
1199
|
-
).forEach(({ required: allOfItemRequired }) => {
|
|
833
|
+
node.allOf.map((allOfNode) => processNode(allOfNode, formValues, formFields, requiredFields)).forEach(({ required: allOfItemRequired }) => {
|
|
1200
834
|
allOfItemRequired.forEach(requiredFields.add, requiredFields);
|
|
1201
835
|
});
|
|
1202
836
|
}
|
|
@@ -1204,27 +838,10 @@ function processNode({
|
|
|
1204
838
|
Object.entries(node.properties).forEach(([name, nestedNode]) => {
|
|
1205
839
|
const inputType = getInputType(nestedNode);
|
|
1206
840
|
if (inputType === supportedTypes.FIELDSET) {
|
|
1207
|
-
processNode({
|
|
1208
|
-
node: nestedNode,
|
|
1209
|
-
formValues: formValues[name] || {},
|
|
1210
|
-
formFields: getField(name, formFields).fields,
|
|
1211
|
-
validations,
|
|
1212
|
-
parentID: name
|
|
1213
|
-
});
|
|
841
|
+
processNode(nestedNode, formValues[name] || {}, getField(name, formFields).fields);
|
|
1214
842
|
}
|
|
1215
843
|
});
|
|
1216
844
|
}
|
|
1217
|
-
if (node["x-jsf-logic"]) {
|
|
1218
|
-
const { required: requiredFromLogic } = processJSONLogicNode({
|
|
1219
|
-
node: node["x-jsf-logic"],
|
|
1220
|
-
formValues,
|
|
1221
|
-
formFields,
|
|
1222
|
-
accRequired: requiredFields,
|
|
1223
|
-
parentID,
|
|
1224
|
-
validations
|
|
1225
|
-
});
|
|
1226
|
-
requiredFromLogic.forEach((field) => requiredFields.add(field));
|
|
1227
|
-
}
|
|
1228
845
|
return {
|
|
1229
846
|
required: requiredFields
|
|
1230
847
|
};
|
|
@@ -1239,11 +856,11 @@ function clearValuesIfNotVisible(fields, formValues) {
|
|
|
1239
856
|
}
|
|
1240
857
|
});
|
|
1241
858
|
}
|
|
1242
|
-
function updateFieldsProperties(fields, formValues, jsonSchema
|
|
859
|
+
function updateFieldsProperties(fields, formValues, jsonSchema) {
|
|
1243
860
|
if (!jsonSchema?.properties) {
|
|
1244
861
|
return;
|
|
1245
862
|
}
|
|
1246
|
-
processNode(
|
|
863
|
+
processNode(jsonSchema, formValues, fields);
|
|
1247
864
|
clearValuesIfNotVisible(fields, formValues);
|
|
1248
865
|
}
|
|
1249
866
|
var notNullOption = (opt) => opt.const !== null;
|
|
@@ -1286,20 +903,12 @@ function extractParametersFromNode(schemaNode) {
|
|
|
1286
903
|
}
|
|
1287
904
|
const presentation = pickXKey(schemaNode, "presentation") ?? {};
|
|
1288
905
|
const errorMessage = pickXKey(schemaNode, "errorMessage") ?? {};
|
|
1289
|
-
const requiredValidations = schemaNode["x-jsf-logic-validations"];
|
|
1290
|
-
const computedAttributes = schemaNode["x-jsf-logic-computedAttrs"];
|
|
1291
|
-
const decoratedComputedAttributes = {
|
|
1292
|
-
...computedAttributes ?? {},
|
|
1293
|
-
...computedAttributes?.const && computedAttributes?.default ? { value: computedAttributes.const } : {}
|
|
1294
|
-
};
|
|
1295
906
|
const node = omit(schemaNode, ["x-jsf-presentation", "presentation"]);
|
|
1296
907
|
const description = presentation?.description || node.description;
|
|
1297
908
|
const statementDescription = containsHTML(presentation.statement?.description) ? wrapWithSpan(presentation.statement.description, { class: "jsf-statement" }) : presentation.statement?.description;
|
|
1298
909
|
return omitBy(
|
|
1299
910
|
{
|
|
1300
911
|
const: node.const,
|
|
1301
|
-
// This is a "forced value" when both const and default are present.
|
|
1302
|
-
...node.const && node.default ? { value: node.const } : {},
|
|
1303
912
|
label: node.title,
|
|
1304
913
|
readOnly: node.readOnly,
|
|
1305
914
|
...node.deprecated && {
|
|
@@ -1334,8 +943,6 @@ function extractParametersFromNode(schemaNode) {
|
|
|
1334
943
|
},
|
|
1335
944
|
// Handle [name].presentation
|
|
1336
945
|
...presentation,
|
|
1337
|
-
requiredValidations,
|
|
1338
|
-
computedAttributes: decoratedComputedAttributes,
|
|
1339
946
|
description: containsHTML(description) ? wrapWithSpan(description, {
|
|
1340
947
|
class: "jsf-description"
|
|
1341
948
|
}) : description,
|
|
@@ -1372,9 +979,9 @@ function yupToFormErrors(yupError) {
|
|
|
1372
979
|
}
|
|
1373
980
|
return errors;
|
|
1374
981
|
}
|
|
1375
|
-
var handleValuesChange = (fields, jsonSchema, config
|
|
1376
|
-
updateFieldsProperties(fields, values, jsonSchema
|
|
1377
|
-
const lazySchema = lazy(() => buildCompleteYupSchema(fields, config
|
|
982
|
+
var handleValuesChange = (fields, jsonSchema, config) => (values) => {
|
|
983
|
+
updateFieldsProperties(fields, values, jsonSchema);
|
|
984
|
+
const lazySchema = lazy(() => buildCompleteYupSchema(fields, config));
|
|
1378
985
|
let errors;
|
|
1379
986
|
try {
|
|
1380
987
|
lazySchema.validateSync(values, {
|
|
@@ -1428,8 +1035,8 @@ function rebuildFieldset(fields, property) {
|
|
|
1428
1035
|
required: isFieldRequired(property, field)
|
|
1429
1036
|
}));
|
|
1430
1037
|
}
|
|
1431
|
-
function calculateConditionalProperties(fieldParams, customProperties
|
|
1432
|
-
return (isRequired, conditionBranch
|
|
1038
|
+
function calculateConditionalProperties(fieldParams, customProperties) {
|
|
1039
|
+
return (isRequired, conditionBranch) => {
|
|
1433
1040
|
const conditionalProperty = conditionBranch?.properties?.[fieldParams.name];
|
|
1434
1041
|
if (conditionalProperty) {
|
|
1435
1042
|
const presentation = pickXKey(conditionalProperty, "presentation") ?? {};
|
|
@@ -1443,31 +1050,17 @@ function calculateConditionalProperties(fieldParams, customProperties, validatio
|
|
|
1443
1050
|
fieldSetFields = rebuildFieldset(fieldParams.fields, conditionalProperty);
|
|
1444
1051
|
newFieldParams.fields = fieldSetFields;
|
|
1445
1052
|
}
|
|
1446
|
-
const { computedAttributes, ...restNewFieldParams } = newFieldParams;
|
|
1447
|
-
const calculatedComputedAttributes = computedAttributes ? calculateComputedAttributes(newFieldParams, config)({ validations, formValues }) : {};
|
|
1448
|
-
const requiredValidations = [
|
|
1449
|
-
...fieldParams.requiredValidations ?? [],
|
|
1450
|
-
...restNewFieldParams.requiredValidations ?? []
|
|
1451
|
-
];
|
|
1452
1053
|
const base = {
|
|
1453
1054
|
isVisible: true,
|
|
1454
1055
|
required: isRequired,
|
|
1455
1056
|
...presentation?.inputType && { type: presentation.inputType },
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
requiredValidations,
|
|
1464
|
-
// If there are inner fields (case of fieldset) they need to be updated based on the condition
|
|
1465
|
-
fields: fieldSetFields,
|
|
1466
|
-
required: isRequired
|
|
1467
|
-
},
|
|
1468
|
-
config,
|
|
1469
|
-
validations
|
|
1470
|
-
)
|
|
1057
|
+
schema: buildYupSchema({
|
|
1058
|
+
...fieldParams,
|
|
1059
|
+
...newFieldParams,
|
|
1060
|
+
// If there are inner fields (case of fieldset) they need to be updated based on the condition
|
|
1061
|
+
fields: fieldSetFields,
|
|
1062
|
+
required: isRequired
|
|
1063
|
+
})
|
|
1471
1064
|
};
|
|
1472
1065
|
return omit2(merge2(base, presentation, newFieldParams), ["inputType"]);
|
|
1473
1066
|
}
|
|
@@ -1561,19 +1154,14 @@ function sortByOrderOrPosition(a, b, order) {
|
|
|
1561
1154
|
function removeInvalidAttributes(fields) {
|
|
1562
1155
|
return omit3(fields, ["items", "maxFileSize", "isDynamic"]);
|
|
1563
1156
|
}
|
|
1564
|
-
function buildFieldParameters(name, fieldProperties, required = [], config = {}
|
|
1157
|
+
function buildFieldParameters(name, fieldProperties, required = [], config = {}) {
|
|
1565
1158
|
const { position } = pickXKey(fieldProperties, "presentation") ?? {};
|
|
1566
1159
|
let fields;
|
|
1567
1160
|
const inputType = getInputType(fieldProperties, config.strictInputType, name);
|
|
1568
1161
|
if (inputType === supportedTypes.FIELDSET) {
|
|
1569
|
-
fields = getFieldsFromJSONSchema(
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
customProperties: get3(config, `customProperties.${name}`, {}),
|
|
1573
|
-
parentID: name
|
|
1574
|
-
},
|
|
1575
|
-
validations
|
|
1576
|
-
);
|
|
1162
|
+
fields = getFieldsFromJSONSchema(fieldProperties, {
|
|
1163
|
+
customProperties: get3(config, `customProperties.${name}`, {})
|
|
1164
|
+
});
|
|
1577
1165
|
}
|
|
1578
1166
|
const result = {
|
|
1579
1167
|
name,
|
|
@@ -1588,9 +1176,9 @@ function buildFieldParameters(name, fieldProperties, required = [], config = {},
|
|
|
1588
1176
|
};
|
|
1589
1177
|
return omitBy2(result, isNil3);
|
|
1590
1178
|
}
|
|
1591
|
-
function convertJSONSchemaPropertiesToFieldParameters({ properties, required, "x-jsf-order": order }, config = {}
|
|
1179
|
+
function convertJSONSchemaPropertiesToFieldParameters({ properties, required, "x-jsf-order": order }, config = {}) {
|
|
1592
1180
|
const sortFields = (a, b) => sortByOrderOrPosition(a, b, order);
|
|
1593
|
-
return Object.entries(properties).filter(([, value]) => typeof value === "object").map(([key, value]) => buildFieldParameters(key, value, required, config
|
|
1181
|
+
return Object.entries(properties).filter(([, value]) => typeof value === "object").map(([key, value]) => buildFieldParameters(key, value, required, config)).sort(sortFields).map(({ position, ...fieldParams }) => fieldParams);
|
|
1594
1182
|
}
|
|
1595
1183
|
function applyFieldsDependencies(fieldsParameters, node) {
|
|
1596
1184
|
if (node?.then) {
|
|
@@ -1612,9 +1200,6 @@ function applyFieldsDependencies(fieldsParameters, node) {
|
|
|
1612
1200
|
applyFieldsDependencies(fieldsParameters, condition);
|
|
1613
1201
|
});
|
|
1614
1202
|
}
|
|
1615
|
-
if (node?.["x-jsf-logic"]) {
|
|
1616
|
-
applyFieldsDependencies(fieldsParameters, node["x-jsf-logic"]);
|
|
1617
|
-
}
|
|
1618
1203
|
}
|
|
1619
1204
|
function getCustomPropertiesForField(fieldParams, config) {
|
|
1620
1205
|
return config?.customProperties?.[fieldParams.name];
|
|
@@ -1626,16 +1211,15 @@ function getComposeFunctionForField(fieldParams, hasCustomizations) {
|
|
|
1626
1211
|
}
|
|
1627
1212
|
return composeFn;
|
|
1628
1213
|
}
|
|
1629
|
-
function buildField(fieldParams, config, scopedJsonSchema
|
|
1214
|
+
function buildField(fieldParams, config, scopedJsonSchema) {
|
|
1630
1215
|
const customProperties = getCustomPropertiesForField(fieldParams, config);
|
|
1631
1216
|
const composeFn = getComposeFunctionForField(fieldParams, !!customProperties);
|
|
1632
|
-
const yupSchema = buildYupSchema(fieldParams, config
|
|
1633
|
-
const calculateConditionalFieldsClosure = fieldParams.isDynamic && calculateConditionalProperties(fieldParams, customProperties
|
|
1217
|
+
const yupSchema = buildYupSchema(fieldParams, config);
|
|
1218
|
+
const calculateConditionalFieldsClosure = fieldParams.isDynamic && calculateConditionalProperties(fieldParams, customProperties);
|
|
1634
1219
|
const calculateCustomValidationPropertiesClosure = calculateCustomValidationProperties(
|
|
1635
1220
|
fieldParams,
|
|
1636
1221
|
customProperties
|
|
1637
1222
|
);
|
|
1638
|
-
const getComputedAttributes = Object.keys(fieldParams.computedAttributes).length > 0 && calculateComputedAttributes(fieldParams, config);
|
|
1639
1223
|
const hasCustomValidations = !!customProperties && size(pick2(customProperties, SUPPORTED_CUSTOM_VALIDATION_FIELD_PARAMS)) > 0;
|
|
1640
1224
|
const finalFieldParams = {
|
|
1641
1225
|
// invalid attribute cleanup
|
|
@@ -1648,7 +1232,6 @@ function buildField(fieldParams, config, scopedJsonSchema, validations) {
|
|
|
1648
1232
|
...hasCustomValidations && {
|
|
1649
1233
|
calculateCustomValidationProperties: calculateCustomValidationPropertiesClosure
|
|
1650
1234
|
},
|
|
1651
|
-
...getComputedAttributes && { getComputedAttributes },
|
|
1652
1235
|
// field customization properties
|
|
1653
1236
|
...customProperties && { fieldCustomization: customProperties },
|
|
1654
1237
|
// base schema
|
|
@@ -1657,15 +1240,11 @@ function buildField(fieldParams, config, scopedJsonSchema, validations) {
|
|
|
1657
1240
|
};
|
|
1658
1241
|
return composeFn(finalFieldParams);
|
|
1659
1242
|
}
|
|
1660
|
-
function getFieldsFromJSONSchema(scopedJsonSchema, config
|
|
1243
|
+
function getFieldsFromJSONSchema(scopedJsonSchema, config) {
|
|
1661
1244
|
if (!scopedJsonSchema) {
|
|
1662
1245
|
return [];
|
|
1663
1246
|
}
|
|
1664
|
-
const fieldParamsList = convertJSONSchemaPropertiesToFieldParameters(
|
|
1665
|
-
scopedJsonSchema,
|
|
1666
|
-
config,
|
|
1667
|
-
validations
|
|
1668
|
-
);
|
|
1247
|
+
const fieldParamsList = convertJSONSchemaPropertiesToFieldParameters(scopedJsonSchema, config);
|
|
1669
1248
|
applyFieldsDependencies(fieldParamsList, scopedJsonSchema);
|
|
1670
1249
|
const fields = [];
|
|
1671
1250
|
fieldParamsList.forEach((fieldParams) => {
|
|
@@ -1685,11 +1264,11 @@ function getFieldsFromJSONSchema(scopedJsonSchema, config, validations) {
|
|
|
1685
1264
|
fields: () => groupArrayFields,
|
|
1686
1265
|
addFieldText: fieldParams.addFieldText
|
|
1687
1266
|
};
|
|
1688
|
-
buildField(fieldParams, config, scopedJsonSchema
|
|
1267
|
+
buildField(fieldParams, config, scopedJsonSchema).forEach((groupField) => {
|
|
1689
1268
|
fields.push(groupField);
|
|
1690
1269
|
});
|
|
1691
1270
|
} else {
|
|
1692
|
-
fields.push(buildField(fieldParams, config, scopedJsonSchema
|
|
1271
|
+
fields.push(buildField(fieldParams, config, scopedJsonSchema));
|
|
1693
1272
|
}
|
|
1694
1273
|
});
|
|
1695
1274
|
return fields;
|
|
@@ -1700,15 +1279,9 @@ function createHeadlessForm(jsonSchema, customConfig = {}) {
|
|
|
1700
1279
|
...customConfig
|
|
1701
1280
|
};
|
|
1702
1281
|
try {
|
|
1703
|
-
const
|
|
1704
|
-
const
|
|
1705
|
-
|
|
1706
|
-
updateFieldsProperties(
|
|
1707
|
-
fields,
|
|
1708
|
-
getPrefillValues(fields, config.initialValues),
|
|
1709
|
-
jsonSchema,
|
|
1710
|
-
validations
|
|
1711
|
-
);
|
|
1282
|
+
const fields = getFieldsFromJSONSchema(jsonSchema, config);
|
|
1283
|
+
const handleValidation = handleValuesChange(fields, jsonSchema, config);
|
|
1284
|
+
updateFieldsProperties(fields, getPrefillValues(fields, config.initialValues), jsonSchema);
|
|
1712
1285
|
return {
|
|
1713
1286
|
fields,
|
|
1714
1287
|
handleValidation,
|