nox-validation 1.6.1 → 1.6.3
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 +89 -14
- package/lib/validate.js +44 -18
- package/package.json +1 -1
package/lib/helpers.js
CHANGED
|
@@ -319,7 +319,7 @@ const generateField = (
|
|
|
319
319
|
hidden: false,
|
|
320
320
|
}
|
|
321
321
|
) => {
|
|
322
|
-
const { staticType } = meta;
|
|
322
|
+
const { staticType = null, parentInterface = null } = meta;
|
|
323
323
|
childrenFields = childrenFields?.map((child) => {
|
|
324
324
|
const childKey = path ? `${path}.${child.key}` : child.key;
|
|
325
325
|
const childValue = path ? `${path}.${child.value}` : child.value;
|
|
@@ -327,7 +327,10 @@ const generateField = (
|
|
|
327
327
|
return {
|
|
328
328
|
...child,
|
|
329
329
|
value: childKey,
|
|
330
|
-
meta:
|
|
330
|
+
meta:
|
|
331
|
+
staticType || parentInterface
|
|
332
|
+
? { ...child?.meta, staticType, parentInterface }
|
|
333
|
+
: child?.meta,
|
|
331
334
|
key: childValue,
|
|
332
335
|
isRelationalUpdate: path.includes("update"),
|
|
333
336
|
};
|
|
@@ -418,7 +421,7 @@ const generateRelationalField = (
|
|
|
418
421
|
[],
|
|
419
422
|
"none",
|
|
420
423
|
[],
|
|
421
|
-
{ staticType: "existing" }
|
|
424
|
+
{ staticType: "existing", parentInterface: relationType }
|
|
422
425
|
);
|
|
423
426
|
existingField.children = [
|
|
424
427
|
generateField(
|
|
@@ -458,7 +461,7 @@ const generateRelationalField = (
|
|
|
458
461
|
[],
|
|
459
462
|
"none",
|
|
460
463
|
[],
|
|
461
|
-
{ staticType: "delete" }
|
|
464
|
+
{ staticType: "delete", parentInterface: relationType }
|
|
462
465
|
);
|
|
463
466
|
deleteField.children = [
|
|
464
467
|
generateField(
|
|
@@ -499,7 +502,7 @@ const generateRelationalField = (
|
|
|
499
502
|
[],
|
|
500
503
|
"none",
|
|
501
504
|
[],
|
|
502
|
-
{ staticType: "create" }
|
|
505
|
+
{ staticType: "create", parentInterface: relationType }
|
|
503
506
|
);
|
|
504
507
|
createField.children = [
|
|
505
508
|
generateField(
|
|
@@ -544,7 +547,7 @@ const generateRelationalField = (
|
|
|
544
547
|
[],
|
|
545
548
|
"none",
|
|
546
549
|
[],
|
|
547
|
-
{ staticType: "update" }
|
|
550
|
+
{ staticType: "update", parentInterface: relationType }
|
|
548
551
|
);
|
|
549
552
|
updateField.children = [
|
|
550
553
|
generateField(
|
|
@@ -591,7 +594,7 @@ const generateRelationalField = (
|
|
|
591
594
|
[],
|
|
592
595
|
"none",
|
|
593
596
|
[],
|
|
594
|
-
{ staticType: "existing" }
|
|
597
|
+
{ staticType: "existing", parentInterface: relationType }
|
|
595
598
|
),
|
|
596
599
|
generateField(
|
|
597
600
|
"delete",
|
|
@@ -601,7 +604,7 @@ const generateRelationalField = (
|
|
|
601
604
|
[],
|
|
602
605
|
"none",
|
|
603
606
|
[],
|
|
604
|
-
{ staticType: "delete" }
|
|
607
|
+
{ staticType: "delete", parentInterface: relationType }
|
|
605
608
|
),
|
|
606
609
|
generateField(
|
|
607
610
|
"create",
|
|
@@ -611,7 +614,7 @@ const generateRelationalField = (
|
|
|
611
614
|
collectionFields,
|
|
612
615
|
"none",
|
|
613
616
|
[],
|
|
614
|
-
{ staticType: "create" }
|
|
617
|
+
{ staticType: "create", parentInterface: relationType }
|
|
615
618
|
),
|
|
616
619
|
generateField(
|
|
617
620
|
"update",
|
|
@@ -621,7 +624,7 @@ const generateRelationalField = (
|
|
|
621
624
|
collectionFields,
|
|
622
625
|
"none",
|
|
623
626
|
[],
|
|
624
|
-
{ staticType: "update" }
|
|
627
|
+
{ staticType: "update", parentInterface: relationType }
|
|
625
628
|
),
|
|
626
629
|
];
|
|
627
630
|
}
|
|
@@ -1401,6 +1404,20 @@ const getM2AItemParentPath = (path) => {
|
|
|
1401
1404
|
return match ? path.replace(".item", "") : null;
|
|
1402
1405
|
};
|
|
1403
1406
|
|
|
1407
|
+
const addIndexToStaticType = (key, staticType) => {
|
|
1408
|
+
const parts = key.split(".");
|
|
1409
|
+
|
|
1410
|
+
return parts
|
|
1411
|
+
.map((part) => {
|
|
1412
|
+
if (part === staticType) {
|
|
1413
|
+
// If staticType is found AND missing index → add [0]
|
|
1414
|
+
return part.includes("[") ? part : `${part}[0]`;
|
|
1415
|
+
}
|
|
1416
|
+
return part;
|
|
1417
|
+
})
|
|
1418
|
+
.join(".");
|
|
1419
|
+
};
|
|
1420
|
+
|
|
1404
1421
|
const getSelectedNodes = ({
|
|
1405
1422
|
node,
|
|
1406
1423
|
skipFn = (node) => node.meta?.interface === constants.interfaces.MANY_TO_ANY,
|
|
@@ -1427,10 +1444,47 @@ const getSelectedNodes = ({
|
|
|
1427
1444
|
return updatedNode;
|
|
1428
1445
|
}
|
|
1429
1446
|
|
|
1430
|
-
function traverse(currentNode) {
|
|
1447
|
+
function traverse(currentNode, parentKey = null) {
|
|
1448
|
+
function mergePathLevels(currentPath, parentPath) {
|
|
1449
|
+
const cur = currentPath.split(".");
|
|
1450
|
+
const par = parentPath.split(".");
|
|
1451
|
+
|
|
1452
|
+
let matchIndex = -1;
|
|
1453
|
+
|
|
1454
|
+
// Find the first matching level
|
|
1455
|
+
for (let i = 0; i < par.length; i++) {
|
|
1456
|
+
if (par[i].replace(/\[\d+\]/, "") === cur[0].replace(/\[\d+\]/, "")) {
|
|
1457
|
+
matchIndex = i;
|
|
1458
|
+
break;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
// If match found
|
|
1463
|
+
if (matchIndex !== -1) {
|
|
1464
|
+
const parentPart = par.slice(0, matchIndex + 1);
|
|
1465
|
+
const currentTail = cur.slice(1); // everything after the matched level
|
|
1466
|
+
return [...parentPart, ...currentTail].join(".");
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
// No match → normal join
|
|
1470
|
+
return [...par, ...cur].join(".");
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
if (currentNode?.meta?.staticType) {
|
|
1474
|
+
currentNode.key = addIndexToStaticType(
|
|
1475
|
+
currentNode.key,
|
|
1476
|
+
currentNode?.meta?.staticType
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
if (parentKey)
|
|
1481
|
+
currentNode.key = mergePathLevels(currentNode.key, parentKey);
|
|
1482
|
+
|
|
1431
1483
|
if (conditionFn(currentNode)) {
|
|
1432
1484
|
actionFn(currentNode);
|
|
1433
|
-
|
|
1485
|
+
const mapped = mapFn(currentNode);
|
|
1486
|
+
|
|
1487
|
+
result.push(mapped);
|
|
1434
1488
|
}
|
|
1435
1489
|
|
|
1436
1490
|
if (Array.isArray(currentNode.children)) {
|
|
@@ -1447,12 +1501,15 @@ const getSelectedNodes = ({
|
|
|
1447
1501
|
}
|
|
1448
1502
|
}
|
|
1449
1503
|
|
|
1450
|
-
if (!skipFn(currentNode))
|
|
1504
|
+
if (!skipFn(currentNode)) {
|
|
1505
|
+
traverse(childNode, currentNode?.key);
|
|
1506
|
+
}
|
|
1451
1507
|
});
|
|
1452
1508
|
}
|
|
1453
1509
|
}
|
|
1454
1510
|
|
|
1455
|
-
traverse(node);
|
|
1511
|
+
traverse(node, node?.key);
|
|
1512
|
+
|
|
1456
1513
|
return result;
|
|
1457
1514
|
};
|
|
1458
1515
|
|
|
@@ -1524,6 +1581,23 @@ const formatDate = ({
|
|
|
1524
1581
|
.replace("A", dayPeriod);
|
|
1525
1582
|
};
|
|
1526
1583
|
|
|
1584
|
+
const rebuildFullPath = (nodePath, fullPath, modifierFn) => {
|
|
1585
|
+
// 1. Find parent path
|
|
1586
|
+
const index = fullPath.lastIndexOf(nodePath);
|
|
1587
|
+
if (index === -1) {
|
|
1588
|
+
return fullPath;
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
const parentPath = fullPath.slice(0, index).replace(/\.$/, "");
|
|
1592
|
+
|
|
1593
|
+
// 2. Modify node path (if function provided)
|
|
1594
|
+
const modifiedNodePath =
|
|
1595
|
+
typeof modifierFn === "function" ? modifierFn(nodePath) : nodePath;
|
|
1596
|
+
|
|
1597
|
+
// 3. Rebuild final full path
|
|
1598
|
+
return `${parentPath}.${modifiedNodePath}`.replace(/\.+/g, ".");
|
|
1599
|
+
};
|
|
1600
|
+
|
|
1527
1601
|
module.exports = {
|
|
1528
1602
|
generateModifiedRules,
|
|
1529
1603
|
getFieldsGroupBySchemaId,
|
|
@@ -1547,4 +1621,5 @@ module.exports = {
|
|
|
1547
1621
|
getSelectedNodes,
|
|
1548
1622
|
remainingItems,
|
|
1549
1623
|
formatDate,
|
|
1624
|
+
rebuildFullPath,
|
|
1550
1625
|
};
|
package/lib/validate.js
CHANGED
|
@@ -13,6 +13,7 @@ const {
|
|
|
13
13
|
getSelectedNodes,
|
|
14
14
|
remainingItems,
|
|
15
15
|
formatDate,
|
|
16
|
+
rebuildFullPath,
|
|
16
17
|
} = require("./helpers");
|
|
17
18
|
|
|
18
19
|
const choices = ["radio", "checkboxes", "dropdown_multiple", "dropdown"];
|
|
@@ -431,23 +432,22 @@ const validateMetaRules = (
|
|
|
431
432
|
constants.interfaces.ONE_TO_MANY,
|
|
432
433
|
constants.interfaces.MANY_TO_ONE,
|
|
433
434
|
constants.interfaces.MANY_TO_ANY,
|
|
434
|
-
|
|
435
|
+
|
|
435
436
|
"none",
|
|
436
437
|
].includes(field?.meta?.interface)) ||
|
|
437
438
|
(field?.meta?.interface === constants.interfaces.TRANSLATIONS &&
|
|
438
439
|
!field?.meta?.hidden &&
|
|
439
440
|
language_codes?.length &&
|
|
440
441
|
!onlyFormFields) ||
|
|
441
|
-
([
|
|
442
|
-
|
|
443
|
-
|
|
442
|
+
([
|
|
443
|
+
constants.interfaces.OBJECT,
|
|
444
|
+
constants.interfaces.SEO,
|
|
445
|
+
constants.interfaces.ITEMS,
|
|
446
|
+
].includes(field?.meta?.interface) &&
|
|
444
447
|
!field?.meta?.hidden &&
|
|
445
448
|
!onlyFormFields &&
|
|
446
449
|
getNodes)
|
|
447
450
|
) {
|
|
448
|
-
const isTranslationChild =
|
|
449
|
-
field?.meta?.interface === constants.interfaces.TRANSLATIONS;
|
|
450
|
-
|
|
451
451
|
getSelectedNodes({
|
|
452
452
|
node: field,
|
|
453
453
|
skipFn: (node) =>
|
|
@@ -459,12 +459,30 @@ const validateMetaRules = (
|
|
|
459
459
|
label: node.display_label,
|
|
460
460
|
}),
|
|
461
461
|
actionFn: (node) => {
|
|
462
|
-
const
|
|
462
|
+
const isTranslationNode =
|
|
463
|
+
node?.meta?.parentInterface === constants.interfaces.TRANSLATIONS ||
|
|
464
|
+
field?.meta?.interface === constants.interfaces.TRANSLATIONS;
|
|
463
465
|
let fPath = node.key?.replace("[0][0]", "[0]");
|
|
466
|
+
const types = ["update", "delete", "existing", "create"];
|
|
467
|
+
|
|
468
|
+
const extractFirstType = (key) => {
|
|
469
|
+
const regex = new RegExp(`(${types.join("|")})\\[`, "i");
|
|
470
|
+
const match = key.match(regex);
|
|
471
|
+
return match ? match[1] : null;
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
const staticType =
|
|
475
|
+
node?.meta?.staticType && types.includes(node?.meta?.staticType)
|
|
476
|
+
? extractFirstType(node.key)
|
|
477
|
+
: null;
|
|
478
|
+
|
|
479
|
+
if (!fPath.includes(currentPath)) {
|
|
480
|
+
fPath = `${currentPath}.${fPath}`;
|
|
481
|
+
}
|
|
464
482
|
|
|
465
483
|
if (staticType === "update") return;
|
|
466
|
-
if (staticType === "delete" && !
|
|
467
|
-
if (staticType === "existing" && !
|
|
484
|
+
if (staticType === "delete" && !isTranslationNode) return;
|
|
485
|
+
if (staticType === "existing" && !isTranslationNode) return;
|
|
468
486
|
|
|
469
487
|
const label = formatLabel(node.display_label);
|
|
470
488
|
const message = error_messages.REQUIRED.replace("{field}", label);
|
|
@@ -484,7 +502,7 @@ const validateMetaRules = (
|
|
|
484
502
|
};
|
|
485
503
|
|
|
486
504
|
const isMultiLang =
|
|
487
|
-
|
|
505
|
+
isTranslationNode &&
|
|
488
506
|
Array.isArray(language_codes) &&
|
|
489
507
|
language_codes.length > 1;
|
|
490
508
|
|
|
@@ -494,17 +512,24 @@ const validateMetaRules = (
|
|
|
494
512
|
transformedPath,
|
|
495
513
|
isAdded = false;
|
|
496
514
|
|
|
497
|
-
if (
|
|
515
|
+
if (node?.value?.includes("create[0].")) {
|
|
498
516
|
const exist = fieldValue?.create?.find(
|
|
499
517
|
(item) => item.languages_code === lang
|
|
500
518
|
);
|
|
501
519
|
if (exist) isAdded = true;
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
520
|
+
langPath = rebuildFullPath(node.value, node.key, (path) =>
|
|
521
|
+
path.replace("create[0].", `create[${index}].`)
|
|
522
|
+
);
|
|
523
|
+
transformedPath = rebuildFullPath(node.value, node.key, (path) =>
|
|
524
|
+
path.replace("create[0].", `${lang}.`)
|
|
525
|
+
);
|
|
505
526
|
} else {
|
|
506
|
-
langPath =
|
|
507
|
-
|
|
527
|
+
langPath = rebuildFullPath(node.value, node.key, (path) =>
|
|
528
|
+
path.replace("create.", `create[${index}].`)
|
|
529
|
+
);
|
|
530
|
+
transformedPath = rebuildFullPath(node.value, node.key, (path) =>
|
|
531
|
+
path.replace("create.", `${lang}.`)
|
|
532
|
+
);
|
|
508
533
|
}
|
|
509
534
|
|
|
510
535
|
if (!isAdded) buildError(langPath, transformedPath);
|
|
@@ -512,7 +537,7 @@ const validateMetaRules = (
|
|
|
512
537
|
} else {
|
|
513
538
|
const singlePath = fPath.replace(
|
|
514
539
|
"create.",
|
|
515
|
-
|
|
540
|
+
isTranslationNode ? "create[lang_code]." : "create[0]."
|
|
516
541
|
);
|
|
517
542
|
if (
|
|
518
543
|
constants.interfaces.ITEMS === field?.meta?.interface
|
|
@@ -1555,6 +1580,7 @@ const validate = (data) => {
|
|
|
1555
1580
|
fieldOptions,
|
|
1556
1581
|
data.language_codes,
|
|
1557
1582
|
existingForm,
|
|
1583
|
+
true,
|
|
1558
1584
|
timeZone
|
|
1559
1585
|
);
|
|
1560
1586
|
});
|