@schema-ts/core 0.1.1 → 0.1.3

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 CHANGED
@@ -1400,7 +1400,6 @@ function resolveEffectiveSchema(validator, schema, value, keywordLocation, insta
1400
1400
  instanceLocation
1401
1401
  );
1402
1402
  effective = mergeSchema(effective, res.effectiveSchema);
1403
- break;
1404
1403
  }
1405
1404
  }
1406
1405
  const { anyOf: _, ...rest } = effective;
@@ -1472,6 +1471,19 @@ function mergeSchemaArrays(a, b) {
1472
1471
  if (b === void 0) return a;
1473
1472
  return [...a, ...b];
1474
1473
  }
1474
+ function mergeSchemaMap(base, override) {
1475
+ if (base === void 0) return override;
1476
+ if (override === void 0) return base;
1477
+ const merged = { ...base };
1478
+ for (const [key, schema] of Object.entries(override)) {
1479
+ if (merged[key]) {
1480
+ merged[key] = mergeSchema(merged[key], schema);
1481
+ } else {
1482
+ merged[key] = schema;
1483
+ }
1484
+ }
1485
+ return merged;
1486
+ }
1475
1487
  function mergeSchema(base, override) {
1476
1488
  if (!override) return base;
1477
1489
  const merged = {
@@ -1498,17 +1510,16 @@ function mergeSchema(base, override) {
1498
1510
  ...override.dependentRequired
1499
1511
  };
1500
1512
  }
1501
- if (base.properties || override.properties) {
1502
- merged.properties = {
1503
- ...base.properties,
1504
- ...override.properties
1505
- };
1513
+ const mergedProperties = mergeSchemaMap(base.properties, override.properties);
1514
+ if (mergedProperties !== void 0) {
1515
+ merged.properties = mergedProperties;
1506
1516
  }
1507
- if (base.patternProperties || override.patternProperties) {
1508
- merged.patternProperties = {
1509
- ...base.patternProperties,
1510
- ...override.patternProperties
1511
- };
1517
+ const mergedPatternProperties = mergeSchemaMap(
1518
+ base.patternProperties,
1519
+ override.patternProperties
1520
+ );
1521
+ if (mergedPatternProperties !== void 0) {
1522
+ merged.patternProperties = mergedPatternProperties;
1512
1523
  }
1513
1524
  if (base.items && override.items) {
1514
1525
  merged.items = mergeSchema(base.items, override.items);
@@ -1543,11 +1554,12 @@ function mergeSchema(base, override) {
1543
1554
  merged[keyword] = mergedArray;
1544
1555
  }
1545
1556
  }
1546
- if (base.dependentSchemas || override.dependentSchemas) {
1547
- merged.dependentSchemas = {
1548
- ...base.dependentSchemas,
1549
- ...override.dependentSchemas
1550
- };
1557
+ const mergedDependentSchemas = mergeSchemaMap(
1558
+ base.dependentSchemas,
1559
+ override.dependentSchemas
1560
+ );
1561
+ if (mergedDependentSchemas !== void 0) {
1562
+ merged.dependentSchemas = mergedDependentSchemas;
1551
1563
  }
1552
1564
  return merged;
1553
1565
  }
@@ -1768,10 +1780,11 @@ function getSubSchema(schema, key) {
1768
1780
  }
1769
1781
 
1770
1782
  // src/default.ts
1771
- function getDefaultValue(schema, value) {
1783
+ function getDefaultValue(schema, value, strategy = "explicit") {
1772
1784
  if (value === void 0) {
1773
1785
  if (schema.const !== void 0) return schema.const;
1774
1786
  if (schema.default !== void 0) return schema.default;
1787
+ if (strategy === "explicit") return void 0;
1775
1788
  }
1776
1789
  const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
1777
1790
  if (type === "object" || !type && schema.properties) {
@@ -1786,9 +1799,9 @@ function getDefaultValue(schema, value) {
1786
1799
  if (schema.properties) {
1787
1800
  for (const [key, subschema] of Object.entries(schema.properties)) {
1788
1801
  if (obj[key] !== void 0) {
1789
- obj[key] = getDefaultValue(subschema, obj[key]);
1802
+ obj[key] = getDefaultValue(subschema, obj[key], strategy);
1790
1803
  } else if (schema.required?.includes(key)) {
1791
- obj[key] = getDefaultValue(subschema);
1804
+ obj[key] = getDefaultValue(subschema, void 0, strategy);
1792
1805
  }
1793
1806
  }
1794
1807
  }
@@ -1806,16 +1819,16 @@ function getDefaultValue(schema, value) {
1806
1819
  if (schema.prefixItems) {
1807
1820
  schema.prefixItems.forEach((subschema, index) => {
1808
1821
  if (index < arr.length) {
1809
- arr[index] = getDefaultValue(subschema, arr[index]);
1822
+ arr[index] = getDefaultValue(subschema, arr[index], strategy);
1810
1823
  } else if (value === void 0) {
1811
- arr.push(getDefaultValue(subschema));
1824
+ arr.push(getDefaultValue(subschema, void 0, strategy));
1812
1825
  }
1813
1826
  });
1814
1827
  }
1815
1828
  if (value !== void 0 && schema.items) {
1816
1829
  const startIndex = schema.prefixItems ? schema.prefixItems.length : 0;
1817
1830
  for (let i = startIndex; i < arr.length; i++) {
1818
- arr[i] = getDefaultValue(schema.items, arr[i]);
1831
+ arr[i] = getDefaultValue(schema.items, arr[i], strategy);
1819
1832
  }
1820
1833
  }
1821
1834
  return arr;
@@ -2029,21 +2042,24 @@ var SchemaRuntime = class {
2029
2042
  value;
2030
2043
  version = 0;
2031
2044
  rootSchema = {};
2045
+ options;
2032
2046
  /**
2033
2047
  * Create a new SchemaRuntime instance.
2034
2048
  *
2035
2049
  * @param validator - The validator instance for schema validation
2036
2050
  * @param schema - The JSON Schema definition (will be normalized and dereferenced)
2037
2051
  * @param value - The initial data value to manage
2052
+ * @param options - Runtime configuration options
2038
2053
  *
2039
2054
  * @example
2040
2055
  * const validator = new Validator();
2041
2056
  * const schema = { type: "object", properties: { name: { type: "string" } } };
2042
2057
  * const runtime = new SchemaRuntime(validator, schema, { name: "Alice" });
2043
2058
  */
2044
- constructor(validator, schema, value) {
2059
+ constructor(validator, schema, value, options = {}) {
2045
2060
  this.validator = validator;
2046
2061
  this.value = value;
2062
+ this.options = { autoFillDefaults: "explicit", ...options };
2047
2063
  const normalized = normalizeSchema(schema);
2048
2064
  this.rootSchema = dereferenceSchemaDeep(normalized, normalized);
2049
2065
  this.root = this.createEmptyNode("", "#");
@@ -2225,6 +2241,21 @@ var SchemaRuntime = class {
2225
2241
  if (normalizedPath === ROOT_PATH) return this.value;
2226
2242
  return getJsonPointer(this.value, normalizedPath);
2227
2243
  }
2244
+ /**
2245
+ * Internal helper to set a value at a normalized path.
2246
+ * Handles both root and non-root paths.
2247
+ *
2248
+ * @param normalizedPath - The normalized JSON Pointer path
2249
+ * @param value - The value to set
2250
+ * @returns true if successful, false if the path cannot be set
2251
+ */
2252
+ setValueAtPath(normalizedPath, value) {
2253
+ if (normalizedPath === ROOT_PATH) {
2254
+ this.value = value;
2255
+ return true;
2256
+ }
2257
+ return setJsonPointer(this.value, normalizedPath, value);
2258
+ }
2228
2259
  /**
2229
2260
  * Remove a node at the specified path.
2230
2261
  * This deletes the value from the data structure (array splice or object delete).
@@ -2265,8 +2296,23 @@ var SchemaRuntime = class {
2265
2296
  if (!parentNode || !parentNode.canAdd) {
2266
2297
  return false;
2267
2298
  }
2268
- const parentValue = this.getValue(normalizedPath);
2299
+ let parentValue = this.getValue(normalizedPath);
2269
2300
  const parentSchema = parentNode.schema;
2301
+ if (parentNode.type === "array") {
2302
+ if (Array.isArray(parentValue)) ; else if (parentValue === void 0 || parentValue === null) {
2303
+ parentValue = [];
2304
+ this.setValueAtPath(normalizedPath, parentValue);
2305
+ } else {
2306
+ return false;
2307
+ }
2308
+ } else if (parentNode.type === "object") {
2309
+ if (parentValue && typeof parentValue === "object") ; else if (parentValue === void 0 || parentValue === null) {
2310
+ parentValue = {};
2311
+ this.setValueAtPath(normalizedPath, parentValue);
2312
+ } else {
2313
+ return false;
2314
+ }
2315
+ }
2270
2316
  if (parentNode.type === "array" && Array.isArray(parentValue)) {
2271
2317
  const newIndex = parentValue.length;
2272
2318
  const { schema: subschema, keywordLocationToken } = getSubSchema(
@@ -2278,8 +2324,12 @@ var SchemaRuntime = class {
2278
2324
  }
2279
2325
  const defaultValue = initialValue !== void 0 ? initialValue : getDefaultValue(subschema);
2280
2326
  const itemPath = jsonPointerJoin(normalizedPath, String(newIndex));
2281
- return this.setValue(itemPath, defaultValue);
2282
- } else if (parentNode.type === "object" && parentValue && typeof parentValue === "object") {
2327
+ const success = setJsonPointer(this.value, itemPath, defaultValue);
2328
+ if (!success) return false;
2329
+ this.reconcile(normalizedPath);
2330
+ this.notify({ type: "value", path: normalizedPath });
2331
+ return true;
2332
+ } else if (parentNode.type === "object" && typeof parentValue === "object") {
2283
2333
  if (!key) {
2284
2334
  return false;
2285
2335
  }
@@ -2292,7 +2342,11 @@ var SchemaRuntime = class {
2292
2342
  }
2293
2343
  const defaultValue = initialValue !== void 0 ? initialValue : getDefaultValue(subschema);
2294
2344
  const propertyPath = jsonPointerJoin(normalizedPath, key);
2295
- return this.setValue(propertyPath, defaultValue);
2345
+ const success = setJsonPointer(this.value, propertyPath, defaultValue);
2346
+ if (!success) return false;
2347
+ this.reconcile(normalizedPath);
2348
+ this.notify({ type: "value", path: normalizedPath });
2349
+ return true;
2296
2350
  }
2297
2351
  return false;
2298
2352
  }
@@ -2311,12 +2365,8 @@ var SchemaRuntime = class {
2311
2365
  */
2312
2366
  setValue(path, value) {
2313
2367
  const normalizedPath = normalizeRootPath(path);
2314
- if (normalizedPath === ROOT_PATH) {
2315
- this.value = value;
2316
- } else {
2317
- const success = setJsonPointer(this.value, normalizedPath, value);
2318
- if (!success) return false;
2319
- }
2368
+ const success = this.setValueAtPath(normalizedPath, value);
2369
+ if (!success) return false;
2320
2370
  this.reconcile(normalizedPath);
2321
2371
  this.notify({ type: "value", path: normalizedPath });
2322
2372
  return true;
@@ -2385,6 +2435,9 @@ var SchemaRuntime = class {
2385
2435
  * @param type - The schema type
2386
2436
  */
2387
2437
  applySchemaDefaults(instanceLocation, newSchema, type) {
2438
+ if (this.options.autoFillDefaults === "never") {
2439
+ return;
2440
+ }
2388
2441
  const value = this.getValue(instanceLocation);
2389
2442
  if (type === "object" && newSchema.properties) {
2390
2443
  const obj = value && typeof value === "object" ? value : null;
@@ -2392,7 +2445,11 @@ var SchemaRuntime = class {
2392
2445
  for (const [key, subschema] of Object.entries(newSchema.properties)) {
2393
2446
  const hasValue = obj[key] !== void 0;
2394
2447
  if (!hasValue) {
2395
- const defaultValue = getDefaultValue(subschema);
2448
+ const defaultValue = getDefaultValue(
2449
+ subschema,
2450
+ void 0,
2451
+ this.options.autoFillDefaults
2452
+ );
2396
2453
  if (defaultValue !== void 0) {
2397
2454
  const propertyPath = jsonPointerJoin(instanceLocation, key);
2398
2455
  setJsonPointer(this.value, propertyPath, defaultValue);
@@ -2406,7 +2463,12 @@ var SchemaRuntime = class {
2406
2463
  if (!arr) return;
2407
2464
  for (let i = 0; i < newSchema.prefixItems.length; i++) {
2408
2465
  if (arr[i] === void 0) {
2409
- const defaultValue = getDefaultValue(newSchema.prefixItems[i]);
2466
+ const itemSchema = newSchema.prefixItems[i];
2467
+ const defaultValue = getDefaultValue(
2468
+ itemSchema,
2469
+ void 0,
2470
+ this.options.autoFillDefaults
2471
+ );
2410
2472
  if (defaultValue !== void 0) {
2411
2473
  const itemPath = jsonPointerJoin(instanceLocation, String(i));
2412
2474
  setJsonPointer(this.value, itemPath, defaultValue);