@schema-ts/core 0.1.4 → 0.1.5
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 +532 -364
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +177 -89
- package/dist/index.d.ts +177 -89
- package/dist/index.js +528 -365
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -146,6 +146,10 @@ function setJsonPointer(obj, jsonPointer, value) {
|
|
|
146
146
|
}
|
|
147
147
|
return true;
|
|
148
148
|
}
|
|
149
|
+
function getJsonPointerParent(path) {
|
|
150
|
+
const lastSlash = path.lastIndexOf("/");
|
|
151
|
+
return lastSlash <= 0 ? "" : path.substring(0, lastSlash);
|
|
152
|
+
}
|
|
149
153
|
function get(obj, path) {
|
|
150
154
|
let current = obj;
|
|
151
155
|
for (const segment of path) {
|
|
@@ -465,6 +469,11 @@ function detectSchemaDraft(schema) {
|
|
|
465
469
|
}
|
|
466
470
|
|
|
467
471
|
// src/normalize.ts
|
|
472
|
+
var DraftNormalizer = class {
|
|
473
|
+
normalize(schema) {
|
|
474
|
+
return normalizeSchema(schema);
|
|
475
|
+
}
|
|
476
|
+
};
|
|
468
477
|
function normalizeSchema(schema, options = {}) {
|
|
469
478
|
if (typeof schema === "boolean") {
|
|
470
479
|
return schema ? {} : { not: {} };
|
|
@@ -548,8 +557,6 @@ function normalizeDraft07(schema) {
|
|
|
548
557
|
} else {
|
|
549
558
|
delete legacy.items;
|
|
550
559
|
}
|
|
551
|
-
} else if ("additionalItems" in legacy) {
|
|
552
|
-
delete legacy.additionalItems;
|
|
553
560
|
}
|
|
554
561
|
if ("dependencies" in legacy) {
|
|
555
562
|
const deps = legacy.dependencies;
|
|
@@ -625,18 +632,16 @@ function normalizeNestedSchemas(schema, options) {
|
|
|
625
632
|
}
|
|
626
633
|
if (schema.properties) {
|
|
627
634
|
schema.properties = Object.fromEntries(
|
|
628
|
-
Object.entries(schema.properties).
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
])
|
|
635
|
+
Object.entries(schema.properties).filter(
|
|
636
|
+
([_, subSchema]) => subSchema !== null && subSchema !== void 0
|
|
637
|
+
).map(([key, subSchema]) => [key, normalizeSchema(subSchema, options)])
|
|
632
638
|
);
|
|
633
639
|
}
|
|
634
640
|
if (schema.patternProperties) {
|
|
635
641
|
schema.patternProperties = Object.fromEntries(
|
|
636
|
-
Object.entries(schema.patternProperties).
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
])
|
|
642
|
+
Object.entries(schema.patternProperties).filter(
|
|
643
|
+
([_, subSchema]) => subSchema !== null && subSchema !== void 0
|
|
644
|
+
).map(([key, subSchema]) => [key, normalizeSchema(subSchema, options)])
|
|
640
645
|
);
|
|
641
646
|
}
|
|
642
647
|
if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
|
|
@@ -679,10 +684,9 @@ function normalizeNestedSchemas(schema, options) {
|
|
|
679
684
|
}
|
|
680
685
|
if (schema.dependentSchemas) {
|
|
681
686
|
schema.dependentSchemas = Object.fromEntries(
|
|
682
|
-
Object.entries(schema.dependentSchemas).
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
])
|
|
687
|
+
Object.entries(schema.dependentSchemas).filter(
|
|
688
|
+
([_, subSchema]) => subSchema !== null && subSchema !== void 0
|
|
689
|
+
).map(([key, subSchema]) => [key, normalizeSchema(subSchema, options)])
|
|
686
690
|
);
|
|
687
691
|
}
|
|
688
692
|
if (schema.unevaluatedItems) {
|
|
@@ -701,6 +705,120 @@ function normalizeNestedSchemas(schema, options) {
|
|
|
701
705
|
schema.contentSchema = normalizeSchema(schema.contentSchema, options);
|
|
702
706
|
}
|
|
703
707
|
}
|
|
708
|
+
var BetterNormalizer = class {
|
|
709
|
+
/**
|
|
710
|
+
* Performs the normalization process:
|
|
711
|
+
* 1. Base draft normalization (DraftNormalizer)
|
|
712
|
+
* 2. Enhanced default value completion (Better logic)
|
|
713
|
+
*/
|
|
714
|
+
normalize(schema) {
|
|
715
|
+
const normalized = normalizeSchema(schema);
|
|
716
|
+
this.defaultSchema(normalized);
|
|
717
|
+
return normalized;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Recursively processes all sub-nodes of the schema, applying default rules.
|
|
721
|
+
*/
|
|
722
|
+
default(schema, forceRequired = false) {
|
|
723
|
+
this.defaultSchema(schema.if, true);
|
|
724
|
+
this.defaultSchema(schema.then);
|
|
725
|
+
this.defaultSchema(schema.else);
|
|
726
|
+
schema.anyOf?.forEach((s) => this.defaultSchema(s));
|
|
727
|
+
schema.oneOf?.forEach((s) => this.defaultSchema(s));
|
|
728
|
+
schema.allOf?.forEach((s) => this.defaultSchema(s));
|
|
729
|
+
this.defaultSchemaMap(schema.properties, forceRequired);
|
|
730
|
+
this.defaultSchemaMap(schema.patternProperties, forceRequired);
|
|
731
|
+
this.defaultSchema(schema.additionalProperties, forceRequired);
|
|
732
|
+
this.defaultSchema(schema.propertyNames);
|
|
733
|
+
this.defaultSchemaMap(schema.dependentSchemas, true);
|
|
734
|
+
this.defaultSchema(schema.items);
|
|
735
|
+
schema.prefixItems?.forEach((s) => this.defaultSchema(s));
|
|
736
|
+
this.defaultSchema(schema.contains);
|
|
737
|
+
this.defaultSchema(schema.unevaluatedItems);
|
|
738
|
+
this.defaultSchema(schema.unevaluatedProperties);
|
|
739
|
+
this.defaultSchema(schema.contentSchema);
|
|
740
|
+
return schema;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Batch processes Record-type sub-schemas.
|
|
744
|
+
*/
|
|
745
|
+
defaultSchemaMap(kvs, forceRequired = false) {
|
|
746
|
+
if (!kvs) {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
Object.entries(kvs).forEach(([_, value]) => {
|
|
750
|
+
this.defaultSchema(value, forceRequired);
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Applies inference and heuristic rules to a single schema object.
|
|
755
|
+
* Includes:
|
|
756
|
+
* - `type` inference based on properties (object/array)
|
|
757
|
+
* - Automatically setting properties with `const`/`default`/`enum` as `required`
|
|
758
|
+
* - Handling `required` fields from OpenAPI `discriminator`
|
|
759
|
+
* - Handling `x-required` and `x-kubernetes-patch-merge-key`
|
|
760
|
+
*/
|
|
761
|
+
defaultSchema(schema, forceRequired = false) {
|
|
762
|
+
if (!schema || typeof schema === "boolean") {
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
if (!schema.type) {
|
|
766
|
+
if (schema.properties || schema.patternProperties || schema.additionalProperties) {
|
|
767
|
+
schema.type = "object";
|
|
768
|
+
} else if (schema.items || schema.prefixItems || schema.additionalItems) {
|
|
769
|
+
schema.type = "array";
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
if (schema.patternProperties && schema.minProperties === void 0) {
|
|
773
|
+
schema.minProperties = 1;
|
|
774
|
+
}
|
|
775
|
+
if (schema.required === void 0) {
|
|
776
|
+
const required = [];
|
|
777
|
+
for (const [key, value] of Object.entries(schema.properties || {})) {
|
|
778
|
+
if (forceRequired || value.const !== void 0 || Array.isArray(value.enum) && value.enum.length > 0) {
|
|
779
|
+
required.push(key);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
if (required.length > 0) {
|
|
783
|
+
schema.required = required;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
const discriminator = toObject(schema.discriminator);
|
|
787
|
+
if (discriminator.propertyName) {
|
|
788
|
+
if (typeof discriminator.propertyName === "string") {
|
|
789
|
+
if (schema.required === void 0) {
|
|
790
|
+
schema.required = [discriminator.propertyName];
|
|
791
|
+
} else if (!schema.required.includes(discriminator.propertyName)) {
|
|
792
|
+
schema.required.push(discriminator.propertyName);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
for (const [key, value] of Object.entries(schema.properties || {})) {
|
|
797
|
+
if (value["x-required"] === true) {
|
|
798
|
+
if (schema.required === void 0) {
|
|
799
|
+
schema.required = [key];
|
|
800
|
+
} else if (!schema.required.includes(key)) {
|
|
801
|
+
schema.required.push(key);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
const mergeKey = schema["x-kubernetes-patch-merge-key"];
|
|
806
|
+
if (typeof mergeKey === "string" && typeof schema.items === "object" && schema.items !== null) {
|
|
807
|
+
const items = schema.items;
|
|
808
|
+
if (!items.required) items.required = [];
|
|
809
|
+
if (!items.required.includes(mergeKey)) {
|
|
810
|
+
items.required.push(mergeKey);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
this.default(schema, forceRequired);
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
function toObject(val) {
|
|
817
|
+
if (typeof val === "object" && val !== null) {
|
|
818
|
+
return val;
|
|
819
|
+
}
|
|
820
|
+
return {};
|
|
821
|
+
}
|
|
704
822
|
|
|
705
823
|
// src/validate.ts
|
|
706
824
|
var Validator = class {
|
|
@@ -1334,14 +1452,15 @@ function validateSchema(schema, value, instancePath = "", schemaPath = "#", fast
|
|
|
1334
1452
|
}
|
|
1335
1453
|
|
|
1336
1454
|
// src/effective.ts
|
|
1337
|
-
function resolveEffectiveSchema(validator, schema, value, keywordLocation, instanceLocation,
|
|
1455
|
+
function resolveEffectiveSchema(validator, schema, value, keywordLocation, instanceLocation, validate = false) {
|
|
1338
1456
|
let effective = schema;
|
|
1339
1457
|
if (effective.if) {
|
|
1340
1458
|
const output = validator.validate(
|
|
1341
1459
|
effective.if,
|
|
1342
1460
|
value,
|
|
1343
1461
|
`${keywordLocation}/if`,
|
|
1344
|
-
instanceLocation
|
|
1462
|
+
instanceLocation,
|
|
1463
|
+
{ fastFail: true }
|
|
1345
1464
|
);
|
|
1346
1465
|
if (output.valid) {
|
|
1347
1466
|
if (effective.then) {
|
|
@@ -1350,9 +1469,14 @@ function resolveEffectiveSchema(validator, schema, value, keywordLocation, insta
|
|
|
1350
1469
|
effective.then,
|
|
1351
1470
|
value,
|
|
1352
1471
|
`${keywordLocation}/then`,
|
|
1353
|
-
instanceLocation
|
|
1472
|
+
instanceLocation,
|
|
1473
|
+
validate
|
|
1474
|
+
);
|
|
1475
|
+
effective = mergeSchema(
|
|
1476
|
+
effective,
|
|
1477
|
+
res.effectiveSchema,
|
|
1478
|
+
`${keywordLocation}/then`
|
|
1354
1479
|
);
|
|
1355
|
-
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1356
1480
|
}
|
|
1357
1481
|
} else {
|
|
1358
1482
|
if (effective.else) {
|
|
@@ -1361,9 +1485,14 @@ function resolveEffectiveSchema(validator, schema, value, keywordLocation, insta
|
|
|
1361
1485
|
effective.else,
|
|
1362
1486
|
value,
|
|
1363
1487
|
`${keywordLocation}/else`,
|
|
1364
|
-
instanceLocation
|
|
1488
|
+
instanceLocation,
|
|
1489
|
+
validate
|
|
1490
|
+
);
|
|
1491
|
+
effective = mergeSchema(
|
|
1492
|
+
effective,
|
|
1493
|
+
res.effectiveSchema,
|
|
1494
|
+
`${keywordLocation}/else`
|
|
1365
1495
|
);
|
|
1366
|
-
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1367
1496
|
}
|
|
1368
1497
|
}
|
|
1369
1498
|
const { if: _, then: __, else: ___, ...rest } = effective;
|
|
@@ -1371,24 +1500,31 @@ function resolveEffectiveSchema(validator, schema, value, keywordLocation, insta
|
|
|
1371
1500
|
}
|
|
1372
1501
|
if (effective.allOf) {
|
|
1373
1502
|
for (const [index, subschema] of effective.allOf.entries()) {
|
|
1503
|
+
const subKeywordLocation = `${keywordLocation}/allOf/${index}`;
|
|
1374
1504
|
const res = resolveEffectiveSchema(
|
|
1375
1505
|
validator,
|
|
1376
1506
|
subschema,
|
|
1377
1507
|
value,
|
|
1378
|
-
|
|
1379
|
-
instanceLocation
|
|
1508
|
+
subKeywordLocation,
|
|
1509
|
+
instanceLocation,
|
|
1510
|
+
validate
|
|
1511
|
+
);
|
|
1512
|
+
effective = mergeSchema(
|
|
1513
|
+
effective,
|
|
1514
|
+
res.effectiveSchema,
|
|
1515
|
+
subKeywordLocation
|
|
1380
1516
|
);
|
|
1381
|
-
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1382
1517
|
}
|
|
1383
1518
|
const { allOf: _, ...rest } = effective;
|
|
1384
1519
|
effective = rest;
|
|
1385
1520
|
}
|
|
1386
1521
|
if (effective.anyOf) {
|
|
1387
1522
|
for (const [index, subschema] of effective.anyOf.entries()) {
|
|
1523
|
+
const subKeywordLocation = `${keywordLocation}/anyOf/${index}`;
|
|
1388
1524
|
const output = validator.validate(
|
|
1389
1525
|
subschema,
|
|
1390
1526
|
value,
|
|
1391
|
-
|
|
1527
|
+
subKeywordLocation,
|
|
1392
1528
|
instanceLocation
|
|
1393
1529
|
);
|
|
1394
1530
|
if (output.valid) {
|
|
@@ -1396,10 +1532,15 @@ function resolveEffectiveSchema(validator, schema, value, keywordLocation, insta
|
|
|
1396
1532
|
validator,
|
|
1397
1533
|
subschema,
|
|
1398
1534
|
value,
|
|
1399
|
-
|
|
1400
|
-
instanceLocation
|
|
1535
|
+
subKeywordLocation,
|
|
1536
|
+
instanceLocation,
|
|
1537
|
+
validate
|
|
1538
|
+
);
|
|
1539
|
+
effective = mergeSchema(
|
|
1540
|
+
effective,
|
|
1541
|
+
res.effectiveSchema,
|
|
1542
|
+
subKeywordLocation
|
|
1401
1543
|
);
|
|
1402
|
-
effective = mergeSchema(effective, res.effectiveSchema);
|
|
1403
1544
|
}
|
|
1404
1545
|
}
|
|
1405
1546
|
const { anyOf: _, ...rest } = effective;
|
|
@@ -1408,6 +1549,7 @@ function resolveEffectiveSchema(validator, schema, value, keywordLocation, insta
|
|
|
1408
1549
|
if (effective.oneOf) {
|
|
1409
1550
|
let validCount = 0;
|
|
1410
1551
|
let lastValidSchema = null;
|
|
1552
|
+
let lastValidIndex = -1;
|
|
1411
1553
|
for (const [index, subschema] of effective.oneOf.entries()) {
|
|
1412
1554
|
const output = validator.validate(
|
|
1413
1555
|
subschema,
|
|
@@ -1418,10 +1560,15 @@ function resolveEffectiveSchema(validator, schema, value, keywordLocation, insta
|
|
|
1418
1560
|
if (output.valid) {
|
|
1419
1561
|
validCount++;
|
|
1420
1562
|
lastValidSchema = subschema;
|
|
1563
|
+
lastValidIndex = index;
|
|
1421
1564
|
}
|
|
1422
1565
|
}
|
|
1423
1566
|
if (validCount === 1 && lastValidSchema) {
|
|
1424
|
-
effective = mergeSchema(
|
|
1567
|
+
effective = mergeSchema(
|
|
1568
|
+
effective,
|
|
1569
|
+
lastValidSchema,
|
|
1570
|
+
`${keywordLocation}/oneOf/${lastValidIndex}`
|
|
1571
|
+
);
|
|
1425
1572
|
}
|
|
1426
1573
|
const { oneOf: _, ...rest } = effective;
|
|
1427
1574
|
effective = rest;
|
|
@@ -1438,7 +1585,7 @@ function resolveEffectiveSchema(validator, schema, value, keywordLocation, insta
|
|
|
1438
1585
|
} else {
|
|
1439
1586
|
type = detectSchemaType(value);
|
|
1440
1587
|
}
|
|
1441
|
-
if (!
|
|
1588
|
+
if (!validate) {
|
|
1442
1589
|
return {
|
|
1443
1590
|
effectiveSchema: effective,
|
|
1444
1591
|
type,
|
|
@@ -1478,25 +1625,42 @@ function mergeSchemaArrays(a, b) {
|
|
|
1478
1625
|
if (b === void 0) return a;
|
|
1479
1626
|
return [...a, ...b];
|
|
1480
1627
|
}
|
|
1481
|
-
function mergeSchemaMap(base, override) {
|
|
1482
|
-
if (base === void 0)
|
|
1628
|
+
function mergeSchemaMap(base, override, overrideOrigin) {
|
|
1629
|
+
if (base === void 0) {
|
|
1630
|
+
if (override === void 0) return void 0;
|
|
1631
|
+
if (overrideOrigin) {
|
|
1632
|
+
const result = {};
|
|
1633
|
+
for (const [key, schema] of Object.entries(override)) {
|
|
1634
|
+
result[key] = {
|
|
1635
|
+
...schema,
|
|
1636
|
+
"x-origin-keyword": `${overrideOrigin}/${key}`
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1639
|
+
return result;
|
|
1640
|
+
}
|
|
1641
|
+
return override;
|
|
1642
|
+
}
|
|
1483
1643
|
if (override === void 0) return base;
|
|
1484
1644
|
const merged = { ...base };
|
|
1485
1645
|
for (const [key, schema] of Object.entries(override)) {
|
|
1646
|
+
const childOrigin = overrideOrigin ? `${overrideOrigin}/${key}` : void 0;
|
|
1486
1647
|
if (merged[key]) {
|
|
1487
|
-
merged[key] = mergeSchema(merged[key], schema);
|
|
1648
|
+
merged[key] = mergeSchema(merged[key], schema, childOrigin);
|
|
1488
1649
|
} else {
|
|
1489
|
-
merged[key] = schema;
|
|
1650
|
+
merged[key] = childOrigin ? { ...schema, "x-origin-keyword": childOrigin } : schema;
|
|
1490
1651
|
}
|
|
1491
1652
|
}
|
|
1492
1653
|
return merged;
|
|
1493
1654
|
}
|
|
1494
|
-
function mergeSchema(base, override) {
|
|
1655
|
+
function mergeSchema(base, override, overrideOrigin) {
|
|
1495
1656
|
if (!override) return base;
|
|
1496
1657
|
const merged = {
|
|
1497
1658
|
...base,
|
|
1498
1659
|
...override
|
|
1499
1660
|
};
|
|
1661
|
+
if (overrideOrigin) {
|
|
1662
|
+
merged["x-origin-keyword"] = overrideOrigin;
|
|
1663
|
+
}
|
|
1500
1664
|
if (base.$defs || override.$defs) {
|
|
1501
1665
|
merged.$defs = {
|
|
1502
1666
|
...base.$defs,
|
|
@@ -1517,23 +1681,31 @@ function mergeSchema(base, override) {
|
|
|
1517
1681
|
...override.dependentRequired
|
|
1518
1682
|
};
|
|
1519
1683
|
}
|
|
1520
|
-
const
|
|
1684
|
+
const propertiesOrigin = overrideOrigin ? `${overrideOrigin}/properties` : void 0;
|
|
1685
|
+
const mergedProperties = mergeSchemaMap(
|
|
1686
|
+
base.properties,
|
|
1687
|
+
override.properties,
|
|
1688
|
+
propertiesOrigin
|
|
1689
|
+
);
|
|
1521
1690
|
if (mergedProperties !== void 0) {
|
|
1522
1691
|
merged.properties = mergedProperties;
|
|
1523
1692
|
}
|
|
1693
|
+
const patternPropertiesOrigin = overrideOrigin ? `${overrideOrigin}/patternProperties` : void 0;
|
|
1524
1694
|
const mergedPatternProperties = mergeSchemaMap(
|
|
1525
1695
|
base.patternProperties,
|
|
1526
|
-
override.patternProperties
|
|
1696
|
+
override.patternProperties,
|
|
1697
|
+
patternPropertiesOrigin
|
|
1527
1698
|
);
|
|
1528
1699
|
if (mergedPatternProperties !== void 0) {
|
|
1529
1700
|
merged.patternProperties = mergedPatternProperties;
|
|
1530
1701
|
}
|
|
1702
|
+
const itemsOrigin = overrideOrigin ? `${overrideOrigin}/items` : void 0;
|
|
1531
1703
|
if (base.items && override.items) {
|
|
1532
|
-
merged.items = mergeSchema(base.items, override.items);
|
|
1704
|
+
merged.items = mergeSchema(base.items, override.items, itemsOrigin);
|
|
1533
1705
|
} else if (base.items) {
|
|
1534
1706
|
merged.items = base.items;
|
|
1535
1707
|
} else if (override.items) {
|
|
1536
|
-
merged.items = override.items;
|
|
1708
|
+
merged.items = itemsOrigin ? { ...override.items, "x-origin-keyword": itemsOrigin } : override.items;
|
|
1537
1709
|
}
|
|
1538
1710
|
if (base.prefixItems || override.prefixItems) {
|
|
1539
1711
|
merged.prefixItems = [];
|
|
@@ -1544,13 +1716,17 @@ function mergeSchema(base, override) {
|
|
|
1544
1716
|
for (let i = 0; i < len; i++) {
|
|
1545
1717
|
const baseSchema = base.prefixItems?.[i];
|
|
1546
1718
|
const overrideSchema = override.prefixItems?.[i];
|
|
1719
|
+
const prefixItemOrigin = overrideOrigin ? `${overrideOrigin}/prefixItems/${i}` : void 0;
|
|
1547
1720
|
if (baseSchema && overrideSchema) {
|
|
1548
|
-
merged.prefixItems.push(
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1721
|
+
merged.prefixItems.push(
|
|
1722
|
+
mergeSchema(baseSchema, overrideSchema, prefixItemOrigin)
|
|
1723
|
+
);
|
|
1724
|
+
} else if (overrideSchema) {
|
|
1725
|
+
merged.prefixItems.push(
|
|
1726
|
+
prefixItemOrigin ? { ...overrideSchema, "x-origin-keyword": prefixItemOrigin } : overrideSchema
|
|
1727
|
+
);
|
|
1728
|
+
} else if (baseSchema) {
|
|
1729
|
+
merged.prefixItems.push(baseSchema);
|
|
1554
1730
|
}
|
|
1555
1731
|
}
|
|
1556
1732
|
}
|
|
@@ -1561,9 +1737,11 @@ function mergeSchema(base, override) {
|
|
|
1561
1737
|
merged[keyword] = mergedArray;
|
|
1562
1738
|
}
|
|
1563
1739
|
}
|
|
1740
|
+
const dependentSchemasOrigin = overrideOrigin ? `${overrideOrigin}/dependentSchemas` : void 0;
|
|
1564
1741
|
const mergedDependentSchemas = mergeSchemaMap(
|
|
1565
1742
|
base.dependentSchemas,
|
|
1566
|
-
override.dependentSchemas
|
|
1743
|
+
override.dependentSchemas,
|
|
1744
|
+
dependentSchemasOrigin
|
|
1567
1745
|
);
|
|
1568
1746
|
if (mergedDependentSchemas !== void 0) {
|
|
1569
1747
|
merged.dependentSchemas = mergedDependentSchemas;
|
|
@@ -1742,7 +1920,8 @@ function getSubSchema(schema, key) {
|
|
|
1742
1920
|
if (schema.properties && schema.properties[key]) {
|
|
1743
1921
|
return {
|
|
1744
1922
|
schema: schema.properties[key],
|
|
1745
|
-
keywordLocationToken: `properties/${key}
|
|
1923
|
+
keywordLocationToken: `properties/${key}`,
|
|
1924
|
+
required: schema.required?.includes(key) || false
|
|
1746
1925
|
};
|
|
1747
1926
|
}
|
|
1748
1927
|
if (schema.patternProperties) {
|
|
@@ -1752,7 +1931,8 @@ function getSubSchema(schema, key) {
|
|
|
1752
1931
|
if (safeRegexTest(pattern, key)) {
|
|
1753
1932
|
return {
|
|
1754
1933
|
schema: subschema,
|
|
1755
|
-
keywordLocationToken: `patternProperties/${pattern}
|
|
1934
|
+
keywordLocationToken: `patternProperties/${pattern}`,
|
|
1935
|
+
required: false
|
|
1756
1936
|
};
|
|
1757
1937
|
}
|
|
1758
1938
|
}
|
|
@@ -1760,7 +1940,8 @@ function getSubSchema(schema, key) {
|
|
|
1760
1940
|
if (schema.additionalProperties !== void 0 && schema.additionalProperties !== false) {
|
|
1761
1941
|
return {
|
|
1762
1942
|
schema: typeof schema.additionalProperties === "object" ? schema.additionalProperties : {},
|
|
1763
|
-
keywordLocationToken: "additionalProperties"
|
|
1943
|
+
keywordLocationToken: "additionalProperties",
|
|
1944
|
+
required: false
|
|
1764
1945
|
};
|
|
1765
1946
|
}
|
|
1766
1947
|
if (schema.items || schema.prefixItems) {
|
|
@@ -1769,102 +1950,124 @@ function getSubSchema(schema, key) {
|
|
|
1769
1950
|
if (schema.prefixItems && index < schema.prefixItems.length) {
|
|
1770
1951
|
return {
|
|
1771
1952
|
schema: schema.prefixItems[index],
|
|
1772
|
-
keywordLocationToken: `prefixItems/${index}
|
|
1953
|
+
keywordLocationToken: `prefixItems/${index}`,
|
|
1954
|
+
required: true
|
|
1955
|
+
// prefixItems are always required
|
|
1773
1956
|
};
|
|
1774
1957
|
}
|
|
1775
1958
|
if (schema.items) {
|
|
1776
1959
|
return {
|
|
1777
1960
|
schema: schema.items,
|
|
1778
|
-
keywordLocationToken: "items"
|
|
1961
|
+
keywordLocationToken: "items",
|
|
1962
|
+
// items beyond prefixItems are not required by default
|
|
1963
|
+
// but usually new item is considered required to hold the place
|
|
1964
|
+
required: true
|
|
1779
1965
|
};
|
|
1780
1966
|
}
|
|
1781
1967
|
}
|
|
1782
1968
|
}
|
|
1783
1969
|
return {
|
|
1784
1970
|
schema: {},
|
|
1785
|
-
keywordLocationToken: ""
|
|
1971
|
+
keywordLocationToken: "",
|
|
1972
|
+
required: false
|
|
1786
1973
|
};
|
|
1787
1974
|
}
|
|
1788
1975
|
|
|
1789
1976
|
// src/default.ts
|
|
1790
|
-
function
|
|
1791
|
-
const
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
if (
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
}
|
|
1807
|
-
if (schema.properties) {
|
|
1808
|
-
for (const [key, subschema] of Object.entries(schema.properties)) {
|
|
1809
|
-
if (obj[key] !== void 0) {
|
|
1810
|
-
obj[key] = getDefaultValue(subschema, { value: obj[key], strategy });
|
|
1811
|
-
} else if (schema.required?.includes(key)) {
|
|
1812
|
-
obj[key] = getDefaultValue(subschema, { strategy });
|
|
1977
|
+
function typeNullable(schema) {
|
|
1978
|
+
const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
|
|
1979
|
+
const nullable = types.includes("null");
|
|
1980
|
+
const type = types.find((t) => t !== "null");
|
|
1981
|
+
return [type, nullable];
|
|
1982
|
+
}
|
|
1983
|
+
function getDefaultValue(schema, required = false) {
|
|
1984
|
+
if (schema.const !== void 0) return schema.const;
|
|
1985
|
+
if (schema.default !== void 0) return schema.default;
|
|
1986
|
+
const [type, nullable] = typeNullable(schema);
|
|
1987
|
+
switch (type) {
|
|
1988
|
+
case "object": {
|
|
1989
|
+
const obj = {};
|
|
1990
|
+
for (const [key, subschema] of Object.entries(schema.properties || {})) {
|
|
1991
|
+
if (schema.required?.includes(key)) {
|
|
1992
|
+
obj[key] = getDefaultValue(subschema, true);
|
|
1813
1993
|
}
|
|
1814
1994
|
}
|
|
1995
|
+
if (Object.keys(obj).length === 0) {
|
|
1996
|
+
return required ? nullable ? null : {} : void 0;
|
|
1997
|
+
}
|
|
1998
|
+
return obj;
|
|
1815
1999
|
}
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
if (value === void 0) {
|
|
1821
|
-
if (strategy === "explicit") return void 0;
|
|
1822
|
-
arr = [];
|
|
1823
|
-
} else if (Array.isArray(value)) {
|
|
1824
|
-
arr = value;
|
|
1825
|
-
} else {
|
|
1826
|
-
return value;
|
|
1827
|
-
}
|
|
1828
|
-
if (schema.prefixItems) {
|
|
1829
|
-
schema.prefixItems.forEach((subschema, index) => {
|
|
1830
|
-
if (index < arr.length) {
|
|
1831
|
-
arr[index] = getDefaultValue(subschema, {
|
|
1832
|
-
value: arr[index],
|
|
1833
|
-
strategy
|
|
1834
|
-
});
|
|
1835
|
-
} else if (value === void 0) {
|
|
1836
|
-
arr.push(getDefaultValue(subschema, { strategy }));
|
|
1837
|
-
}
|
|
2000
|
+
case "array": {
|
|
2001
|
+
const arr = [];
|
|
2002
|
+
schema.prefixItems?.forEach((subschema) => {
|
|
2003
|
+
arr.push(getDefaultValue(subschema, true));
|
|
1838
2004
|
});
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
const startIndex = schema.prefixItems ? schema.prefixItems.length : 0;
|
|
1842
|
-
for (let i = startIndex; i < arr.length; i++) {
|
|
1843
|
-
arr[i] = getDefaultValue(schema.items, { value: arr[i], strategy });
|
|
2005
|
+
if (arr.length === 0) {
|
|
2006
|
+
return required ? nullable ? null : [] : void 0;
|
|
1844
2007
|
}
|
|
2008
|
+
return arr;
|
|
1845
2009
|
}
|
|
1846
|
-
return arr;
|
|
1847
|
-
}
|
|
1848
|
-
if (value !== void 0) {
|
|
1849
|
-
return value;
|
|
1850
|
-
}
|
|
1851
|
-
if (strategy === "explicit") {
|
|
1852
|
-
return void 0;
|
|
1853
|
-
}
|
|
1854
|
-
switch (type) {
|
|
1855
2010
|
case "string":
|
|
1856
|
-
return "";
|
|
2011
|
+
return required ? nullable ? null : "" : void 0;
|
|
1857
2012
|
case "number":
|
|
2013
|
+
return required ? nullable ? null : 0 : void 0;
|
|
1858
2014
|
case "integer":
|
|
1859
|
-
return 0;
|
|
2015
|
+
return required ? nullable ? null : 0 : void 0;
|
|
1860
2016
|
case "boolean":
|
|
1861
|
-
return false;
|
|
2017
|
+
return required ? nullable ? null : false : void 0;
|
|
1862
2018
|
case "null":
|
|
1863
2019
|
return null;
|
|
1864
2020
|
default:
|
|
1865
2021
|
return void 0;
|
|
1866
2022
|
}
|
|
1867
2023
|
}
|
|
2024
|
+
function applyDefaults(type, value, schema, required = false) {
|
|
2025
|
+
if (value === void 0) {
|
|
2026
|
+
if (!required) {
|
|
2027
|
+
return [value, false];
|
|
2028
|
+
}
|
|
2029
|
+
const defaultValue = getDefaultValue(schema, required);
|
|
2030
|
+
return [defaultValue, defaultValue !== void 0];
|
|
2031
|
+
}
|
|
2032
|
+
const [_, nullable] = typeNullable(schema);
|
|
2033
|
+
if (nullable && value === null) {
|
|
2034
|
+
return [null, false];
|
|
2035
|
+
}
|
|
2036
|
+
let changed = false;
|
|
2037
|
+
if (type === "object") {
|
|
2038
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2039
|
+
return [value, false];
|
|
2040
|
+
}
|
|
2041
|
+
const obj = value;
|
|
2042
|
+
for (const [key, subschema] of Object.entries(schema.properties || {})) {
|
|
2043
|
+
if (obj[key] !== void 0) continue;
|
|
2044
|
+
if (schema.required?.includes(key) || subschema.default) {
|
|
2045
|
+
const defaultValue = getDefaultValue(subschema, required);
|
|
2046
|
+
if (defaultValue !== void 0) {
|
|
2047
|
+
obj[key] = defaultValue;
|
|
2048
|
+
changed = true;
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
return [obj, changed];
|
|
2053
|
+
}
|
|
2054
|
+
if (type === "array") {
|
|
2055
|
+
if (!Array.isArray(value)) {
|
|
2056
|
+
return [value, false];
|
|
2057
|
+
}
|
|
2058
|
+
const arr = value;
|
|
2059
|
+
schema.prefixItems?.forEach((subschema, index) => {
|
|
2060
|
+
if (arr[index] !== void 0) return;
|
|
2061
|
+
const defaultValue = getDefaultValue(subschema, true);
|
|
2062
|
+
if (defaultValue !== void 0) {
|
|
2063
|
+
arr[index] = defaultValue;
|
|
2064
|
+
changed = true;
|
|
2065
|
+
}
|
|
2066
|
+
});
|
|
2067
|
+
return [arr, changed];
|
|
2068
|
+
}
|
|
2069
|
+
return [value, false];
|
|
2070
|
+
}
|
|
1868
2071
|
|
|
1869
2072
|
// src/dependency.ts
|
|
1870
2073
|
function collectDependencies(schema, instanceLocation) {
|
|
@@ -2026,12 +2229,8 @@ function extractReferencedPaths(conditionSchema, basePath = "", depth = 0) {
|
|
|
2026
2229
|
}
|
|
2027
2230
|
}
|
|
2028
2231
|
}
|
|
2029
|
-
if (schema.
|
|
2030
|
-
|
|
2031
|
-
const keyPath = basePath ? `${basePath}/${key}` : `/${key}`;
|
|
2032
|
-
paths.push(keyPath);
|
|
2033
|
-
paths.push(...extractReferencedPaths(subSchema, basePath, depth + 1));
|
|
2034
|
-
}
|
|
2232
|
+
if (schema.not) {
|
|
2233
|
+
paths.push(...extractReferencedPaths(schema.not, basePath, depth + 1));
|
|
2035
2234
|
}
|
|
2036
2235
|
if (schema.contains) {
|
|
2037
2236
|
paths.push(basePath || "/");
|
|
@@ -2041,12 +2240,9 @@ function extractReferencedPaths(conditionSchema, basePath = "", depth = 0) {
|
|
|
2041
2240
|
}
|
|
2042
2241
|
|
|
2043
2242
|
// src/render.ts
|
|
2044
|
-
var ROOT_PATH = "";
|
|
2045
|
-
function normalizeRootPath(path) {
|
|
2046
|
-
return path === "#" ? ROOT_PATH : path;
|
|
2047
|
-
}
|
|
2048
2243
|
var SchemaRuntime = class {
|
|
2049
2244
|
validator;
|
|
2245
|
+
normalizer;
|
|
2050
2246
|
watchers = {};
|
|
2051
2247
|
globalWatchers = /* @__PURE__ */ new Set();
|
|
2052
2248
|
// Reverse dependency index: path -> nodes that depend on this path's value
|
|
@@ -2073,17 +2269,30 @@ var SchemaRuntime = class {
|
|
|
2073
2269
|
*/
|
|
2074
2270
|
constructor(validator, schema, value, options = {}) {
|
|
2075
2271
|
this.validator = validator;
|
|
2076
|
-
this.value = value;
|
|
2077
2272
|
this.options = {
|
|
2078
|
-
|
|
2273
|
+
fillDefaults: "auto",
|
|
2079
2274
|
removeEmptyContainers: "auto",
|
|
2080
2275
|
...options
|
|
2081
2276
|
};
|
|
2082
|
-
|
|
2083
|
-
this.
|
|
2277
|
+
this.normalizer = options.schemaNormalizer || new DraftNormalizer();
|
|
2278
|
+
this.value = value;
|
|
2279
|
+
this.rootSchema = this.resolveSchema(schema);
|
|
2280
|
+
this.root = this.createEmptyNode("", "#");
|
|
2281
|
+
this.buildNode(this.root, this.rootSchema);
|
|
2282
|
+
}
|
|
2283
|
+
resolveSchema(schema) {
|
|
2284
|
+
const normalized = this.normalizer.normalize(schema);
|
|
2285
|
+
const dereferenced = dereferenceSchemaDeep(normalized, normalized);
|
|
2286
|
+
return dereferenced;
|
|
2287
|
+
}
|
|
2288
|
+
/**
|
|
2289
|
+
* Update the entire schema.
|
|
2290
|
+
* This triggers a full rebuild of the node tree while preserving the current value.
|
|
2291
|
+
*/
|
|
2292
|
+
setSchema(schema) {
|
|
2293
|
+
this.rootSchema = this.resolveSchema(schema);
|
|
2084
2294
|
this.root = this.createEmptyNode("", "#");
|
|
2085
2295
|
this.buildNode(this.root, this.rootSchema);
|
|
2086
|
-
this.notify({ type: "schema", path: ROOT_PATH });
|
|
2087
2296
|
}
|
|
2088
2297
|
/**
|
|
2089
2298
|
* Register a node as dependent on a path
|
|
@@ -2140,8 +2349,9 @@ var SchemaRuntime = class {
|
|
|
2140
2349
|
originalSchema: {},
|
|
2141
2350
|
canRemove: false,
|
|
2142
2351
|
canAdd: false,
|
|
2143
|
-
|
|
2144
|
-
children: []
|
|
2352
|
+
required: false,
|
|
2353
|
+
children: [],
|
|
2354
|
+
activated: false
|
|
2145
2355
|
};
|
|
2146
2356
|
}
|
|
2147
2357
|
/**
|
|
@@ -2149,13 +2359,12 @@ var SchemaRuntime = class {
|
|
|
2149
2359
|
* Uses findNearestExistingNode to find the target node (or parent if path doesn't exist).
|
|
2150
2360
|
* Only rebuilds the affected subtree, not the entire tree.
|
|
2151
2361
|
*/
|
|
2152
|
-
reconcile(path) {
|
|
2153
|
-
const
|
|
2154
|
-
const targetNode = this.findNearestExistingNode(normalizedPath);
|
|
2362
|
+
reconcile(path, config = {}) {
|
|
2363
|
+
const targetNode = this.findNearestExistingNode(path);
|
|
2155
2364
|
if (!targetNode) {
|
|
2156
2365
|
return;
|
|
2157
2366
|
}
|
|
2158
|
-
this.buildNode(targetNode, targetNode.originalSchema);
|
|
2367
|
+
this.buildNode(targetNode, targetNode.originalSchema, config);
|
|
2159
2368
|
}
|
|
2160
2369
|
/**
|
|
2161
2370
|
* Get the current version number.
|
|
@@ -2182,17 +2391,16 @@ var SchemaRuntime = class {
|
|
|
2182
2391
|
* // Later: unsubscribe();
|
|
2183
2392
|
*/
|
|
2184
2393
|
subscribe(path, cb) {
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
this.watchers[normalizedPath] = /* @__PURE__ */ new Set();
|
|
2394
|
+
if (!this.watchers[path]) {
|
|
2395
|
+
this.watchers[path] = /* @__PURE__ */ new Set();
|
|
2188
2396
|
}
|
|
2189
|
-
this.watchers[
|
|
2397
|
+
this.watchers[path].add(cb);
|
|
2190
2398
|
return () => {
|
|
2191
|
-
const watcherSet = this.watchers[
|
|
2399
|
+
const watcherSet = this.watchers[path];
|
|
2192
2400
|
if (watcherSet) {
|
|
2193
2401
|
watcherSet.delete(cb);
|
|
2194
2402
|
if (watcherSet.size === 0) {
|
|
2195
|
-
delete this.watchers[
|
|
2403
|
+
delete this.watchers[path];
|
|
2196
2404
|
}
|
|
2197
2405
|
}
|
|
2198
2406
|
};
|
|
@@ -2218,8 +2426,7 @@ var SchemaRuntime = class {
|
|
|
2218
2426
|
*/
|
|
2219
2427
|
notify(event) {
|
|
2220
2428
|
this.version++;
|
|
2221
|
-
const
|
|
2222
|
-
const watchers = this.watchers[normalizedPath];
|
|
2429
|
+
const watchers = this.watchers[event.path];
|
|
2223
2430
|
if (watchers) {
|
|
2224
2431
|
for (const cb of watchers) {
|
|
2225
2432
|
try {
|
|
@@ -2237,17 +2444,6 @@ var SchemaRuntime = class {
|
|
|
2237
2444
|
}
|
|
2238
2445
|
}
|
|
2239
2446
|
}
|
|
2240
|
-
/**
|
|
2241
|
-
* Update the entire schema.
|
|
2242
|
-
* This triggers a full rebuild of the node tree while preserving the current value.
|
|
2243
|
-
*/
|
|
2244
|
-
setSchema(schema) {
|
|
2245
|
-
const normalized = normalizeSchema(schema);
|
|
2246
|
-
this.rootSchema = dereferenceSchemaDeep(normalized, normalized);
|
|
2247
|
-
this.root = this.createEmptyNode("", "#");
|
|
2248
|
-
this.buildNode(this.root, this.rootSchema);
|
|
2249
|
-
this.notify({ type: "schema", path: ROOT_PATH });
|
|
2250
|
-
}
|
|
2251
2447
|
/**
|
|
2252
2448
|
* Get the value at a specific path.
|
|
2253
2449
|
*
|
|
@@ -2259,24 +2455,28 @@ var SchemaRuntime = class {
|
|
|
2259
2455
|
* runtime.getValue("/name"); // returns value at /name
|
|
2260
2456
|
*/
|
|
2261
2457
|
getValue(path) {
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2458
|
+
if (path === "" || path === "#") {
|
|
2459
|
+
return this.value;
|
|
2460
|
+
}
|
|
2461
|
+
return getJsonPointer(this.value, path);
|
|
2265
2462
|
}
|
|
2266
2463
|
/**
|
|
2267
2464
|
* Internal helper to set a value at a normalized path.
|
|
2268
2465
|
* Handles both root and non-root paths.
|
|
2269
2466
|
*
|
|
2270
|
-
* @param
|
|
2467
|
+
* @param path - The JSON Pointer path
|
|
2271
2468
|
* @param value - The value to set
|
|
2272
2469
|
* @returns true if successful, false if the path cannot be set
|
|
2273
2470
|
*/
|
|
2274
|
-
|
|
2275
|
-
if (
|
|
2471
|
+
setJsonPointer(path, value) {
|
|
2472
|
+
if (path === "" || path === "#") {
|
|
2276
2473
|
this.value = value;
|
|
2277
2474
|
return true;
|
|
2278
2475
|
}
|
|
2279
|
-
|
|
2476
|
+
if (!this.value) {
|
|
2477
|
+
this.value = {};
|
|
2478
|
+
}
|
|
2479
|
+
return setJsonPointer(this.value, path, value);
|
|
2280
2480
|
}
|
|
2281
2481
|
/**
|
|
2282
2482
|
* Internal method to remove a value at a path.
|
|
@@ -2290,9 +2490,9 @@ var SchemaRuntime = class {
|
|
|
2290
2490
|
if (!success) {
|
|
2291
2491
|
return false;
|
|
2292
2492
|
}
|
|
2293
|
-
const
|
|
2294
|
-
|
|
2295
|
-
|
|
2493
|
+
const reconcilePath = this.cleanupEmptyContainers(
|
|
2494
|
+
getJsonPointerParent(path)
|
|
2495
|
+
);
|
|
2296
2496
|
this.reconcile(reconcilePath);
|
|
2297
2497
|
this.notify({ type: "value", path: reconcilePath });
|
|
2298
2498
|
return true;
|
|
@@ -2305,37 +2505,29 @@ var SchemaRuntime = class {
|
|
|
2305
2505
|
* @returns true if successful, false if the path cannot be removed
|
|
2306
2506
|
*/
|
|
2307
2507
|
removeValue(path) {
|
|
2308
|
-
|
|
2309
|
-
if (normalizedPath === ROOT_PATH) {
|
|
2310
|
-
return false;
|
|
2311
|
-
}
|
|
2312
|
-
const node = this.findNode(normalizedPath);
|
|
2313
|
-
if (!node || !node.canRemove) {
|
|
2314
|
-
return false;
|
|
2315
|
-
}
|
|
2316
|
-
return this.removeValueInternal(normalizedPath);
|
|
2508
|
+
return this.removeValueInternal(path);
|
|
2317
2509
|
}
|
|
2318
2510
|
/**
|
|
2319
2511
|
* Clean up empty parent containers after element removal.
|
|
2320
2512
|
* Recursively removes empty arrays/objects based on removeEmptyContainers option.
|
|
2321
2513
|
* @param path - The path to check for empty container
|
|
2322
|
-
* @returns The topmost parent path
|
|
2514
|
+
* @returns The topmost parent path changed
|
|
2323
2515
|
*/
|
|
2324
2516
|
cleanupEmptyContainers(path) {
|
|
2325
2517
|
const strategy = this.options.removeEmptyContainers;
|
|
2326
|
-
if (strategy === "never"
|
|
2327
|
-
return
|
|
2518
|
+
if (strategy === "never") {
|
|
2519
|
+
return "";
|
|
2328
2520
|
}
|
|
2329
|
-
const node = this.
|
|
2521
|
+
const node = this.getNode(path);
|
|
2330
2522
|
if (!node) {
|
|
2331
2523
|
return path;
|
|
2332
2524
|
}
|
|
2333
2525
|
const value = this.getValue(path);
|
|
2334
|
-
const isEmpty =
|
|
2526
|
+
const isEmpty = value === null || typeof value === "object" && Object.keys(value).length === 0;
|
|
2335
2527
|
if (!isEmpty) {
|
|
2336
2528
|
return path;
|
|
2337
2529
|
}
|
|
2338
|
-
const shouldRemove = strategy === "
|
|
2530
|
+
const shouldRemove = strategy === "auto" && !node.required;
|
|
2339
2531
|
if (!shouldRemove) {
|
|
2340
2532
|
return path;
|
|
2341
2533
|
}
|
|
@@ -2343,24 +2535,70 @@ var SchemaRuntime = class {
|
|
|
2343
2535
|
if (!success) {
|
|
2344
2536
|
return path;
|
|
2345
2537
|
}
|
|
2346
|
-
|
|
2347
|
-
const parentPath = lastSlash <= 0 ? ROOT_PATH : path.substring(0, lastSlash);
|
|
2348
|
-
return this.cleanupEmptyContainers(parentPath);
|
|
2538
|
+
return this.cleanupEmptyContainers(getJsonPointerParent(path));
|
|
2349
2539
|
}
|
|
2350
2540
|
/**
|
|
2351
2541
|
* Get default value for a schema, respecting autoFillDefaults option.
|
|
2352
2542
|
* Falls back to 'always' strategy if configured strategy returns undefined.
|
|
2543
|
+
* If still undefined (e.g., schema has no type), falls back to null as a valid JSON value.
|
|
2353
2544
|
*/
|
|
2354
|
-
|
|
2355
|
-
const strategy = this.options.
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
defaultValue = getDefaultValue(schema, { strategy });
|
|
2545
|
+
newDefaultValue(schema, required) {
|
|
2546
|
+
const strategy = this.options.fillDefaults;
|
|
2547
|
+
if (strategy === "never") {
|
|
2548
|
+
return void 0;
|
|
2359
2549
|
}
|
|
2360
|
-
|
|
2361
|
-
|
|
2550
|
+
return getDefaultValue(schema, required);
|
|
2551
|
+
}
|
|
2552
|
+
addObjectProperty(parent, parentValue, propertyName, propertyValue) {
|
|
2553
|
+
if (!propertyName) {
|
|
2554
|
+
return false;
|
|
2555
|
+
}
|
|
2556
|
+
if (parentValue === void 0 || parentValue === null) {
|
|
2557
|
+
parentValue = {};
|
|
2558
|
+
this.setJsonPointer(parent.instanceLocation, parentValue);
|
|
2559
|
+
}
|
|
2560
|
+
if (typeof parentValue !== "object") {
|
|
2561
|
+
return false;
|
|
2562
|
+
}
|
|
2563
|
+
const { schema, keywordLocationToken, required } = getSubSchema(
|
|
2564
|
+
parent.schema,
|
|
2565
|
+
propertyName
|
|
2566
|
+
);
|
|
2567
|
+
if (!keywordLocationToken) {
|
|
2568
|
+
return false;
|
|
2362
2569
|
}
|
|
2363
|
-
|
|
2570
|
+
const defaultValue = propertyValue !== void 0 ? propertyValue : this.newDefaultValue(schema, required);
|
|
2571
|
+
const propertyPath = jsonPointerJoin(parent.instanceLocation, propertyName);
|
|
2572
|
+
const success = setJsonPointer(this.value, propertyPath, defaultValue);
|
|
2573
|
+
if (!success) return false;
|
|
2574
|
+
this.reconcile(parent.instanceLocation);
|
|
2575
|
+
this.notify({ type: "value", path: parent.instanceLocation });
|
|
2576
|
+
return true;
|
|
2577
|
+
}
|
|
2578
|
+
addArrayItem(parent, parentValue, initialValue) {
|
|
2579
|
+
if (parentValue === void 0 || parentValue === null) {
|
|
2580
|
+
parentValue = [];
|
|
2581
|
+
this.setJsonPointer(parent.instanceLocation, parentValue);
|
|
2582
|
+
}
|
|
2583
|
+
if (!Array.isArray(parentValue)) {
|
|
2584
|
+
return false;
|
|
2585
|
+
}
|
|
2586
|
+
const newItemIndex = String(parentValue.length);
|
|
2587
|
+
const {
|
|
2588
|
+
schema: subschema,
|
|
2589
|
+
keywordLocationToken,
|
|
2590
|
+
required
|
|
2591
|
+
} = getSubSchema(parent.schema, newItemIndex);
|
|
2592
|
+
if (!keywordLocationToken) {
|
|
2593
|
+
return false;
|
|
2594
|
+
}
|
|
2595
|
+
const defaultValue = initialValue !== void 0 ? initialValue : this.newDefaultValue(subschema, required);
|
|
2596
|
+
const itemPath = jsonPointerJoin(parent.instanceLocation, newItemIndex);
|
|
2597
|
+
const success = setJsonPointer(this.value, itemPath, defaultValue);
|
|
2598
|
+
if (!success) return false;
|
|
2599
|
+
this.reconcile(parent.instanceLocation);
|
|
2600
|
+
this.notify({ type: "value", path: parent.instanceLocation });
|
|
2601
|
+
return true;
|
|
2364
2602
|
}
|
|
2365
2603
|
/**
|
|
2366
2604
|
* Add a new child to an array or object at the specified parent path.
|
|
@@ -2371,63 +2609,19 @@ var SchemaRuntime = class {
|
|
|
2371
2609
|
* @param initialValue - Optional initial value to set. If not provided, uses default from schema.
|
|
2372
2610
|
* @returns true if successful, false if cannot add
|
|
2373
2611
|
*/
|
|
2374
|
-
|
|
2375
|
-
const
|
|
2376
|
-
const parentNode = this.findNode(normalizedPath);
|
|
2612
|
+
addChild(parentPath, key, initialValue) {
|
|
2613
|
+
const parentNode = this.getNode(parentPath);
|
|
2377
2614
|
if (!parentNode || !parentNode.canAdd) {
|
|
2378
2615
|
return false;
|
|
2379
2616
|
}
|
|
2380
|
-
|
|
2381
|
-
const parentSchema = parentNode.schema;
|
|
2617
|
+
const parentValue = this.getValue(parentPath);
|
|
2382
2618
|
if (parentNode.type === "array") {
|
|
2383
|
-
|
|
2384
|
-
parentValue = [];
|
|
2385
|
-
this.setValueAtPath(normalizedPath, parentValue);
|
|
2386
|
-
} else {
|
|
2387
|
-
return false;
|
|
2388
|
-
}
|
|
2619
|
+
return this.addArrayItem(parentNode, parentValue, initialValue);
|
|
2389
2620
|
} else if (parentNode.type === "object") {
|
|
2390
|
-
if (parentValue && typeof parentValue === "object") ; else if (parentValue === void 0 || parentValue === null) {
|
|
2391
|
-
parentValue = {};
|
|
2392
|
-
this.setValueAtPath(normalizedPath, parentValue);
|
|
2393
|
-
} else {
|
|
2394
|
-
return false;
|
|
2395
|
-
}
|
|
2396
|
-
}
|
|
2397
|
-
if (parentNode.type === "array" && Array.isArray(parentValue)) {
|
|
2398
|
-
const newIndex = parentValue.length;
|
|
2399
|
-
const { schema: subschema, keywordLocationToken } = getSubSchema(
|
|
2400
|
-
parentSchema,
|
|
2401
|
-
String(newIndex)
|
|
2402
|
-
);
|
|
2403
|
-
if (!keywordLocationToken) {
|
|
2404
|
-
return false;
|
|
2405
|
-
}
|
|
2406
|
-
const defaultValue = initialValue !== void 0 ? initialValue : this.getDefaultValueForAdd(subschema);
|
|
2407
|
-
const itemPath = jsonPointerJoin(normalizedPath, String(newIndex));
|
|
2408
|
-
const success = setJsonPointer(this.value, itemPath, defaultValue);
|
|
2409
|
-
if (!success) return false;
|
|
2410
|
-
this.reconcile(normalizedPath);
|
|
2411
|
-
this.notify({ type: "value", path: normalizedPath });
|
|
2412
|
-
return true;
|
|
2413
|
-
} else if (parentNode.type === "object" && typeof parentValue === "object") {
|
|
2414
2621
|
if (!key) {
|
|
2415
2622
|
return false;
|
|
2416
2623
|
}
|
|
2417
|
-
|
|
2418
|
-
parentSchema,
|
|
2419
|
-
key
|
|
2420
|
-
);
|
|
2421
|
-
if (!keywordLocationToken) {
|
|
2422
|
-
return false;
|
|
2423
|
-
}
|
|
2424
|
-
const defaultValue = initialValue !== void 0 ? initialValue : this.getDefaultValueForAdd(subschema);
|
|
2425
|
-
const propertyPath = jsonPointerJoin(normalizedPath, key);
|
|
2426
|
-
const success = setJsonPointer(this.value, propertyPath, defaultValue);
|
|
2427
|
-
if (!success) return false;
|
|
2428
|
-
this.reconcile(normalizedPath);
|
|
2429
|
-
this.notify({ type: "value", path: normalizedPath });
|
|
2430
|
-
return true;
|
|
2624
|
+
return this.addObjectProperty(parentNode, parentValue, key, initialValue);
|
|
2431
2625
|
}
|
|
2432
2626
|
return false;
|
|
2433
2627
|
}
|
|
@@ -2449,34 +2643,29 @@ var SchemaRuntime = class {
|
|
|
2449
2643
|
* runtime.setValue("/optional", undefined); // remove optional field
|
|
2450
2644
|
*/
|
|
2451
2645
|
setValue(path, value) {
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
const node = this.findNode(normalizedPath);
|
|
2455
|
-
if (node && !node.isRequired) {
|
|
2456
|
-
return this.removeValueInternal(normalizedPath);
|
|
2457
|
-
}
|
|
2646
|
+
if (value === void 0) {
|
|
2647
|
+
return this.removeValueInternal(path);
|
|
2458
2648
|
}
|
|
2459
|
-
const success = this.
|
|
2649
|
+
const success = this.setJsonPointer(path, value);
|
|
2460
2650
|
if (!success) return false;
|
|
2461
|
-
this.reconcile(
|
|
2462
|
-
this.notify({ type: "value", path
|
|
2651
|
+
this.reconcile(path);
|
|
2652
|
+
this.notify({ type: "value", path });
|
|
2463
2653
|
return true;
|
|
2464
2654
|
}
|
|
2465
2655
|
/**
|
|
2466
|
-
*
|
|
2656
|
+
* Get the FieldNode at a specific path.
|
|
2467
2657
|
* Returns the node tree representation that includes schema, type, error, and children.
|
|
2468
2658
|
*
|
|
2469
2659
|
* @param path - The JSON Pointer path (e.g., "/user/name", "" for root)
|
|
2470
2660
|
* @returns The FieldNode at the path, or undefined if not found
|
|
2471
2661
|
*
|
|
2472
2662
|
* @example
|
|
2473
|
-
* const node = runtime.
|
|
2663
|
+
* const node = runtime.getNode("/name");
|
|
2474
2664
|
* console.log(node?.schema, node?.type, node?.error);
|
|
2475
2665
|
*/
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
const segments = parseJsonPointer(normalizedPath);
|
|
2666
|
+
getNode(path) {
|
|
2667
|
+
if (path === "") return this.root;
|
|
2668
|
+
const segments = parseJsonPointer(path);
|
|
2480
2669
|
let current = this.root;
|
|
2481
2670
|
for (const segment of segments) {
|
|
2482
2671
|
if (!current?.children) return void 0;
|
|
@@ -2490,23 +2679,28 @@ var SchemaRuntime = class {
|
|
|
2490
2679
|
return current;
|
|
2491
2680
|
}
|
|
2492
2681
|
findNearestExistingNode(path) {
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
const node = this.findNode(currentPath);
|
|
2682
|
+
let currentPath = path;
|
|
2683
|
+
while (currentPath) {
|
|
2684
|
+
const node = this.getNode(currentPath);
|
|
2497
2685
|
if (node) return node;
|
|
2498
|
-
|
|
2499
|
-
currentPath = lastSlash <= 0 ? ROOT_PATH : currentPath.substring(0, lastSlash);
|
|
2686
|
+
currentPath = getJsonPointerParent(currentPath);
|
|
2500
2687
|
}
|
|
2501
2688
|
return this.root;
|
|
2502
2689
|
}
|
|
2690
|
+
validate(path) {
|
|
2691
|
+
const node = this.getNode(path);
|
|
2692
|
+
if (node) {
|
|
2693
|
+
this.buildNode(node, void 0, { setActivated: true });
|
|
2694
|
+
}
|
|
2695
|
+
this.reconcile(path);
|
|
2696
|
+
this.notify({ type: "value", path });
|
|
2697
|
+
}
|
|
2503
2698
|
/**
|
|
2504
2699
|
* Update node dependencies when schema changes.
|
|
2505
2700
|
* Unregisters old dependencies and registers new ones.
|
|
2506
2701
|
*/
|
|
2507
2702
|
updateNodeDependencies(node, schema) {
|
|
2508
2703
|
const { instanceLocation } = node;
|
|
2509
|
-
node.originalSchema = schema;
|
|
2510
2704
|
const dependencies = collectDependencies(schema, instanceLocation);
|
|
2511
2705
|
for (const depPath of node.dependencies || []) {
|
|
2512
2706
|
this.unregisterDependent(depPath, node);
|
|
@@ -2522,75 +2716,37 @@ var SchemaRuntime = class {
|
|
|
2522
2716
|
* may appear when conditions change.
|
|
2523
2717
|
*
|
|
2524
2718
|
* Container initialization rules:
|
|
2525
|
-
* -
|
|
2719
|
+
* - Required containers will be initialized if it has defaults or required properties
|
|
2526
2720
|
* - Nested containers are initialized only if they are in parent's required array
|
|
2527
2721
|
*
|
|
2528
2722
|
* @param instanceLocation - The path to the node
|
|
2529
2723
|
* @param newSchema - The new effective schema
|
|
2530
2724
|
* @param type - The schema type
|
|
2531
|
-
* @param
|
|
2725
|
+
* @param required - Whether this node is required by its parent
|
|
2532
2726
|
*/
|
|
2533
|
-
applySchemaDefaults(instanceLocation, newSchema, type,
|
|
2534
|
-
const strategy = this.options.
|
|
2727
|
+
applySchemaDefaults(instanceLocation, newSchema, type, required = true) {
|
|
2728
|
+
const strategy = this.options.fillDefaults;
|
|
2535
2729
|
if (strategy === "never") {
|
|
2536
2730
|
return;
|
|
2537
2731
|
}
|
|
2538
|
-
|
|
2539
|
-
const
|
|
2540
|
-
if (
|
|
2541
|
-
|
|
2542
|
-
const hasAnyDefaults = Object.entries(newSchema.properties).some(
|
|
2543
|
-
([key, subschema]) => {
|
|
2544
|
-
const defaultValue = getDefaultValue(subschema, { strategy });
|
|
2545
|
-
if (defaultValue !== void 0) return true;
|
|
2546
|
-
const isChildRequired = requiredSet.has(key);
|
|
2547
|
-
if (isChildRequired && (subschema.type === "object" || subschema.type === "array")) {
|
|
2548
|
-
return true;
|
|
2549
|
-
}
|
|
2550
|
-
return false;
|
|
2551
|
-
}
|
|
2552
|
-
);
|
|
2553
|
-
const shouldInitialize = (value === void 0 || value === null) && hasAnyDefaults && (isRoot || isRequired);
|
|
2554
|
-
if (shouldInitialize) {
|
|
2555
|
-
value = {};
|
|
2556
|
-
this.setValueAtPath(normalizeRootPath(instanceLocation), value);
|
|
2557
|
-
}
|
|
2558
|
-
const obj = value && typeof value === "object" ? value : null;
|
|
2559
|
-
if (!obj) return;
|
|
2560
|
-
for (const [key, subschema] of Object.entries(newSchema.properties)) {
|
|
2561
|
-
const hasValue = obj[key] !== void 0;
|
|
2562
|
-
const isChildRequired = requiredSet.has(key);
|
|
2563
|
-
if (!hasValue) {
|
|
2564
|
-
const defaultValue = getDefaultValue(subschema, { strategy });
|
|
2565
|
-
if (defaultValue !== void 0) {
|
|
2566
|
-
const propertyPath = jsonPointerJoin(instanceLocation, key);
|
|
2567
|
-
setJsonPointer(this.value, propertyPath, defaultValue);
|
|
2568
|
-
} else if (isChildRequired && subschema.type === "object") {
|
|
2569
|
-
const propertyPath = jsonPointerJoin(instanceLocation, key);
|
|
2570
|
-
setJsonPointer(this.value, propertyPath, {});
|
|
2571
|
-
} else if (isChildRequired && subschema.type === "array") {
|
|
2572
|
-
const propertyPath = jsonPointerJoin(instanceLocation, key);
|
|
2573
|
-
setJsonPointer(this.value, propertyPath, []);
|
|
2574
|
-
}
|
|
2575
|
-
}
|
|
2576
|
-
}
|
|
2577
|
-
return;
|
|
2578
|
-
}
|
|
2579
|
-
if (type === "array" && newSchema.prefixItems) {
|
|
2580
|
-
const arr = Array.isArray(value) ? value : null;
|
|
2581
|
-
if (!arr) return;
|
|
2582
|
-
for (let i = 0; i < newSchema.prefixItems.length; i++) {
|
|
2583
|
-
if (arr[i] === void 0) {
|
|
2584
|
-
const itemSchema = newSchema.prefixItems[i];
|
|
2585
|
-
const defaultValue = getDefaultValue(itemSchema, { strategy });
|
|
2586
|
-
if (defaultValue !== void 0) {
|
|
2587
|
-
const itemPath = jsonPointerJoin(instanceLocation, String(i));
|
|
2588
|
-
setJsonPointer(this.value, itemPath, defaultValue);
|
|
2589
|
-
}
|
|
2590
|
-
}
|
|
2591
|
-
}
|
|
2732
|
+
const value = this.getValue(instanceLocation);
|
|
2733
|
+
const [newValue, changed] = applyDefaults(type, value, newSchema, required);
|
|
2734
|
+
if (changed) {
|
|
2735
|
+
this.setJsonPointer(instanceLocation, newValue);
|
|
2592
2736
|
}
|
|
2593
2737
|
}
|
|
2738
|
+
/**
|
|
2739
|
+
* Sort property entries by x-order.
|
|
2740
|
+
* Properties with lower x-order values come first.
|
|
2741
|
+
* Properties without x-order are placed at the end.
|
|
2742
|
+
*/
|
|
2743
|
+
sortPropertiesByOrder(entries) {
|
|
2744
|
+
return entries.sort(([, schemaA], [, schemaB]) => {
|
|
2745
|
+
const orderA = typeof schemaA["x-order"] === "number" ? schemaA["x-order"] : Infinity;
|
|
2746
|
+
const orderB = typeof schemaB["x-order"] === "number" ? schemaB["x-order"] : Infinity;
|
|
2747
|
+
return orderA - orderB;
|
|
2748
|
+
});
|
|
2749
|
+
}
|
|
2594
2750
|
/**
|
|
2595
2751
|
* Build children for object and array nodes.
|
|
2596
2752
|
* Reuses existing child nodes where possible.
|
|
@@ -2599,40 +2755,41 @@ var SchemaRuntime = class {
|
|
|
2599
2755
|
const { keywordLocation, instanceLocation } = node;
|
|
2600
2756
|
const effectiveSchema = node.schema;
|
|
2601
2757
|
const type = node.type;
|
|
2758
|
+
const processedKeys = /* @__PURE__ */ new Set();
|
|
2759
|
+
const newChildren = [];
|
|
2602
2760
|
const oldChildrenMap = /* @__PURE__ */ new Map();
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
oldChildrenMap.set(child.instanceLocation, child);
|
|
2606
|
-
}
|
|
2761
|
+
for (const child of node.children || []) {
|
|
2762
|
+
oldChildrenMap.set(child.instanceLocation, child);
|
|
2607
2763
|
}
|
|
2608
|
-
const newChildren = [];
|
|
2609
2764
|
const processChild = (childKey, childSchema, childkeywordLocation, canRemove = false, isRequired = false) => {
|
|
2610
2765
|
const childinstanceLocation = jsonPointerJoin(instanceLocation, childKey);
|
|
2766
|
+
if (processedKeys.has(childinstanceLocation)) {
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2769
|
+
processedKeys.add(childinstanceLocation);
|
|
2611
2770
|
let childNode = oldChildrenMap.get(childinstanceLocation);
|
|
2612
|
-
if (childNode) {
|
|
2613
|
-
oldChildrenMap.delete(childinstanceLocation);
|
|
2614
|
-
childNode.keywordLocation = childkeywordLocation;
|
|
2615
|
-
} else {
|
|
2771
|
+
if (!childNode) {
|
|
2616
2772
|
childNode = this.createEmptyNode(
|
|
2617
2773
|
childinstanceLocation,
|
|
2618
2774
|
childkeywordLocation
|
|
2619
2775
|
);
|
|
2620
2776
|
}
|
|
2777
|
+
childNode.keywordLocation = childkeywordLocation;
|
|
2778
|
+
childNode.originKeywordLocation = typeof childSchema["x-origin-keyword"] === "string" ? childSchema["x-origin-keyword"] : childkeywordLocation;
|
|
2621
2779
|
childNode.canRemove = canRemove;
|
|
2622
|
-
childNode.
|
|
2623
|
-
this.buildNode(childNode, childSchema, { ...options
|
|
2780
|
+
childNode.required = isRequired;
|
|
2781
|
+
this.buildNode(childNode, childSchema, { ...options });
|
|
2624
2782
|
newChildren.push(childNode);
|
|
2625
2783
|
};
|
|
2626
2784
|
switch (type) {
|
|
2627
2785
|
case "object": {
|
|
2628
2786
|
const valueKeys = value && typeof value === "object" ? Object.keys(value) : [];
|
|
2629
|
-
|
|
2630
|
-
node.canAdd = !!effectiveSchema.additionalProperties;
|
|
2787
|
+
node.canAdd = !!effectiveSchema.additionalProperties || !!effectiveSchema.patternProperties;
|
|
2631
2788
|
if (effectiveSchema.properties) {
|
|
2632
|
-
|
|
2633
|
-
effectiveSchema.properties
|
|
2634
|
-
)
|
|
2635
|
-
|
|
2789
|
+
const propertyEntries = this.sortPropertiesByOrder(
|
|
2790
|
+
Object.entries(effectiveSchema.properties)
|
|
2791
|
+
);
|
|
2792
|
+
for (const [key, subschema] of propertyEntries) {
|
|
2636
2793
|
const isChildRequired = effectiveSchema.required?.includes(key) ?? false;
|
|
2637
2794
|
processChild(
|
|
2638
2795
|
key,
|
|
@@ -2648,8 +2805,7 @@ var SchemaRuntime = class {
|
|
|
2648
2805
|
effectiveSchema.patternProperties
|
|
2649
2806
|
)) {
|
|
2650
2807
|
for (const key of valueKeys) {
|
|
2651
|
-
if (safeRegexTest(pattern, key)
|
|
2652
|
-
processedKeys.add(key);
|
|
2808
|
+
if (safeRegexTest(pattern, key)) {
|
|
2653
2809
|
processChild(
|
|
2654
2810
|
key,
|
|
2655
2811
|
subschema,
|
|
@@ -2665,16 +2821,14 @@ var SchemaRuntime = class {
|
|
|
2665
2821
|
if (effectiveSchema.additionalProperties) {
|
|
2666
2822
|
const subschema = typeof effectiveSchema.additionalProperties === "object" ? effectiveSchema.additionalProperties : {};
|
|
2667
2823
|
for (const key of valueKeys) {
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
);
|
|
2677
|
-
}
|
|
2824
|
+
processChild(
|
|
2825
|
+
key,
|
|
2826
|
+
subschema,
|
|
2827
|
+
`${keywordLocation}/additionalProperties`,
|
|
2828
|
+
true,
|
|
2829
|
+
false
|
|
2830
|
+
// additionalProperties are never required
|
|
2831
|
+
);
|
|
2678
2832
|
}
|
|
2679
2833
|
}
|
|
2680
2834
|
break;
|
|
@@ -2692,7 +2846,7 @@ var SchemaRuntime = class {
|
|
|
2692
2846
|
`${keywordLocation}/prefixItems/${i}`,
|
|
2693
2847
|
false,
|
|
2694
2848
|
true
|
|
2695
|
-
// array items are always considered required
|
|
2849
|
+
// array prefix items are always considered required
|
|
2696
2850
|
);
|
|
2697
2851
|
}
|
|
2698
2852
|
}
|
|
@@ -2712,8 +2866,10 @@ var SchemaRuntime = class {
|
|
|
2712
2866
|
break;
|
|
2713
2867
|
}
|
|
2714
2868
|
}
|
|
2715
|
-
for (const
|
|
2716
|
-
|
|
2869
|
+
for (const [location, child] of oldChildrenMap) {
|
|
2870
|
+
if (!processedKeys.has(location)) {
|
|
2871
|
+
this.unregisterNodeDependencies(child);
|
|
2872
|
+
}
|
|
2717
2873
|
}
|
|
2718
2874
|
node.children = newChildren;
|
|
2719
2875
|
}
|
|
@@ -2726,6 +2882,9 @@ var SchemaRuntime = class {
|
|
|
2726
2882
|
buildNode(node, schema, options = {}) {
|
|
2727
2883
|
const { keywordLocation, instanceLocation } = node;
|
|
2728
2884
|
const value = this.getValue(instanceLocation);
|
|
2885
|
+
if (options.setActivated) {
|
|
2886
|
+
node.activated = true;
|
|
2887
|
+
}
|
|
2729
2888
|
if (this.updatingNodes.has(instanceLocation)) {
|
|
2730
2889
|
return;
|
|
2731
2890
|
}
|
|
@@ -2737,26 +2896,25 @@ var SchemaRuntime = class {
|
|
|
2737
2896
|
try {
|
|
2738
2897
|
const schemaChanged = schema !== void 0 && !deepEqual(schema, node.originalSchema);
|
|
2739
2898
|
if (schemaChanged) {
|
|
2899
|
+
node.originalSchema = schema;
|
|
2740
2900
|
this.updateNodeDependencies(node, schema);
|
|
2741
2901
|
}
|
|
2742
|
-
const isRequired = options.isRequired ?? true;
|
|
2743
2902
|
const { type, effectiveSchema, error } = resolveEffectiveSchema(
|
|
2744
2903
|
this.validator,
|
|
2745
2904
|
node.originalSchema,
|
|
2746
2905
|
value,
|
|
2747
2906
|
keywordLocation,
|
|
2748
2907
|
instanceLocation,
|
|
2749
|
-
|
|
2908
|
+
node.activated
|
|
2750
2909
|
);
|
|
2751
|
-
const
|
|
2752
|
-
const
|
|
2753
|
-
const errorChanged = isInitialBuild || !deepEqual(error, node.error);
|
|
2910
|
+
const effectiveSchemaChanged = !deepEqual(effectiveSchema, node.schema) || type !== node.type;
|
|
2911
|
+
const errorChanged = !deepEqual(error, node.error);
|
|
2754
2912
|
if (effectiveSchemaChanged) {
|
|
2755
2913
|
this.applySchemaDefaults(
|
|
2756
2914
|
instanceLocation,
|
|
2757
2915
|
effectiveSchema,
|
|
2758
2916
|
type,
|
|
2759
|
-
|
|
2917
|
+
node.required
|
|
2760
2918
|
);
|
|
2761
2919
|
}
|
|
2762
2920
|
node.schema = effectiveSchema;
|
|
@@ -2764,34 +2922,42 @@ var SchemaRuntime = class {
|
|
|
2764
2922
|
node.error = error;
|
|
2765
2923
|
node.version++;
|
|
2766
2924
|
const currentValue = this.getValue(instanceLocation);
|
|
2767
|
-
this.buildNodeChildren(node, currentValue, {
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
this.notify({ type: "error", path: instanceLocation });
|
|
2773
|
-
}
|
|
2925
|
+
this.buildNodeChildren(node, currentValue, {
|
|
2926
|
+
setActivated: options.setActivated || void 0,
|
|
2927
|
+
// propagate activation
|
|
2928
|
+
updatedNodes
|
|
2929
|
+
});
|
|
2774
2930
|
updatedNodes.add(instanceLocation);
|
|
2775
2931
|
const dependentNodes = this.dependentsMap.get(instanceLocation);
|
|
2776
2932
|
if (dependentNodes) {
|
|
2777
2933
|
for (const dependentNode of dependentNodes) {
|
|
2778
2934
|
this.buildNode(dependentNode, void 0, {
|
|
2779
|
-
|
|
2935
|
+
setActivated: void 0,
|
|
2936
|
+
// do not change dependent node activation state
|
|
2780
2937
|
updatedNodes
|
|
2781
2938
|
});
|
|
2782
2939
|
}
|
|
2783
2940
|
}
|
|
2941
|
+
if (effectiveSchemaChanged) {
|
|
2942
|
+
this.notify({ type: "schema", path: instanceLocation });
|
|
2943
|
+
}
|
|
2944
|
+
if (errorChanged) {
|
|
2945
|
+
this.notify({ type: "error", path: instanceLocation });
|
|
2946
|
+
}
|
|
2784
2947
|
} finally {
|
|
2785
2948
|
this.updatingNodes.delete(instanceLocation);
|
|
2786
2949
|
}
|
|
2787
2950
|
}
|
|
2788
2951
|
};
|
|
2789
2952
|
|
|
2953
|
+
exports.BetterNormalizer = BetterNormalizer;
|
|
2790
2954
|
exports.DRAFT_URIS = DRAFT_URIS;
|
|
2955
|
+
exports.DraftNormalizer = DraftNormalizer;
|
|
2791
2956
|
exports.MESSAGES = MESSAGES;
|
|
2792
2957
|
exports.SchemaRuntime = SchemaRuntime;
|
|
2793
2958
|
exports.StringFormatValidator = StringFormatValidator;
|
|
2794
2959
|
exports.Validator = Validator;
|
|
2960
|
+
exports.applyDefaults = applyDefaults;
|
|
2795
2961
|
exports.collectDependencies = collectDependencies;
|
|
2796
2962
|
exports.deepEqual = deepEqual;
|
|
2797
2963
|
exports.defaultErrorFormatter = defaultErrorFormatter;
|
|
@@ -2801,6 +2967,7 @@ exports.extractReferencedPaths = extractReferencedPaths;
|
|
|
2801
2967
|
exports.get = get;
|
|
2802
2968
|
exports.getDefaultValue = getDefaultValue;
|
|
2803
2969
|
exports.getJsonPointer = getJsonPointer;
|
|
2970
|
+
exports.getJsonPointerParent = getJsonPointerParent;
|
|
2804
2971
|
exports.jsonPointerEscape = jsonPointerEscape;
|
|
2805
2972
|
exports.jsonPointerJoin = jsonPointerJoin;
|
|
2806
2973
|
exports.jsonPointerUnescape = jsonPointerUnescape;
|
|
@@ -2812,6 +2979,7 @@ exports.resolveAbsolutePath = resolveAbsolutePath;
|
|
|
2812
2979
|
exports.safeRegexTest = safeRegexTest;
|
|
2813
2980
|
exports.setJsonPointer = setJsonPointer;
|
|
2814
2981
|
exports.stringFormatValidator = stringFormatValidator;
|
|
2982
|
+
exports.typeNullable = typeNullable;
|
|
2815
2983
|
exports.validateSchema = validateSchema;
|
|
2816
2984
|
//# sourceMappingURL=index.cjs.map
|
|
2817
2985
|
//# sourceMappingURL=index.cjs.map
|