nox-validation 1.7.1 → 1.7.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/index.js CHANGED
@@ -5,19 +5,34 @@ const {
5
5
  buildNestedStructure,
6
6
  getValue,
7
7
  setValue,
8
- getDefaultValues
8
+ getDefaultValues,
9
9
  } = require("./lib/helpers");
10
10
 
11
+ const optimizedValidate = require("./lib/validate.optimized");
12
+ const helpersOptimized = require("./lib/helpers.optimized");
13
+
11
14
  module.exports = {
12
15
  validate,
13
16
  CONSTANTS: constants,
14
17
  helpers: {
15
18
  validateSingleField: validateField,
16
19
  validateType: typeChecks,
17
- fieldsMapping:getFieldsGroupBySchemaId,
18
- convertTree:buildNestedStructure,
19
- getValueByDynamicKey:getValue,
20
- setValueByDynamicKey:setValue,
21
- getTreeDefaultValues:getDefaultValues
20
+ fieldsMapping: getFieldsGroupBySchemaId,
21
+ convertTree: buildNestedStructure,
22
+ getValueByDynamicKey: getValue,
23
+ setValueByDynamicKey: setValue,
24
+ getTreeDefaultValues: getDefaultValues,
25
+ },
26
+ optimized: {
27
+ validate: optimizedValidate.validate,
28
+ helpers: {
29
+ validateSingleField: helpersOptimized.validateField,
30
+ validateType: helpersOptimized.typeChecks,
31
+ fieldsMapping: helpersOptimized.getFieldsGroupBySchemaId,
32
+ convertTree: helpersOptimized.buildNestedStructure,
33
+ getValueByDynamicKey: helpersOptimized.getValue,
34
+ setValueByDynamicKey: helpersOptimized.setValue,
35
+ getTreeDefaultValues: helpersOptimized.getDefaultValues,
36
+ },
22
37
  },
23
38
  };
