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