@makehq/forman-schema 1.10.0 → 1.11.0
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/dist/index.cjs +107 -45
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +107 -45
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1151,6 +1151,7 @@ var FORMAN_TYPE_MAP2 = {
|
|
|
1151
1151
|
};
|
|
1152
1152
|
async function validateFormanWithDomainsInternal(domains, options) {
|
|
1153
1153
|
const errors = [];
|
|
1154
|
+
const warnings = [];
|
|
1154
1155
|
const roots = Object.keys(domains).reduce(
|
|
1155
1156
|
(acc, domain) => {
|
|
1156
1157
|
acc[domain] = {
|
|
@@ -1215,6 +1216,7 @@ async function validateFormanWithDomainsInternal(domains, options) {
|
|
|
1215
1216
|
}
|
|
1216
1217
|
);
|
|
1217
1218
|
errors.push(...result.errors);
|
|
1219
|
+
warnings.push(...result.warnings);
|
|
1218
1220
|
const restoreExtras = options?.states && domains[domain]?.restoreExtras;
|
|
1219
1221
|
if (restoreExtras) {
|
|
1220
1222
|
const fieldStateMap = new Map(
|
|
@@ -1250,6 +1252,7 @@ async function validateFormanWithDomainsInternal(domains, options) {
|
|
|
1250
1252
|
return {
|
|
1251
1253
|
valid: errors.length === 0,
|
|
1252
1254
|
errors,
|
|
1255
|
+
warnings,
|
|
1253
1256
|
states: errors.length === 0 && options?.states ? buildRestoreStructure(
|
|
1254
1257
|
Object.keys(domains).map((domain) => roots[domain].fieldStates.map((state) => ({ domain, ...state }))).flat()
|
|
1255
1258
|
) : void 0,
|
|
@@ -1260,7 +1263,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1260
1263
|
if (isVisualType(field.type)) {
|
|
1261
1264
|
return {
|
|
1262
1265
|
valid: true,
|
|
1263
|
-
errors: []
|
|
1266
|
+
errors: [],
|
|
1267
|
+
warnings: []
|
|
1264
1268
|
};
|
|
1265
1269
|
}
|
|
1266
1270
|
const normalizedField = normalizeFormanFieldType(field);
|
|
@@ -1273,7 +1277,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1273
1277
|
path: context.path.join("."),
|
|
1274
1278
|
message: "Field is mandatory."
|
|
1275
1279
|
}
|
|
1276
|
-
]
|
|
1280
|
+
],
|
|
1281
|
+
warnings: []
|
|
1277
1282
|
};
|
|
1278
1283
|
}
|
|
1279
1284
|
if (value == null || value === "") {
|
|
@@ -1282,7 +1287,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1282
1287
|
}
|
|
1283
1288
|
return {
|
|
1284
1289
|
valid: true,
|
|
1285
|
-
errors: []
|
|
1290
|
+
errors: [],
|
|
1291
|
+
warnings: []
|
|
1286
1292
|
};
|
|
1287
1293
|
}
|
|
1288
1294
|
const expectedType = FORMAN_TYPE_MAP2[normalizedField.type];
|
|
@@ -1297,7 +1303,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1297
1303
|
path: context.path.join("."),
|
|
1298
1304
|
message: `Expected type '${expectedType}', got type '${actualType}'.`
|
|
1299
1305
|
}
|
|
1300
|
-
]
|
|
1306
|
+
],
|
|
1307
|
+
warnings: []
|
|
1301
1308
|
};
|
|
1302
1309
|
}
|
|
1303
1310
|
if (containsIMLExpression(value)) {
|
|
@@ -1310,7 +1317,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1310
1317
|
path: context.path.join("."),
|
|
1311
1318
|
message: "Value contains prohibited IML expression."
|
|
1312
1319
|
}
|
|
1313
|
-
]
|
|
1320
|
+
],
|
|
1321
|
+
warnings: []
|
|
1314
1322
|
};
|
|
1315
1323
|
}
|
|
1316
1324
|
if (isEditableType(normalizedField.type)) {
|
|
@@ -1325,7 +1333,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1325
1333
|
}
|
|
1326
1334
|
return {
|
|
1327
1335
|
valid: true,
|
|
1328
|
-
errors: []
|
|
1336
|
+
errors: [],
|
|
1337
|
+
warnings: []
|
|
1329
1338
|
};
|
|
1330
1339
|
}
|
|
1331
1340
|
if (normalizedField.type === "udttype") {
|
|
@@ -1360,6 +1369,7 @@ async function validateFormanValue(value, field, context) {
|
|
|
1360
1369
|
}
|
|
1361
1370
|
async function handleCollectionType2(value, field, context) {
|
|
1362
1371
|
const errors = [];
|
|
1372
|
+
const warnings = [];
|
|
1363
1373
|
const seen = context.path.length === 0 ? context.roots[context.domain].seenFields : /* @__PURE__ */ new Set();
|
|
1364
1374
|
const path = context.path;
|
|
1365
1375
|
if (Array.isArray(field.spec)) {
|
|
@@ -1386,7 +1396,8 @@ async function handleCollectionType2(value, field, context) {
|
|
|
1386
1396
|
path: context.path.join("."),
|
|
1387
1397
|
message: `Failed to resolve remote resource ${subField}: ${error}`
|
|
1388
1398
|
}
|
|
1389
|
-
]
|
|
1399
|
+
],
|
|
1400
|
+
warnings
|
|
1390
1401
|
};
|
|
1391
1402
|
}
|
|
1392
1403
|
}
|
|
@@ -1430,10 +1441,12 @@ async function handleCollectionType2(value, field, context) {
|
|
|
1430
1441
|
path: [...path, subField2.name]
|
|
1431
1442
|
});
|
|
1432
1443
|
errors.push(...result2.errors);
|
|
1444
|
+
warnings.push(...result2.warnings);
|
|
1433
1445
|
}
|
|
1434
1446
|
}
|
|
1435
1447
|
});
|
|
1436
1448
|
errors.push(...result.errors);
|
|
1449
|
+
warnings.push(...result.warnings);
|
|
1437
1450
|
}
|
|
1438
1451
|
}
|
|
1439
1452
|
if (context.strict && context.path.length > 0) {
|
|
@@ -1450,11 +1463,13 @@ async function handleCollectionType2(value, field, context) {
|
|
|
1450
1463
|
}
|
|
1451
1464
|
return {
|
|
1452
1465
|
valid: errors.length === 0,
|
|
1453
|
-
errors
|
|
1466
|
+
errors,
|
|
1467
|
+
warnings
|
|
1454
1468
|
};
|
|
1455
1469
|
}
|
|
1456
1470
|
async function handleArrayType2(value, field, context) {
|
|
1457
1471
|
const errors = [];
|
|
1472
|
+
const warnings = [];
|
|
1458
1473
|
if (field.spec) {
|
|
1459
1474
|
for (const [index, item] of value.entries()) {
|
|
1460
1475
|
const result = await validateFormanValue(
|
|
@@ -1463,6 +1478,7 @@ async function handleArrayType2(value, field, context) {
|
|
|
1463
1478
|
{ ...context, path: [...context.path, index] }
|
|
1464
1479
|
);
|
|
1465
1480
|
errors.push(...result.errors);
|
|
1481
|
+
warnings.push(...result.warnings);
|
|
1466
1482
|
}
|
|
1467
1483
|
}
|
|
1468
1484
|
if (field.validate) {
|
|
@@ -1483,7 +1499,8 @@ async function handleArrayType2(value, field, context) {
|
|
|
1483
1499
|
}
|
|
1484
1500
|
return {
|
|
1485
1501
|
valid: errors.length === 0,
|
|
1486
|
-
errors
|
|
1502
|
+
errors,
|
|
1503
|
+
warnings
|
|
1487
1504
|
};
|
|
1488
1505
|
}
|
|
1489
1506
|
async function handleFilterType2(value, field, context) {
|
|
@@ -1540,6 +1557,7 @@ async function handleFilterType2(value, field, context) {
|
|
|
1540
1557
|
}
|
|
1541
1558
|
async function handlePathType(value, field, context) {
|
|
1542
1559
|
const errors = [];
|
|
1560
|
+
const warnings = [];
|
|
1543
1561
|
if (typeof value !== "string") {
|
|
1544
1562
|
return {
|
|
1545
1563
|
valid: false,
|
|
@@ -1550,7 +1568,8 @@ async function handlePathType(value, field, context) {
|
|
|
1550
1568
|
path: context.path.join("."),
|
|
1551
1569
|
message: `Expected type 'string' for path, got type '${typeof value}'.`
|
|
1552
1570
|
}
|
|
1553
|
-
]
|
|
1571
|
+
],
|
|
1572
|
+
warnings
|
|
1554
1573
|
};
|
|
1555
1574
|
}
|
|
1556
1575
|
let showRoot = true;
|
|
@@ -1575,7 +1594,8 @@ async function handlePathType(value, field, context) {
|
|
|
1575
1594
|
path: context.path.join("."),
|
|
1576
1595
|
message: `Single level path cannot contain slashes.`
|
|
1577
1596
|
}
|
|
1578
|
-
]
|
|
1597
|
+
],
|
|
1598
|
+
warnings
|
|
1579
1599
|
};
|
|
1580
1600
|
}
|
|
1581
1601
|
let nested = field.nested ? field.nested : isObject(field.options) ? field.options.nested : void 0;
|
|
@@ -1584,7 +1604,8 @@ async function handlePathType(value, field, context) {
|
|
|
1584
1604
|
if (showRoot && value === "/" && field.type === "folder") {
|
|
1585
1605
|
return {
|
|
1586
1606
|
valid: true,
|
|
1587
|
-
errors: []
|
|
1607
|
+
errors: [],
|
|
1608
|
+
warnings
|
|
1588
1609
|
};
|
|
1589
1610
|
}
|
|
1590
1611
|
if (levels.length < 2) {
|
|
@@ -1597,11 +1618,13 @@ async function handlePathType(value, field, context) {
|
|
|
1597
1618
|
path: context.path.join("."),
|
|
1598
1619
|
message: `Invalid path "${value}" encountered.`
|
|
1599
1620
|
}
|
|
1600
|
-
]
|
|
1621
|
+
],
|
|
1622
|
+
warnings
|
|
1601
1623
|
};
|
|
1602
1624
|
}
|
|
1603
1625
|
const selectedPath = [];
|
|
1604
1626
|
let levelOptions = [];
|
|
1627
|
+
let optionsFromRPC = false;
|
|
1605
1628
|
for (let levelIndex = 0; levelIndex < levels.length - 1; ++levelIndex) {
|
|
1606
1629
|
const isLastLevel = levelIndex === levels.length - 2;
|
|
1607
1630
|
const levelSelectedValue = levels[levelIndex + 1];
|
|
@@ -1616,7 +1639,8 @@ async function handlePathType(value, field, context) {
|
|
|
1616
1639
|
path: context.path.join("."),
|
|
1617
1640
|
message: `Invalid selected value of "${value}" encountered.`
|
|
1618
1641
|
}
|
|
1619
|
-
]
|
|
1642
|
+
],
|
|
1643
|
+
warnings
|
|
1620
1644
|
};
|
|
1621
1645
|
}
|
|
1622
1646
|
if (typeof options === "string") {
|
|
@@ -1624,6 +1648,7 @@ async function handlePathType(value, field, context) {
|
|
|
1624
1648
|
levelOptions = await context.resolveRemote(options, context, {
|
|
1625
1649
|
[field.name]: (showRoot && !selectedPathValue.startsWith("/") ? "/" : "") + selectedPathValue
|
|
1626
1650
|
});
|
|
1651
|
+
optionsFromRPC = true;
|
|
1627
1652
|
} catch (error) {
|
|
1628
1653
|
return {
|
|
1629
1654
|
valid: false,
|
|
@@ -1634,7 +1659,8 @@ async function handlePathType(value, field, context) {
|
|
|
1634
1659
|
path: context.path.join("."),
|
|
1635
1660
|
message: `Failed to resolve remote resource ${options}: ${error}`
|
|
1636
1661
|
}
|
|
1637
|
-
]
|
|
1662
|
+
],
|
|
1663
|
+
warnings
|
|
1638
1664
|
};
|
|
1639
1665
|
}
|
|
1640
1666
|
} else if (isLastLevel) {
|
|
@@ -1651,6 +1677,14 @@ async function handlePathType(value, field, context) {
|
|
|
1651
1677
|
});
|
|
1652
1678
|
const selectedOption = selectableOptions.find((candidate) => candidate.value === levelSelectedValue);
|
|
1653
1679
|
if (!selectedOption) {
|
|
1680
|
+
if (optionsFromRPC) {
|
|
1681
|
+
warnings.push({
|
|
1682
|
+
domain: context.domain,
|
|
1683
|
+
path: context.path.join("."),
|
|
1684
|
+
message: `Path '${levelSelectedValue}' not found in options.`
|
|
1685
|
+
});
|
|
1686
|
+
break;
|
|
1687
|
+
}
|
|
1654
1688
|
return {
|
|
1655
1689
|
valid: false,
|
|
1656
1690
|
errors: [
|
|
@@ -1660,7 +1694,8 @@ async function handlePathType(value, field, context) {
|
|
|
1660
1694
|
path: context.path.join("."),
|
|
1661
1695
|
message: `Path '${levelSelectedValue}' not found in options.`
|
|
1662
1696
|
}
|
|
1663
|
-
]
|
|
1697
|
+
],
|
|
1698
|
+
warnings
|
|
1664
1699
|
};
|
|
1665
1700
|
}
|
|
1666
1701
|
selectedPath.push(selectedOption);
|
|
@@ -1677,16 +1712,20 @@ async function handlePathType(value, field, context) {
|
|
|
1677
1712
|
if (nested) {
|
|
1678
1713
|
const result = await handleNestedFields(nested, value, field, context);
|
|
1679
1714
|
errors.push(...result.errors);
|
|
1715
|
+
warnings.push(...result.warnings);
|
|
1680
1716
|
}
|
|
1681
1717
|
return {
|
|
1682
1718
|
valid: errors.length === 0,
|
|
1683
|
-
errors
|
|
1719
|
+
errors,
|
|
1720
|
+
warnings
|
|
1684
1721
|
};
|
|
1685
1722
|
}
|
|
1686
1723
|
async function handleSelectType(value, field, context) {
|
|
1687
1724
|
const errors = [];
|
|
1725
|
+
const warnings = [];
|
|
1688
1726
|
let optionsOrGroups = isObject(field.options) ? field.options.store : field.options;
|
|
1689
1727
|
let nested = extractNestedFromField(field);
|
|
1728
|
+
let optionsFromRPC = false;
|
|
1690
1729
|
if (typeof optionsOrGroups === "string") {
|
|
1691
1730
|
try {
|
|
1692
1731
|
const resolved = await context.resolveRemote(optionsOrGroups, context);
|
|
@@ -1700,10 +1739,12 @@ async function handleSelectType(value, field, context) {
|
|
|
1700
1739
|
path: context.path.join("."),
|
|
1701
1740
|
message: `Remote resource ${optionsOrGroups} returned no data.`
|
|
1702
1741
|
}
|
|
1703
|
-
]
|
|
1742
|
+
],
|
|
1743
|
+
warnings
|
|
1704
1744
|
};
|
|
1705
1745
|
}
|
|
1706
1746
|
optionsOrGroups = Array.isArray(resolved) ? resolved : [resolved];
|
|
1747
|
+
optionsFromRPC = true;
|
|
1707
1748
|
} catch (error) {
|
|
1708
1749
|
return {
|
|
1709
1750
|
valid: false,
|
|
@@ -1714,7 +1755,8 @@ async function handleSelectType(value, field, context) {
|
|
|
1714
1755
|
path: context.path.join("."),
|
|
1715
1756
|
message: `Failed to resolve remote resource ${optionsOrGroups}: ${error}`
|
|
1716
1757
|
}
|
|
1717
|
-
]
|
|
1758
|
+
],
|
|
1759
|
+
warnings
|
|
1718
1760
|
};
|
|
1719
1761
|
}
|
|
1720
1762
|
}
|
|
@@ -1729,7 +1771,8 @@ async function handleSelectType(value, field, context) {
|
|
|
1729
1771
|
path: context.path.join("."),
|
|
1730
1772
|
message: `Value is not an array.`
|
|
1731
1773
|
}
|
|
1732
|
-
]
|
|
1774
|
+
],
|
|
1775
|
+
warnings
|
|
1733
1776
|
};
|
|
1734
1777
|
}
|
|
1735
1778
|
for (const singleValue of value) {
|
|
@@ -1739,7 +1782,7 @@ async function handleSelectType(value, field, context) {
|
|
|
1739
1782
|
optionsOrGroups
|
|
1740
1783
|
);
|
|
1741
1784
|
if (!found) {
|
|
1742
|
-
errors.push({
|
|
1785
|
+
(optionsFromRPC ? warnings : errors).push({
|
|
1743
1786
|
domain: context.domain,
|
|
1744
1787
|
path: context.path.join("."),
|
|
1745
1788
|
message: `Value '${singleValue}' not found in options.`
|
|
@@ -1777,40 +1820,53 @@ async function handleSelectType(value, field, context) {
|
|
|
1777
1820
|
} else {
|
|
1778
1821
|
const item = findValueInSelectOptions(field, value, optionsOrGroups);
|
|
1779
1822
|
if (!item) {
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
{
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1823
|
+
if (optionsFromRPC) {
|
|
1824
|
+
warnings.push({
|
|
1825
|
+
domain: context.domain,
|
|
1826
|
+
path: context.path.join("."),
|
|
1827
|
+
message: `Value '${value}' not found in options.`
|
|
1828
|
+
});
|
|
1829
|
+
} else {
|
|
1830
|
+
return {
|
|
1831
|
+
valid: false,
|
|
1832
|
+
errors: [
|
|
1833
|
+
...errors,
|
|
1834
|
+
{
|
|
1835
|
+
domain: context.domain,
|
|
1836
|
+
path: context.path.join("."),
|
|
1837
|
+
message: `Value '${value}' not found in options.`
|
|
1838
|
+
}
|
|
1839
|
+
],
|
|
1840
|
+
warnings
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
} else {
|
|
1844
|
+
if (item.label) {
|
|
1845
|
+
context.roots[context.domain].fieldStates.push({
|
|
1846
|
+
path: context.path,
|
|
1847
|
+
state: {
|
|
1848
|
+
mode: isReferenceType(field.type) ? void 0 : "chose",
|
|
1849
|
+
label: item.label
|
|
1788
1850
|
}
|
|
1789
|
-
|
|
1790
|
-
}
|
|
1791
|
-
|
|
1792
|
-
if (item.label) {
|
|
1793
|
-
context.roots[context.domain].fieldStates.push({
|
|
1794
|
-
path: context.path,
|
|
1795
|
-
state: {
|
|
1796
|
-
mode: isReferenceType(field.type) ? void 0 : "chose",
|
|
1797
|
-
label: item.label
|
|
1798
|
-
}
|
|
1799
|
-
});
|
|
1851
|
+
});
|
|
1852
|
+
}
|
|
1853
|
+
if (item.nested) nested = item.nested;
|
|
1800
1854
|
}
|
|
1801
|
-
if (item.nested) nested = item.nested;
|
|
1802
1855
|
}
|
|
1803
1856
|
if (nested) {
|
|
1804
1857
|
const result = await handleNestedFields(nested, value, field, context);
|
|
1805
1858
|
errors.push(...result.errors);
|
|
1859
|
+
warnings.push(...result.warnings);
|
|
1806
1860
|
}
|
|
1807
1861
|
return {
|
|
1808
1862
|
valid: errors.length === 0,
|
|
1809
|
-
errors
|
|
1863
|
+
errors,
|
|
1864
|
+
warnings
|
|
1810
1865
|
};
|
|
1811
1866
|
}
|
|
1812
1867
|
async function handleNestedFields(nested, value, field, context) {
|
|
1813
1868
|
const errors = [];
|
|
1869
|
+
const warnings = [];
|
|
1814
1870
|
let store = isObject(nested) ? nested.store : nested;
|
|
1815
1871
|
const domain = isObject(nested) && nested.domain ? nested.domain : void 0;
|
|
1816
1872
|
context = {
|
|
@@ -1841,7 +1897,8 @@ async function handleNestedFields(nested, value, field, context) {
|
|
|
1841
1897
|
path: context.path.join("."),
|
|
1842
1898
|
message: `Failed to resolve remote resource ${item}: ${error}`
|
|
1843
1899
|
}
|
|
1844
|
-
]
|
|
1900
|
+
],
|
|
1901
|
+
warnings
|
|
1845
1902
|
};
|
|
1846
1903
|
}
|
|
1847
1904
|
} else {
|
|
@@ -1861,17 +1918,20 @@ async function handleNestedFields(nested, value, field, context) {
|
|
|
1861
1918
|
} else {
|
|
1862
1919
|
const result = await context.roots[resolvedDomain].validateFields(store, context);
|
|
1863
1920
|
errors.push(...result.errors);
|
|
1921
|
+
warnings.push(...result.warnings);
|
|
1864
1922
|
}
|
|
1865
1923
|
} else if (store) {
|
|
1866
1924
|
await context.validateNestedFields(store, context);
|
|
1867
1925
|
}
|
|
1868
1926
|
return {
|
|
1869
1927
|
valid: errors.length === 0,
|
|
1870
|
-
errors
|
|
1928
|
+
errors,
|
|
1929
|
+
warnings
|
|
1871
1930
|
};
|
|
1872
1931
|
}
|
|
1873
1932
|
async function handlePrimitiveType2(value, field, context) {
|
|
1874
1933
|
const errors = [];
|
|
1934
|
+
const warnings = [];
|
|
1875
1935
|
if (field.validate) {
|
|
1876
1936
|
if (typeof value === "string") {
|
|
1877
1937
|
if (field.validate.pattern && !new RegExp(
|
|
@@ -1925,10 +1985,12 @@ async function handlePrimitiveType2(value, field, context) {
|
|
|
1925
1985
|
if (nested) {
|
|
1926
1986
|
const result = await handleNestedFields(nested, value, field, context);
|
|
1927
1987
|
errors.push(...result.errors);
|
|
1988
|
+
warnings.push(...result.warnings);
|
|
1928
1989
|
}
|
|
1929
1990
|
return {
|
|
1930
1991
|
valid: errors.length === 0,
|
|
1931
|
-
errors
|
|
1992
|
+
errors,
|
|
1993
|
+
warnings
|
|
1932
1994
|
};
|
|
1933
1995
|
}
|
|
1934
1996
|
|
package/dist/index.d.cts
CHANGED
|
@@ -197,6 +197,15 @@ type FormanValidationResult = {
|
|
|
197
197
|
/** Error message */
|
|
198
198
|
message: string;
|
|
199
199
|
}[];
|
|
200
|
+
/** Warnings (do not affect validity) */
|
|
201
|
+
warnings: {
|
|
202
|
+
/** Field domain */
|
|
203
|
+
domain: string;
|
|
204
|
+
/** Field path */
|
|
205
|
+
path: string;
|
|
206
|
+
/** Warning message */
|
|
207
|
+
message: string;
|
|
208
|
+
}[];
|
|
200
209
|
/** States of fields grouped by domain */
|
|
201
210
|
states?: Record<string, FormanSchemaFieldState>;
|
|
202
211
|
/** Resolved schema fields per domain */
|
package/dist/index.d.ts
CHANGED
|
@@ -197,6 +197,15 @@ type FormanValidationResult = {
|
|
|
197
197
|
/** Error message */
|
|
198
198
|
message: string;
|
|
199
199
|
}[];
|
|
200
|
+
/** Warnings (do not affect validity) */
|
|
201
|
+
warnings: {
|
|
202
|
+
/** Field domain */
|
|
203
|
+
domain: string;
|
|
204
|
+
/** Field path */
|
|
205
|
+
path: string;
|
|
206
|
+
/** Warning message */
|
|
207
|
+
message: string;
|
|
208
|
+
}[];
|
|
200
209
|
/** States of fields grouped by domain */
|
|
201
210
|
states?: Record<string, FormanSchemaFieldState>;
|
|
202
211
|
/** Resolved schema fields per domain */
|
package/dist/index.js
CHANGED
|
@@ -1122,6 +1122,7 @@ var FORMAN_TYPE_MAP2 = {
|
|
|
1122
1122
|
};
|
|
1123
1123
|
async function validateFormanWithDomainsInternal(domains, options) {
|
|
1124
1124
|
const errors = [];
|
|
1125
|
+
const warnings = [];
|
|
1125
1126
|
const roots = Object.keys(domains).reduce(
|
|
1126
1127
|
(acc, domain) => {
|
|
1127
1128
|
acc[domain] = {
|
|
@@ -1186,6 +1187,7 @@ async function validateFormanWithDomainsInternal(domains, options) {
|
|
|
1186
1187
|
}
|
|
1187
1188
|
);
|
|
1188
1189
|
errors.push(...result.errors);
|
|
1190
|
+
warnings.push(...result.warnings);
|
|
1189
1191
|
const restoreExtras = options?.states && domains[domain]?.restoreExtras;
|
|
1190
1192
|
if (restoreExtras) {
|
|
1191
1193
|
const fieldStateMap = new Map(
|
|
@@ -1221,6 +1223,7 @@ async function validateFormanWithDomainsInternal(domains, options) {
|
|
|
1221
1223
|
return {
|
|
1222
1224
|
valid: errors.length === 0,
|
|
1223
1225
|
errors,
|
|
1226
|
+
warnings,
|
|
1224
1227
|
states: errors.length === 0 && options?.states ? buildRestoreStructure(
|
|
1225
1228
|
Object.keys(domains).map((domain) => roots[domain].fieldStates.map((state) => ({ domain, ...state }))).flat()
|
|
1226
1229
|
) : void 0,
|
|
@@ -1231,7 +1234,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1231
1234
|
if (isVisualType(field.type)) {
|
|
1232
1235
|
return {
|
|
1233
1236
|
valid: true,
|
|
1234
|
-
errors: []
|
|
1237
|
+
errors: [],
|
|
1238
|
+
warnings: []
|
|
1235
1239
|
};
|
|
1236
1240
|
}
|
|
1237
1241
|
const normalizedField = normalizeFormanFieldType(field);
|
|
@@ -1244,7 +1248,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1244
1248
|
path: context.path.join("."),
|
|
1245
1249
|
message: "Field is mandatory."
|
|
1246
1250
|
}
|
|
1247
|
-
]
|
|
1251
|
+
],
|
|
1252
|
+
warnings: []
|
|
1248
1253
|
};
|
|
1249
1254
|
}
|
|
1250
1255
|
if (value == null || value === "") {
|
|
@@ -1253,7 +1258,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1253
1258
|
}
|
|
1254
1259
|
return {
|
|
1255
1260
|
valid: true,
|
|
1256
|
-
errors: []
|
|
1261
|
+
errors: [],
|
|
1262
|
+
warnings: []
|
|
1257
1263
|
};
|
|
1258
1264
|
}
|
|
1259
1265
|
const expectedType = FORMAN_TYPE_MAP2[normalizedField.type];
|
|
@@ -1268,7 +1274,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1268
1274
|
path: context.path.join("."),
|
|
1269
1275
|
message: `Expected type '${expectedType}', got type '${actualType}'.`
|
|
1270
1276
|
}
|
|
1271
|
-
]
|
|
1277
|
+
],
|
|
1278
|
+
warnings: []
|
|
1272
1279
|
};
|
|
1273
1280
|
}
|
|
1274
1281
|
if (containsIMLExpression(value)) {
|
|
@@ -1281,7 +1288,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1281
1288
|
path: context.path.join("."),
|
|
1282
1289
|
message: "Value contains prohibited IML expression."
|
|
1283
1290
|
}
|
|
1284
|
-
]
|
|
1291
|
+
],
|
|
1292
|
+
warnings: []
|
|
1285
1293
|
};
|
|
1286
1294
|
}
|
|
1287
1295
|
if (isEditableType(normalizedField.type)) {
|
|
@@ -1296,7 +1304,8 @@ async function validateFormanValue(value, field, context) {
|
|
|
1296
1304
|
}
|
|
1297
1305
|
return {
|
|
1298
1306
|
valid: true,
|
|
1299
|
-
errors: []
|
|
1307
|
+
errors: [],
|
|
1308
|
+
warnings: []
|
|
1300
1309
|
};
|
|
1301
1310
|
}
|
|
1302
1311
|
if (normalizedField.type === "udttype") {
|
|
@@ -1331,6 +1340,7 @@ async function validateFormanValue(value, field, context) {
|
|
|
1331
1340
|
}
|
|
1332
1341
|
async function handleCollectionType2(value, field, context) {
|
|
1333
1342
|
const errors = [];
|
|
1343
|
+
const warnings = [];
|
|
1334
1344
|
const seen = context.path.length === 0 ? context.roots[context.domain].seenFields : /* @__PURE__ */ new Set();
|
|
1335
1345
|
const path = context.path;
|
|
1336
1346
|
if (Array.isArray(field.spec)) {
|
|
@@ -1357,7 +1367,8 @@ async function handleCollectionType2(value, field, context) {
|
|
|
1357
1367
|
path: context.path.join("."),
|
|
1358
1368
|
message: `Failed to resolve remote resource ${subField}: ${error}`
|
|
1359
1369
|
}
|
|
1360
|
-
]
|
|
1370
|
+
],
|
|
1371
|
+
warnings
|
|
1361
1372
|
};
|
|
1362
1373
|
}
|
|
1363
1374
|
}
|
|
@@ -1401,10 +1412,12 @@ async function handleCollectionType2(value, field, context) {
|
|
|
1401
1412
|
path: [...path, subField2.name]
|
|
1402
1413
|
});
|
|
1403
1414
|
errors.push(...result2.errors);
|
|
1415
|
+
warnings.push(...result2.warnings);
|
|
1404
1416
|
}
|
|
1405
1417
|
}
|
|
1406
1418
|
});
|
|
1407
1419
|
errors.push(...result.errors);
|
|
1420
|
+
warnings.push(...result.warnings);
|
|
1408
1421
|
}
|
|
1409
1422
|
}
|
|
1410
1423
|
if (context.strict && context.path.length > 0) {
|
|
@@ -1421,11 +1434,13 @@ async function handleCollectionType2(value, field, context) {
|
|
|
1421
1434
|
}
|
|
1422
1435
|
return {
|
|
1423
1436
|
valid: errors.length === 0,
|
|
1424
|
-
errors
|
|
1437
|
+
errors,
|
|
1438
|
+
warnings
|
|
1425
1439
|
};
|
|
1426
1440
|
}
|
|
1427
1441
|
async function handleArrayType2(value, field, context) {
|
|
1428
1442
|
const errors = [];
|
|
1443
|
+
const warnings = [];
|
|
1429
1444
|
if (field.spec) {
|
|
1430
1445
|
for (const [index, item] of value.entries()) {
|
|
1431
1446
|
const result = await validateFormanValue(
|
|
@@ -1434,6 +1449,7 @@ async function handleArrayType2(value, field, context) {
|
|
|
1434
1449
|
{ ...context, path: [...context.path, index] }
|
|
1435
1450
|
);
|
|
1436
1451
|
errors.push(...result.errors);
|
|
1452
|
+
warnings.push(...result.warnings);
|
|
1437
1453
|
}
|
|
1438
1454
|
}
|
|
1439
1455
|
if (field.validate) {
|
|
@@ -1454,7 +1470,8 @@ async function handleArrayType2(value, field, context) {
|
|
|
1454
1470
|
}
|
|
1455
1471
|
return {
|
|
1456
1472
|
valid: errors.length === 0,
|
|
1457
|
-
errors
|
|
1473
|
+
errors,
|
|
1474
|
+
warnings
|
|
1458
1475
|
};
|
|
1459
1476
|
}
|
|
1460
1477
|
async function handleFilterType2(value, field, context) {
|
|
@@ -1511,6 +1528,7 @@ async function handleFilterType2(value, field, context) {
|
|
|
1511
1528
|
}
|
|
1512
1529
|
async function handlePathType(value, field, context) {
|
|
1513
1530
|
const errors = [];
|
|
1531
|
+
const warnings = [];
|
|
1514
1532
|
if (typeof value !== "string") {
|
|
1515
1533
|
return {
|
|
1516
1534
|
valid: false,
|
|
@@ -1521,7 +1539,8 @@ async function handlePathType(value, field, context) {
|
|
|
1521
1539
|
path: context.path.join("."),
|
|
1522
1540
|
message: `Expected type 'string' for path, got type '${typeof value}'.`
|
|
1523
1541
|
}
|
|
1524
|
-
]
|
|
1542
|
+
],
|
|
1543
|
+
warnings
|
|
1525
1544
|
};
|
|
1526
1545
|
}
|
|
1527
1546
|
let showRoot = true;
|
|
@@ -1546,7 +1565,8 @@ async function handlePathType(value, field, context) {
|
|
|
1546
1565
|
path: context.path.join("."),
|
|
1547
1566
|
message: `Single level path cannot contain slashes.`
|
|
1548
1567
|
}
|
|
1549
|
-
]
|
|
1568
|
+
],
|
|
1569
|
+
warnings
|
|
1550
1570
|
};
|
|
1551
1571
|
}
|
|
1552
1572
|
let nested = field.nested ? field.nested : isObject(field.options) ? field.options.nested : void 0;
|
|
@@ -1555,7 +1575,8 @@ async function handlePathType(value, field, context) {
|
|
|
1555
1575
|
if (showRoot && value === "/" && field.type === "folder") {
|
|
1556
1576
|
return {
|
|
1557
1577
|
valid: true,
|
|
1558
|
-
errors: []
|
|
1578
|
+
errors: [],
|
|
1579
|
+
warnings
|
|
1559
1580
|
};
|
|
1560
1581
|
}
|
|
1561
1582
|
if (levels.length < 2) {
|
|
@@ -1568,11 +1589,13 @@ async function handlePathType(value, field, context) {
|
|
|
1568
1589
|
path: context.path.join("."),
|
|
1569
1590
|
message: `Invalid path "${value}" encountered.`
|
|
1570
1591
|
}
|
|
1571
|
-
]
|
|
1592
|
+
],
|
|
1593
|
+
warnings
|
|
1572
1594
|
};
|
|
1573
1595
|
}
|
|
1574
1596
|
const selectedPath = [];
|
|
1575
1597
|
let levelOptions = [];
|
|
1598
|
+
let optionsFromRPC = false;
|
|
1576
1599
|
for (let levelIndex = 0; levelIndex < levels.length - 1; ++levelIndex) {
|
|
1577
1600
|
const isLastLevel = levelIndex === levels.length - 2;
|
|
1578
1601
|
const levelSelectedValue = levels[levelIndex + 1];
|
|
@@ -1587,7 +1610,8 @@ async function handlePathType(value, field, context) {
|
|
|
1587
1610
|
path: context.path.join("."),
|
|
1588
1611
|
message: `Invalid selected value of "${value}" encountered.`
|
|
1589
1612
|
}
|
|
1590
|
-
]
|
|
1613
|
+
],
|
|
1614
|
+
warnings
|
|
1591
1615
|
};
|
|
1592
1616
|
}
|
|
1593
1617
|
if (typeof options === "string") {
|
|
@@ -1595,6 +1619,7 @@ async function handlePathType(value, field, context) {
|
|
|
1595
1619
|
levelOptions = await context.resolveRemote(options, context, {
|
|
1596
1620
|
[field.name]: (showRoot && !selectedPathValue.startsWith("/") ? "/" : "") + selectedPathValue
|
|
1597
1621
|
});
|
|
1622
|
+
optionsFromRPC = true;
|
|
1598
1623
|
} catch (error) {
|
|
1599
1624
|
return {
|
|
1600
1625
|
valid: false,
|
|
@@ -1605,7 +1630,8 @@ async function handlePathType(value, field, context) {
|
|
|
1605
1630
|
path: context.path.join("."),
|
|
1606
1631
|
message: `Failed to resolve remote resource ${options}: ${error}`
|
|
1607
1632
|
}
|
|
1608
|
-
]
|
|
1633
|
+
],
|
|
1634
|
+
warnings
|
|
1609
1635
|
};
|
|
1610
1636
|
}
|
|
1611
1637
|
} else if (isLastLevel) {
|
|
@@ -1622,6 +1648,14 @@ async function handlePathType(value, field, context) {
|
|
|
1622
1648
|
});
|
|
1623
1649
|
const selectedOption = selectableOptions.find((candidate) => candidate.value === levelSelectedValue);
|
|
1624
1650
|
if (!selectedOption) {
|
|
1651
|
+
if (optionsFromRPC) {
|
|
1652
|
+
warnings.push({
|
|
1653
|
+
domain: context.domain,
|
|
1654
|
+
path: context.path.join("."),
|
|
1655
|
+
message: `Path '${levelSelectedValue}' not found in options.`
|
|
1656
|
+
});
|
|
1657
|
+
break;
|
|
1658
|
+
}
|
|
1625
1659
|
return {
|
|
1626
1660
|
valid: false,
|
|
1627
1661
|
errors: [
|
|
@@ -1631,7 +1665,8 @@ async function handlePathType(value, field, context) {
|
|
|
1631
1665
|
path: context.path.join("."),
|
|
1632
1666
|
message: `Path '${levelSelectedValue}' not found in options.`
|
|
1633
1667
|
}
|
|
1634
|
-
]
|
|
1668
|
+
],
|
|
1669
|
+
warnings
|
|
1635
1670
|
};
|
|
1636
1671
|
}
|
|
1637
1672
|
selectedPath.push(selectedOption);
|
|
@@ -1648,16 +1683,20 @@ async function handlePathType(value, field, context) {
|
|
|
1648
1683
|
if (nested) {
|
|
1649
1684
|
const result = await handleNestedFields(nested, value, field, context);
|
|
1650
1685
|
errors.push(...result.errors);
|
|
1686
|
+
warnings.push(...result.warnings);
|
|
1651
1687
|
}
|
|
1652
1688
|
return {
|
|
1653
1689
|
valid: errors.length === 0,
|
|
1654
|
-
errors
|
|
1690
|
+
errors,
|
|
1691
|
+
warnings
|
|
1655
1692
|
};
|
|
1656
1693
|
}
|
|
1657
1694
|
async function handleSelectType(value, field, context) {
|
|
1658
1695
|
const errors = [];
|
|
1696
|
+
const warnings = [];
|
|
1659
1697
|
let optionsOrGroups = isObject(field.options) ? field.options.store : field.options;
|
|
1660
1698
|
let nested = extractNestedFromField(field);
|
|
1699
|
+
let optionsFromRPC = false;
|
|
1661
1700
|
if (typeof optionsOrGroups === "string") {
|
|
1662
1701
|
try {
|
|
1663
1702
|
const resolved = await context.resolveRemote(optionsOrGroups, context);
|
|
@@ -1671,10 +1710,12 @@ async function handleSelectType(value, field, context) {
|
|
|
1671
1710
|
path: context.path.join("."),
|
|
1672
1711
|
message: `Remote resource ${optionsOrGroups} returned no data.`
|
|
1673
1712
|
}
|
|
1674
|
-
]
|
|
1713
|
+
],
|
|
1714
|
+
warnings
|
|
1675
1715
|
};
|
|
1676
1716
|
}
|
|
1677
1717
|
optionsOrGroups = Array.isArray(resolved) ? resolved : [resolved];
|
|
1718
|
+
optionsFromRPC = true;
|
|
1678
1719
|
} catch (error) {
|
|
1679
1720
|
return {
|
|
1680
1721
|
valid: false,
|
|
@@ -1685,7 +1726,8 @@ async function handleSelectType(value, field, context) {
|
|
|
1685
1726
|
path: context.path.join("."),
|
|
1686
1727
|
message: `Failed to resolve remote resource ${optionsOrGroups}: ${error}`
|
|
1687
1728
|
}
|
|
1688
|
-
]
|
|
1729
|
+
],
|
|
1730
|
+
warnings
|
|
1689
1731
|
};
|
|
1690
1732
|
}
|
|
1691
1733
|
}
|
|
@@ -1700,7 +1742,8 @@ async function handleSelectType(value, field, context) {
|
|
|
1700
1742
|
path: context.path.join("."),
|
|
1701
1743
|
message: `Value is not an array.`
|
|
1702
1744
|
}
|
|
1703
|
-
]
|
|
1745
|
+
],
|
|
1746
|
+
warnings
|
|
1704
1747
|
};
|
|
1705
1748
|
}
|
|
1706
1749
|
for (const singleValue of value) {
|
|
@@ -1710,7 +1753,7 @@ async function handleSelectType(value, field, context) {
|
|
|
1710
1753
|
optionsOrGroups
|
|
1711
1754
|
);
|
|
1712
1755
|
if (!found) {
|
|
1713
|
-
errors.push({
|
|
1756
|
+
(optionsFromRPC ? warnings : errors).push({
|
|
1714
1757
|
domain: context.domain,
|
|
1715
1758
|
path: context.path.join("."),
|
|
1716
1759
|
message: `Value '${singleValue}' not found in options.`
|
|
@@ -1748,40 +1791,53 @@ async function handleSelectType(value, field, context) {
|
|
|
1748
1791
|
} else {
|
|
1749
1792
|
const item = findValueInSelectOptions(field, value, optionsOrGroups);
|
|
1750
1793
|
if (!item) {
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
{
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1794
|
+
if (optionsFromRPC) {
|
|
1795
|
+
warnings.push({
|
|
1796
|
+
domain: context.domain,
|
|
1797
|
+
path: context.path.join("."),
|
|
1798
|
+
message: `Value '${value}' not found in options.`
|
|
1799
|
+
});
|
|
1800
|
+
} else {
|
|
1801
|
+
return {
|
|
1802
|
+
valid: false,
|
|
1803
|
+
errors: [
|
|
1804
|
+
...errors,
|
|
1805
|
+
{
|
|
1806
|
+
domain: context.domain,
|
|
1807
|
+
path: context.path.join("."),
|
|
1808
|
+
message: `Value '${value}' not found in options.`
|
|
1809
|
+
}
|
|
1810
|
+
],
|
|
1811
|
+
warnings
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
} else {
|
|
1815
|
+
if (item.label) {
|
|
1816
|
+
context.roots[context.domain].fieldStates.push({
|
|
1817
|
+
path: context.path,
|
|
1818
|
+
state: {
|
|
1819
|
+
mode: isReferenceType(field.type) ? void 0 : "chose",
|
|
1820
|
+
label: item.label
|
|
1759
1821
|
}
|
|
1760
|
-
|
|
1761
|
-
}
|
|
1762
|
-
|
|
1763
|
-
if (item.label) {
|
|
1764
|
-
context.roots[context.domain].fieldStates.push({
|
|
1765
|
-
path: context.path,
|
|
1766
|
-
state: {
|
|
1767
|
-
mode: isReferenceType(field.type) ? void 0 : "chose",
|
|
1768
|
-
label: item.label
|
|
1769
|
-
}
|
|
1770
|
-
});
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1824
|
+
if (item.nested) nested = item.nested;
|
|
1771
1825
|
}
|
|
1772
|
-
if (item.nested) nested = item.nested;
|
|
1773
1826
|
}
|
|
1774
1827
|
if (nested) {
|
|
1775
1828
|
const result = await handleNestedFields(nested, value, field, context);
|
|
1776
1829
|
errors.push(...result.errors);
|
|
1830
|
+
warnings.push(...result.warnings);
|
|
1777
1831
|
}
|
|
1778
1832
|
return {
|
|
1779
1833
|
valid: errors.length === 0,
|
|
1780
|
-
errors
|
|
1834
|
+
errors,
|
|
1835
|
+
warnings
|
|
1781
1836
|
};
|
|
1782
1837
|
}
|
|
1783
1838
|
async function handleNestedFields(nested, value, field, context) {
|
|
1784
1839
|
const errors = [];
|
|
1840
|
+
const warnings = [];
|
|
1785
1841
|
let store = isObject(nested) ? nested.store : nested;
|
|
1786
1842
|
const domain = isObject(nested) && nested.domain ? nested.domain : void 0;
|
|
1787
1843
|
context = {
|
|
@@ -1812,7 +1868,8 @@ async function handleNestedFields(nested, value, field, context) {
|
|
|
1812
1868
|
path: context.path.join("."),
|
|
1813
1869
|
message: `Failed to resolve remote resource ${item}: ${error}`
|
|
1814
1870
|
}
|
|
1815
|
-
]
|
|
1871
|
+
],
|
|
1872
|
+
warnings
|
|
1816
1873
|
};
|
|
1817
1874
|
}
|
|
1818
1875
|
} else {
|
|
@@ -1832,17 +1889,20 @@ async function handleNestedFields(nested, value, field, context) {
|
|
|
1832
1889
|
} else {
|
|
1833
1890
|
const result = await context.roots[resolvedDomain].validateFields(store, context);
|
|
1834
1891
|
errors.push(...result.errors);
|
|
1892
|
+
warnings.push(...result.warnings);
|
|
1835
1893
|
}
|
|
1836
1894
|
} else if (store) {
|
|
1837
1895
|
await context.validateNestedFields(store, context);
|
|
1838
1896
|
}
|
|
1839
1897
|
return {
|
|
1840
1898
|
valid: errors.length === 0,
|
|
1841
|
-
errors
|
|
1899
|
+
errors,
|
|
1900
|
+
warnings
|
|
1842
1901
|
};
|
|
1843
1902
|
}
|
|
1844
1903
|
async function handlePrimitiveType2(value, field, context) {
|
|
1845
1904
|
const errors = [];
|
|
1905
|
+
const warnings = [];
|
|
1846
1906
|
if (field.validate) {
|
|
1847
1907
|
if (typeof value === "string") {
|
|
1848
1908
|
if (field.validate.pattern && !new RegExp(
|
|
@@ -1896,10 +1956,12 @@ async function handlePrimitiveType2(value, field, context) {
|
|
|
1896
1956
|
if (nested) {
|
|
1897
1957
|
const result = await handleNestedFields(nested, value, field, context);
|
|
1898
1958
|
errors.push(...result.errors);
|
|
1959
|
+
warnings.push(...result.warnings);
|
|
1899
1960
|
}
|
|
1900
1961
|
return {
|
|
1901
1962
|
valid: errors.length === 0,
|
|
1902
|
-
errors
|
|
1963
|
+
errors,
|
|
1964
|
+
warnings
|
|
1903
1965
|
};
|
|
1904
1966
|
}
|
|
1905
1967
|
|