@@ -1105,21 +1105,53 @@ const buildNestedStructure = ({
1105
1105
  const root = {};
1106
1106
  const nodeMap = new Map();
1107
1107
 
1108
- // Sort fields by path depth once
1109
1108
  const sortedFields = [...schemaFields].sort(
1110
1109
  (a, b) => a.path.split(".").length - b.path.split(".").length
1111
1110
  );
1112
1111
 
1113
- // Pre-compute interface checks
1114
- const isV2FileInterface = (interface) =>
1112
+ const isV2FileInterface = (interfaceName) =>
1115
1113
  apiVersion === constants.API_VERSION.V2 &&
1116
1114
  [
1117
1115
  constants.interfaces.FILES,
1118
1116
  constants.interfaces.FILE,
1119
1117
  constants.interfaces.FILE_IMAGE,
1120
- ].includes(interface);
1118
+ ].includes(interfaceName);
1119
+
1120
+ // utility to adjust children keys as required
1121
+ function adjustChildKeys(
1122
+ children,
1123
+ parentType,
1124
+ parentKey,
1125
+ parentMetaInterface
1126
+ ) {
1127
+ if (!Array.isArray(children) || children.length === 0) return children;
1128
+ // For array parent type
1129
+ if (parentType === constants.types.ARRAY) {
1130
+ // If translation
1131
+ if (parentMetaInterface === constants.interfaces.TRANSLATIONS) {
1132
+ // e.g., parent.key[lang_code].child.key
1133
+ return children.map((child) => ({
1134
+ ...child,
1135
+ key: `${parentKey}[lang_code].${child.key.split(".").pop()}`,
1136
+ value: `${parentKey}[lang_code].${child.key.split(".").pop()}`,
1137
+ }));
1138
+ } else {
1139
+ // e.g., parent.key[idx].child.key
1140
+ return children.map((child) => ({
1141
+ ...child,
1142
+ key: `${parentKey}[idx].${child.key.split(".").pop()}`,
1143
+ value: `${parentKey}[idx].${child.key.split(".").pop()}`,
1144
+ }));
1145
+ }
1146
+ }
1147
+ // For normal object type, just parent.key.child.key
1148
+ return children.map((child) => ({
1149
+ ...child,
1150
+ key: `${parentKey}.${child.key.split(".").pop()}`,
1151
+ value: `${parentKey}.${child.key.split(".").pop()}`,
1152
+ }));
1153
+ }
1121
1154
 
1122
- // Process each field in a single pass
1123
1155
  for (const item of sortedFields) {
1124
1156
  const pathParts = item.path.split(".");
1125
1157
  const key = pathParts.join(".");
@@ -1215,6 +1247,13 @@ const buildNestedStructure = ({
1215
1247
  } else {
1216
1248
  children = childFields;
1217
1249
  }
1250
+ // Now, adjust children keys as required
1251
+ children = adjustChildKeys(
1252
+ children,
1253
+ definedType.type,
1254
+ key,
1255
+ item.meta?.interface
1256
+ );
1218
1257
  }
1219
1258
 
1220
1259
  // Add _id field for arrays
@@ -1382,7 +1421,7 @@ const RULE_TRANSFORM_MAP = {
1382
1421
  case: constants.rulesTypes.REGEX,
1383
1422
  options: (rule) => ({
1384
1423
  type: constants.regexTypes.CONTAINS,
1385
- case_sensitive: !rule[rule.type].insensitive,
1424
+ case_sensitive: !rule[rule.type]?.insensitive,
1386
1425
  multiline: false,
1387
1426
  global: false,
1388
1427
  }),
@@ -1391,7 +1430,7 @@ const RULE_TRANSFORM_MAP = {
1391
1430
  case: constants.rulesTypes.REGEX,
1392
1431
  options: (rule) => ({
1393
1432
  type: constants.regexTypes.NOT_CONTAINS,
1394
- case_sensitive: !rule[rule.type].insensitive,
1433
+ case_sensitive: !rule[rule.type]?.insensitive,
1395
1434
  multiline: false,
1396
1435
  global: false,
1397
1436
  }),
@@ -1400,28 +1439,28 @@ const RULE_TRANSFORM_MAP = {
1400
1439
  case: constants.rulesTypes.REGEX,
1401
1440
  options: (rule) => ({
1402
1441
  type: constants.regexTypes.START_WITH,
1403
- case_sensitive: !rule[rule.type].insensitive,
1442
+ case_sensitive: !rule[rule.type]?.insensitive,
1404
1443
  }),
1405
1444
  },
1406
1445
  doesNotStartWith: {
1407
1446
  case: constants.rulesTypes.REGEX,
1408
1447
  options: (rule) => ({
1409
1448
  type: constants.regexTypes.NOT_START_WITH,
1410
- case_sensitive: !rule[rule.type].insensitive,
1449
+ case_sensitive: !rule[rule.type]?.insensitive,
1411
1450
  }),
1412
1451
  },
1413
1452
  endsWith: {
1414
1453
  case: constants.rulesTypes.REGEX,
1415
1454
  options: (rule) => ({
1416
1455
  type: constants.regexTypes.ENDS_WITH,
1417
- case_sensitive: !rule[rule.type].insensitive,
1456
+ case_sensitive: !rule[rule.type]?.insensitive,
1418
1457
  }),
1419
1458
  },
1420
1459
  doesNotEndWith: {
1421
1460
  case: constants.rulesTypes.REGEX,
1422
1461
  options: (rule) => ({
1423
1462
  type: constants.regexTypes.NOT_ENDS_WITH,
1424
- case_sensitive: !rule[rule.type].insensitive,
1463
+ case_sensitive: !rule[rule.type]?.insensitive,
1425
1464
  }),
1426
1465
  },
1427
1466
  matchesRegExp: {
@@ -1465,12 +1504,12 @@ const RULE_TRANSFORM_MAP = {
1465
1504
  isOneOf: {
1466
1505
  case: constants.rulesTypes.ONE_OF,
1467
1506
  options: () => ({}),
1468
- value: (rule) => rule[rule.type].value,
1507
+ value: (rule) => rule[rule.type]?.value,
1469
1508
  },
1470
1509
  isNotOneOf: {
1471
1510
  case: constants.rulesTypes.NOT_ONE_OF,
1472
1511
  options: () => ({}),
1473
- value: (rule) => [rule[rule.type].value],
1512
+ value: (rule) => [rule[rule.type]?.value],
1474
1513
  },
1475
1514
  };
1476
1515
 
package/lib/validate.js CHANGED
@@ -224,7 +224,18 @@ const isEmptyRelational = ({
224
224
  }
225
225
  } else if (api_version === constants.API_VERSION.V2) {
226
226
  if (isEmpty(existingValue)) return true;
227
-
227
+ let all = Array.isArray(existingValue)
228
+ ? existingValue.length === 0
229
+ ? []
230
+ : typeof existingValue[0] === "string"
231
+ ? existingValue
232
+ : existingValue.map((item) => item._id)
233
+ : typeof existingValue === "string"
234
+ ? [existingValue]
235
+ : existingValue && typeof existingValue === "object"
236
+ ? [existingValue._id]
237
+ : [];
238
+ all = Array.isArray(all) ? all?.filter(Boolean) : all;
228
239
  switch (interface) {
229
240
  case constants.interfaces.FILE:
230
241
  case constants.interfaces.FILE_IMAGE:
@@ -232,30 +243,17 @@ const isEmptyRelational = ({
232
243
  case constants.interfaces.MANY_TO_MANY:
233
244
  case constants.interfaces.ONE_TO_MANY:
234
245
  case constants.interfaces.MANY_TO_ONE:
235
- case constants.interfaces.SEO:
246
+ case constants.interfaces.MANY_TO_ANY:
236
247
  return remainingItems({
237
- all: Array.isArray(existingValue)
238
- ? existingValue.length === 0
239
- ? []
240
- : typeof existingValue[0] === "string"
241
- ? existingValue
242
- : existingValue.map((item) => item._id)
243
- : typeof existingValue === "string"
244
- ? [existingValue]
245
- : existingValue && typeof existingValue === "object"
246
- ? [existingValue._id]
247
- : [],
248
+ all: all,
248
249
  obj: value,
250
+ isM2A: interface === constants.interfaces.MANY_TO_ANY,
249
251
  });
250
- case constants.interfaces.MANY_TO_ANY:
252
+ case constants.interfaces.SEO:
251
253
  return remainingItems({
252
- all: Array.isArray(existingValue)
253
- ? existingValue?.map((item) => item.item)
254
- : [],
254
+ all: all,
255
255
  obj: value,
256
- isM2A: true,
257
256
  });
258
-
259
257
  // constants.interfaces.TRANSLATIONS,
260
258
  default:
261
259
  return true;
@@ -365,7 +363,16 @@ const validateMetaRules = (
365
363
  value: fieldValue,
366
364
  interface: field?.meta?.interface,
367
365
  onlyFormFields,
368
- existingValue: getValue(existingForm, currentPath),
366
+ existingValue:
367
+ getValue(existingForm, currentPath) ||
368
+ getValue(
369
+ existingForm,
370
+ currentPath
371
+ ?.replace(".create", "")
372
+ ?.replace(".update", "")
373
+ ?.replace(".existing", "")
374
+ ?.replace(".delete", "")
375
+ ), // TODO: Need to Generate Form Path Without create, update, existing, delete
369
376
  })
370
377
  : true;
371
378
 
@@ -475,6 +482,7 @@ const validateMetaRules = (
475
482
  const isTranslationNode =
476
483
  node?.meta?.parentInterface === constants.interfaces.TRANSLATIONS ||
477
484
  field?.meta?.interface === constants.interfaces.TRANSLATIONS;
485
+
478
486
  let fPath = node.key?.replace("[0][0]", "[0]");
479
487
  const types = ["update", "delete", "existing", "create"];
480
488
  const extractFirstType = (key) => {
@@ -1203,10 +1211,12 @@ const validateField = (
1203
1211
  if (itemType) {
1204
1212
  value.forEach((item, index) => {
1205
1213
  const itemPath = `${currentPath}[${index}]`;
1206
-
1207
1214
  if (
1208
1215
  (choices.includes(field?.meta?.interface) && !isEmpty(item)) ||
1209
- (["tags", "array_of_values"].includes(field?.meta?.interface) &&
1216
+ ([
1217
+ constants.interfaces.TAGS,
1218
+ constants.interfaces.ARRAY_OF_VALUES,
1219
+ ].includes(field?.meta?.interface) &&
1210
1220
  !isEmpty(item))
1211
1221
  ) {
1212
1222
  applyValidations(
@@ -1404,11 +1414,14 @@ const validate = (data) => {
1404
1414
  };
1405
1415
 
1406
1416
  const addError = (fieldPath, obj, field) => {
1407
- fieldPath = [...choices, "tags", "array_of_values"].includes(
1408
- field?.meta?.interface
1409
- )
1410
- ? fieldPath?.replace(/\[\d+\].*$/, "")
1411
- : fieldPath;
1417
+ // fieldPath = [
1418
+ // ...choices,
1419
+ // constants.interfaces.TAGS,
1420
+ // constants.interfaces.ARRAY_OF_VALUES,
1421
+ // ].includes(field?.meta?.interface)
1422
+ // ? fieldPath?.replace(/\[\d+\].*$/, "")
1423
+ // : fieldPath;
1424
+ // TODO: Path is Sometimes Become Wrong (Like Unflatten) if we uncomment this
1412
1425
 
1413
1426
  const fieldKey = getLastChildKey(fieldPath);
1414
1427
  const isBypass = byPassKeys?.some((key) => key === fieldKey);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nox-validation",
3
- "version": "1.7.1",
3
+ "version": "1.7.2",
4
4
  "description": "validate dynamic schema",
5
5
  "main": "index.js",
6
6
  "scripts": {