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 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: "{field} bevat een ongeldig invoertype. Alleen {type} is toegestaan.",
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:`Please add at least one choice for {field}.`,
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.BOOLEAN]: (val, data) => {
40
- if (typeof val === "boolean") return true;
41
- if (typeof val === "string") {
42
- const lowerVal = val.toLowerCase();
43
- if (lowerVal === "true" || lowerVal === "false") {
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.DATE_TIME]: (val, data) => {
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
- const relational_interfaces = [
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((child) => child.schema_id === itemSchemaId)
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.startsWith(key))) return;
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
- if (fieldKey && !result.errors[fieldPath]) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nox-validation",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "validate dynamic schema",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -18,4 +18,4 @@
18
18
  ],
19
19
  "author": "NowOnline Team",
20
20
  "license": "ISC"
21
- }
21
+ }