nox-validation 1.7.2 → 1.7.4

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/helpers.js CHANGED
@@ -1604,6 +1604,23 @@ const rebuildFullPath = (nodePath, fullPath, modifierFn) => {
1604
1604
  : `${modifiedNodePath}`.replace(/\.+/g, ".");
1605
1605
  };
1606
1606
 
1607
+ const trimBasicPath = (basePath, staticType = "update") => {
1608
+ const regex = new RegExp(`${staticType}\\[\\d+\\]`, "g");
1609
+ const matches = [...basePath.matchAll(regex)];
1610
+
1611
+ if (matches.length === 0) return basePath; // no update/create/delete/etc found
1612
+
1613
+ // Last matched dynamic segment (e.g. "update[3]")
1614
+ const lastSegment = matches[matches.length - 1][0];
1615
+
1616
+ // Find starting index of this last segment
1617
+ const idx = basePath.lastIndexOf(lastSegment);
1618
+
1619
+ // Return everything BEFORE this segment (and remove trailing dot)
1620
+ const result = basePath.substring(0, idx).replace(/\.$/, "");
1621
+ return result;
1622
+ };
1623
+
1607
1624
  module.exports = {
1608
1625
  generateModifiedRules,
1609
1626
  getFieldsGroupBySchemaId,
@@ -1628,4 +1645,5 @@ module.exports = {
1628
1645
  remainingItems,
1629
1646
  formatDate,
1630
1647
  rebuildFullPath,
1648
+ trimBasicPath,
1631
1649
  };
package/lib/validate.js CHANGED
@@ -14,6 +14,7 @@ const {
14
14
  remainingItems,
15
15
  formatDate,
16
16
  rebuildFullPath,
17
+ trimBasicPath,
17
18
  } = require("./helpers");
18
19
 
19
20
  const choices = ["radio", "checkboxes", "dropdown_multiple", "dropdown"];
@@ -399,6 +400,7 @@ const validateMetaRules = (
399
400
  `{field}`,
400
401
  formatLabel(field.display_label)
401
402
  );
403
+
402
404
  addError(
403
405
  currentPath,
404
406
  translatedPath
@@ -470,8 +472,23 @@ const validateMetaRules = (
470
472
  ) {
471
473
  getSelectedNodes({
472
474
  node: field,
473
- skipFn: (node) =>
474
- node.meta?.interface === constants.interfaces.MANY_TO_ANY,
475
+ skipFn: (node) => {
476
+ let status = false;
477
+ if (node.meta?.interface === constants.interfaces.MANY_TO_ANY)
478
+ status = true;
479
+
480
+ if (
481
+ [
482
+ constants.interfaces.MANY_TO_MANY,
483
+ constants.interfaces.ONE_TO_MANY,
484
+ constants.interfaces.MANY_TO_ONE,
485
+ constants.interfaces.SEO,
486
+ ].includes(node.meta?.interface) &&
487
+ (!node.meta?.required || !node.meta?.hidden)
488
+ )
489
+ status = true;
490
+ return status;
491
+ },
475
492
  conditionFn: (node) =>
476
493
  node.meta?.required === true && !node.isRelationalUpdate,
477
494
  mapFn: (node) => ({
@@ -479,6 +496,24 @@ const validateMetaRules = (
479
496
  label: node.display_label,
480
497
  }),
481
498
  actionFn: (node) => {
499
+ const normalize = (path) => path.replace(/\[\d+\]/g, "[]");
500
+
501
+ const getRoot = (path) => normalize(path).split(".")[0];
502
+
503
+ const buildError = (path, translated) => {
504
+ if (!isEmpty(getValue(formData, path))) return;
505
+ let obj = {
506
+ label,
507
+ fieldPath: path,
508
+ description: "",
509
+ message,
510
+ };
511
+ if (translated) {
512
+ obj.translation_path = translated;
513
+ }
514
+ addError(path, obj, node);
515
+ };
516
+
482
517
  const isTranslationNode =
483
518
  node?.meta?.parentInterface === constants.interfaces.TRANSLATIONS ||
484
519
  field?.meta?.interface === constants.interfaces.TRANSLATIONS;
@@ -498,12 +533,25 @@ const validateMetaRules = (
498
533
 
499
534
  if (
500
535
  currentPath &&
501
- currentPath?.trim() !== "" &&
502
- !fPath.includes(currentPath)
536
+ currentPath.trim() !== "" &&
537
+ !normalize(fPath).startsWith(normalize(currentPath)) &&
538
+ getRoot(fPath) !== getRoot(currentPath)
503
539
  ) {
504
- fPath = `${currentPath}.${fPath}`;
540
+ if (currentPath.includes(fPath)) {
541
+ fPath = currentPath;
542
+ } else fPath = `${currentPath}.${fPath}`;
505
543
  }
506
544
 
545
+ // if (
546
+ // currentPath &&
547
+ // currentPath?.trim() !== "" &&
548
+ // !fPath.includes(currentPath)
549
+ // // TODO: Need to Optimize This fPath => group.items.dropdown currentPath => group.items[0].dropdown final path becomes => group.items[0].dropdown.group.items.dropdown
550
+ // // also translations.create[0].meta_description <=fPath condition currentPath => seo.create[0].translations.create[0].meta_description then condition becomes true but parent is not same then need to merge
551
+ // ) {
552
+ // fPath = `${currentPath}.${fPath}`;
553
+ // }
554
+
507
555
  if (staticType === "update") return;
508
556
  if (staticType === "delete" && !isTranslationNode) return;
509
557
  if (staticType === "existing" && !isTranslationNode) return;
@@ -511,34 +559,21 @@ const validateMetaRules = (
511
559
  const label = formatLabel(node.display_label);
512
560
  const message = error_messages.REQUIRED.replace("{field}", label);
513
561
 
514
- const buildError = (path, translated) => {
515
- if (!isEmpty(getValue(formData, path))) return;
516
- let obj = {
517
- label,
518
- fieldPath: path,
519
- description: "",
520
- message,
521
- };
522
- if (translated) {
523
- obj.translation_path = translated;
524
- }
525
- addError(path, obj, node);
526
- };
527
-
528
562
  const isMultiLang =
529
563
  isTranslationNode &&
530
564
  Array.isArray(language_codes) &&
531
565
  language_codes.length > 1;
566
+
532
567
  if (isMultiLang) {
568
+ const fullPath = fPath;
569
+
533
570
  language_codes.forEach((lang, index) => {
534
571
  let langPath, transformedPath;
535
572
  let isAdded = false;
536
-
537
- // Check if current language entry exists in fieldValue.create
573
+ // // Check if current language entry exists in fieldValue.create
538
574
  if (
539
575
  Array.isArray(fieldValue?.create) &&
540
576
  fieldValue?.create.some((item, idx) => {
541
- // Check by languages_code or by index match
542
577
  return item.languages_code === lang || idx === index;
543
578
  })
544
579
  ) {
@@ -549,25 +584,21 @@ const validateMetaRules = (
549
584
  node?.value?.includes("create[0].") ||
550
585
  node?.value?.includes("create[0]")
551
586
  ) {
552
- langPath = rebuildFullPath(node.value, node.key, (path) =>
587
+ langPath = rebuildFullPath(node.value, fPath, (path) =>
553
588
  path.replace(/create\[0\]\./, `create[${index}].`)
554
589
  );
555
- transformedPath = rebuildFullPath(
556
- node.value,
557
- node.key,
558
- (path) => {
559
- const newPath = path
560
- .replace(/\[0\]\./, `.${lang}.`)
561
- ?.replace("create", "");
562
- return newPath;
563
- }
564
- );
590
+ transformedPath = rebuildFullPath(node.value, fPath, (path) => {
591
+ const newPath = path
592
+ .replace(/\[0\]\./, `.${lang}.`)
593
+ ?.replace("create", "");
594
+ return newPath;
595
+ });
565
596
  } else {
566
- langPath = rebuildFullPath(node.value, node.key, (path) => {
597
+ langPath = rebuildFullPath(node.value, fPath, (path) => {
567
598
  return path.replace(/create\./, `create[${index}].`);
568
599
  });
569
600
 
570
- transformedPath = rebuildFullPath(node.value, node.key, (path) =>
601
+ transformedPath = rebuildFullPath(node.value, fPath, (path) =>
571
602
  path.replace(/\[0\]\./, `.${lang}.`)?.replace("create", "")
572
603
  );
573
604
  }
@@ -1128,16 +1159,7 @@ const validateField = (
1128
1159
  timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone,
1129
1160
  translatedPath = null
1130
1161
  ) => {
1131
- if (
1132
- onlyFormFields == true &&
1133
- value === undefined &&
1134
- ![constants.interfaces.TRANSLATIONS, constants.interfaces.SEO].includes(
1135
- field?.meta?.interface
1136
- )
1137
- )
1138
- return;
1139
-
1140
- const { is_m2a_item } = field?.meta;
1162
+ const { is_m2a_item, staticType = null, parentInterface } = field?.meta;
1141
1163
  const currentPath = fieldPath
1142
1164
  ? `${fieldPath}.${field.key.split(".").pop()}`
1143
1165
  : field.key;
@@ -1147,6 +1169,50 @@ const validateField = (
1147
1169
  ? `${translatedPath}.${field.key.split(".").pop()}`
1148
1170
  : field.key;
1149
1171
  }
1172
+
1173
+ if (
1174
+ onlyFormFields == true &&
1175
+ value === undefined &&
1176
+ ![constants.interfaces.TRANSLATIONS, constants.interfaces.SEO].includes(
1177
+ field?.meta?.interface
1178
+ )
1179
+ ) {
1180
+ if (
1181
+ onlyFormFields == true &&
1182
+ value === undefined &&
1183
+ staticType === "update" &&
1184
+ parentInterface === constants.interfaces.TRANSLATIONS &&
1185
+ field?.meta.required
1186
+ ) {
1187
+ const langCode = getValue(formData, fieldPath)?.languages_code;
1188
+ const translationFieldPath = trimBasicPath(currentPath, staticType);
1189
+ const existingItemValue = getValue(
1190
+ existingForm,
1191
+ translationFieldPath
1192
+ )?.find((item) => item.languages_code === langCode)?.[
1193
+ `${field.key.split(".").pop()}`
1194
+ ];
1195
+
1196
+ if (isEmpty(existingItemValue)) {
1197
+ const message = error_messages.REQUIRED.replace(
1198
+ `{field}`,
1199
+ formatLabel(`${field.key.split(".").pop()}`)
1200
+ );
1201
+ addError(
1202
+ currentPath,
1203
+ {
1204
+ label: formatLabel(`${field.key.split(".").pop()}`),
1205
+ fieldPath: currentPath,
1206
+ translation_path: translatedPath,
1207
+ description: "",
1208
+ message,
1209
+ },
1210
+ field
1211
+ );
1212
+ }
1213
+ } else return;
1214
+ }
1215
+
1150
1216
  const fieldLabel = formatLabel(field.display_label);
1151
1217
 
1152
1218
  validateMetaRules(
@@ -1263,6 +1329,13 @@ const validateField = (
1263
1329
  )
1264
1330
  trPath = trPath.replace(".update.", ".");
1265
1331
 
1332
+ if (
1333
+ trPath &&
1334
+ field.meta?.staticType === "create" &&
1335
+ trPath.includes(".create.")
1336
+ )
1337
+ trPath = trPath.replace(".create.", ".");
1338
+
1266
1339
  validateField(
1267
1340
  child,
1268
1341
  item[child.key.split(".").pop()],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nox-validation",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
4
4
  "description": "validate dynamic schema",
5
5
  "main": "index.js",
6
6
  "scripts": {