nox-validation 1.4.0 → 1.4.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/lib/constant.js +24 -17
- package/lib/validate.js +80 -33
- package/package.json +2 -2
package/lib/constant.js
CHANGED
|
@@ -128,6 +128,7 @@ const types = Object.freeze({
|
|
|
128
128
|
MIXED: "Mixed",
|
|
129
129
|
DATE_TIME: "datetime",
|
|
130
130
|
TIME: "time",
|
|
131
|
+
TIMESTAMP: "timestamp",
|
|
131
132
|
});
|
|
132
133
|
|
|
133
134
|
const interfaces = Object.freeze({
|
|
@@ -142,6 +143,11 @@ const interfaces = Object.freeze({
|
|
|
142
143
|
FILES: "files",
|
|
143
144
|
TRANSLATIONS: "translations",
|
|
144
145
|
RELATIONAL: "relational",
|
|
146
|
+
CHECKBOX: "checkboxes",
|
|
147
|
+
ITEMS: "items",
|
|
148
|
+
MULTIPLE_DROPDOWN: "dropdown_multiple",
|
|
149
|
+
TAGS: "tags",
|
|
150
|
+
ARRAY_OF_VALUES: "array_of_values",
|
|
145
151
|
});
|
|
146
152
|
|
|
147
153
|
const API_VERSION = Object.freeze({
|
|
@@ -154,14 +160,14 @@ const API_VERSIONS = Object.freeze(Object.values(API_VERSION));
|
|
|
154
160
|
const LANGUAGES = Object.freeze({
|
|
155
161
|
en: "en",
|
|
156
162
|
nl: "nl",
|
|
157
|
-
lv:"lv",
|
|
158
|
-
pl:"pl",
|
|
159
|
-
ro:"ro",
|
|
160
|
-
ru:"ru",
|
|
163
|
+
lv: "lv",
|
|
164
|
+
pl: "pl",
|
|
165
|
+
ro: "ro",
|
|
166
|
+
ru: "ru",
|
|
161
167
|
});
|
|
162
168
|
|
|
163
169
|
const LOCALE_NL_MESSAGES = Object.freeze({
|
|
164
|
-
ADD_CHOICE: `Voeg minstens één optie toe voor {field}.`,
|
|
170
|
+
ADD_CHOICE: `Voeg minstens één optie toe voor {field}.`,
|
|
165
171
|
INVALID_VALUE: `{field} bevat een ongeldige waarde.`,
|
|
166
172
|
EMPTY: `{field} moet leeg zijn.`,
|
|
167
173
|
NOT_EMPTY: `{field} mag niet leeg zijn.`,
|
|
@@ -170,7 +176,8 @@ const LOCALE_NL_MESSAGES = Object.freeze({
|
|
|
170
176
|
REQUIRED: `{field} is verplicht.`,
|
|
171
177
|
OPTIONAL: `{field} is optioneel.`,
|
|
172
178
|
NOT_NULLABLE: `{field} mag niet null zijn.`,
|
|
173
|
-
INVALID_TYPE:
|
|
179
|
+
INVALID_TYPE:
|
|
180
|
+
"{field} bevat een ongeldig invoertype. Alleen {type} is toegestaan.",
|
|
174
181
|
NOT_ALLOWED_FIELD: `{field} is niet toegestaan.`,
|
|
175
182
|
COMPARE: `{field} komt niet overeen met de verwachte waarde.`,
|
|
176
183
|
RULES_COMPARE: `{field} voldoet niet aan de vergelijkingsregels.`,
|
|
@@ -206,7 +213,7 @@ const LOCALE_NL_MESSAGES = Object.freeze({
|
|
|
206
213
|
});
|
|
207
214
|
|
|
208
215
|
const LOCALE_EN_MESSAGES = Object.freeze({
|
|
209
|
-
ADD_CHOICE
|
|
216
|
+
ADD_CHOICE: `Please add at least one choice for {field}.`,
|
|
210
217
|
INVALID_VALUE: `{field} contains invalid value.`,
|
|
211
218
|
EMPTY: `{field} should be empty.`,
|
|
212
219
|
NOT_EMPTY: `{field} should not be empty.`,
|
|
@@ -251,7 +258,7 @@ const LOCALE_EN_MESSAGES = Object.freeze({
|
|
|
251
258
|
});
|
|
252
259
|
|
|
253
260
|
const LOCALE_LV_MESSAGES = Object.freeze({
|
|
254
|
-
ADD_CHOICE: `Lūdzu, pievienojiet vismaz vienu izvēli laukam {field}.`,
|
|
261
|
+
ADD_CHOICE: `Lūdzu, pievienojiet vismaz vienu izvēli laukam {field}.`,
|
|
255
262
|
INVALID_VALUE: `{field} satur nederīgu vērtību.`,
|
|
256
263
|
EMPTY: `{field} jābūt tukšam.`,
|
|
257
264
|
NOT_EMPTY: `{field} nedrīkst būt tukšs.`,
|
|
@@ -341,7 +348,7 @@ const LOCALE_PL_MESSAGES = Object.freeze({
|
|
|
341
348
|
});
|
|
342
349
|
|
|
343
350
|
const LOCALE_RO_MESSAGES = Object.freeze({
|
|
344
|
-
ADD_CHOICE: `Vă rugăm să adăugați cel puțin o opțiune pentru {field}.`,
|
|
351
|
+
ADD_CHOICE: `Vă rugăm să adăugați cel puțin o opțiune pentru {field}.`,
|
|
345
352
|
INVALID_VALUE: `{field} conține o valoare invalidă.`,
|
|
346
353
|
EMPTY: `{field} trebuie să fie gol.`,
|
|
347
354
|
NOT_EMPTY: `{field} nu trebuie să fie gol.`,
|
|
@@ -431,13 +438,13 @@ const LOCALE_RU_MESSAGES = Object.freeze({
|
|
|
431
438
|
});
|
|
432
439
|
|
|
433
440
|
const LOCALE_MESSAGES = Object.freeze({
|
|
434
|
-
[LANGUAGES.en]:LOCALE_EN_MESSAGES,
|
|
435
|
-
[LANGUAGES.nl]:LOCALE_NL_MESSAGES,
|
|
436
|
-
[LANGUAGES.lv]:LOCALE_LV_MESSAGES,
|
|
437
|
-
[LANGUAGES.pl]:LOCALE_PL_MESSAGES,
|
|
438
|
-
[LANGUAGES.ro]:LOCALE_RO_MESSAGES,
|
|
439
|
-
[LANGUAGES.ru]:LOCALE_RU_MESSAGES
|
|
440
|
-
})
|
|
441
|
+
[LANGUAGES.en]: LOCALE_EN_MESSAGES,
|
|
442
|
+
[LANGUAGES.nl]: LOCALE_NL_MESSAGES,
|
|
443
|
+
[LANGUAGES.lv]: LOCALE_LV_MESSAGES,
|
|
444
|
+
[LANGUAGES.pl]: LOCALE_PL_MESSAGES,
|
|
445
|
+
[LANGUAGES.ro]: LOCALE_RO_MESSAGES,
|
|
446
|
+
[LANGUAGES.ru]: LOCALE_RU_MESSAGES,
|
|
447
|
+
});
|
|
441
448
|
|
|
442
449
|
module.exports = {
|
|
443
450
|
dataTypes,
|
|
@@ -451,5 +458,5 @@ module.exports = {
|
|
|
451
458
|
API_VERSIONS,
|
|
452
459
|
API_VERSION,
|
|
453
460
|
LANGUAGES,
|
|
454
|
-
LOCALE_MESSAGES
|
|
461
|
+
LOCALE_MESSAGES,
|
|
455
462
|
};
|
package/lib/validate.js
CHANGED
|
@@ -14,6 +14,16 @@ const {
|
|
|
14
14
|
} = require("./helpers");
|
|
15
15
|
|
|
16
16
|
const choices = ["radio", "checkboxes", "dropdown_multiple", "dropdown"];
|
|
17
|
+
const relational_interfaces = [
|
|
18
|
+
constants.interfaces.FILES,
|
|
19
|
+
constants.interfaces.FILE,
|
|
20
|
+
constants.interfaces.FILE_IMAGE,
|
|
21
|
+
constants.interfaces.MANY_TO_MANY,
|
|
22
|
+
constants.interfaces.ONE_TO_MANY,
|
|
23
|
+
constants.interfaces.MANY_TO_ONE,
|
|
24
|
+
constants.interfaces.MANY_TO_ANY,
|
|
25
|
+
constants.interfaces.TRANSLATIONS,
|
|
26
|
+
];
|
|
17
27
|
|
|
18
28
|
const typeChecks = {
|
|
19
29
|
date: (val, data) => {
|
|
@@ -26,6 +36,7 @@ const typeChecks = {
|
|
|
26
36
|
}
|
|
27
37
|
return false;
|
|
28
38
|
},
|
|
39
|
+
|
|
29
40
|
[constants.types.DATE]: (val, data) => {
|
|
30
41
|
if (val instanceof Date && !isNaN(val)) return true;
|
|
31
42
|
if (typeof val === "string" && !isNaN(Date.parse(val))) {
|
|
@@ -36,20 +47,20 @@ const typeChecks = {
|
|
|
36
47
|
}
|
|
37
48
|
return false;
|
|
38
49
|
},
|
|
39
|
-
[constants.types.
|
|
40
|
-
if (
|
|
41
|
-
if (typeof val === "string") {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (data && data?.key && data?.updateValue) {
|
|
45
|
-
data.updateValue(data.key, lowerVal === "true");
|
|
46
|
-
}
|
|
47
|
-
return true;
|
|
50
|
+
[constants.types.DATE_TIME]: (val, data) => {
|
|
51
|
+
if (val instanceof Date && !isNaN(val)) return true;
|
|
52
|
+
if (typeof val === "string" && !isNaN(Date.parse(val))) {
|
|
53
|
+
if (data && data?.key && data?.updateValue) {
|
|
54
|
+
data.updateValue(data.key, new Date(val));
|
|
48
55
|
}
|
|
56
|
+
return true;
|
|
49
57
|
}
|
|
50
58
|
return false;
|
|
51
59
|
},
|
|
52
|
-
[constants.types.
|
|
60
|
+
[constants.types.TIME]: (val) =>
|
|
61
|
+
typeof val === "string" &&
|
|
62
|
+
/^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/.test(val),
|
|
63
|
+
[constants.types.TIMESTAMP]: (val, data) => {
|
|
53
64
|
if (val instanceof Date && !isNaN(val)) return true;
|
|
54
65
|
if (typeof val === "string" && !isNaN(Date.parse(val))) {
|
|
55
66
|
if (data && data?.key && data?.updateValue) {
|
|
@@ -59,6 +70,20 @@ const typeChecks = {
|
|
|
59
70
|
}
|
|
60
71
|
return false;
|
|
61
72
|
},
|
|
73
|
+
|
|
74
|
+
[constants.types.BOOLEAN]: (val, data) => {
|
|
75
|
+
if (typeof val === "boolean") return true;
|
|
76
|
+
if (typeof val === "string") {
|
|
77
|
+
const lowerVal = val.toLowerCase();
|
|
78
|
+
if (lowerVal === "true" || lowerVal === "false") {
|
|
79
|
+
if (data && data?.key && data?.updateValue) {
|
|
80
|
+
data.updateValue(data.key, lowerVal === "true");
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
},
|
|
62
87
|
[constants.types.NUMBER]: (val, data) => {
|
|
63
88
|
if (typeof val === "number" && !isNaN(val)) return true;
|
|
64
89
|
if (typeof val === "string" && !isNaN(parseFloat(val))) {
|
|
@@ -69,10 +94,6 @@ const typeChecks = {
|
|
|
69
94
|
}
|
|
70
95
|
return false;
|
|
71
96
|
},
|
|
72
|
-
|
|
73
|
-
[constants.types.TIME]: (val) =>
|
|
74
|
-
typeof val === "string" &&
|
|
75
|
-
/^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/.test(val),
|
|
76
97
|
[constants.types.STRING]: (val) => typeof val === "string",
|
|
77
98
|
[constants.types.OBJECT]: (val) =>
|
|
78
99
|
typeof val === "object" && val !== null && !Array.isArray(val),
|
|
@@ -198,16 +219,7 @@ const validateMetaRules = (
|
|
|
198
219
|
const fieldValue = providedValue;
|
|
199
220
|
|
|
200
221
|
const { required = false, nullable = false, options } = field?.meta ?? {};
|
|
201
|
-
|
|
202
|
-
constants.interfaces.FILES,
|
|
203
|
-
constants.interfaces.FILE,
|
|
204
|
-
constants.interfaces.FILE_IMAGE,
|
|
205
|
-
constants.interfaces.MANY_TO_MANY,
|
|
206
|
-
constants.interfaces.ONE_TO_MANY,
|
|
207
|
-
constants.interfaces.MANY_TO_ONE,
|
|
208
|
-
constants.interfaces.MANY_TO_ANY,
|
|
209
|
-
constants.interfaces.TRANSLATIONS,
|
|
210
|
-
];
|
|
222
|
+
|
|
211
223
|
const isRelational = relational_interfaces.includes(field?.meta?.interface);
|
|
212
224
|
|
|
213
225
|
if (
|
|
@@ -230,6 +242,38 @@ const validateMetaRules = (
|
|
|
230
242
|
);
|
|
231
243
|
}
|
|
232
244
|
|
|
245
|
+
const arrayInterfaces = [
|
|
246
|
+
constants.interfaces.CHECKBOX,
|
|
247
|
+
constants.interfaces.ITEMS,
|
|
248
|
+
constants.interfaces.MULTIPLE_DROPDOWN,
|
|
249
|
+
constants.interfaces.TAGS,
|
|
250
|
+
constants.interfaces.ARRAY_OF_VALUES,
|
|
251
|
+
];
|
|
252
|
+
|
|
253
|
+
if (
|
|
254
|
+
required &&
|
|
255
|
+
arrayInterfaces.includes(field?.meta?.interface) &&
|
|
256
|
+
onlyFormFields &&
|
|
257
|
+
fieldValue &&
|
|
258
|
+
Array.isArray(fieldValue) &&
|
|
259
|
+
fieldValue?.length === 0
|
|
260
|
+
) {
|
|
261
|
+
const message = error_messages.NOT_EMPTY.replace(
|
|
262
|
+
`{field}`,
|
|
263
|
+
formatLabel(field.display_label)
|
|
264
|
+
);
|
|
265
|
+
addError(
|
|
266
|
+
currentPath,
|
|
267
|
+
{
|
|
268
|
+
label: formatLabel(field.display_label),
|
|
269
|
+
fieldPath: currentPath,
|
|
270
|
+
description: "",
|
|
271
|
+
message,
|
|
272
|
+
},
|
|
273
|
+
field
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
233
277
|
const isValidRelational =
|
|
234
278
|
required && isRelational && !onlyFormFields
|
|
235
279
|
? isEmptyRelational({
|
|
@@ -284,7 +328,7 @@ const validateMetaRules = (
|
|
|
284
328
|
constants.interfaces.ONE_TO_MANY,
|
|
285
329
|
constants.interfaces.MANY_TO_ONE,
|
|
286
330
|
constants.interfaces.MANY_TO_ANY,
|
|
287
|
-
"none"
|
|
331
|
+
"none",
|
|
288
332
|
].includes(field?.meta?.interface)
|
|
289
333
|
) {
|
|
290
334
|
const isTranslationChild =
|
|
@@ -304,7 +348,6 @@ const validateMetaRules = (
|
|
|
304
348
|
if (fPath.includes("delete.") && !isTranslationChild) return;
|
|
305
349
|
if (fPath.includes("existing.") && !isTranslationChild) return;
|
|
306
350
|
|
|
307
|
-
|
|
308
351
|
const label = formatLabel(node.display_label);
|
|
309
352
|
const message = error_messages.REQUIRED.replace("{field}", label);
|
|
310
353
|
|
|
@@ -793,6 +836,7 @@ const validateField = (
|
|
|
793
836
|
const currentPath = fieldPath
|
|
794
837
|
? `${fieldPath}.${field.key.split(".").pop()}`
|
|
795
838
|
: field.key;
|
|
839
|
+
|
|
796
840
|
const fieldLabel = formatLabel(field.display_label);
|
|
797
841
|
|
|
798
842
|
validateMetaRules(
|
|
@@ -816,15 +860,17 @@ const validateField = (
|
|
|
816
860
|
typeChecks[constants.types.OBJECT](value)
|
|
817
861
|
) {
|
|
818
862
|
let itemSchemaId = null;
|
|
819
|
-
let childrenToValidate = field.children
|
|
863
|
+
let childrenToValidate = field.children;
|
|
820
864
|
if (is_m2a_item) {
|
|
821
865
|
const fieldPath = getM2AItemParentPath(currentPath);
|
|
822
866
|
if (fieldPath) {
|
|
823
867
|
itemSchemaId = getValue(formData, fieldPath)?.collection_id;
|
|
824
|
-
if(!itemSchemaId){
|
|
825
|
-
childrenToValidate = []
|
|
826
|
-
}else{
|
|
827
|
-
childrenToValidate = field.children.filter(
|
|
868
|
+
if (!itemSchemaId) {
|
|
869
|
+
childrenToValidate = [];
|
|
870
|
+
} else {
|
|
871
|
+
childrenToValidate = field.children.filter(
|
|
872
|
+
(child) => child.schema_id === itemSchemaId
|
|
873
|
+
);
|
|
828
874
|
}
|
|
829
875
|
}
|
|
830
876
|
}
|
|
@@ -1011,7 +1057,7 @@ const validate = (data) => {
|
|
|
1011
1057
|
};
|
|
1012
1058
|
|
|
1013
1059
|
const addError = (fieldPath, obj, field) => {
|
|
1014
|
-
if (byPassKeys.some((key) => fieldPath.
|
|
1060
|
+
if (byPassKeys.some((key) => fieldPath.includes(key))) return;
|
|
1015
1061
|
if (!result.errors[fieldPath] && !field?.meta?.hidden) {
|
|
1016
1062
|
const pathResult = extractRelationalParents(fieldPath);
|
|
1017
1063
|
if (pathResult) {
|
|
@@ -1217,7 +1263,8 @@ const validate = (data) => {
|
|
|
1217
1263
|
findDisallowedKeys(formData, fieldOptions, maxLevel).forEach((fieldPath) => {
|
|
1218
1264
|
if (abortEarly && !result.status) return result;
|
|
1219
1265
|
const fieldKey = getLastChildKey(fieldPath);
|
|
1220
|
-
|
|
1266
|
+
const isBypass = byPassKeys?.some((key) => fieldPath?.includes(key));
|
|
1267
|
+
if (fieldKey && !result.errors[fieldPath] && !isBypass) {
|
|
1221
1268
|
addError(fieldPath, {
|
|
1222
1269
|
label: formatLabel(fieldKey),
|
|
1223
1270
|
fieldPath,
|
package/package.json
CHANGED