@remoteoss/json-schema-form 0.5.0-dev.20230719162322 → 0.5.0-dev.20230901130231
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/CHANGELOG.md +24 -0
- package/dist/index.cjs +278 -86
- package/dist/index.js +278 -86
- package/dist/standalone.js +655 -85
- package/package.json +2 -1
- package/src/tests/checkIfConditionMatches.test.js +51 -0
- package/src/tests/conditions.test.js +58 -0
- package/src/tests/const.test.js +86 -0
- package/src/tests/createHeadlessForm.test.js +31 -10
- package/src/tests/helpers.custom.js +0 -1
- package/src/tests/helpers.js +6 -6
- package/src/tests/jsonLogic.fixtures.js +162 -0
- package/src/tests/jsonLogic.test.js +230 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
#### 0.4.5-beta.0 (2023-08-31)
|
|
2
|
+
|
|
3
|
+
##### Changes
|
|
4
|
+
|
|
5
|
+
* Allow validation of consts to support single values ([#34](https://github.com/remoteoss/json-schema-form/pull/34)) ([bf07870d](https://github.com/remoteoss/json-schema-form/commit/bf07870d407d9b9b078882a078b9e4c7928df868))
|
|
6
|
+
|
|
7
|
+
#### 0.4.4-beta.0 (2023-08-30)
|
|
8
|
+
|
|
9
|
+
##### Chores
|
|
10
|
+
|
|
11
|
+
* **fieldset:** ignore values not matching the field type ([#44](https://github.com/remoteoss/json-schema-form/pull/44)) ([f0af54e5](https://github.com/remoteoss/json-schema-form/commit/f0af54e5d425fb78524ab150bb31629d00369a61))
|
|
12
|
+
|
|
13
|
+
#### 0.4.3-beta.0 (2023-08-09)
|
|
14
|
+
|
|
15
|
+
##### Bug fixes
|
|
16
|
+
|
|
17
|
+
* **conditions:** Validate a deeply nested if (e.g. checking an object with a number property) in an if property now doesn't break the form. ([#33](https://github.com/remoteoss/json-schema-form/pull/33)) ([e34cfcc](https://github.com/remoteoss/json-schema-form/commit/e34cfccaf45f1460b346f3cff0c797b3d11259e3))
|
|
18
|
+
|
|
19
|
+
#### 0.4.2-beta.0 (2023-07-20)
|
|
20
|
+
|
|
21
|
+
##### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* **date:** Validate based on minDate and maxDate ([#30](https://github.com/remoteoss/json-schema-form/pull/30)) ([01c0143e](https://github.com/remoteoss/json-schema-form/commit/01c0143ea4a3775f9489ae6cb8fd99a90b3f1394))
|
|
24
|
+
|
|
1
25
|
#### 0.4.1-beta.0 (2023-07-03)
|
|
2
26
|
|
|
3
27
|
##### Bug Fixes
|
package/dist/index.cjs
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.5.0-dev.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.5.0-dev.20230901130231
|
|
5
|
+
Generated: Fri, 01 Sep 2023 13:03:04 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -84,6 +84,69 @@ var import_omitBy = __toESM(require("lodash/omitBy"));
|
|
|
84
84
|
var import_set = __toESM(require("lodash/set"));
|
|
85
85
|
var import_yup2 = require("yup");
|
|
86
86
|
|
|
87
|
+
// src/utils.js
|
|
88
|
+
function convertDiskSizeFromTo(from, to) {
|
|
89
|
+
const units = ["bytes", "kb", "mb"];
|
|
90
|
+
return function convert(value) {
|
|
91
|
+
return value * Math.pow(1024, units.indexOf(from.toLowerCase())) / Math.pow(1024, units.indexOf(to.toLowerCase()));
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function containsHTML(str = "") {
|
|
95
|
+
return /<[a-z][\s\S]*>/i.test(str);
|
|
96
|
+
}
|
|
97
|
+
function wrapWithSpan(html, properties = {}) {
|
|
98
|
+
const attributes = Object.entries(properties).reduce((acc, [key, value]) => `${acc}${key}="${value}" `, "").trim();
|
|
99
|
+
return `<span ${attributes}>${html}</span>`;
|
|
100
|
+
}
|
|
101
|
+
function hasProperty(object2, propertyName) {
|
|
102
|
+
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// src/checkIfConditionMatches.js
|
|
106
|
+
function checkIfConditionMatches(node, formValues, formFields) {
|
|
107
|
+
return Object.keys(node.if.properties).every((name) => {
|
|
108
|
+
const currentProperty = node.if.properties[name];
|
|
109
|
+
const value = formValues[name];
|
|
110
|
+
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
111
|
+
value === null;
|
|
112
|
+
const hasIfExplicit = node.if.required?.includes(name);
|
|
113
|
+
if (hasEmptyValue && !hasIfExplicit) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
if (hasProperty(currentProperty, "const")) {
|
|
117
|
+
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
118
|
+
}
|
|
119
|
+
if (currentProperty.contains?.pattern) {
|
|
120
|
+
const formValue = value || [];
|
|
121
|
+
if (Array.isArray(formValue)) {
|
|
122
|
+
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
123
|
+
return (value || []).some((item) => pattern.test(item));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (currentProperty.enum) {
|
|
127
|
+
return currentProperty.enum.includes(value);
|
|
128
|
+
}
|
|
129
|
+
if (currentProperty.properties) {
|
|
130
|
+
return checkIfConditionMatches(
|
|
131
|
+
{ if: currentProperty },
|
|
132
|
+
formValues[name],
|
|
133
|
+
getField(name, formFields).fields
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
const field = getField(name, formFields);
|
|
137
|
+
return validateFieldSchema(
|
|
138
|
+
{
|
|
139
|
+
options: field.options,
|
|
140
|
+
// @TODO/CODE SMELL. We are passing the property (raw field), but buildYupSchema() expected the output field.
|
|
141
|
+
...currentProperty,
|
|
142
|
+
inputType: field.inputType,
|
|
143
|
+
required: true
|
|
144
|
+
},
|
|
145
|
+
value
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
87
150
|
// src/internals/helpers.js
|
|
88
151
|
var import_merge = __toESM(require("lodash/fp/merge"));
|
|
89
152
|
var import_get = __toESM(require("lodash/get"));
|
|
@@ -343,29 +406,108 @@ function _composeFieldCustomClosure(defaultComposeFn) {
|
|
|
343
406
|
};
|
|
344
407
|
}
|
|
345
408
|
|
|
346
|
-
// src/
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
409
|
+
// src/yupSchema.js
|
|
410
|
+
var import_flow = __toESM(require("lodash/flow"));
|
|
411
|
+
var import_noop = __toESM(require("lodash/noop"));
|
|
412
|
+
var import_randexp = require("randexp");
|
|
413
|
+
var import_yup = require("yup");
|
|
414
|
+
|
|
415
|
+
// src/jsonLogic.js
|
|
416
|
+
var import_json_logic_js = __toESM(require("json-logic-js"));
|
|
417
|
+
function createValidationChecker(schema) {
|
|
418
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
419
|
+
function createScopes(jsonSchema, key = "root") {
|
|
420
|
+
scopes.set(key, createValidationsScope(jsonSchema));
|
|
421
|
+
Object.entries(jsonSchema?.properties ?? {}).filter(([, property]) => property.type === "object" || property.type === "array").forEach(([key2, property]) => {
|
|
422
|
+
if (property.type === "array") {
|
|
423
|
+
createScopes(property.items, `${key2}[]`);
|
|
424
|
+
} else {
|
|
425
|
+
createScopes(property, key2);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
createScopes(schema);
|
|
430
|
+
return {
|
|
431
|
+
scopes,
|
|
432
|
+
getScope(name = "root") {
|
|
433
|
+
return scopes.get(name);
|
|
434
|
+
}
|
|
351
435
|
};
|
|
352
436
|
}
|
|
353
|
-
function
|
|
354
|
-
|
|
437
|
+
function createValidationsScope(schema) {
|
|
438
|
+
const validationMap = /* @__PURE__ */ new Map();
|
|
439
|
+
const computedValuesMap = /* @__PURE__ */ new Map();
|
|
440
|
+
const logic = schema?.["x-jsf-logic"] ?? {
|
|
441
|
+
validations: {},
|
|
442
|
+
computedValues: {}
|
|
443
|
+
};
|
|
444
|
+
const validations = Object.entries(logic.validations ?? {});
|
|
445
|
+
const computedValues = Object.entries(logic.computedValues ?? {});
|
|
446
|
+
validations.forEach(([id, validation]) => {
|
|
447
|
+
validationMap.set(id, validation);
|
|
448
|
+
});
|
|
449
|
+
computedValues.forEach(([id, computedValue]) => {
|
|
450
|
+
computedValuesMap.set(id, computedValue);
|
|
451
|
+
});
|
|
452
|
+
function validate(rule, values) {
|
|
453
|
+
return import_json_logic_js.default.apply(rule, replaceUndefinedValuesWithNulls(values));
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
validationMap,
|
|
457
|
+
computedValuesMap,
|
|
458
|
+
validate,
|
|
459
|
+
applyValidationRuleInCondition(id, values) {
|
|
460
|
+
const validation = validationMap.get(id);
|
|
461
|
+
return validate(validation.rule, values);
|
|
462
|
+
},
|
|
463
|
+
applyComputedValueInField(id, values) {
|
|
464
|
+
const validation = computedValuesMap.get(id);
|
|
465
|
+
return validate(validation.rule, values);
|
|
466
|
+
},
|
|
467
|
+
applyComputedValueRuleInCondition(id, values) {
|
|
468
|
+
const validation = computedValuesMap.get(id);
|
|
469
|
+
return validate(validation.rule, values);
|
|
470
|
+
}
|
|
471
|
+
};
|
|
355
472
|
}
|
|
356
|
-
function
|
|
357
|
-
|
|
358
|
-
|
|
473
|
+
function replaceUndefinedValuesWithNulls(values = {}) {
|
|
474
|
+
return Object.entries(values).reduce((prev, [key, value]) => {
|
|
475
|
+
return { ...prev, [key]: value === void 0 ? null : value };
|
|
476
|
+
}, {});
|
|
359
477
|
}
|
|
360
|
-
function
|
|
361
|
-
|
|
478
|
+
function yupSchemaWithCustomJSONLogic({ field, logic, config, id }) {
|
|
479
|
+
const { parentID = "root" } = config;
|
|
480
|
+
const validation = logic.getScope(parentID).validationMap.get(id);
|
|
481
|
+
return (yupSchema) => yupSchema.test(
|
|
482
|
+
`${field.name}-validation-${id}`,
|
|
483
|
+
validation?.errorMessage ?? "This field is invalid.",
|
|
484
|
+
(value, { parent }) => {
|
|
485
|
+
if (value === void 0 && !field.required)
|
|
486
|
+
return true;
|
|
487
|
+
return import_json_logic_js.default.apply(validation.rule, parent);
|
|
488
|
+
}
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
function calculateComputedAttributes(fieldParams, { parentID = "root" } = {}) {
|
|
492
|
+
return ({ logic, formValues }) => {
|
|
493
|
+
const { computedAttributes } = fieldParams;
|
|
494
|
+
const attributes = Object.fromEntries(
|
|
495
|
+
Object.entries(computedAttributes).map(handleComputedAttribute(logic, formValues, parentID)).filter(([, value]) => value !== null)
|
|
496
|
+
);
|
|
497
|
+
return attributes;
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
function handleComputedAttribute(logic, formValues, parentID) {
|
|
501
|
+
return ([key, value]) => {
|
|
502
|
+
if (key === "const")
|
|
503
|
+
return [key, logic.getScope(parentID).applyComputedValueInField(value, formValues)];
|
|
504
|
+
if (typeof value === "string") {
|
|
505
|
+
return [key, logic.getScope(parentID).applyComputedValueInField(value, formValues)];
|
|
506
|
+
}
|
|
507
|
+
};
|
|
362
508
|
}
|
|
363
509
|
|
|
364
510
|
// src/yupSchema.js
|
|
365
|
-
var import_flow = __toESM(require("lodash/flow"));
|
|
366
|
-
var import_noop = __toESM(require("lodash/noop"));
|
|
367
|
-
var import_randexp = require("randexp");
|
|
368
|
-
var import_yup = require("yup");
|
|
369
511
|
var DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
|
|
370
512
|
var baseString = (0, import_yup.string)().trim();
|
|
371
513
|
var todayDateHint = (/* @__PURE__ */ new Date()).toISOString().substring(0, 10);
|
|
@@ -488,7 +630,7 @@ var getYupSchema = ({ inputType, ...field }) => {
|
|
|
488
630
|
}
|
|
489
631
|
return yupSchemas[inputType] || yupSchemasToJsonTypes[jsonType];
|
|
490
632
|
};
|
|
491
|
-
function buildYupSchema(field, config) {
|
|
633
|
+
function buildYupSchema(field, config, logic) {
|
|
492
634
|
const { inputType, jsonType: jsonTypeValue, errorMessage = {}, ...propertyFields } = field;
|
|
493
635
|
const isCheckboxBoolean = typeof propertyFields.checkboxValue === "boolean";
|
|
494
636
|
let baseSchema;
|
|
@@ -561,6 +703,13 @@ function buildYupSchema(field, config) {
|
|
|
561
703
|
}) : true
|
|
562
704
|
);
|
|
563
705
|
}
|
|
706
|
+
function withConst(yupSchema) {
|
|
707
|
+
return yupSchema.test(
|
|
708
|
+
"isConst",
|
|
709
|
+
errorMessage.const ?? errorMessageFromConfig.const ?? `The only accepted value is ${propertyFields.const}.`,
|
|
710
|
+
(value) => propertyFields.required === false && value === void 0 || value === null || value === propertyFields.const
|
|
711
|
+
);
|
|
712
|
+
}
|
|
564
713
|
function withBaseSchema() {
|
|
565
714
|
const customErrorMsg = errorMessage.type || errorMessageFromConfig.type;
|
|
566
715
|
if (customErrorMsg) {
|
|
@@ -628,6 +777,14 @@ function buildYupSchema(field, config) {
|
|
|
628
777
|
if (propertyFields.accept) {
|
|
629
778
|
validators.push(withFileFormat);
|
|
630
779
|
}
|
|
780
|
+
if (propertyFields.const) {
|
|
781
|
+
validators.push(withConst);
|
|
782
|
+
}
|
|
783
|
+
if (propertyFields.requiredValidations) {
|
|
784
|
+
propertyFields.requiredValidations.forEach(
|
|
785
|
+
(id) => validators.push(yupSchemaWithCustomJSONLogic({ field, id, logic, config }))
|
|
786
|
+
);
|
|
787
|
+
}
|
|
631
788
|
return (0, import_flow.default)(validators);
|
|
632
789
|
}
|
|
633
790
|
function getNoSortEdges(fields = []) {
|
|
@@ -667,50 +824,14 @@ function hasType(type, typeName) {
|
|
|
667
824
|
function getField(fieldName, fields) {
|
|
668
825
|
return fields.find(({ name }) => name === fieldName);
|
|
669
826
|
}
|
|
670
|
-
function validateFieldSchema(field, value) {
|
|
671
|
-
const validator = buildYupSchema(field);
|
|
827
|
+
function validateFieldSchema(field, value, logic) {
|
|
828
|
+
const validator = buildYupSchema(field, {}, logic);
|
|
672
829
|
return validator().isValidSync(value);
|
|
673
830
|
}
|
|
674
831
|
function compareFormValueWithSchemaValue(formValue, schemaValue) {
|
|
675
832
|
const currentPropertyValue = typeof schemaValue === "number" ? schemaValue : schemaValue || void 0;
|
|
676
833
|
return String(formValue) === String(currentPropertyValue);
|
|
677
834
|
}
|
|
678
|
-
function checkIfConditionMatches(node, formValues, formFields) {
|
|
679
|
-
return Object.keys(node.if.properties).every((name) => {
|
|
680
|
-
const currentProperty = node.if.properties[name];
|
|
681
|
-
const value = formValues[name];
|
|
682
|
-
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
683
|
-
value === null;
|
|
684
|
-
const hasIfExplicit = node.if.required?.includes(name);
|
|
685
|
-
if (hasEmptyValue && !hasIfExplicit) {
|
|
686
|
-
return true;
|
|
687
|
-
}
|
|
688
|
-
if (hasProperty(currentProperty, "const")) {
|
|
689
|
-
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
690
|
-
}
|
|
691
|
-
if (currentProperty.contains?.pattern) {
|
|
692
|
-
const formValue = value || [];
|
|
693
|
-
if (Array.isArray(formValue)) {
|
|
694
|
-
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
695
|
-
return (value || []).some((item) => pattern.test(item));
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
if (currentProperty.enum) {
|
|
699
|
-
return currentProperty.enum.includes(value);
|
|
700
|
-
}
|
|
701
|
-
const field = getField(name, formFields);
|
|
702
|
-
return validateFieldSchema(
|
|
703
|
-
{
|
|
704
|
-
options: field.options,
|
|
705
|
-
// @TODO/CODE SMELL. We are passing the property (raw field), but buildYupSchema() expected the output field.
|
|
706
|
-
...currentProperty,
|
|
707
|
-
inputType: field.inputType,
|
|
708
|
-
required: true
|
|
709
|
-
},
|
|
710
|
-
value
|
|
711
|
-
);
|
|
712
|
-
});
|
|
713
|
-
}
|
|
714
835
|
function isFieldFilled(fieldValue) {
|
|
715
836
|
return Array.isArray(fieldValue) ? fieldValue.length > 0 : !!fieldValue;
|
|
716
837
|
}
|
|
@@ -740,7 +861,16 @@ function getPrefillSubFieldValues(field, defaultValues, parentFieldKeyPath) {
|
|
|
740
861
|
initialValue[field.name] = subFieldValues;
|
|
741
862
|
}
|
|
742
863
|
} else {
|
|
743
|
-
|
|
864
|
+
if (typeof initialValue !== "object") {
|
|
865
|
+
console.warn(
|
|
866
|
+
`Field "${parentFieldKeyPath}"'s value is "${initialValue}", but should be type object.`
|
|
867
|
+
);
|
|
868
|
+
initialValue = getPrefillValues([field], {
|
|
869
|
+
// TODO nested fieldsets are not handled
|
|
870
|
+
});
|
|
871
|
+
} else {
|
|
872
|
+
initialValue = getPrefillValues([field], initialValue);
|
|
873
|
+
}
|
|
744
874
|
}
|
|
745
875
|
return initialValue;
|
|
746
876
|
}
|
|
@@ -769,7 +899,7 @@ function getPrefillValues(fields, initialValues = {}) {
|
|
|
769
899
|
});
|
|
770
900
|
return initialValues;
|
|
771
901
|
}
|
|
772
|
-
function updateField(field, requiredFields, node, formValues) {
|
|
902
|
+
function updateField(field, requiredFields, node, formValues, logic, config) {
|
|
773
903
|
if (!field) {
|
|
774
904
|
return;
|
|
775
905
|
}
|
|
@@ -791,6 +921,17 @@ function updateField(field, requiredFields, node, formValues) {
|
|
|
791
921
|
}
|
|
792
922
|
}
|
|
793
923
|
});
|
|
924
|
+
if (field.getComputedAttributes) {
|
|
925
|
+
const computedFieldValues = field.getComputedAttributes({
|
|
926
|
+
field,
|
|
927
|
+
isRequired: fieldIsRequired,
|
|
928
|
+
node,
|
|
929
|
+
formValues,
|
|
930
|
+
config,
|
|
931
|
+
logic
|
|
932
|
+
});
|
|
933
|
+
updateValues(computedFieldValues);
|
|
934
|
+
}
|
|
794
935
|
if (field.calculateConditionalProperties) {
|
|
795
936
|
const newFieldValues = field.calculateConditionalProperties(fieldIsRequired, node);
|
|
796
937
|
updateValues(newFieldValues);
|
|
@@ -804,33 +945,46 @@ function updateField(field, requiredFields, node, formValues) {
|
|
|
804
945
|
updateValues(newFieldValues);
|
|
805
946
|
}
|
|
806
947
|
}
|
|
807
|
-
function processNode(
|
|
948
|
+
function processNode({
|
|
949
|
+
node,
|
|
950
|
+
formValues,
|
|
951
|
+
formFields,
|
|
952
|
+
accRequired = /* @__PURE__ */ new Set(),
|
|
953
|
+
parentID = "root",
|
|
954
|
+
logic
|
|
955
|
+
}) {
|
|
808
956
|
const requiredFields = new Set(accRequired);
|
|
809
957
|
Object.keys(node.properties ?? []).forEach((fieldName) => {
|
|
810
958
|
const field = getField(fieldName, formFields);
|
|
811
|
-
updateField(field, requiredFields, node, formValues);
|
|
959
|
+
updateField(field, requiredFields, node, formValues, logic, { parentID });
|
|
812
960
|
});
|
|
813
961
|
node.required?.forEach((fieldName) => {
|
|
814
962
|
requiredFields.add(fieldName);
|
|
815
|
-
updateField(getField(fieldName, formFields), requiredFields, node, formValues
|
|
963
|
+
updateField(getField(fieldName, formFields), requiredFields, node, formValues, logic, {
|
|
964
|
+
parentID
|
|
965
|
+
});
|
|
816
966
|
});
|
|
817
967
|
if (node.if) {
|
|
818
|
-
const matchesCondition = checkIfConditionMatches(node, formValues, formFields);
|
|
968
|
+
const matchesCondition = checkIfConditionMatches(node, formValues, formFields, logic);
|
|
819
969
|
if (matchesCondition && node.then) {
|
|
820
|
-
const { required: branchRequired } = processNode(
|
|
821
|
-
node.then,
|
|
970
|
+
const { required: branchRequired } = processNode({
|
|
971
|
+
node: node.then,
|
|
822
972
|
formValues,
|
|
823
973
|
formFields,
|
|
824
|
-
requiredFields
|
|
825
|
-
|
|
974
|
+
accRequired: requiredFields,
|
|
975
|
+
parentID,
|
|
976
|
+
logic
|
|
977
|
+
});
|
|
826
978
|
branchRequired.forEach((field) => requiredFields.add(field));
|
|
827
979
|
} else if (node.else) {
|
|
828
|
-
const { required: branchRequired } = processNode(
|
|
829
|
-
node.else,
|
|
980
|
+
const { required: branchRequired } = processNode({
|
|
981
|
+
node: node.else,
|
|
830
982
|
formValues,
|
|
831
983
|
formFields,
|
|
832
|
-
requiredFields
|
|
833
|
-
|
|
984
|
+
accRequired: requiredFields,
|
|
985
|
+
parentID,
|
|
986
|
+
logic
|
|
987
|
+
});
|
|
834
988
|
branchRequired.forEach((field) => requiredFields.add(field));
|
|
835
989
|
}
|
|
836
990
|
}
|
|
@@ -842,12 +996,21 @@ function processNode(node, formValues, formFields, accRequired = /* @__PURE__ */
|
|
|
842
996
|
node.anyOf.forEach(({ required = [] }) => {
|
|
843
997
|
required.forEach((fieldName) => {
|
|
844
998
|
const field = getField(fieldName, formFields);
|
|
845
|
-
updateField(field, requiredFields, node, formValues);
|
|
999
|
+
updateField(field, requiredFields, node, formValues, logic, { parentID });
|
|
846
1000
|
});
|
|
847
1001
|
});
|
|
848
1002
|
}
|
|
849
1003
|
if (node.allOf) {
|
|
850
|
-
node.allOf.map(
|
|
1004
|
+
node.allOf.map(
|
|
1005
|
+
(allOfNode) => processNode({
|
|
1006
|
+
node: allOfNode,
|
|
1007
|
+
formValues,
|
|
1008
|
+
formFields,
|
|
1009
|
+
accRequired: requiredFields,
|
|
1010
|
+
parentID,
|
|
1011
|
+
logic
|
|
1012
|
+
})
|
|
1013
|
+
).forEach(({ required: allOfItemRequired }) => {
|
|
851
1014
|
allOfItemRequired.forEach(requiredFields.add, requiredFields);
|
|
852
1015
|
});
|
|
853
1016
|
}
|
|
@@ -855,7 +1018,13 @@ function processNode(node, formValues, formFields, accRequired = /* @__PURE__ */
|
|
|
855
1018
|
Object.entries(node.properties).forEach(([name, nestedNode]) => {
|
|
856
1019
|
const inputType = getInputType(nestedNode);
|
|
857
1020
|
if (inputType === supportedTypes.FIELDSET) {
|
|
858
|
-
processNode(
|
|
1021
|
+
processNode({
|
|
1022
|
+
node: nestedNode,
|
|
1023
|
+
formValues: formValues[name] || {},
|
|
1024
|
+
formFields: getField(name, formFields).fields,
|
|
1025
|
+
parentID: name,
|
|
1026
|
+
logic
|
|
1027
|
+
});
|
|
859
1028
|
}
|
|
860
1029
|
});
|
|
861
1030
|
}
|
|
@@ -873,11 +1042,11 @@ function clearValuesIfNotVisible(fields, formValues) {
|
|
|
873
1042
|
}
|
|
874
1043
|
});
|
|
875
1044
|
}
|
|
876
|
-
function updateFieldsProperties(fields, formValues, jsonSchema) {
|
|
1045
|
+
function updateFieldsProperties(fields, formValues, jsonSchema, logic) {
|
|
877
1046
|
if (!jsonSchema?.properties) {
|
|
878
1047
|
return;
|
|
879
1048
|
}
|
|
880
|
-
processNode(jsonSchema, formValues, fields);
|
|
1049
|
+
processNode({ node: jsonSchema, formValues, formFields: fields, logic });
|
|
881
1050
|
clearValuesIfNotVisible(fields, formValues);
|
|
882
1051
|
}
|
|
883
1052
|
var notNullOption = (opt) => opt.const !== null;
|
|
@@ -920,11 +1089,15 @@ function extractParametersFromNode(schemaNode) {
|
|
|
920
1089
|
}
|
|
921
1090
|
const presentation = pickXKey(schemaNode, "presentation") ?? {};
|
|
922
1091
|
const errorMessage = pickXKey(schemaNode, "errorMessage") ?? {};
|
|
1092
|
+
const requiredValidations = schemaNode["x-jsf-logic-validations"];
|
|
1093
|
+
const computedAttributes = schemaNode["x-jsf-logic-computedAttrs"];
|
|
1094
|
+
const decoratedComputedAttributes = getDecoratedComputedAttributes(computedAttributes);
|
|
923
1095
|
const node = (0, import_omit.default)(schemaNode, ["x-jsf-presentation", "presentation"]);
|
|
924
1096
|
const description = presentation?.description || node.description;
|
|
925
1097
|
const statementDescription = containsHTML(presentation.statement?.description) ? wrapWithSpan(presentation.statement.description, { class: "jsf-statement" }) : presentation.statement?.description;
|
|
926
1098
|
return (0, import_omitBy.default)(
|
|
927
1099
|
{
|
|
1100
|
+
const: node.const,
|
|
928
1101
|
label: node.title,
|
|
929
1102
|
readOnly: node.readOnly,
|
|
930
1103
|
...node.deprecated && {
|
|
@@ -959,6 +1132,8 @@ function extractParametersFromNode(schemaNode) {
|
|
|
959
1132
|
},
|
|
960
1133
|
// Handle [name].presentation
|
|
961
1134
|
...presentation,
|
|
1135
|
+
requiredValidations,
|
|
1136
|
+
computedAttributes: decoratedComputedAttributes,
|
|
962
1137
|
description: containsHTML(description) ? wrapWithSpan(description, {
|
|
963
1138
|
class: "jsf-description"
|
|
964
1139
|
}) : description,
|
|
@@ -995,8 +1170,8 @@ function yupToFormErrors(yupError) {
|
|
|
995
1170
|
}
|
|
996
1171
|
return errors;
|
|
997
1172
|
}
|
|
998
|
-
var handleValuesChange = (fields, jsonSchema, config) => (values) => {
|
|
999
|
-
updateFieldsProperties(fields, values, jsonSchema);
|
|
1173
|
+
var handleValuesChange = (fields, jsonSchema, config, logic) => (values) => {
|
|
1174
|
+
updateFieldsProperties(fields, values, jsonSchema, logic);
|
|
1000
1175
|
const lazySchema = (0, import_yup2.lazy)(() => buildCompleteYupSchema(fields, config));
|
|
1001
1176
|
let errors;
|
|
1002
1177
|
try {
|
|
@@ -1015,6 +1190,12 @@ var handleValuesChange = (fields, jsonSchema, config) => (values) => {
|
|
|
1015
1190
|
formErrors: yupToFormErrors(errors)
|
|
1016
1191
|
};
|
|
1017
1192
|
};
|
|
1193
|
+
function getDecoratedComputedAttributes(computedAttributes) {
|
|
1194
|
+
return {
|
|
1195
|
+
...computedAttributes ?? {},
|
|
1196
|
+
...computedAttributes?.const && computedAttributes?.default ? { value: computedAttributes.const } : {}
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1018
1199
|
|
|
1019
1200
|
// src/calculateConditionalProperties.js
|
|
1020
1201
|
function isFieldRequired(node, field) {
|
|
@@ -1216,6 +1397,9 @@ function applyFieldsDependencies(fieldsParameters, node) {
|
|
|
1216
1397
|
applyFieldsDependencies(fieldsParameters, condition);
|
|
1217
1398
|
});
|
|
1218
1399
|
}
|
|
1400
|
+
if (node?.["x-jsf-logic"]) {
|
|
1401
|
+
applyFieldsDependencies(fieldsParameters, node["x-jsf-logic"]);
|
|
1402
|
+
}
|
|
1219
1403
|
}
|
|
1220
1404
|
function getCustomPropertiesForField(fieldParams, config) {
|
|
1221
1405
|
return config?.customProperties?.[fieldParams.name];
|
|
@@ -1227,15 +1411,16 @@ function getComposeFunctionForField(fieldParams, hasCustomizations) {
|
|
|
1227
1411
|
}
|
|
1228
1412
|
return composeFn;
|
|
1229
1413
|
}
|
|
1230
|
-
function buildField(fieldParams, config, scopedJsonSchema) {
|
|
1414
|
+
function buildField(fieldParams, config, scopedJsonSchema, logic) {
|
|
1231
1415
|
const customProperties = getCustomPropertiesForField(fieldParams, config);
|
|
1232
1416
|
const composeFn = getComposeFunctionForField(fieldParams, !!customProperties);
|
|
1233
|
-
const yupSchema = buildYupSchema(fieldParams, config);
|
|
1417
|
+
const yupSchema = buildYupSchema(fieldParams, config, logic);
|
|
1234
1418
|
const calculateConditionalFieldsClosure = fieldParams.isDynamic && calculateConditionalProperties(fieldParams, customProperties);
|
|
1235
1419
|
const calculateCustomValidationPropertiesClosure = calculateCustomValidationProperties(
|
|
1236
1420
|
fieldParams,
|
|
1237
1421
|
customProperties
|
|
1238
1422
|
);
|
|
1423
|
+
const getComputedAttributes = Object.keys(fieldParams.computedAttributes).length > 0 && calculateComputedAttributes(fieldParams, config);
|
|
1239
1424
|
const hasCustomValidations = !!customProperties && (0, import_size.default)((0, import_pick2.default)(customProperties, SUPPORTED_CUSTOM_VALIDATION_FIELD_PARAMS)) > 0;
|
|
1240
1425
|
const finalFieldParams = {
|
|
1241
1426
|
// invalid attribute cleanup
|
|
@@ -1248,6 +1433,7 @@ function buildField(fieldParams, config, scopedJsonSchema) {
|
|
|
1248
1433
|
...hasCustomValidations && {
|
|
1249
1434
|
calculateCustomValidationProperties: calculateCustomValidationPropertiesClosure
|
|
1250
1435
|
},
|
|
1436
|
+
...getComputedAttributes && { getComputedAttributes },
|
|
1251
1437
|
// field customization properties
|
|
1252
1438
|
...customProperties && { fieldCustomization: customProperties },
|
|
1253
1439
|
// base schema
|
|
@@ -1256,7 +1442,7 @@ function buildField(fieldParams, config, scopedJsonSchema) {
|
|
|
1256
1442
|
};
|
|
1257
1443
|
return composeFn(finalFieldParams);
|
|
1258
1444
|
}
|
|
1259
|
-
function getFieldsFromJSONSchema(scopedJsonSchema, config) {
|
|
1445
|
+
function getFieldsFromJSONSchema(scopedJsonSchema, config, logic) {
|
|
1260
1446
|
if (!scopedJsonSchema) {
|
|
1261
1447
|
return [];
|
|
1262
1448
|
}
|
|
@@ -1280,11 +1466,11 @@ function getFieldsFromJSONSchema(scopedJsonSchema, config) {
|
|
|
1280
1466
|
fields: () => groupArrayFields,
|
|
1281
1467
|
addFieldText: fieldParams.addFieldText
|
|
1282
1468
|
};
|
|
1283
|
-
buildField(fieldParams, config, scopedJsonSchema).forEach((groupField) => {
|
|
1469
|
+
buildField(fieldParams, config, scopedJsonSchema, logic).forEach((groupField) => {
|
|
1284
1470
|
fields.push(groupField);
|
|
1285
1471
|
});
|
|
1286
1472
|
} else {
|
|
1287
|
-
fields.push(buildField(fieldParams, config, scopedJsonSchema));
|
|
1473
|
+
fields.push(buildField(fieldParams, config, scopedJsonSchema, logic));
|
|
1288
1474
|
}
|
|
1289
1475
|
});
|
|
1290
1476
|
return fields;
|
|
@@ -1295,9 +1481,15 @@ function createHeadlessForm(jsonSchema, customConfig = {}) {
|
|
|
1295
1481
|
...customConfig
|
|
1296
1482
|
};
|
|
1297
1483
|
try {
|
|
1298
|
-
const
|
|
1299
|
-
const
|
|
1300
|
-
|
|
1484
|
+
const logic = createValidationChecker(jsonSchema);
|
|
1485
|
+
const fields = getFieldsFromJSONSchema(jsonSchema, config, logic);
|
|
1486
|
+
const handleValidation = handleValuesChange(fields, jsonSchema, config, logic);
|
|
1487
|
+
updateFieldsProperties(
|
|
1488
|
+
fields,
|
|
1489
|
+
getPrefillValues(fields, config.initialValues),
|
|
1490
|
+
jsonSchema,
|
|
1491
|
+
logic
|
|
1492
|
+
);
|
|
1301
1493
|
return {
|
|
1302
1494
|
fields,
|
|
1303
1495
|
handleValidation,
|