nox-validation 1.6.1 → 1.6.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/helpers.js +68 -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
|
}
|
|
@@ -1427,10 +1430,40 @@ const getSelectedNodes = ({
|
|
|
1427
1430
|
return updatedNode;
|
|
1428
1431
|
}
|
|
1429
1432
|
|
|
1430
|
-
function traverse(currentNode) {
|
|
1433
|
+
function traverse(currentNode, parentKey = null) {
|
|
1434
|
+
function mergePathLevels(currentPath, parentPath) {
|
|
1435
|
+
const cur = currentPath.split(".");
|
|
1436
|
+
const par = parentPath.split(".");
|
|
1437
|
+
|
|
1438
|
+
let matchIndex = -1;
|
|
1439
|
+
|
|
1440
|
+
// Find the first matching level
|
|
1441
|
+
for (let i = 0; i < par.length; i++) {
|
|
1442
|
+
if (par[i].replace(/\[\d+\]/, "") === cur[0].replace(/\[\d+\]/, "")) {
|
|
1443
|
+
matchIndex = i;
|
|
1444
|
+
break;
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
// If match found
|
|
1449
|
+
if (matchIndex !== -1) {
|
|
1450
|
+
const parentPart = par.slice(0, matchIndex + 1);
|
|
1451
|
+
const currentTail = cur.slice(1); // everything after the matched level
|
|
1452
|
+
return [...parentPart, ...currentTail].join(".");
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
// No match → normal join
|
|
1456
|
+
return [...par, ...cur].join(".");
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
if (parentKey)
|
|
1460
|
+
currentNode.key = mergePathLevels(currentNode.key, parentKey);
|
|
1461
|
+
|
|
1431
1462
|
if (conditionFn(currentNode)) {
|
|
1432
1463
|
actionFn(currentNode);
|
|
1433
|
-
|
|
1464
|
+
const mapped = mapFn(currentNode);
|
|
1465
|
+
|
|
1466
|
+
result.push(mapped);
|
|
1434
1467
|
}
|
|
1435
1468
|
|
|
1436
1469
|
if (Array.isArray(currentNode.children)) {
|
|
@@ -1447,12 +1480,15 @@ const getSelectedNodes = ({
|
|
|
1447
1480
|
}
|
|
1448
1481
|
}
|
|
1449
1482
|
|
|
1450
|
-
if (!skipFn(currentNode))
|
|
1483
|
+
if (!skipFn(currentNode)) {
|
|
1484
|
+
traverse(childNode, currentNode?.key);
|
|
1485
|
+
}
|
|
1451
1486
|
});
|
|
1452
1487
|
}
|
|
1453
1488
|
}
|
|
1454
1489
|
|
|
1455
|
-
traverse(node);
|
|
1490
|
+
traverse(node, node?.key);
|
|
1491
|
+
|
|
1456
1492
|
return result;
|
|
1457
1493
|
};
|
|
1458
1494
|
|
|
@@ -1524,6 +1560,23 @@ const formatDate = ({
|
|
|
1524
1560
|
.replace("A", dayPeriod);
|
|
1525
1561
|
};
|
|
1526
1562
|
|
|
1563
|
+
const rebuildFullPath = (nodePath, fullPath, modifierFn) => {
|
|
1564
|
+
// 1. Find parent path
|
|
1565
|
+
const index = fullPath.lastIndexOf(nodePath);
|
|
1566
|
+
if (index === -1) {
|
|
1567
|
+
throw new Error("nodePath not found inside fullPath");
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
const parentPath = fullPath.slice(0, index).replace(/\.$/, "");
|
|
1571
|
+
|
|
1572
|
+
// 2. Modify node path (if function provided)
|
|
1573
|
+
const modifiedNodePath =
|
|
1574
|
+
typeof modifierFn === "function" ? modifierFn(nodePath) : nodePath;
|
|
1575
|
+
|
|
1576
|
+
// 3. Rebuild final full path
|
|
1577
|
+
return `${parentPath}.${modifiedNodePath}`.replace(/\.+/g, ".");
|
|
1578
|
+
};
|
|
1579
|
+
|
|
1527
1580
|
module.exports = {
|
|
1528
1581
|
generateModifiedRules,
|
|
1529
1582
|
getFieldsGroupBySchemaId,
|
|
@@ -1547,4 +1600,5 @@ module.exports = {
|
|
|
1547
1600
|
getSelectedNodes,
|
|
1548
1601
|
remainingItems,
|
|
1549
1602
|
formatDate,
|
|
1603
|
+
rebuildFullPath,
|
|
1550
1604
|
};
|
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
|
});
|