@schema-ts/core 0.1.0 → 0.1.1
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/LICENSE +21 -0
- package/dist/index.cjs +584 -492
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -10
- package/dist/index.d.ts +76 -10
- package/dist/index.js +582 -493
- package/dist/index.js.map +1 -1
- package/package.json +14 -13
package/dist/index.cjs
CHANGED
|
@@ -1333,6 +1333,225 @@ function validateSchema(schema, value, instancePath = "", schemaPath = "#", fast
|
|
|
1333
1333
|
});
|
|
1334
1334
|
}
|
|
1335
1335
|
|
|
1336
|
+
// src/effective.ts
|
|
1337
|
+
function resolveEffectiveSchema(validator, schema, value, keywordLocation, instanceLocation) {
|
|
1338
|
+
let effective = schema;
|
|
1339
|
+
if (effective.if) {
|
|
1340
|
+
const output = validator.validate(
|
|
1341
|
+
effective.if,
|
|
1342
|
+
value,
|
|
1343
|
+
`${keywordLocation}/if`,
|
|
1344
|
+
instanceLocation
|
|
1345
|
+
);
|
|
1346
|
+
if (output.valid) {
|
|
1347
|
+
if (effective.then) {
|
|
1348
|
+
const res = resolveEffectiveSchema(
|
|
1349
|
+
validator,
|
|
1350
|
+
effective.then,
|
|
1351
|
+
value,
|
|
1352
|
+
`${keywordLocation}/then`,
|
|
1353
|
+
instanceLocation
|
|
1354
|
+
);
|
|
1355
|
+
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1356
|
+
}
|
|
1357
|
+
} else {
|
|
1358
|
+
if (effective.else) {
|
|
1359
|
+
const res = resolveEffectiveSchema(
|
|
1360
|
+
validator,
|
|
1361
|
+
effective.else,
|
|
1362
|
+
value,
|
|
1363
|
+
`${keywordLocation}/else`,
|
|
1364
|
+
instanceLocation
|
|
1365
|
+
);
|
|
1366
|
+
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
const { if: _, then: __, else: ___, ...rest } = effective;
|
|
1370
|
+
effective = rest;
|
|
1371
|
+
}
|
|
1372
|
+
if (effective.allOf) {
|
|
1373
|
+
for (const [index, subschema] of effective.allOf.entries()) {
|
|
1374
|
+
const res = resolveEffectiveSchema(
|
|
1375
|
+
validator,
|
|
1376
|
+
subschema,
|
|
1377
|
+
value,
|
|
1378
|
+
`${keywordLocation}/allOf/${index}`,
|
|
1379
|
+
instanceLocation
|
|
1380
|
+
);
|
|
1381
|
+
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1382
|
+
}
|
|
1383
|
+
const { allOf: _, ...rest } = effective;
|
|
1384
|
+
effective = rest;
|
|
1385
|
+
}
|
|
1386
|
+
if (effective.anyOf) {
|
|
1387
|
+
for (const [index, subschema] of effective.anyOf.entries()) {
|
|
1388
|
+
const output = validator.validate(
|
|
1389
|
+
subschema,
|
|
1390
|
+
value,
|
|
1391
|
+
keywordLocation + `/anyOf/` + index,
|
|
1392
|
+
instanceLocation
|
|
1393
|
+
);
|
|
1394
|
+
if (output.valid) {
|
|
1395
|
+
const res = resolveEffectiveSchema(
|
|
1396
|
+
validator,
|
|
1397
|
+
subschema,
|
|
1398
|
+
value,
|
|
1399
|
+
keywordLocation + `/anyOf/` + index,
|
|
1400
|
+
instanceLocation
|
|
1401
|
+
);
|
|
1402
|
+
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1403
|
+
break;
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
const { anyOf: _, ...rest } = effective;
|
|
1407
|
+
effective = rest;
|
|
1408
|
+
}
|
|
1409
|
+
if (effective.oneOf) {
|
|
1410
|
+
let validCount = 0;
|
|
1411
|
+
let lastValidSchema = null;
|
|
1412
|
+
for (const [index, subschema] of effective.oneOf.entries()) {
|
|
1413
|
+
const output = validator.validate(
|
|
1414
|
+
subschema,
|
|
1415
|
+
value,
|
|
1416
|
+
`${keywordLocation}/oneOf/${index}`,
|
|
1417
|
+
instanceLocation
|
|
1418
|
+
);
|
|
1419
|
+
if (output.valid) {
|
|
1420
|
+
validCount++;
|
|
1421
|
+
lastValidSchema = subschema;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
if (validCount === 1 && lastValidSchema) {
|
|
1425
|
+
effective = mergeSchema(effective, lastValidSchema);
|
|
1426
|
+
}
|
|
1427
|
+
const { oneOf: _, ...rest } = effective;
|
|
1428
|
+
effective = rest;
|
|
1429
|
+
}
|
|
1430
|
+
let type = "unknown";
|
|
1431
|
+
if (effective.type) {
|
|
1432
|
+
const allowedTypes = Array.isArray(effective.type) ? effective.type : [effective.type];
|
|
1433
|
+
const matched = allowedTypes.find((t) => matchSchemaType(value, t));
|
|
1434
|
+
if (matched) {
|
|
1435
|
+
type = matched;
|
|
1436
|
+
} else {
|
|
1437
|
+
type = allowedTypes[0];
|
|
1438
|
+
}
|
|
1439
|
+
} else {
|
|
1440
|
+
type = detectSchemaType(value);
|
|
1441
|
+
}
|
|
1442
|
+
const validationOutput = validator.validate(
|
|
1443
|
+
effective,
|
|
1444
|
+
value,
|
|
1445
|
+
keywordLocation,
|
|
1446
|
+
instanceLocation,
|
|
1447
|
+
{ shallow: true }
|
|
1448
|
+
);
|
|
1449
|
+
return {
|
|
1450
|
+
effectiveSchema: effective,
|
|
1451
|
+
type,
|
|
1452
|
+
error: validationOutput.valid ? void 0 : validationOutput
|
|
1453
|
+
};
|
|
1454
|
+
}
|
|
1455
|
+
function mergeStrings(a, b) {
|
|
1456
|
+
if (a === void 0) return b;
|
|
1457
|
+
if (b === void 0) return a;
|
|
1458
|
+
const merged = Array.from(/* @__PURE__ */ new Set([...a, ...b]));
|
|
1459
|
+
return merged.length === 0 ? void 0 : merged;
|
|
1460
|
+
}
|
|
1461
|
+
function mergeType(a, b) {
|
|
1462
|
+
if (a === void 0) return b;
|
|
1463
|
+
if (b === void 0) return a;
|
|
1464
|
+
const arrayA = Array.isArray(a) ? a : [a];
|
|
1465
|
+
const arrayB = Array.isArray(b) ? b : [b];
|
|
1466
|
+
const merged = arrayA.filter((t) => arrayB.includes(t));
|
|
1467
|
+
if (merged.length === 0) return void 0;
|
|
1468
|
+
return merged.length === 1 ? merged[0] : merged;
|
|
1469
|
+
}
|
|
1470
|
+
function mergeSchemaArrays(a, b) {
|
|
1471
|
+
if (a === void 0) return b;
|
|
1472
|
+
if (b === void 0) return a;
|
|
1473
|
+
return [...a, ...b];
|
|
1474
|
+
}
|
|
1475
|
+
function mergeSchema(base, override) {
|
|
1476
|
+
if (!override) return base;
|
|
1477
|
+
const merged = {
|
|
1478
|
+
...base,
|
|
1479
|
+
...override
|
|
1480
|
+
};
|
|
1481
|
+
if (base.$defs || override.$defs) {
|
|
1482
|
+
merged.$defs = {
|
|
1483
|
+
...base.$defs,
|
|
1484
|
+
...override.$defs
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
1487
|
+
const mergedRequired = mergeStrings(base.required, override.required);
|
|
1488
|
+
if (mergedRequired !== void 0) {
|
|
1489
|
+
merged.required = mergedRequired;
|
|
1490
|
+
}
|
|
1491
|
+
const mergedType = mergeType(base.type, override.type);
|
|
1492
|
+
if (mergedType !== void 0) {
|
|
1493
|
+
merged.type = mergedType;
|
|
1494
|
+
}
|
|
1495
|
+
if (base.dependentRequired || override.dependentRequired) {
|
|
1496
|
+
merged.dependentRequired = {
|
|
1497
|
+
...base.dependentRequired,
|
|
1498
|
+
...override.dependentRequired
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
if (base.properties || override.properties) {
|
|
1502
|
+
merged.properties = {
|
|
1503
|
+
...base.properties,
|
|
1504
|
+
...override.properties
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
if (base.patternProperties || override.patternProperties) {
|
|
1508
|
+
merged.patternProperties = {
|
|
1509
|
+
...base.patternProperties,
|
|
1510
|
+
...override.patternProperties
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
if (base.items && override.items) {
|
|
1514
|
+
merged.items = mergeSchema(base.items, override.items);
|
|
1515
|
+
} else if (base.items) {
|
|
1516
|
+
merged.items = base.items;
|
|
1517
|
+
} else if (override.items) {
|
|
1518
|
+
merged.items = override.items;
|
|
1519
|
+
}
|
|
1520
|
+
if (base.prefixItems || override.prefixItems) {
|
|
1521
|
+
merged.prefixItems = [];
|
|
1522
|
+
const len = Math.max(
|
|
1523
|
+
base.prefixItems?.length || 0,
|
|
1524
|
+
override.prefixItems?.length || 0
|
|
1525
|
+
);
|
|
1526
|
+
for (let i = 0; i < len; i++) {
|
|
1527
|
+
const baseSchema = base.prefixItems?.[i];
|
|
1528
|
+
const overrideSchema = override.prefixItems?.[i];
|
|
1529
|
+
if (baseSchema && overrideSchema) {
|
|
1530
|
+
merged.prefixItems.push(mergeSchema(baseSchema, overrideSchema));
|
|
1531
|
+
} else {
|
|
1532
|
+
const schema = baseSchema || overrideSchema;
|
|
1533
|
+
if (schema) {
|
|
1534
|
+
merged.prefixItems.push(schema);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
const combinatorKeywords = ["allOf", "anyOf", "oneOf"];
|
|
1540
|
+
for (const keyword of combinatorKeywords) {
|
|
1541
|
+
const mergedArray = mergeSchemaArrays(base[keyword], override[keyword]);
|
|
1542
|
+
if (mergedArray !== void 0) {
|
|
1543
|
+
merged[keyword] = mergedArray;
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
if (base.dependentSchemas || override.dependentSchemas) {
|
|
1547
|
+
merged.dependentSchemas = {
|
|
1548
|
+
...base.dependentSchemas,
|
|
1549
|
+
...override.dependentSchemas
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
return merged;
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1336
1555
|
// src/schema-util.ts
|
|
1337
1556
|
var schemaUtilLogger = {
|
|
1338
1557
|
warn: (message) => console.warn(message)
|
|
@@ -1500,411 +1719,297 @@ function dereferenceSchemaDeep(schema, rootSchema, processed = /* @__PURE__ */ n
|
|
|
1500
1719
|
processed.set(schema, result);
|
|
1501
1720
|
return result;
|
|
1502
1721
|
}
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
return [];
|
|
1722
|
+
function getSubSchema(schema, key) {
|
|
1723
|
+
if (schema.properties && schema.properties[key]) {
|
|
1724
|
+
return {
|
|
1725
|
+
schema: schema.properties[key],
|
|
1726
|
+
keywordLocationToken: `properties/${key}`
|
|
1727
|
+
};
|
|
1510
1728
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1729
|
+
if (schema.patternProperties) {
|
|
1730
|
+
for (const [pattern, subschema] of Object.entries(
|
|
1731
|
+
schema.patternProperties
|
|
1732
|
+
)) {
|
|
1733
|
+
if (safeRegexTest(pattern, key)) {
|
|
1734
|
+
return {
|
|
1735
|
+
schema: subschema,
|
|
1736
|
+
keywordLocationToken: `patternProperties/${pattern}`
|
|
1737
|
+
};
|
|
1738
|
+
}
|
|
1520
1739
|
}
|
|
1521
1740
|
}
|
|
1522
|
-
if (schema.
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
schema.prefixItems.forEach((itemSchema, index) => {
|
|
1528
|
-
const indexPath = basePath ? `${basePath}/${index}` : `/${index}`;
|
|
1529
|
-
paths.push(indexPath);
|
|
1530
|
-
paths.push(...extractReferencedPaths(itemSchema, indexPath, depth + 1));
|
|
1531
|
-
});
|
|
1741
|
+
if (schema.additionalProperties !== void 0 && schema.additionalProperties !== false) {
|
|
1742
|
+
return {
|
|
1743
|
+
schema: typeof schema.additionalProperties === "object" ? schema.additionalProperties : {},
|
|
1744
|
+
keywordLocationToken: "additionalProperties"
|
|
1745
|
+
};
|
|
1532
1746
|
}
|
|
1533
|
-
if (schema.
|
|
1534
|
-
|
|
1535
|
-
|
|
1747
|
+
if (schema.items || schema.prefixItems) {
|
|
1748
|
+
const index = parseInt(key, 10);
|
|
1749
|
+
if (!isNaN(index)) {
|
|
1750
|
+
if (schema.prefixItems && index < schema.prefixItems.length) {
|
|
1751
|
+
return {
|
|
1752
|
+
schema: schema.prefixItems[index],
|
|
1753
|
+
keywordLocationToken: `prefixItems/${index}`
|
|
1754
|
+
};
|
|
1755
|
+
}
|
|
1756
|
+
if (schema.items) {
|
|
1757
|
+
return {
|
|
1758
|
+
schema: schema.items,
|
|
1759
|
+
keywordLocationToken: "items"
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1536
1762
|
}
|
|
1537
1763
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1764
|
+
return {
|
|
1765
|
+
schema: {},
|
|
1766
|
+
keywordLocationToken: ""
|
|
1767
|
+
};
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
// src/default.ts
|
|
1771
|
+
function getDefaultValue(schema, value) {
|
|
1772
|
+
if (value === void 0) {
|
|
1773
|
+
if (schema.const !== void 0) return schema.const;
|
|
1774
|
+
if (schema.default !== void 0) return schema.default;
|
|
1540
1775
|
}
|
|
1541
|
-
const
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
"
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
break;
|
|
1776
|
+
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
1777
|
+
if (type === "object" || !type && schema.properties) {
|
|
1778
|
+
let obj;
|
|
1779
|
+
if (value === void 0) {
|
|
1780
|
+
obj = {};
|
|
1781
|
+
} else if (typeof value === "object" && value !== null) {
|
|
1782
|
+
obj = value;
|
|
1783
|
+
} else {
|
|
1784
|
+
return value;
|
|
1785
|
+
}
|
|
1786
|
+
if (schema.properties) {
|
|
1787
|
+
for (const [key, subschema] of Object.entries(schema.properties)) {
|
|
1788
|
+
if (obj[key] !== void 0) {
|
|
1789
|
+
obj[key] = getDefaultValue(subschema, obj[key]);
|
|
1790
|
+
} else if (schema.required?.includes(key)) {
|
|
1791
|
+
obj[key] = getDefaultValue(subschema);
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1560
1794
|
}
|
|
1795
|
+
return obj;
|
|
1561
1796
|
}
|
|
1797
|
+
if (type === "array") {
|
|
1798
|
+
let arr;
|
|
1799
|
+
if (value === void 0) {
|
|
1800
|
+
arr = [];
|
|
1801
|
+
} else if (Array.isArray(value)) {
|
|
1802
|
+
arr = value;
|
|
1803
|
+
} else {
|
|
1804
|
+
return value;
|
|
1805
|
+
}
|
|
1806
|
+
if (schema.prefixItems) {
|
|
1807
|
+
schema.prefixItems.forEach((subschema, index) => {
|
|
1808
|
+
if (index < arr.length) {
|
|
1809
|
+
arr[index] = getDefaultValue(subschema, arr[index]);
|
|
1810
|
+
} else if (value === void 0) {
|
|
1811
|
+
arr.push(getDefaultValue(subschema));
|
|
1812
|
+
}
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
if (value !== void 0 && schema.items) {
|
|
1816
|
+
const startIndex = schema.prefixItems ? schema.prefixItems.length : 0;
|
|
1817
|
+
for (let i = startIndex; i < arr.length; i++) {
|
|
1818
|
+
arr[i] = getDefaultValue(schema.items, arr[i]);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
return arr;
|
|
1822
|
+
}
|
|
1823
|
+
if (value !== void 0) {
|
|
1824
|
+
return value;
|
|
1825
|
+
}
|
|
1826
|
+
switch (type) {
|
|
1827
|
+
case "string":
|
|
1828
|
+
return "";
|
|
1829
|
+
case "number":
|
|
1830
|
+
case "integer":
|
|
1831
|
+
return 0;
|
|
1832
|
+
case "boolean":
|
|
1833
|
+
return false;
|
|
1834
|
+
case "null":
|
|
1835
|
+
return null;
|
|
1836
|
+
default:
|
|
1837
|
+
return void 0;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
// src/dependency.ts
|
|
1842
|
+
function collectDependencies(schema, instanceLocation) {
|
|
1843
|
+
const deps = /* @__PURE__ */ new Set();
|
|
1562
1844
|
if (schema.required) {
|
|
1563
1845
|
for (const req of schema.required) {
|
|
1564
|
-
|
|
1846
|
+
deps.add(resolveAbsolutePath(instanceLocation, `/${req}`));
|
|
1565
1847
|
}
|
|
1566
1848
|
}
|
|
1567
1849
|
if (schema.dependentRequired) {
|
|
1568
1850
|
for (const [prop, reqs] of Object.entries(schema.dependentRequired)) {
|
|
1569
|
-
|
|
1851
|
+
deps.add(resolveAbsolutePath(instanceLocation, `/${prop}`));
|
|
1570
1852
|
for (const req of reqs) {
|
|
1571
|
-
|
|
1853
|
+
deps.add(resolveAbsolutePath(instanceLocation, `/${req}`));
|
|
1572
1854
|
}
|
|
1573
1855
|
}
|
|
1574
1856
|
}
|
|
1575
1857
|
if (schema.dependentSchemas) {
|
|
1576
1858
|
for (const [prop, subSchema] of Object.entries(schema.dependentSchemas)) {
|
|
1577
|
-
|
|
1578
|
-
|
|
1859
|
+
deps.add(resolveAbsolutePath(instanceLocation, `/${prop}`));
|
|
1860
|
+
const subDeps = collectDependencies(subSchema, instanceLocation);
|
|
1861
|
+
subDeps.forEach((d) => deps.add(d));
|
|
1579
1862
|
}
|
|
1580
1863
|
}
|
|
1581
1864
|
if (schema.if) {
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
paths.push(...extractReferencedPaths(schema.then, basePath, depth + 1));
|
|
1586
|
-
}
|
|
1587
|
-
if (schema.else) {
|
|
1588
|
-
paths.push(...extractReferencedPaths(schema.else, basePath, depth + 1));
|
|
1589
|
-
}
|
|
1590
|
-
for (const keyword of ["allOf", "anyOf", "oneOf"]) {
|
|
1591
|
-
const subSchemas = schema[keyword];
|
|
1592
|
-
if (subSchemas) {
|
|
1593
|
-
for (const subSchema of subSchemas) {
|
|
1594
|
-
paths.push(...extractReferencedPaths(subSchema, basePath, depth + 1));
|
|
1595
|
-
}
|
|
1865
|
+
const relativePaths = extractReferencedPaths(schema.if, "");
|
|
1866
|
+
for (const relPath of relativePaths) {
|
|
1867
|
+
deps.add(resolveAbsolutePath(instanceLocation, relPath));
|
|
1596
1868
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
const keyPath = basePath ? `${basePath}/${key}` : `/${key}`;
|
|
1601
|
-
paths.push(keyPath);
|
|
1602
|
-
paths.push(...extractReferencedPaths(subSchema, basePath, depth + 1));
|
|
1869
|
+
if (schema.then) {
|
|
1870
|
+
const thenDeps = collectDependencies(schema.then, instanceLocation);
|
|
1871
|
+
thenDeps.forEach((d) => deps.add(d));
|
|
1603
1872
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
paths.push(...extractReferencedPaths(schema.contains, basePath, depth + 1));
|
|
1608
|
-
}
|
|
1609
|
-
return [...new Set(paths)];
|
|
1610
|
-
}
|
|
1611
|
-
function resolveEffectiveSchema(validator, schema, value, keywordLocation, instanceLocation) {
|
|
1612
|
-
let effective = schema;
|
|
1613
|
-
if (effective.if) {
|
|
1614
|
-
const output = validator.validate(
|
|
1615
|
-
effective.if,
|
|
1616
|
-
value,
|
|
1617
|
-
`${keywordLocation}/if`,
|
|
1618
|
-
instanceLocation
|
|
1619
|
-
);
|
|
1620
|
-
if (output.valid) {
|
|
1621
|
-
if (effective.then) {
|
|
1622
|
-
const res = resolveEffectiveSchema(
|
|
1623
|
-
validator,
|
|
1624
|
-
effective.then,
|
|
1625
|
-
value,
|
|
1626
|
-
`${keywordLocation}/then`,
|
|
1627
|
-
instanceLocation
|
|
1628
|
-
);
|
|
1629
|
-
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1630
|
-
}
|
|
1631
|
-
} else {
|
|
1632
|
-
if (effective.else) {
|
|
1633
|
-
const res = resolveEffectiveSchema(
|
|
1634
|
-
validator,
|
|
1635
|
-
effective.else,
|
|
1636
|
-
value,
|
|
1637
|
-
`${keywordLocation}/else`,
|
|
1638
|
-
instanceLocation
|
|
1639
|
-
);
|
|
1640
|
-
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1641
|
-
}
|
|
1873
|
+
if (schema.else) {
|
|
1874
|
+
const elseDeps = collectDependencies(schema.else, instanceLocation);
|
|
1875
|
+
elseDeps.forEach((d) => deps.add(d));
|
|
1642
1876
|
}
|
|
1643
|
-
const { if: _, then: __, else: ___, ...rest } = effective;
|
|
1644
|
-
effective = rest;
|
|
1645
1877
|
}
|
|
1646
|
-
if (
|
|
1647
|
-
for (const
|
|
1648
|
-
const
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
value,
|
|
1652
|
-
`${keywordLocation}/allOf/${index}`,
|
|
1653
|
-
instanceLocation
|
|
1654
|
-
);
|
|
1655
|
-
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1656
|
-
}
|
|
1657
|
-
const { allOf: _, ...rest } = effective;
|
|
1658
|
-
effective = rest;
|
|
1659
|
-
}
|
|
1660
|
-
if (effective.anyOf) {
|
|
1661
|
-
for (const [index, subschema] of effective.anyOf.entries()) {
|
|
1662
|
-
const output = validator.validate(
|
|
1663
|
-
subschema,
|
|
1664
|
-
value,
|
|
1665
|
-
keywordLocation + `/anyOf/` + index,
|
|
1666
|
-
instanceLocation
|
|
1667
|
-
);
|
|
1668
|
-
if (output.valid) {
|
|
1669
|
-
const res = resolveEffectiveSchema(
|
|
1670
|
-
validator,
|
|
1671
|
-
subschema,
|
|
1672
|
-
value,
|
|
1673
|
-
keywordLocation + `/anyOf/` + index,
|
|
1674
|
-
instanceLocation
|
|
1675
|
-
);
|
|
1676
|
-
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1677
|
-
break;
|
|
1878
|
+
if (schema.oneOf) {
|
|
1879
|
+
for (const subSchema of schema.oneOf) {
|
|
1880
|
+
const relativePaths = extractReferencedPaths(subSchema, "");
|
|
1881
|
+
for (const relPath of relativePaths) {
|
|
1882
|
+
deps.add(resolveAbsolutePath(instanceLocation, relPath));
|
|
1678
1883
|
}
|
|
1884
|
+
const subDeps = collectDependencies(subSchema, instanceLocation);
|
|
1885
|
+
subDeps.forEach((d) => deps.add(d));
|
|
1679
1886
|
}
|
|
1680
|
-
const { anyOf: _, ...rest } = effective;
|
|
1681
|
-
effective = rest;
|
|
1682
1887
|
}
|
|
1683
|
-
if (
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
subschema,
|
|
1689
|
-
value,
|
|
1690
|
-
`${keywordLocation}/oneOf/${index}`,
|
|
1691
|
-
instanceLocation
|
|
1692
|
-
);
|
|
1693
|
-
if (output.valid) {
|
|
1694
|
-
validCount++;
|
|
1695
|
-
lastValidSchema = subschema;
|
|
1888
|
+
if (schema.anyOf) {
|
|
1889
|
+
for (const subSchema of schema.anyOf) {
|
|
1890
|
+
const relativePaths = extractReferencedPaths(subSchema, "");
|
|
1891
|
+
for (const relPath of relativePaths) {
|
|
1892
|
+
deps.add(resolveAbsolutePath(instanceLocation, relPath));
|
|
1696
1893
|
}
|
|
1894
|
+
const subDeps = collectDependencies(subSchema, instanceLocation);
|
|
1895
|
+
subDeps.forEach((d) => deps.add(d));
|
|
1697
1896
|
}
|
|
1698
|
-
if (validCount === 1 && lastValidSchema) {
|
|
1699
|
-
effective = mergeSchema(effective, lastValidSchema);
|
|
1700
|
-
}
|
|
1701
|
-
const { oneOf: _, ...rest } = effective;
|
|
1702
|
-
effective = rest;
|
|
1703
1897
|
}
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
if (matched) {
|
|
1709
|
-
type = matched;
|
|
1710
|
-
} else {
|
|
1711
|
-
type = allowedTypes[0];
|
|
1898
|
+
if (schema.allOf) {
|
|
1899
|
+
for (const subSchema of schema.allOf) {
|
|
1900
|
+
const subDeps = collectDependencies(subSchema, instanceLocation);
|
|
1901
|
+
subDeps.forEach((d) => deps.add(d));
|
|
1712
1902
|
}
|
|
1713
|
-
} else {
|
|
1714
|
-
type = detectSchemaType(value);
|
|
1715
1903
|
}
|
|
1716
|
-
|
|
1717
|
-
effective,
|
|
1718
|
-
value,
|
|
1719
|
-
keywordLocation,
|
|
1720
|
-
instanceLocation,
|
|
1721
|
-
{ shallow: true }
|
|
1722
|
-
);
|
|
1723
|
-
return {
|
|
1724
|
-
effectiveSchema: effective,
|
|
1725
|
-
type,
|
|
1726
|
-
error: validationOutput.valid ? void 0 : validationOutput
|
|
1727
|
-
};
|
|
1728
|
-
}
|
|
1729
|
-
function mergeStrings(a, b) {
|
|
1730
|
-
if (a === void 0) return b;
|
|
1731
|
-
if (b === void 0) return a;
|
|
1732
|
-
const merged = Array.from(/* @__PURE__ */ new Set([...a, ...b]));
|
|
1733
|
-
return merged.length === 0 ? void 0 : merged;
|
|
1734
|
-
}
|
|
1735
|
-
function mergeType(a, b) {
|
|
1736
|
-
if (a === void 0) return b;
|
|
1737
|
-
if (b === void 0) return a;
|
|
1738
|
-
const arrayA = Array.isArray(a) ? a : [a];
|
|
1739
|
-
const arrayB = Array.isArray(b) ? b : [b];
|
|
1740
|
-
const merged = arrayA.filter((t) => arrayB.includes(t));
|
|
1741
|
-
if (merged.length === 0) return void 0;
|
|
1742
|
-
return merged.length === 1 ? merged[0] : merged;
|
|
1904
|
+
return deps;
|
|
1743
1905
|
}
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
if (
|
|
1747
|
-
|
|
1748
|
-
}
|
|
1749
|
-
function mergeSchema(base, override) {
|
|
1750
|
-
if (!override) return base;
|
|
1751
|
-
const merged = {
|
|
1752
|
-
...base,
|
|
1753
|
-
...override
|
|
1754
|
-
};
|
|
1755
|
-
if (base.$defs || override.$defs) {
|
|
1756
|
-
merged.$defs = {
|
|
1757
|
-
...base.$defs,
|
|
1758
|
-
...override.$defs
|
|
1759
|
-
};
|
|
1760
|
-
}
|
|
1761
|
-
const mergedRequired = mergeStrings(base.required, override.required);
|
|
1762
|
-
if (mergedRequired !== void 0) {
|
|
1763
|
-
merged.required = mergedRequired;
|
|
1764
|
-
}
|
|
1765
|
-
const mergedType = mergeType(base.type, override.type);
|
|
1766
|
-
if (mergedType !== void 0) {
|
|
1767
|
-
merged.type = mergedType;
|
|
1768
|
-
}
|
|
1769
|
-
if (base.dependentRequired || override.dependentRequired) {
|
|
1770
|
-
merged.dependentRequired = {
|
|
1771
|
-
...base.dependentRequired,
|
|
1772
|
-
...override.dependentRequired
|
|
1773
|
-
};
|
|
1774
|
-
}
|
|
1775
|
-
if (base.properties || override.properties) {
|
|
1776
|
-
merged.properties = {
|
|
1777
|
-
...base.properties,
|
|
1778
|
-
...override.properties
|
|
1779
|
-
};
|
|
1780
|
-
}
|
|
1781
|
-
if (base.patternProperties || override.patternProperties) {
|
|
1782
|
-
merged.patternProperties = {
|
|
1783
|
-
...base.patternProperties,
|
|
1784
|
-
...override.patternProperties
|
|
1785
|
-
};
|
|
1786
|
-
}
|
|
1787
|
-
if (base.items && override.items) {
|
|
1788
|
-
merged.items = mergeSchema(base.items, override.items);
|
|
1789
|
-
} else if (base.items) {
|
|
1790
|
-
merged.items = base.items;
|
|
1791
|
-
} else if (override.items) {
|
|
1792
|
-
merged.items = override.items;
|
|
1793
|
-
}
|
|
1794
|
-
if (base.prefixItems || override.prefixItems) {
|
|
1795
|
-
merged.prefixItems = [];
|
|
1796
|
-
const len = Math.max(
|
|
1797
|
-
base.prefixItems?.length || 0,
|
|
1798
|
-
override.prefixItems?.length || 0
|
|
1906
|
+
var MAX_EXTRACT_DEPTH = 100;
|
|
1907
|
+
function extractReferencedPaths(conditionSchema, basePath = "", depth = 0) {
|
|
1908
|
+
if (depth > MAX_EXTRACT_DEPTH) {
|
|
1909
|
+
console.warn(
|
|
1910
|
+
`extractReferencedPaths: max depth (${MAX_EXTRACT_DEPTH}) exceeded at path: ${basePath}`
|
|
1799
1911
|
);
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1912
|
+
return [];
|
|
1913
|
+
}
|
|
1914
|
+
const paths = [];
|
|
1915
|
+
const schema = conditionSchema;
|
|
1916
|
+
if (schema.properties) {
|
|
1917
|
+
for (const key of Object.keys(schema.properties)) {
|
|
1918
|
+
const childPath = basePath ? `${basePath}/${key}` : `/${key}`;
|
|
1919
|
+
paths.push(childPath);
|
|
1920
|
+
paths.push(
|
|
1921
|
+
...extractReferencedPaths(schema.properties[key], childPath, depth + 1)
|
|
1922
|
+
);
|
|
1811
1923
|
}
|
|
1812
1924
|
}
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1925
|
+
if (schema.items && typeof schema.items === "object") {
|
|
1926
|
+
paths.push(basePath || "/");
|
|
1927
|
+
paths.push(...extractReferencedPaths(schema.items, basePath, depth + 1));
|
|
1928
|
+
}
|
|
1929
|
+
if (schema.prefixItems) {
|
|
1930
|
+
schema.prefixItems.forEach((itemSchema, index) => {
|
|
1931
|
+
const indexPath = basePath ? `${basePath}/${index}` : `/${index}`;
|
|
1932
|
+
paths.push(indexPath);
|
|
1933
|
+
paths.push(...extractReferencedPaths(itemSchema, indexPath, depth + 1));
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
if (schema.const !== void 0 || schema.enum) {
|
|
1937
|
+
if (basePath) {
|
|
1938
|
+
paths.push(basePath);
|
|
1818
1939
|
}
|
|
1819
1940
|
}
|
|
1820
|
-
if (
|
|
1821
|
-
|
|
1822
|
-
...base.dependentSchemas,
|
|
1823
|
-
...override.dependentSchemas
|
|
1824
|
-
};
|
|
1941
|
+
if (schema.type && basePath) {
|
|
1942
|
+
paths.push(basePath);
|
|
1825
1943
|
}
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1944
|
+
const valueConstraints = [
|
|
1945
|
+
"minimum",
|
|
1946
|
+
"maximum",
|
|
1947
|
+
"exclusiveMinimum",
|
|
1948
|
+
"exclusiveMaximum",
|
|
1949
|
+
"minLength",
|
|
1950
|
+
"maxLength",
|
|
1951
|
+
"pattern",
|
|
1952
|
+
"format",
|
|
1953
|
+
"minItems",
|
|
1954
|
+
"maxItems",
|
|
1955
|
+
"uniqueItems",
|
|
1956
|
+
"minProperties",
|
|
1957
|
+
"maxProperties"
|
|
1958
|
+
];
|
|
1959
|
+
for (const constraint of valueConstraints) {
|
|
1960
|
+
if (schema[constraint] !== void 0 && basePath) {
|
|
1961
|
+
paths.push(basePath);
|
|
1962
|
+
break;
|
|
1963
|
+
}
|
|
1834
1964
|
}
|
|
1835
|
-
if (schema.
|
|
1836
|
-
for (const
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1965
|
+
if (schema.required) {
|
|
1966
|
+
for (const req of schema.required) {
|
|
1967
|
+
paths.push(basePath ? `${basePath}/${req}` : `/${req}`);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
if (schema.dependentRequired) {
|
|
1971
|
+
for (const [prop, reqs] of Object.entries(schema.dependentRequired)) {
|
|
1972
|
+
paths.push(basePath ? `${basePath}/${prop}` : `/${prop}`);
|
|
1973
|
+
for (const req of reqs) {
|
|
1974
|
+
paths.push(basePath ? `${basePath}/${req}` : `/${req}`);
|
|
1844
1975
|
}
|
|
1845
1976
|
}
|
|
1846
1977
|
}
|
|
1847
|
-
if (schema.
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
}
|
|
1978
|
+
if (schema.dependentSchemas) {
|
|
1979
|
+
for (const [prop, subSchema] of Object.entries(schema.dependentSchemas)) {
|
|
1980
|
+
paths.push(basePath ? `${basePath}/${prop}` : `/${prop}`);
|
|
1981
|
+
paths.push(...extractReferencedPaths(subSchema, basePath, depth + 1));
|
|
1982
|
+
}
|
|
1852
1983
|
}
|
|
1853
|
-
if (schema.
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1984
|
+
if (schema.if) {
|
|
1985
|
+
paths.push(...extractReferencedPaths(schema.if, basePath, depth + 1));
|
|
1986
|
+
}
|
|
1987
|
+
if (schema.then) {
|
|
1988
|
+
paths.push(...extractReferencedPaths(schema.then, basePath, depth + 1));
|
|
1989
|
+
}
|
|
1990
|
+
if (schema.else) {
|
|
1991
|
+
paths.push(...extractReferencedPaths(schema.else, basePath, depth + 1));
|
|
1992
|
+
}
|
|
1993
|
+
for (const keyword of ["allOf", "anyOf", "oneOf"]) {
|
|
1994
|
+
const subSchemas = schema[keyword];
|
|
1995
|
+
if (subSchemas) {
|
|
1996
|
+
for (const subSchema of subSchemas) {
|
|
1997
|
+
paths.push(...extractReferencedPaths(subSchema, basePath, depth + 1));
|
|
1867
1998
|
}
|
|
1868
1999
|
}
|
|
1869
2000
|
}
|
|
1870
|
-
|
|
1871
|
-
schema
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
function getDefaultValue(schema) {
|
|
1876
|
-
if (schema.const !== void 0) return schema.const;
|
|
1877
|
-
if (schema.default !== void 0) return schema.default;
|
|
1878
|
-
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
1879
|
-
switch (type) {
|
|
1880
|
-
case "string":
|
|
1881
|
-
return "";
|
|
1882
|
-
case "number":
|
|
1883
|
-
case "integer":
|
|
1884
|
-
return 0;
|
|
1885
|
-
case "boolean":
|
|
1886
|
-
return false;
|
|
1887
|
-
case "null":
|
|
1888
|
-
return null;
|
|
1889
|
-
case "object": {
|
|
1890
|
-
const obj = {};
|
|
1891
|
-
if (schema.properties) {
|
|
1892
|
-
for (const [key, subschema] of Object.entries(schema.properties)) {
|
|
1893
|
-
if (schema.required?.includes(key)) {
|
|
1894
|
-
obj[key] = getDefaultValue(subschema);
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
return obj;
|
|
2001
|
+
if (schema.dependentSchemas) {
|
|
2002
|
+
for (const [key, subSchema] of Object.entries(schema.dependentSchemas)) {
|
|
2003
|
+
const keyPath = basePath ? `${basePath}/${key}` : `/${key}`;
|
|
2004
|
+
paths.push(keyPath);
|
|
2005
|
+
paths.push(...extractReferencedPaths(subSchema, basePath, depth + 1));
|
|
1899
2006
|
}
|
|
1900
|
-
case "array":
|
|
1901
|
-
return [];
|
|
1902
|
-
default:
|
|
1903
|
-
if (schema.properties) {
|
|
1904
|
-
return getDefaultValue({ ...schema, type: "object" });
|
|
1905
|
-
}
|
|
1906
|
-
return void 0;
|
|
1907
2007
|
}
|
|
2008
|
+
if (schema.contains) {
|
|
2009
|
+
paths.push(basePath || "/");
|
|
2010
|
+
paths.push(...extractReferencedPaths(schema.contains, basePath, depth + 1));
|
|
2011
|
+
}
|
|
2012
|
+
return [...new Set(paths)];
|
|
1908
2013
|
}
|
|
1909
2014
|
|
|
1910
2015
|
// src/render.ts
|
|
@@ -1937,90 +2042,13 @@ var SchemaRuntime = class {
|
|
|
1937
2042
|
* const runtime = new SchemaRuntime(validator, schema, { name: "Alice" });
|
|
1938
2043
|
*/
|
|
1939
2044
|
constructor(validator, schema, value) {
|
|
1940
|
-
const normalized = normalizeSchema(schema);
|
|
1941
|
-
this.rootSchema = dereferenceSchemaDeep(normalized, normalized);
|
|
1942
2045
|
this.validator = validator;
|
|
1943
2046
|
this.value = value;
|
|
2047
|
+
const normalized = normalizeSchema(schema);
|
|
2048
|
+
this.rootSchema = dereferenceSchemaDeep(normalized, normalized);
|
|
1944
2049
|
this.root = this.createEmptyNode("", "#");
|
|
1945
2050
|
this.buildNode(this.root, this.rootSchema);
|
|
1946
|
-
|
|
1947
|
-
/**
|
|
1948
|
-
* Collect all dependencies for a node's schema.
|
|
1949
|
-
*
|
|
1950
|
-
* Key insight: We extract paths from condition keywords (if, oneOf, anyOf)
|
|
1951
|
-
* using extractReferencedPaths, but for then/else/allOf keywords, we recursively
|
|
1952
|
-
* call collectDependencies to ensure proper dependency isolation between
|
|
1953
|
-
* parent and child nodes.
|
|
1954
|
-
*/
|
|
1955
|
-
collectDependencies(schema, instanceLocation) {
|
|
1956
|
-
const deps = /* @__PURE__ */ new Set();
|
|
1957
|
-
if (schema.required) {
|
|
1958
|
-
for (const req of schema.required) {
|
|
1959
|
-
deps.add(resolveAbsolutePath(instanceLocation, `/${req}`));
|
|
1960
|
-
}
|
|
1961
|
-
}
|
|
1962
|
-
if (schema.dependentRequired) {
|
|
1963
|
-
for (const [prop, reqs] of Object.entries(schema.dependentRequired)) {
|
|
1964
|
-
deps.add(resolveAbsolutePath(instanceLocation, `/${prop}`));
|
|
1965
|
-
for (const req of reqs) {
|
|
1966
|
-
deps.add(resolveAbsolutePath(instanceLocation, `/${req}`));
|
|
1967
|
-
}
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
if (schema.dependentSchemas) {
|
|
1971
|
-
for (const [prop, subSchema] of Object.entries(schema.dependentSchemas)) {
|
|
1972
|
-
deps.add(resolveAbsolutePath(instanceLocation, `/${prop}`));
|
|
1973
|
-
const subDeps = this.collectDependencies(subSchema, instanceLocation);
|
|
1974
|
-
subDeps.forEach((d) => deps.add(d));
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
if (schema.if) {
|
|
1978
|
-
const relativePaths = extractReferencedPaths(schema.if, "");
|
|
1979
|
-
for (const relPath of relativePaths) {
|
|
1980
|
-
deps.add(resolveAbsolutePath(instanceLocation, relPath));
|
|
1981
|
-
}
|
|
1982
|
-
if (schema.then) {
|
|
1983
|
-
const thenDeps = this.collectDependencies(
|
|
1984
|
-
schema.then,
|
|
1985
|
-
instanceLocation
|
|
1986
|
-
);
|
|
1987
|
-
thenDeps.forEach((d) => deps.add(d));
|
|
1988
|
-
}
|
|
1989
|
-
if (schema.else) {
|
|
1990
|
-
const elseDeps = this.collectDependencies(
|
|
1991
|
-
schema.else,
|
|
1992
|
-
instanceLocation
|
|
1993
|
-
);
|
|
1994
|
-
elseDeps.forEach((d) => deps.add(d));
|
|
1995
|
-
}
|
|
1996
|
-
}
|
|
1997
|
-
if (schema.oneOf) {
|
|
1998
|
-
for (const subSchema of schema.oneOf) {
|
|
1999
|
-
const relativePaths = extractReferencedPaths(subSchema, "");
|
|
2000
|
-
for (const relPath of relativePaths) {
|
|
2001
|
-
deps.add(resolveAbsolutePath(instanceLocation, relPath));
|
|
2002
|
-
}
|
|
2003
|
-
const subDeps = this.collectDependencies(subSchema, instanceLocation);
|
|
2004
|
-
subDeps.forEach((d) => deps.add(d));
|
|
2005
|
-
}
|
|
2006
|
-
}
|
|
2007
|
-
if (schema.anyOf) {
|
|
2008
|
-
for (const subSchema of schema.anyOf) {
|
|
2009
|
-
const relativePaths = extractReferencedPaths(subSchema, "");
|
|
2010
|
-
for (const relPath of relativePaths) {
|
|
2011
|
-
deps.add(resolveAbsolutePath(instanceLocation, relPath));
|
|
2012
|
-
}
|
|
2013
|
-
const subDeps = this.collectDependencies(subSchema, instanceLocation);
|
|
2014
|
-
subDeps.forEach((d) => deps.add(d));
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
if (schema.allOf) {
|
|
2018
|
-
for (const subSchema of schema.allOf) {
|
|
2019
|
-
const subDeps = this.collectDependencies(subSchema, instanceLocation);
|
|
2020
|
-
subDeps.forEach((d) => deps.add(d));
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
return deps;
|
|
2051
|
+
this.notify({ type: "schema", path: ROOT_PATH });
|
|
2024
2052
|
}
|
|
2025
2053
|
/**
|
|
2026
2054
|
* Register a node as dependent on a path
|
|
@@ -2241,10 +2269,13 @@ var SchemaRuntime = class {
|
|
|
2241
2269
|
const parentSchema = parentNode.schema;
|
|
2242
2270
|
if (parentNode.type === "array" && Array.isArray(parentValue)) {
|
|
2243
2271
|
const newIndex = parentValue.length;
|
|
2244
|
-
const { schema: subschema } = getSubSchema(
|
|
2272
|
+
const { schema: subschema, keywordLocationToken } = getSubSchema(
|
|
2245
2273
|
parentSchema,
|
|
2246
2274
|
String(newIndex)
|
|
2247
2275
|
);
|
|
2276
|
+
if (!keywordLocationToken) {
|
|
2277
|
+
return false;
|
|
2278
|
+
}
|
|
2248
2279
|
const defaultValue = initialValue !== void 0 ? initialValue : getDefaultValue(subschema);
|
|
2249
2280
|
const itemPath = jsonPointerJoin(normalizedPath, String(newIndex));
|
|
2250
2281
|
return this.setValue(itemPath, defaultValue);
|
|
@@ -2252,8 +2283,11 @@ var SchemaRuntime = class {
|
|
|
2252
2283
|
if (!key) {
|
|
2253
2284
|
return false;
|
|
2254
2285
|
}
|
|
2255
|
-
const { schema: subschema } = getSubSchema(
|
|
2256
|
-
|
|
2286
|
+
const { schema: subschema, keywordLocationToken } = getSubSchema(
|
|
2287
|
+
parentSchema,
|
|
2288
|
+
key
|
|
2289
|
+
);
|
|
2290
|
+
if (!keywordLocationToken) {
|
|
2257
2291
|
return false;
|
|
2258
2292
|
}
|
|
2259
2293
|
const defaultValue = initialValue !== void 0 ? initialValue : getDefaultValue(subschema);
|
|
@@ -2326,56 +2360,69 @@ var SchemaRuntime = class {
|
|
|
2326
2360
|
return this.root;
|
|
2327
2361
|
}
|
|
2328
2362
|
/**
|
|
2329
|
-
*
|
|
2330
|
-
*
|
|
2331
|
-
* @param schema - Optional. If provided, updates node.originalSchema. Otherwise uses existing.
|
|
2363
|
+
* Update node dependencies when schema changes.
|
|
2364
|
+
* Unregisters old dependencies and registers new ones.
|
|
2332
2365
|
*/
|
|
2333
|
-
|
|
2334
|
-
const {
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
this.
|
|
2339
|
-
return;
|
|
2366
|
+
updateNodeDependencies(node, schema) {
|
|
2367
|
+
const { instanceLocation } = node;
|
|
2368
|
+
node.originalSchema = schema;
|
|
2369
|
+
const dependencies = collectDependencies(schema, instanceLocation);
|
|
2370
|
+
for (const depPath of node.dependencies || []) {
|
|
2371
|
+
this.unregisterDependent(depPath, node);
|
|
2340
2372
|
}
|
|
2341
|
-
|
|
2342
|
-
|
|
2373
|
+
node.dependencies = dependencies;
|
|
2374
|
+
for (const depPath of dependencies) {
|
|
2375
|
+
this.registerDependent(depPath, node);
|
|
2343
2376
|
}
|
|
2344
|
-
|
|
2345
|
-
|
|
2377
|
+
}
|
|
2378
|
+
/**
|
|
2379
|
+
* Apply default values when effective schema changes.
|
|
2380
|
+
* This handles cases like if-then-else where new properties with defaults
|
|
2381
|
+
* may appear when conditions change.
|
|
2382
|
+
*
|
|
2383
|
+
* @param instanceLocation - The path to the node
|
|
2384
|
+
* @param newSchema - The new effective schema
|
|
2385
|
+
* @param type - The schema type
|
|
2386
|
+
*/
|
|
2387
|
+
applySchemaDefaults(instanceLocation, newSchema, type) {
|
|
2388
|
+
const value = this.getValue(instanceLocation);
|
|
2389
|
+
if (type === "object" && newSchema.properties) {
|
|
2390
|
+
const obj = value && typeof value === "object" ? value : null;
|
|
2391
|
+
if (!obj) return;
|
|
2392
|
+
for (const [key, subschema] of Object.entries(newSchema.properties)) {
|
|
2393
|
+
const hasValue = obj[key] !== void 0;
|
|
2394
|
+
if (!hasValue) {
|
|
2395
|
+
const defaultValue = getDefaultValue(subschema);
|
|
2396
|
+
if (defaultValue !== void 0) {
|
|
2397
|
+
const propertyPath = jsonPointerJoin(instanceLocation, key);
|
|
2398
|
+
setJsonPointer(this.value, propertyPath, defaultValue);
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2346
2402
|
return;
|
|
2347
2403
|
}
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
}
|
|
2359
|
-
node.dependencies = dependencies;
|
|
2360
|
-
if (!options.skipDependencyRegistration) {
|
|
2361
|
-
for (const depPath of dependencies) {
|
|
2362
|
-
this.registerDependent(depPath, node);
|
|
2404
|
+
if (type === "array" && newSchema.prefixItems) {
|
|
2405
|
+
const arr = Array.isArray(value) ? value : null;
|
|
2406
|
+
if (!arr) return;
|
|
2407
|
+
for (let i = 0; i < newSchema.prefixItems.length; i++) {
|
|
2408
|
+
if (arr[i] === void 0) {
|
|
2409
|
+
const defaultValue = getDefaultValue(newSchema.prefixItems[i]);
|
|
2410
|
+
if (defaultValue !== void 0) {
|
|
2411
|
+
const itemPath = jsonPointerJoin(instanceLocation, String(i));
|
|
2412
|
+
setJsonPointer(this.value, itemPath, defaultValue);
|
|
2413
|
+
}
|
|
2363
2414
|
}
|
|
2364
2415
|
}
|
|
2365
2416
|
}
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
const
|
|
2374
|
-
const
|
|
2375
|
-
node.schema = effectiveSchema;
|
|
2376
|
-
node.type = type;
|
|
2377
|
-
node.error = error;
|
|
2378
|
-
node.version++;
|
|
2417
|
+
}
|
|
2418
|
+
/**
|
|
2419
|
+
* Build children for object and array nodes.
|
|
2420
|
+
* Reuses existing child nodes where possible.
|
|
2421
|
+
*/
|
|
2422
|
+
buildNodeChildren(node, value, options) {
|
|
2423
|
+
const { keywordLocation, instanceLocation } = node;
|
|
2424
|
+
const effectiveSchema = node.schema;
|
|
2425
|
+
const type = node.type;
|
|
2379
2426
|
const oldChildrenMap = /* @__PURE__ */ new Map();
|
|
2380
2427
|
if (node.children) {
|
|
2381
2428
|
for (const child of node.children) {
|
|
@@ -2482,22 +2529,64 @@ var SchemaRuntime = class {
|
|
|
2482
2529
|
this.unregisterNodeDependencies(oldChild);
|
|
2483
2530
|
}
|
|
2484
2531
|
node.children = newChildren;
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
const
|
|
2494
|
-
if (
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2532
|
+
}
|
|
2533
|
+
/**
|
|
2534
|
+
* Build/update a FieldNode in place.
|
|
2535
|
+
* Updates the node's schema, type, error, and children based on the current value.
|
|
2536
|
+
* @param schema - Optional. If provided, updates node.originalSchema. Otherwise uses existing.
|
|
2537
|
+
*/
|
|
2538
|
+
buildNode(node, schema, options = {}) {
|
|
2539
|
+
const { keywordLocation, instanceLocation } = node;
|
|
2540
|
+
const value = this.getValue(instanceLocation);
|
|
2541
|
+
if (this.updatingNodes.has(instanceLocation)) {
|
|
2542
|
+
return;
|
|
2543
|
+
}
|
|
2544
|
+
const updatedNodes = options.updatedNodes || /* @__PURE__ */ new Set();
|
|
2545
|
+
if (updatedNodes.has(instanceLocation)) {
|
|
2546
|
+
return;
|
|
2547
|
+
}
|
|
2548
|
+
this.updatingNodes.add(instanceLocation);
|
|
2549
|
+
try {
|
|
2550
|
+
const schemaChanged = schema !== void 0 && !deepEqual(schema, node.originalSchema);
|
|
2551
|
+
if (schemaChanged) {
|
|
2552
|
+
this.updateNodeDependencies(node, schema);
|
|
2553
|
+
}
|
|
2554
|
+
const { type, effectiveSchema, error } = resolveEffectiveSchema(
|
|
2555
|
+
this.validator,
|
|
2556
|
+
node.originalSchema,
|
|
2557
|
+
value,
|
|
2558
|
+
keywordLocation,
|
|
2559
|
+
instanceLocation
|
|
2560
|
+
);
|
|
2561
|
+
const effectiveSchemaChanged = !deepEqual(effectiveSchema, node.schema) || type !== node.type;
|
|
2562
|
+
const errorChanged = !deepEqual(error, node.error);
|
|
2563
|
+
if (effectiveSchemaChanged) {
|
|
2564
|
+
this.applySchemaDefaults(instanceLocation, effectiveSchema, type);
|
|
2565
|
+
}
|
|
2566
|
+
node.schema = effectiveSchema;
|
|
2567
|
+
node.type = type;
|
|
2568
|
+
node.error = error;
|
|
2569
|
+
node.version++;
|
|
2570
|
+
const currentValue = this.getValue(instanceLocation);
|
|
2571
|
+
this.buildNodeChildren(node, currentValue, { ...options, updatedNodes });
|
|
2572
|
+
if (effectiveSchemaChanged) {
|
|
2573
|
+
this.notify({ type: "schema", path: instanceLocation });
|
|
2574
|
+
}
|
|
2575
|
+
if (errorChanged) {
|
|
2576
|
+
this.notify({ type: "error", path: instanceLocation });
|
|
2577
|
+
}
|
|
2578
|
+
updatedNodes.add(instanceLocation);
|
|
2579
|
+
const dependentNodes = this.dependentsMap.get(instanceLocation);
|
|
2580
|
+
if (dependentNodes) {
|
|
2581
|
+
for (const dependentNode of dependentNodes) {
|
|
2582
|
+
this.buildNode(dependentNode, void 0, {
|
|
2583
|
+
...options,
|
|
2584
|
+
updatedNodes
|
|
2585
|
+
});
|
|
2586
|
+
}
|
|
2500
2587
|
}
|
|
2588
|
+
} finally {
|
|
2589
|
+
this.updatingNodes.delete(instanceLocation);
|
|
2501
2590
|
}
|
|
2502
2591
|
}
|
|
2503
2592
|
};
|
|
@@ -2507,11 +2596,14 @@ exports.MESSAGES = MESSAGES;
|
|
|
2507
2596
|
exports.SchemaRuntime = SchemaRuntime;
|
|
2508
2597
|
exports.StringFormatValidator = StringFormatValidator;
|
|
2509
2598
|
exports.Validator = Validator;
|
|
2599
|
+
exports.collectDependencies = collectDependencies;
|
|
2510
2600
|
exports.deepEqual = deepEqual;
|
|
2511
2601
|
exports.defaultErrorFormatter = defaultErrorFormatter;
|
|
2512
2602
|
exports.detectSchemaDraft = detectSchemaDraft;
|
|
2513
2603
|
exports.detectSchemaType = detectSchemaType;
|
|
2604
|
+
exports.extractReferencedPaths = extractReferencedPaths;
|
|
2514
2605
|
exports.get = get;
|
|
2606
|
+
exports.getDefaultValue = getDefaultValue;
|
|
2515
2607
|
exports.getJsonPointer = getJsonPointer;
|
|
2516
2608
|
exports.jsonPointerEscape = jsonPointerEscape;
|
|
2517
2609
|
exports.jsonPointerJoin = jsonPointerJoin;
|