json-schema-compatibility-checker 1.1.4 → 1.1.6

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/README.md CHANGED
@@ -232,16 +232,80 @@ engine.overlay(node1Output, node2Output);
232
232
  When `check()` is called with `{ data }`, the library uses [AJV](https://ajv.js.org/) (JSON Schema validator) to:
233
233
 
234
234
  1. **Resolve `if/then/else` conditions** — evaluates the `if` schema against the data to determine which branch applies
235
- 2. **Validate data against both resolved schemas** catches data-level violations (wrong format, out of range, etc.)
235
+ 2. **Narrow schemas** using runtime values (e.g. enum materialization)
236
+ 3. **Perform the static subset check** on the resolved/narrowed schemas
237
+ 4. **Validate data against targeted resolved schemas** (opt-in via `validate`) — catches data-level violations (wrong format, out of range, etc.)
238
+ 5. **Validate custom constraints** against data for targeted schemas (opt-in via `validate`)
236
239
 
237
240
  ```ts
241
+ // Resolve conditions + narrowing only (no runtime validation)
238
242
  const result = checker.check(sub, sup, {
239
243
  data: { kind: "email", value: "test@example.com" },
240
244
  });
241
- // result.isSubset — structural compatibility
245
+
246
+ // Full pipeline including AJV + constraint runtime validation on both schemas
247
+ const result = checker.check(sub, sup, {
248
+ data: { kind: "email", value: "test@example.com" },
249
+ validate: true,
250
+ });
251
+ // result.isSubset — structural compatibility + runtime validation
242
252
  // result.errors — includes runtime validation errors prefixed with $sub / $sup
243
253
  ```
244
254
 
255
+ ### Validate targets
256
+
257
+ The `validate` option controls **which schemas** undergo runtime validation:
258
+
259
+ ```ts
260
+ // Validate both sub and sup (equivalent to validate: true)
261
+ checker.check(sub, sup, { data, validate: { sub: true, sup: true } });
262
+
263
+ // Validate only the sup schema (e.g. target input with constraints)
264
+ checker.check(sub, sup, { data, validate: { sup: true } });
265
+
266
+ // Validate only the sub schema
267
+ checker.check(sub, sup, { data, validate: { sub: true } });
268
+ ```
269
+
270
+ ### Partial validation mode
271
+
272
+ When you have **partial data** (e.g. only some properties known at design-time), standard runtime validation fails on missing `required` properties and `additionalProperties` constraints. The `partial` option strips these constraints before AJV validation so that only the properties **present** in data are validated:
273
+
274
+ ```ts
275
+ const sup = {
276
+ type: "object",
277
+ properties: {
278
+ accountId: { type: "string", enum: ["salut", "coucou"] },
279
+ meetingId: { type: "string" },
280
+ extraField: { type: "number" },
281
+ },
282
+ required: ["accountId", "meetingId", "extraField"],
283
+ };
284
+
285
+ // ❌ Without partial: fails on missing meetingId and extraField
286
+ const result = await checker.check(sup, sup, {
287
+ data: { accountId: "salut" },
288
+ validate: { sup: true },
289
+ });
290
+ // errors: meetingId missing, extraField missing
291
+
292
+ // ✅ With partial: validates only accountId (present in data)
293
+ const result = await checker.check(sup, sup, {
294
+ data: { accountId: "salut" },
295
+ validate: { sup: { partial: true } },
296
+ });
297
+ // errors: [] — accountId is valid, missing properties are ignored
298
+
299
+ // ✅ Partial still catches invalid values on present properties
300
+ const result = await checker.check(sup, sup, {
301
+ data: { accountId: "bad_value" },
302
+ validate: { sup: { partial: true } },
303
+ });
304
+ // errors: [{ key: "$sup.accountId", expected: "salut or coucou", received: "bad_value" }]
305
+ ```
306
+
307
+ Partial mode applies recursively to nested objects and works with `oneOf`/`anyOf` branches, `if/then/else` conditions, and array items. Custom constraint validators already handle partial data correctly (they skip properties not present in data), so constraints are evaluated normally regardless of partial mode.
308
+
245
309
  ### Custom `constraints` keyword
246
310
 
247
311
  The library extends JSON Schema with a custom `constraints` keyword for domain-specific validation rules that go beyond what JSON Schema can express (e.g. "is a valid UUID", "belongs to scope", "minimum age"):
@@ -295,7 +359,7 @@ Constraints are handled at three levels:
295
359
  | **[Features Guide](./docs/features-guide.md)** | Complete feature tour: types, `required`, numeric constraints, `enum`/`const`, `anyOf`/`oneOf`, `not`, `format`, `pattern`, `if/then/else` conditions, `allOf`, custom `constraints`... |
296
360
  | **[Utility Functions](./docs/utilities.md)** | `isPatternSubset`, `arePatternsEquivalent`, `isTrivialPattern` |
297
361
  | **[Use Cases](./docs/use-cases.md)** | Node connection, sequential pipeline (overlay), API response validation, discriminated unions, conditional forms |
298
- | **[Exported Types](./docs/types.md)** | `SubsetResult`, `SchemaError`, `ResolvedConditionResult`, `ResolvedSubsetResult`, `CheckRuntimeOptions`, `ConstraintValidator`, `CheckerOptions` |
362
+ | **[Exported Types](./docs/types.md)** | `SubsetResult`, `SchemaError`, `ResolvedConditionResult`, `ResolvedSubsetResult`, `CheckRuntimeOptions`, `ValidateTargets`, `ValidateTargetOptions`, `ConstraintValidator`, `CheckerOptions` |
299
363
  | **[Known Limitations](./docs/limitations.md)** | Cross-keyword constraints, `oneOf` exclusivity, probabilistic patterns, `$ref` not supported |
300
364
  | **[Internal Architecture](./docs/architecture.md)** | Module diagram, verification flow, merge vs overlay, dependencies |
301
365
 
@@ -3,4 +3,4 @@ export { JsonSchemaCompatibilityChecker } from "./json-schema-compatibility-chec
3
3
  export { MergeEngine } from "./merge-engine.js";
4
4
  export { arePatternsEquivalent, isPatternSubset, isTrivialPattern, } from "./pattern-subset.js";
5
5
  export { formatSchemaType } from "./semantic-errors.js";
6
- export type { CheckerOptions, CheckRuntimeOptions, Constraint, Constraints, ConstraintValidationResult, ConstraintValidator, ConstraintValidatorRegistry, ResolvedConditionResult, ResolvedSubsetResult, SchemaError, SubsetResult, } from "./types.js";
6
+ export type { CheckerOptions, CheckRuntimeOptions, Constraint, Constraints, ConstraintValidationResult, ConstraintValidator, ConstraintValidatorRegistry, ResolvedConditionResult, ResolvedSubsetResult, SchemaError, SubsetResult, ValidateTargetOptions, ValidateTargets, } from "./types.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export { resolveConditions } from \"./condition-resolver.ts\";\nexport { JsonSchemaCompatibilityChecker } from \"./json-schema-compatibility-checker.ts\";\nexport { MergeEngine } from \"./merge-engine.ts\";\nexport {\n\tarePatternsEquivalent,\n\tisPatternSubset,\n\tisTrivialPattern,\n} from \"./pattern-subset.ts\";\nexport { formatSchemaType } from \"./semantic-errors.ts\";\nexport type {\n\tCheckerOptions,\n\tCheckRuntimeOptions,\n\tConstraint,\n\tConstraints,\n\tConstraintValidationResult,\n\tConstraintValidator,\n\tConstraintValidatorRegistry,\n\tResolvedConditionResult,\n\tResolvedSubsetResult,\n\tSchemaError,\n\tSubsetResult,\n} from \"./types.ts\";\n"],"names":["JsonSchemaCompatibilityChecker","MergeEngine","arePatternsEquivalent","formatSchemaType","isPatternSubset","isTrivialPattern","resolveConditions"],"mappings":"mPACSA,wCAAAA,gEAA8B,MAC9BC,qBAAAA,0BAAW,MAEnBC,+BAAAA,sCAAqB,MAIbC,0BAAAA,kCAAgB,MAHxBC,yBAAAA,gCAAe,MACfC,0BAAAA,iCAAgB,MANRC,2BAAAA,sCAAiB,uCAAQ,2EACa,uEACnB,oDAKrB,uDAC0B"}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export { resolveConditions } from \"./condition-resolver.ts\";\nexport { JsonSchemaCompatibilityChecker } from \"./json-schema-compatibility-checker.ts\";\nexport { MergeEngine } from \"./merge-engine.ts\";\nexport {\n\tarePatternsEquivalent,\n\tisPatternSubset,\n\tisTrivialPattern,\n} from \"./pattern-subset.ts\";\nexport { formatSchemaType } from \"./semantic-errors.ts\";\nexport type {\n\tCheckerOptions,\n\tCheckRuntimeOptions,\n\tConstraint,\n\tConstraints,\n\tConstraintValidationResult,\n\tConstraintValidator,\n\tConstraintValidatorRegistry,\n\tResolvedConditionResult,\n\tResolvedSubsetResult,\n\tSchemaError,\n\tSubsetResult,\n\tValidateTargetOptions,\n\tValidateTargets,\n} from \"./types.ts\";\n"],"names":["JsonSchemaCompatibilityChecker","MergeEngine","arePatternsEquivalent","formatSchemaType","isPatternSubset","isTrivialPattern","resolveConditions"],"mappings":"mPACSA,wCAAAA,gEAA8B,MAC9BC,qBAAAA,0BAAW,MAEnBC,+BAAAA,sCAAqB,MAIbC,0BAAAA,kCAAgB,MAHxBC,yBAAAA,gCAAe,MACfC,0BAAAA,iCAAgB,MANRC,2BAAAA,sCAAiB,uCAAQ,2EACa,uEACnB,oDAKrB,uDAC0B"}
@@ -5,8 +5,8 @@ import { MergeEngine } from "./merge-engine.js";
5
5
  import { normalize } from "./normalizer.js";
6
6
  import { arePatternsEquivalent, isPatternSubset, isTrivialPattern } from "./pattern-subset.js";
7
7
  import type { BranchResult, BranchType } from "./subset-checker.js";
8
- import type { CheckerOptions, CheckRuntimeOptions, ResolvedConditionResult, ResolvedSubsetResult, SchemaError, SubsetResult } from "./types.js";
9
- export type { SchemaError, SubsetResult, ResolvedConditionResult, ResolvedSubsetResult, CheckRuntimeOptions, BranchType, BranchResult, };
8
+ import type { CheckerOptions, CheckRuntimeOptions, ResolvedConditionResult, ResolvedSubsetResult, SchemaError, SubsetResult, ValidateTargets } from "./types.js";
9
+ export type { SchemaError, SubsetResult, ResolvedConditionResult, ResolvedSubsetResult, CheckRuntimeOptions, ValidateTargets, BranchType, BranchResult, };
10
10
  export { normalize, resolveConditions, formatResult, MergeEngine, isPatternSubset, arePatternsEquivalent, isTrivialPattern, };
11
11
  export declare class JsonSchemaCompatibilityChecker {
12
12
  private readonly constraintValidators;
@@ -31,10 +31,16 @@ export declare class JsonSchemaCompatibilityChecker {
31
31
  * 2. Schemas are narrowed using runtime values (enum materialization)
32
32
  * 3. The static subset check runs on the resolved/narrowed schemas
33
33
  *
34
- * When `validate: true` is set in options, two additional runtime steps
35
- * run **after** the static check passes:
36
- * 4. `data` is validated against both resolved schemas via AJV
37
- * 5. Custom constraints are validated against `data`
34
+ * When `validate` is enabled, additional runtime steps run **after** the
35
+ * static check passes:
36
+ * 4. `data` is validated against the targeted resolved schema(s) via AJV
37
+ * 5. Custom constraints are validated against `data` for the targeted schema(s)
38
+ *
39
+ * `validate` accepts:
40
+ * - `true` — validate against **both** sub and sup
41
+ * - `{ sub: true }` — validate only against the sub schema
42
+ * - `{ sup: true }` — validate only against the sup schema
43
+ * - `{ sub: true, sup: true }` — equivalent to `true`
38
44
  *
39
45
  * @param sub - The source schema (subset candidate)
40
46
  * @param sup - The target schema (expected superset)
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});function _export(target,all){for(var name in all)Object.defineProperty(target,name,{enumerable:true,get:Object.getOwnPropertyDescriptor(all,name).get})}_export(exports,{get JsonSchemaCompatibilityChecker(){return JsonSchemaCompatibilityChecker},get MergeEngine(){return _mergeenginets.MergeEngine},get arePatternsEquivalent(){return _patternsubsetts.arePatternsEquivalent},get formatResult(){return _formatterts.formatResult},get isPatternSubset(){return _patternsubsetts.isPatternSubset},get isTrivialPattern(){return _patternsubsetts.isTrivialPattern},get normalize(){return _normalizerts.normalize},get resolveConditions(){return _conditionresolverts.resolveConditions}});const _conditionresolverts=require("./condition-resolver.js");const _constraintvalidatorts=require("./constraint-validator.js");const _datanarrowingts=require("./data-narrowing.js");const _formatterts=require("./formatter.js");const _mergeenginets=require("./merge-engine.js");const _normalizerts=require("./normalizer.js");const _patternsubsetts=require("./pattern-subset.js");const _runtimevalidatorts=require("./runtime-validator.js");const _subsetcheckerts=require("./subset-checker.js");const _utilsts=require("./utils.js");function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}class JsonSchemaCompatibilityChecker{isSubset(sub,sup){if(sub===sup)return true;if((0,_utilsts.deepEqual)(sub,sup))return true;const nSub=(0,_normalizerts.normalize)(sub);const nSup=(0,_normalizerts.normalize)(sup);if(nSub!==sub&&nSup!==sup&&(0,_utilsts.deepEqual)(nSub,nSup))return true;if(nSub!==nSup&&(0,_utilsts.deepEqual)(nSub,nSup))return true;const{branches:subBranches}=(0,_subsetcheckerts.getBranchesTyped)(nSub);if(subBranches.length>1||subBranches[0]!==nSub){return subBranches.every(branch=>(0,_subsetcheckerts.isAtomicSubsetOf)(branch,nSup,this.engine))}return(0,_subsetcheckerts.isAtomicSubsetOf)(nSub,nSup,this.engine)}check(sub,sup,options){if(options){return this.checkWithOptions(sub,sup,options)}return this.checkInternal(sub,sup)}isEqual(a,b){return this.engine.isEqual((0,_normalizerts.normalize)(a),(0,_normalizerts.normalize)(b))}intersect(a,b){if(a===b||(0,_utilsts.deepEqual)(a,b))return(0,_normalizerts.normalize)(a);const nA=(0,_normalizerts.normalize)(a);const nB=(0,_normalizerts.normalize)(b);if((0,_utilsts.deepEqual)(nA,nB))return nA;const merged=this.engine.merge(nA,nB);if(merged===null)return null;if((0,_utilsts.deepEqual)(merged,nA)||(0,_utilsts.deepEqual)(merged,nB))return merged;return(0,_normalizerts.normalize)(merged)}normalize(def){return(0,_normalizerts.normalize)(def)}formatResult(label,result){return(0,_formatterts.formatResult)(label,result)}resolveConditions(schema,data){return(0,_conditionresolverts.resolveConditions)(schema,data,this.engine)}async checkWithOptions(sub,sup,options){const data=options.data;const shouldValidate=options.validate===true;const dataForConditions=(0,_utilsts.isPlainObj)(data)?data:{};const resolvedSub=(0,_conditionresolverts.resolveConditions)(sub,dataForConditions,this.engine);const resolvedSup=(0,_conditionresolverts.resolveConditions)(sup,dataForConditions,this.engine);const canNarrow=data!==undefined;const canNarrowSub=canNarrow&&(0,_utilsts.isPlainObj)(resolvedSub.resolved);const canNarrowSup=canNarrow&&(0,_utilsts.isPlainObj)(resolvedSup.resolved);const narrowedSubResolved=canNarrowSub?(0,_datanarrowingts.narrowSchemaWithData)(resolvedSub.resolved,data,resolvedSup.resolved):resolvedSub.resolved;const narrowedSupResolved=canNarrowSup?(0,_datanarrowingts.narrowSchemaWithData)(resolvedSup.resolved,data,resolvedSub.resolved):resolvedSup.resolved;const staticResult=this.checkInternal(narrowedSubResolved,narrowedSupResolved);if(!staticResult.isSubset){return{...staticResult,resolvedSub:{...resolvedSub,resolved:narrowedSubResolved},resolvedSup:{...resolvedSup,resolved:narrowedSupResolved}}}if(shouldValidate&&data!==undefined){const runtimeErrors=[];runtimeErrors.push(...this.prefixRuntimeErrors((0,_runtimevalidatorts.getRuntimeValidationErrors)(narrowedSubResolved,data),"$sub"));runtimeErrors.push(...this.prefixRuntimeErrors((0,_runtimevalidatorts.getRuntimeValidationErrors)(narrowedSupResolved,data),"$sup"));runtimeErrors.push(...this.prefixRuntimeErrors(await (0,_constraintvalidatorts.validateSchemaConstraints)(narrowedSubResolved,data,this.constraintValidators),"$sub"));runtimeErrors.push(...this.prefixRuntimeErrors(await (0,_constraintvalidatorts.validateSchemaConstraints)(narrowedSupResolved,data,this.constraintValidators),"$sup"));if(runtimeErrors.length>0){return{isSubset:false,merged:null,errors:runtimeErrors,resolvedSub:{...resolvedSub,resolved:narrowedSubResolved},resolvedSup:{...resolvedSup,resolved:narrowedSupResolved}}}}return{...staticResult,resolvedSub:{...resolvedSub,resolved:narrowedSubResolved},resolvedSup:{...resolvedSup,resolved:narrowedSupResolved}}}prefixRuntimeErrors(errors,rootKey){return errors.map(error=>({...error,key:error.key==="$root"?rootKey:`${rootKey}.${error.key}`}))}checkInternal(sub,sup){if(sub===sup){return{isSubset:true,merged:sub,errors:[]}}if((0,_utilsts.deepEqual)(sub,sup)){return{isSubset:true,merged:sub,errors:[]}}const nSub=(0,_normalizerts.normalize)(sub);const nSup=(0,_normalizerts.normalize)(sup);if((0,_utilsts.deepEqual)(nSub,nSup)){return{isSubset:true,merged:nSub,errors:[]}}const{branches:subBranches,type:subBranchType}=(0,_subsetcheckerts.getBranchesTyped)(nSub);const{branches:supBranches,type:supBranchType}=(0,_subsetcheckerts.getBranchesTyped)(nSup);if(subBranches.length>1||subBranches[0]!==nSub){return(0,_subsetcheckerts.checkBranchedSub)(subBranches,nSup,this.engine,subBranchType)}if(supBranches.length>1||supBranches[0]!==nSup){return(0,_subsetcheckerts.checkBranchedSup)(nSub,supBranches,this.engine,supBranchType)}return(0,_subsetcheckerts.checkAtomic)(nSub,nSup,this.engine)}static clearCache(){(0,_runtimevalidatorts.clearAllValidatorCaches)()}constructor(options){_define_property(this,"constraintValidators",void 0);_define_property(this,"engine",void 0);this.engine=new _mergeenginets.MergeEngine;this.constraintValidators=options?.constraints??{}}}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});function _export(target,all){for(var name in all)Object.defineProperty(target,name,{enumerable:true,get:Object.getOwnPropertyDescriptor(all,name).get})}_export(exports,{get JsonSchemaCompatibilityChecker(){return JsonSchemaCompatibilityChecker},get MergeEngine(){return _mergeenginets.MergeEngine},get arePatternsEquivalent(){return _patternsubsetts.arePatternsEquivalent},get formatResult(){return _formatterts.formatResult},get isPatternSubset(){return _patternsubsetts.isPatternSubset},get isTrivialPattern(){return _patternsubsetts.isTrivialPattern},get normalize(){return _normalizerts.normalize},get resolveConditions(){return _conditionresolverts.resolveConditions}});const _conditionresolverts=require("./condition-resolver.js");const _constraintvalidatorts=require("./constraint-validator.js");const _datanarrowingts=require("./data-narrowing.js");const _formatterts=require("./formatter.js");const _mergeenginets=require("./merge-engine.js");const _normalizerts=require("./normalizer.js");const _patternsubsetts=require("./pattern-subset.js");const _runtimevalidatorts=require("./runtime-validator.js");const _subsetcheckerts=require("./subset-checker.js");const _utilsts=require("./utils.js");const _validatetargetsts=require("./validate-targets.js");function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}class JsonSchemaCompatibilityChecker{isSubset(sub,sup){if(sub===sup)return true;if((0,_utilsts.deepEqual)(sub,sup))return true;const nSub=(0,_normalizerts.normalize)(sub);const nSup=(0,_normalizerts.normalize)(sup);if(nSub!==sub&&nSup!==sup&&(0,_utilsts.deepEqual)(nSub,nSup))return true;if(nSub!==nSup&&(0,_utilsts.deepEqual)(nSub,nSup))return true;const{branches:subBranches}=(0,_subsetcheckerts.getBranchesTyped)(nSub);if(subBranches.length>1||subBranches[0]!==nSub){return subBranches.every(branch=>(0,_subsetcheckerts.isAtomicSubsetOf)(branch,nSup,this.engine))}return(0,_subsetcheckerts.isAtomicSubsetOf)(nSub,nSup,this.engine)}check(sub,sup,options){if(options){return this.checkWithOptions(sub,sup,options)}return this.checkInternal(sub,sup)}isEqual(a,b){return this.engine.isEqual((0,_normalizerts.normalize)(a),(0,_normalizerts.normalize)(b))}intersect(a,b){if(a===b||(0,_utilsts.deepEqual)(a,b))return(0,_normalizerts.normalize)(a);const nA=(0,_normalizerts.normalize)(a);const nB=(0,_normalizerts.normalize)(b);if((0,_utilsts.deepEqual)(nA,nB))return nA;const merged=this.engine.merge(nA,nB);if(merged===null)return null;if((0,_utilsts.deepEqual)(merged,nA)||(0,_utilsts.deepEqual)(merged,nB))return merged;return(0,_normalizerts.normalize)(merged)}normalize(def){return(0,_normalizerts.normalize)(def)}formatResult(label,result){return(0,_formatterts.formatResult)(label,result)}resolveConditions(schema,data){return(0,_conditionresolverts.resolveConditions)(schema,data,this.engine)}async checkWithOptions(sub,sup,options){const data=options.data;const{sub:validateSub,sup:validateSup,partialSub,partialSup}=(0,_validatetargetsts.resolveValidateTargets)(options.validate);const dataForConditions=(0,_utilsts.isPlainObj)(data)?data:{};const resolvedSub=(0,_conditionresolverts.resolveConditions)(sub,dataForConditions,this.engine);const resolvedSup=(0,_conditionresolverts.resolveConditions)(sup,dataForConditions,this.engine);const canNarrow=data!==undefined;const canNarrowSub=canNarrow&&(0,_utilsts.isPlainObj)(resolvedSub.resolved);const canNarrowSup=canNarrow&&(0,_utilsts.isPlainObj)(resolvedSup.resolved);const narrowedSubResolved=canNarrowSub?(0,_datanarrowingts.narrowSchemaWithData)(resolvedSub.resolved,data,resolvedSup.resolved):resolvedSub.resolved;const narrowedSupResolved=canNarrowSup?(0,_datanarrowingts.narrowSchemaWithData)(resolvedSup.resolved,data,resolvedSub.resolved):resolvedSup.resolved;const staticResult=this.checkInternal(narrowedSubResolved,narrowedSupResolved);if(!staticResult.isSubset){return{...staticResult,resolvedSub:{...resolvedSub,resolved:narrowedSubResolved},resolvedSup:{...resolvedSup,resolved:narrowedSupResolved}}}if((validateSub||validateSup)&&data!==undefined){const runtimeErrors=[];if(validateSub){const getErrors=partialSub?_runtimevalidatorts.getPartialRuntimeValidationErrors:_runtimevalidatorts.getRuntimeValidationErrors;runtimeErrors.push(...this.prefixRuntimeErrors(getErrors(narrowedSubResolved,data),"$sub"))}if(validateSup){const getErrors=partialSup?_runtimevalidatorts.getPartialRuntimeValidationErrors:_runtimevalidatorts.getRuntimeValidationErrors;runtimeErrors.push(...this.prefixRuntimeErrors(getErrors(narrowedSupResolved,data),"$sup"))}if(validateSub){runtimeErrors.push(...this.prefixRuntimeErrors(await (0,_constraintvalidatorts.validateSchemaConstraints)(narrowedSubResolved,data,this.constraintValidators),"$sub"))}if(validateSup){runtimeErrors.push(...this.prefixRuntimeErrors(await (0,_constraintvalidatorts.validateSchemaConstraints)(narrowedSupResolved,data,this.constraintValidators),"$sup"))}if(runtimeErrors.length>0){return{isSubset:false,merged:null,errors:runtimeErrors,resolvedSub:{...resolvedSub,resolved:narrowedSubResolved},resolvedSup:{...resolvedSup,resolved:narrowedSupResolved}}}}return{...staticResult,resolvedSub:{...resolvedSub,resolved:narrowedSubResolved},resolvedSup:{...resolvedSup,resolved:narrowedSupResolved}}}prefixRuntimeErrors(errors,rootKey){return errors.map(error=>({...error,key:error.key==="$root"?rootKey:`${rootKey}.${error.key}`}))}checkInternal(sub,sup){if(sub===sup){return{isSubset:true,merged:sub,errors:[]}}if((0,_utilsts.deepEqual)(sub,sup)){return{isSubset:true,merged:sub,errors:[]}}const nSub=(0,_normalizerts.normalize)(sub);const nSup=(0,_normalizerts.normalize)(sup);if((0,_utilsts.deepEqual)(nSub,nSup)){return{isSubset:true,merged:nSub,errors:[]}}const{branches:subBranches,type:subBranchType}=(0,_subsetcheckerts.getBranchesTyped)(nSub);const{branches:supBranches,type:supBranchType}=(0,_subsetcheckerts.getBranchesTyped)(nSup);if(subBranches.length>1||subBranches[0]!==nSub){return(0,_subsetcheckerts.checkBranchedSub)(subBranches,nSup,this.engine,subBranchType)}if(supBranches.length>1||supBranches[0]!==nSup){return(0,_subsetcheckerts.checkBranchedSup)(nSub,supBranches,this.engine,supBranchType)}return(0,_subsetcheckerts.checkAtomic)(nSub,nSup,this.engine)}static clearCache(){(0,_runtimevalidatorts.clearAllValidatorCaches)()}constructor(options){_define_property(this,"constraintValidators",void 0);_define_property(this,"engine",void 0);this.engine=new _mergeenginets.MergeEngine;this.constraintValidators=options?.constraints??{}}}
2
2
  //# sourceMappingURL=json-schema-compatibility-checker.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/json-schema-compatibility-checker.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { resolveConditions } from \"./condition-resolver.ts\";\nimport { validateSchemaConstraints } from \"./constraint-validator.ts\";\nimport { narrowSchemaWithData } from \"./data-narrowing.ts\";\nimport { formatResult } from \"./formatter.ts\";\nimport { MergeEngine } from \"./merge-engine.ts\";\nimport { normalize } from \"./normalizer.ts\";\nimport {\n\tarePatternsEquivalent,\n\tisPatternSubset,\n\tisTrivialPattern,\n} from \"./pattern-subset.ts\";\nimport {\n\tclearAllValidatorCaches,\n\tgetRuntimeValidationErrors,\n} from \"./runtime-validator.ts\";\nimport type { BranchResult, BranchType } from \"./subset-checker.ts\";\nimport {\n\tcheckAtomic,\n\tcheckBranchedSub,\n\tcheckBranchedSup,\n\tgetBranchesTyped,\n\tisAtomicSubsetOf,\n} from \"./subset-checker.ts\";\nimport type {\n\tCheckerOptions,\n\tCheckRuntimeOptions,\n\tConstraintValidatorRegistry,\n\tResolvedConditionResult,\n\tResolvedSubsetResult,\n\tSchemaError,\n\tSubsetResult,\n} from \"./types.ts\";\nimport { deepEqual, isPlainObj } from \"./utils.ts\";\n\n// ─── Re-exports ──────────────────────────────────────────────────────────────\n\nexport type {\n\tSchemaError,\n\tSubsetResult,\n\tResolvedConditionResult,\n\tResolvedSubsetResult,\n\tCheckRuntimeOptions,\n\tBranchType,\n\tBranchResult,\n};\n\nexport {\n\tnormalize,\n\tresolveConditions,\n\tformatResult,\n\tMergeEngine,\n\tisPatternSubset,\n\tarePatternsEquivalent,\n\tisTrivialPattern,\n};\n\n// ─── Main Class ──────────────────────────────────────────────────────────────\n//\n// Lightweight facade that orchestrates sub-modules to verify compatibility\n// between JSON Schemas (Draft-07).\n//\n// Mathematical principle:\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// In JSON Schema terms:\n// - A ∩ B = allOf([A, B]) resolved via merge\n// - ≡ = structural comparison\n//\n// @example\n// ```ts\n// const checker = new JsonSchemaCompatibilityChecker();\n//\n// checker.isSubset(strict, loose); // true\n// checker.check(loose, strict); // { isSubset: false, diffs: [...] }\n// checker.check(sub, sup, { data: {...} }); // resolves conditions then checks\n// ```\n\nexport class JsonSchemaCompatibilityChecker {\n\tprivate readonly constraintValidators: ConstraintValidatorRegistry;\n\tprivate readonly engine: MergeEngine;\n\n\tconstructor(options?: CheckerOptions) {\n\t\tthis.engine = new MergeEngine();\n\t\tthis.constraintValidators = options?.constraints ?? {};\n\t}\n\n\t// ── Subset check (boolean) ─────────────────────────────────────────────\n\n\t/**\n\t * Checks whether `sub ⊆ sup`.\n\t * Is every value valid for sub also valid for sup?\n\t *\n\t * Uses `getBranchesTyped` to distinguish `anyOf` from `oneOf`\n\t * internally, although the boolean result does not reflect the distinction.\n\t */\n\tisSubset(sub: JSONSchema7Definition, sup: JSONSchema7Definition): boolean {\n\t\t// ── Identity short-circuit ──\n\t\t// If sub and sup are the same reference, sub ⊆ sup is trivially true.\n\t\t// This avoids the entire normalize + merge + compare pipeline.\n\t\tif (sub === sup) return true;\n\n\t\t// ── Pre-normalize structural equality ──\n\t\t// If sub and sup are structurally identical before normalization,\n\t\t// they represent the same schema → sub ⊆ sup trivially.\n\t\t// This avoids the WeakMap overhead of normalize() for common cases\n\t\t// like {} ⊆ {} or identical schema objects with different references.\n\t\tif (deepEqual(sub, sup)) return true;\n\n\t\tconst nSub = normalize(sub);\n\t\tconst nSup = normalize(sup);\n\n\t\t// ── Post-normalize structural identity ──\n\t\t// After normalization, schemas that were syntactically different\n\t\t// but semantically equivalent become structurally equal\n\t\t// (e.g. {const:1} vs {const:1, type:\"integer\"}).\n\t\tif (nSub !== sub && nSup !== sup && deepEqual(nSub, nSup)) return true;\n\t\tif (nSub !== nSup && deepEqual(nSub, nSup)) return true;\n\n\t\tconst { branches: subBranches } = getBranchesTyped(nSub);\n\n\t\tif (subBranches.length > 1 || subBranches[0] !== nSub) {\n\t\t\treturn subBranches.every((branch) =>\n\t\t\t\tisAtomicSubsetOf(branch, nSup, this.engine),\n\t\t\t);\n\t\t}\n\n\t\treturn isAtomicSubsetOf(nSub, nSup, this.engine);\n\t}\n\n\t// ── Subset check (detailed) ────────────────────────────────────────────\n\n\t/**\n\t * Checks `sub ⊆ sup` and returns a detailed diagnostic\n\t * with human-readable semantic errors.\n\t *\n\t * When `options` is provided, both schemas go through runtime-aware\n\t * processing before the static check:\n\t * 1. Conditions (`if/then/else`) are resolved using `data`\n\t * (if `data` is `undefined`, conditions are resolved with `{}`)\n\t * 2. Schemas are narrowed using runtime values (enum materialization)\n\t * 3. The static subset check runs on the resolved/narrowed schemas\n\t *\n\t * When `validate: true` is set in options, two additional runtime steps\n\t * run **after** the static check passes:\n\t * 4. `data` is validated against both resolved schemas via AJV\n\t * 5. Custom constraints are validated against `data`\n\t *\n\t * @param sub - The source schema (subset candidate)\n\t * @param sup - The target schema (expected superset)\n\t * @param options - Runtime options with `data` and optional `validate` flag\n\t * @returns SubsetResult if no options, ResolvedSubsetResult if options provided\n\t *\n\t * @example\n\t * ```ts\n\t * // Static check (no runtime data)\n\t * checker.check(sub, sup);\n\t *\n\t * // Resolve conditions + narrowing + static check (no runtime validation)\n\t * checker.check(sub, sup, { data: { kind: \"text\", value: \"hello\" } });\n\t *\n\t * // Full pipeline including AJV + constraint runtime validation\n\t * checker.check(sub, sup, { data: { kind: \"text\", value: \"hello\" }, validate: true });\n\t * ```\n\t */\n\tcheck(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t\toptions: CheckRuntimeOptions,\n\t): Promise<ResolvedSubsetResult>;\n\tcheck(sub: JSONSchema7Definition, sup: JSONSchema7Definition): SubsetResult;\n\tcheck(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t\toptions?: CheckRuntimeOptions,\n\t): SubsetResult | Promise<ResolvedSubsetResult> {\n\t\t// ── Runtime-aware path ──\n\t\tif (options) {\n\t\t\treturn this.checkWithOptions(sub, sup, options);\n\t\t}\n\n\t\t// ── Standard path (no condition resolution) ──\n\t\treturn this.checkInternal(sub, sup);\n\t}\n\n\t// ── Equality ───────────────────────────────────────────────────────────\n\n\t/**\n\t * Checks structural equality between two schemas.\n\t */\n\tisEqual(a: JSONSchema7Definition, b: JSONSchema7Definition): boolean {\n\t\treturn this.engine.isEqual(normalize(a), normalize(b));\n\t}\n\n\t// ── Intersection ───────────────────────────────────────────────────────\n\n\t/**\n\t * Computes the intersection of two schemas (allOf merge).\n\t * Returns null if the schemas are incompatible.\n\t *\n\t * The result is normalized to eliminate structural artifacts\n\t * from the merge (e.g. redundant `enum` when `const` is present).\n\t */\n\tintersect(\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t): JSONSchema7Definition | null {\n\t\t// ── Identity short-circuit ──\n\t\t// If a and b are the same reference or structurally equal,\n\t\t// intersection is just normalize(a) — skip the merge entirely.\n\t\tif (a === b || deepEqual(a, b)) return normalize(a);\n\n\t\tconst nA = normalize(a);\n\t\tconst nB = normalize(b);\n\n\t\t// ── Post-normalize identity ──\n\t\tif (deepEqual(nA, nB)) return nA;\n\n\t\tconst merged = this.engine.merge(nA, nB);\n\t\tif (merged === null) return null;\n\t\t// Fast path: if merge result equals one of the normalized inputs,\n\t\t// it's already normalized — skip redundant normalize call.\n\t\tif (deepEqual(merged, nA) || deepEqual(merged, nB)) return merged;\n\t\treturn normalize(merged);\n\t}\n\n\t// ── Normalization ──────────────────────────────────────────────────────\n\n\t/**\n\t * Normalizes a schema: infers `type` from `const`/`enum`,\n\t * and recursively normalizes all sub-schemas.\n\t */\n\tnormalize(def: JSONSchema7Definition): JSONSchema7Definition {\n\t\treturn normalize(def);\n\t}\n\n\t// ── Formatting ─────────────────────────────────────────────────────────\n\n\t/**\n\t * Formats a SubsetResult into a readable string (useful for logs/debug).\n\t */\n\tformatResult(label: string, result: SubsetResult): string {\n\t\treturn formatResult(label, result);\n\t}\n\n\t// ── Condition Resolution ────────────────────────────────────────────────\n\n\t/**\n\t * Resolves `if/then/else` conditions in a schema by evaluating the `if`\n\t * against runtime data.\n\t *\n\t * @param schema - The schema containing conditions to resolve\n\t * @param data - The runtime data used to evaluate conditions\n\t * @returns The resolved schema with branch info and discriminants\n\t */\n\tresolveConditions(\n\t\tschema: JSONSchema7,\n\t\tdata: Record<string, unknown>,\n\t): ResolvedConditionResult {\n\t\treturn resolveConditions(schema, data, this.engine);\n\t}\n\n\t// ── Private ────────────────────────────────────────────────────────────\n\n\t/**\n\t * Internal runtime-aware check logic. Extracted as an async method\n\t * so that `check()` without options stays synchronous while the\n\t * runtime path can `await` async constraint validators.\n\t */\n\tprivate async checkWithOptions(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t\toptions: CheckRuntimeOptions,\n\t): Promise<ResolvedSubsetResult> {\n\t\tconst data = options.data;\n\t\tconst shouldValidate = options.validate === true;\n\n\t\t// resolveConditions expects Record<string, unknown> for property access;\n\t\t// coerce non-object / undefined data to empty object so conditions\n\t\t// are always resolved (v1.0.11 compat: subData: undefined → {})\n\t\tconst dataForConditions: Record<string, unknown> = isPlainObj(data)\n\t\t\t? data\n\t\t\t: {};\n\n\t\tconst resolvedSub = resolveConditions(\n\t\t\tsub as JSONSchema7,\n\t\t\tdataForConditions,\n\t\t\tthis.engine,\n\t\t);\n\t\tconst resolvedSup = resolveConditions(\n\t\t\tsup as JSONSchema7,\n\t\t\tdataForConditions,\n\t\t\tthis.engine,\n\t\t);\n\n\t\t// ── Runtime-aware data narrowing ──\n\t\t// Apply narrowing only when concrete data is available.\n\t\t// When data is undefined there is nothing to narrow with.\n\t\t// Boolean schemas (true/false) cannot be narrowed — skip narrowing\n\t\t// to avoid passing a non-object to narrowSchemaWithData.\n\t\tconst canNarrow = data !== undefined;\n\t\tconst canNarrowSub = canNarrow && isPlainObj(resolvedSub.resolved);\n\t\tconst canNarrowSup = canNarrow && isPlainObj(resolvedSup.resolved);\n\n\t\tconst narrowedSubResolved = canNarrowSub\n\t\t\t? narrowSchemaWithData(resolvedSub.resolved, data, resolvedSup.resolved)\n\t\t\t: resolvedSub.resolved;\n\n\t\tconst narrowedSupResolved = canNarrowSup\n\t\t\t? narrowSchemaWithData(resolvedSup.resolved, data, resolvedSub.resolved)\n\t\t\t: resolvedSup.resolved;\n\n\t\t// ── Static subset check ──\n\t\t// Structural incompatibilities are schema-level problems — they are\n\t\t// permanent regardless of the concrete data. Run this before runtime\n\t\t// validation so that static errors always surface with higher priority.\n\t\tconst staticResult = this.checkInternal(\n\t\t\tnarrowedSubResolved,\n\t\t\tnarrowedSupResolved,\n\t\t);\n\n\t\tif (!staticResult.isSubset) {\n\t\t\treturn {\n\t\t\t\t...staticResult,\n\t\t\t\tresolvedSub: { ...resolvedSub, resolved: narrowedSubResolved },\n\t\t\t\tresolvedSup: { ...resolvedSup, resolved: narrowedSupResolved },\n\t\t\t};\n\t\t}\n\n\t\t// ── Runtime validation (opt-in) ──\n\t\t// Only runs when `validate: true` is explicitly set.\n\t\t// Validates the concrete data against both resolved/narrowed schemas\n\t\t// via AJV, then runs custom constraint validators if registered.\n\t\tif (shouldValidate && data !== undefined) {\n\t\t\tconst runtimeErrors: SchemaError[] = [];\n\n\t\t\truntimeErrors.push(\n\t\t\t\t...this.prefixRuntimeErrors(\n\t\t\t\t\tgetRuntimeValidationErrors(narrowedSubResolved, data),\n\t\t\t\t\t\"$sub\",\n\t\t\t\t),\n\t\t\t);\n\n\t\t\truntimeErrors.push(\n\t\t\t\t...this.prefixRuntimeErrors(\n\t\t\t\t\tgetRuntimeValidationErrors(narrowedSupResolved, data),\n\t\t\t\t\t\"$sup\",\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// ── Constraint validation ──\n\t\t\t// Validate runtime data against custom constraints in both schemas.\n\t\t\t// Always runs when validate: true — if a schema declares constraints\n\t\t\t// that are not registered in the registry, validateSchemaConstraints\n\t\t\t// will report them as \"unknown constraint (not registered)\" errors.\n\t\t\t// Constraint validators may be async, so we await the results.\n\t\t\truntimeErrors.push(\n\t\t\t\t...this.prefixRuntimeErrors(\n\t\t\t\t\tawait validateSchemaConstraints(\n\t\t\t\t\t\tnarrowedSubResolved,\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\tthis.constraintValidators,\n\t\t\t\t\t),\n\t\t\t\t\t\"$sub\",\n\t\t\t\t),\n\t\t\t);\n\n\t\t\truntimeErrors.push(\n\t\t\t\t...this.prefixRuntimeErrors(\n\t\t\t\t\tawait validateSchemaConstraints(\n\t\t\t\t\t\tnarrowedSupResolved,\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\tthis.constraintValidators,\n\t\t\t\t\t),\n\t\t\t\t\t\"$sup\",\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tif (runtimeErrors.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tisSubset: false,\n\t\t\t\t\tmerged: null,\n\t\t\t\t\terrors: runtimeErrors,\n\t\t\t\t\tresolvedSub: { ...resolvedSub, resolved: narrowedSubResolved },\n\t\t\t\t\tresolvedSup: { ...resolvedSup, resolved: narrowedSupResolved },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t...staticResult,\n\t\t\tresolvedSub: { ...resolvedSub, resolved: narrowedSubResolved },\n\t\t\tresolvedSup: { ...resolvedSup, resolved: narrowedSupResolved },\n\t\t};\n\t}\n\n\tprivate prefixRuntimeErrors(\n\t\terrors: SchemaError[],\n\t\trootKey: \"$sub\" | \"$sup\",\n\t): SchemaError[] {\n\t\treturn errors.map((error) => ({\n\t\t\t...error,\n\t\t\tkey: error.key === \"$root\" ? rootKey : `${rootKey}.${error.key}`,\n\t\t}));\n\t}\n\n\t/**\n\t * Internal check logic without condition resolution.\n\t * Factorizes the normalize → branch → atomic pipeline to avoid\n\t * duplication between the two paths of `check()`.\n\t */\n\tprivate checkInternal(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t): SubsetResult {\n\t\t// ── Identity short-circuit ──\n\t\t// Same reference → no errors, no merge needed.\n\t\tif (sub === sup) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\t// ── Pre-normalize structural equality ──\n\t\t// Avoids WeakMap overhead for identical schemas ({} ⊆ {}, etc.).\n\t\tif (deepEqual(sub, sup)) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst nSub = normalize(sub);\n\t\tconst nSup = normalize(sup);\n\n\t\t// ── Post-normalize structural identity ──\n\t\t// Catches semantically equivalent schemas after normalization.\n\t\tif (deepEqual(nSub, nSup)) {\n\t\t\treturn { isSubset: true, merged: nSub, errors: [] };\n\t\t}\n\n\t\tconst { branches: subBranches, type: subBranchType } =\n\t\t\tgetBranchesTyped(nSub);\n\t\tconst { branches: supBranches, type: supBranchType } =\n\t\t\tgetBranchesTyped(nSup);\n\n\t\t// anyOf/oneOf in sub\n\t\tif (subBranches.length > 1 || subBranches[0] !== nSub) {\n\t\t\treturn checkBranchedSub(subBranches, nSup, this.engine, subBranchType);\n\t\t}\n\n\t\t// anyOf/oneOf in sup only\n\t\tif (supBranches.length > 1 || supBranches[0] !== nSup) {\n\t\t\treturn checkBranchedSup(nSub, supBranches, this.engine, supBranchType);\n\t\t}\n\n\t\t// Standard case\n\t\treturn checkAtomic(nSub, nSup, this.engine);\n\t}\n\n\t// ── Cache management ───────────────────────────────────────────────────\n\n\t/**\n\t * Clears all compiled AJV validator caches (WeakMap, LRU, and AJV internal).\n\t *\n\t * Useful for:\n\t * - Long-running processes where schemas evolve over time\n\t * - Test isolation (ensuring no cross-test cache pollution)\n\t * - Memory pressure situations where cached validators are no longer needed\n\t *\n\t * After calling this, the next validation call will recompile validators\n\t * from scratch — there is a one-time performance cost per unique schema.\n\t *\n\t * This is a static method because the AJV instance is a module-level\n\t * singleton shared across all `JsonSchemaCompatibilityChecker` instances.\n\t *\n\t * @example\n\t * ```ts\n\t * JsonSchemaCompatibilityChecker.clearCache();\n\t * ```\n\t */\n\tstatic clearCache(): void {\n\t\tclearAllValidatorCaches();\n\t}\n}\n"],"names":["JsonSchemaCompatibilityChecker","MergeEngine","arePatternsEquivalent","formatResult","isPatternSubset","isTrivialPattern","normalize","resolveConditions","isSubset","sub","sup","deepEqual","nSub","nSup","branches","subBranches","getBranchesTyped","length","every","branch","isAtomicSubsetOf","engine","check","options","checkWithOptions","checkInternal","isEqual","a","b","intersect","nA","nB","merged","merge","def","label","result","schema","data","shouldValidate","validate","dataForConditions","isPlainObj","resolvedSub","resolvedSup","canNarrow","undefined","canNarrowSub","resolved","canNarrowSup","narrowedSubResolved","narrowSchemaWithData","narrowedSupResolved","staticResult","runtimeErrors","push","prefixRuntimeErrors","getRuntimeValidationErrors","validateSchemaConstraints","constraintValidators","errors","rootKey","map","error","key","type","subBranchType","supBranches","supBranchType","checkBranchedSub","checkBranchedSup","checkAtomic","clearCache","clearAllValidatorCaches","constraints"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/json-schema-compatibility-checker.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { resolveConditions } from \"./condition-resolver.ts\";\nimport { validateSchemaConstraints } from \"./constraint-validator.ts\";\nimport { narrowSchemaWithData } from \"./data-narrowing.ts\";\nimport { formatResult } from \"./formatter.ts\";\nimport { MergeEngine } from \"./merge-engine.ts\";\nimport { normalize } from \"./normalizer.ts\";\nimport {\n\tarePatternsEquivalent,\n\tisPatternSubset,\n\tisTrivialPattern,\n} from \"./pattern-subset.ts\";\nimport {\n\tclearAllValidatorCaches,\n\tgetPartialRuntimeValidationErrors,\n\tgetRuntimeValidationErrors,\n} from \"./runtime-validator.ts\";\nimport type { BranchResult, BranchType } from \"./subset-checker.ts\";\nimport {\n\tcheckAtomic,\n\tcheckBranchedSub,\n\tcheckBranchedSup,\n\tgetBranchesTyped,\n\tisAtomicSubsetOf,\n} from \"./subset-checker.ts\";\nimport type {\n\tCheckerOptions,\n\tCheckRuntimeOptions,\n\tConstraintValidatorRegistry,\n\tResolvedConditionResult,\n\tResolvedSubsetResult,\n\tSchemaError,\n\tSubsetResult,\n\tValidateTargets,\n} from \"./types.ts\";\nimport { deepEqual, isPlainObj } from \"./utils.ts\";\nimport { resolveValidateTargets } from \"./validate-targets.ts\";\n\n// ─── Re-exports ──────────────────────────────────────────────────────────────\n\nexport type {\n\tSchemaError,\n\tSubsetResult,\n\tResolvedConditionResult,\n\tResolvedSubsetResult,\n\tCheckRuntimeOptions,\n\tValidateTargets,\n\tBranchType,\n\tBranchResult,\n};\n\nexport {\n\tnormalize,\n\tresolveConditions,\n\tformatResult,\n\tMergeEngine,\n\tisPatternSubset,\n\tarePatternsEquivalent,\n\tisTrivialPattern,\n};\n\n// ─── Main Class ──────────────────────────────────────────────────────────────\n//\n// Lightweight facade that orchestrates sub-modules to verify compatibility\n// between JSON Schemas (Draft-07).\n//\n// Mathematical principle:\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// In JSON Schema terms:\n// - A ∩ B = allOf([A, B]) resolved via merge\n// - ≡ = structural comparison\n//\n// @example\n// ```ts\n// const checker = new JsonSchemaCompatibilityChecker();\n//\n// checker.isSubset(strict, loose); // true\n// checker.check(loose, strict); // { isSubset: false, diffs: [...] }\n// checker.check(sub, sup, { data: {...} }); // resolves conditions then checks\n// ```\n\nexport class JsonSchemaCompatibilityChecker {\n\tprivate readonly constraintValidators: ConstraintValidatorRegistry;\n\tprivate readonly engine: MergeEngine;\n\n\tconstructor(options?: CheckerOptions) {\n\t\tthis.engine = new MergeEngine();\n\t\tthis.constraintValidators = options?.constraints ?? {};\n\t}\n\n\t// ── Subset check (boolean) ─────────────────────────────────────────────\n\n\t/**\n\t * Checks whether `sub ⊆ sup`.\n\t * Is every value valid for sub also valid for sup?\n\t *\n\t * Uses `getBranchesTyped` to distinguish `anyOf` from `oneOf`\n\t * internally, although the boolean result does not reflect the distinction.\n\t */\n\tisSubset(sub: JSONSchema7Definition, sup: JSONSchema7Definition): boolean {\n\t\t// ── Identity short-circuit ──\n\t\t// If sub and sup are the same reference, sub ⊆ sup is trivially true.\n\t\t// This avoids the entire normalize + merge + compare pipeline.\n\t\tif (sub === sup) return true;\n\n\t\t// ── Pre-normalize structural equality ──\n\t\t// If sub and sup are structurally identical before normalization,\n\t\t// they represent the same schema → sub ⊆ sup trivially.\n\t\t// This avoids the WeakMap overhead of normalize() for common cases\n\t\t// like {} ⊆ {} or identical schema objects with different references.\n\t\tif (deepEqual(sub, sup)) return true;\n\n\t\tconst nSub = normalize(sub);\n\t\tconst nSup = normalize(sup);\n\n\t\t// ── Post-normalize structural identity ──\n\t\t// After normalization, schemas that were syntactically different\n\t\t// but semantically equivalent become structurally equal\n\t\t// (e.g. {const:1} vs {const:1, type:\"integer\"}).\n\t\tif (nSub !== sub && nSup !== sup && deepEqual(nSub, nSup)) return true;\n\t\tif (nSub !== nSup && deepEqual(nSub, nSup)) return true;\n\n\t\tconst { branches: subBranches } = getBranchesTyped(nSub);\n\n\t\tif (subBranches.length > 1 || subBranches[0] !== nSub) {\n\t\t\treturn subBranches.every((branch) =>\n\t\t\t\tisAtomicSubsetOf(branch, nSup, this.engine),\n\t\t\t);\n\t\t}\n\n\t\treturn isAtomicSubsetOf(nSub, nSup, this.engine);\n\t}\n\n\t// ── Subset check (detailed) ────────────────────────────────────────────\n\n\t/**\n\t * Checks `sub ⊆ sup` and returns a detailed diagnostic\n\t * with human-readable semantic errors.\n\t *\n\t * When `options` is provided, both schemas go through runtime-aware\n\t * processing before the static check:\n\t * 1. Conditions (`if/then/else`) are resolved using `data`\n\t * (if `data` is `undefined`, conditions are resolved with `{}`)\n\t * 2. Schemas are narrowed using runtime values (enum materialization)\n\t * 3. The static subset check runs on the resolved/narrowed schemas\n\t *\n\t * When `validate` is enabled, additional runtime steps run **after** the\n\t * static check passes:\n\t * 4. `data` is validated against the targeted resolved schema(s) via AJV\n\t * 5. Custom constraints are validated against `data` for the targeted schema(s)\n\t *\n\t * `validate` accepts:\n\t * - `true` — validate against **both** sub and sup\n\t * - `{ sub: true }` — validate only against the sub schema\n\t * - `{ sup: true }` — validate only against the sup schema\n\t * - `{ sub: true, sup: true }` — equivalent to `true`\n\t *\n\t * @param sub - The source schema (subset candidate)\n\t * @param sup - The target schema (expected superset)\n\t * @param options - Runtime options with `data` and optional `validate` flag\n\t * @returns SubsetResult if no options, ResolvedSubsetResult if options provided\n\t *\n\t * @example\n\t * ```ts\n\t * // Static check (no runtime data)\n\t * checker.check(sub, sup);\n\t *\n\t * // Resolve conditions + narrowing + static check (no runtime validation)\n\t * checker.check(sub, sup, { data: { kind: \"text\", value: \"hello\" } });\n\t *\n\t * // Full pipeline including AJV + constraint runtime validation\n\t * checker.check(sub, sup, { data: { kind: \"text\", value: \"hello\" }, validate: true });\n\t * ```\n\t */\n\tcheck(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t\toptions: CheckRuntimeOptions,\n\t): Promise<ResolvedSubsetResult>;\n\tcheck(sub: JSONSchema7Definition, sup: JSONSchema7Definition): SubsetResult;\n\tcheck(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t\toptions?: CheckRuntimeOptions,\n\t): SubsetResult | Promise<ResolvedSubsetResult> {\n\t\t// ── Runtime-aware path ──\n\t\tif (options) {\n\t\t\treturn this.checkWithOptions(sub, sup, options);\n\t\t}\n\n\t\t// ── Standard path (no condition resolution) ──\n\t\treturn this.checkInternal(sub, sup);\n\t}\n\n\t// ── Equality ───────────────────────────────────────────────────────────\n\n\t/**\n\t * Checks structural equality between two schemas.\n\t */\n\tisEqual(a: JSONSchema7Definition, b: JSONSchema7Definition): boolean {\n\t\treturn this.engine.isEqual(normalize(a), normalize(b));\n\t}\n\n\t// ── Intersection ───────────────────────────────────────────────────────\n\n\t/**\n\t * Computes the intersection of two schemas (allOf merge).\n\t * Returns null if the schemas are incompatible.\n\t *\n\t * The result is normalized to eliminate structural artifacts\n\t * from the merge (e.g. redundant `enum` when `const` is present).\n\t */\n\tintersect(\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t): JSONSchema7Definition | null {\n\t\t// ── Identity short-circuit ──\n\t\t// If a and b are the same reference or structurally equal,\n\t\t// intersection is just normalize(a) — skip the merge entirely.\n\t\tif (a === b || deepEqual(a, b)) return normalize(a);\n\n\t\tconst nA = normalize(a);\n\t\tconst nB = normalize(b);\n\n\t\t// ── Post-normalize identity ──\n\t\tif (deepEqual(nA, nB)) return nA;\n\n\t\tconst merged = this.engine.merge(nA, nB);\n\t\tif (merged === null) return null;\n\t\t// Fast path: if merge result equals one of the normalized inputs,\n\t\t// it's already normalized — skip redundant normalize call.\n\t\tif (deepEqual(merged, nA) || deepEqual(merged, nB)) return merged;\n\t\treturn normalize(merged);\n\t}\n\n\t// ── Normalization ──────────────────────────────────────────────────────\n\n\t/**\n\t * Normalizes a schema: infers `type` from `const`/`enum`,\n\t * and recursively normalizes all sub-schemas.\n\t */\n\tnormalize(def: JSONSchema7Definition): JSONSchema7Definition {\n\t\treturn normalize(def);\n\t}\n\n\t// ── Formatting ─────────────────────────────────────────────────────────\n\n\t/**\n\t * Formats a SubsetResult into a readable string (useful for logs/debug).\n\t */\n\tformatResult(label: string, result: SubsetResult): string {\n\t\treturn formatResult(label, result);\n\t}\n\n\t// ── Condition Resolution ────────────────────────────────────────────────\n\n\t/**\n\t * Resolves `if/then/else` conditions in a schema by evaluating the `if`\n\t * against runtime data.\n\t *\n\t * @param schema - The schema containing conditions to resolve\n\t * @param data - The runtime data used to evaluate conditions\n\t * @returns The resolved schema with branch info and discriminants\n\t */\n\tresolveConditions(\n\t\tschema: JSONSchema7,\n\t\tdata: Record<string, unknown>,\n\t): ResolvedConditionResult {\n\t\treturn resolveConditions(schema, data, this.engine);\n\t}\n\n\t// ── Private ────────────────────────────────────────────────────────────\n\n\t/**\n\t * Internal runtime-aware check logic. Extracted as an async method\n\t * so that `check()` without options stays synchronous while the\n\t * runtime path can `await` async constraint validators.\n\t */\n\tprivate async checkWithOptions(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t\toptions: CheckRuntimeOptions,\n\t): Promise<ResolvedSubsetResult> {\n\t\tconst data = options.data;\n\t\tconst {\n\t\t\tsub: validateSub,\n\t\t\tsup: validateSup,\n\t\t\tpartialSub,\n\t\t\tpartialSup,\n\t\t} = resolveValidateTargets(options.validate);\n\n\t\t// resolveConditions expects Record<string, unknown> for property access;\n\t\t// coerce non-object / undefined data to empty object so conditions\n\t\t// are always resolved (v1.0.11 compat: subData: undefined → {})\n\t\tconst dataForConditions: Record<string, unknown> = isPlainObj(data)\n\t\t\t? data\n\t\t\t: {};\n\n\t\tconst resolvedSub = resolveConditions(\n\t\t\tsub as JSONSchema7,\n\t\t\tdataForConditions,\n\t\t\tthis.engine,\n\t\t);\n\t\tconst resolvedSup = resolveConditions(\n\t\t\tsup as JSONSchema7,\n\t\t\tdataForConditions,\n\t\t\tthis.engine,\n\t\t);\n\n\t\t// ── Runtime-aware data narrowing ──\n\t\t// Apply narrowing only when concrete data is available.\n\t\t// When data is undefined there is nothing to narrow with.\n\t\t// Boolean schemas (true/false) cannot be narrowed — skip narrowing\n\t\t// to avoid passing a non-object to narrowSchemaWithData.\n\t\tconst canNarrow = data !== undefined;\n\t\tconst canNarrowSub = canNarrow && isPlainObj(resolvedSub.resolved);\n\t\tconst canNarrowSup = canNarrow && isPlainObj(resolvedSup.resolved);\n\n\t\tconst narrowedSubResolved = canNarrowSub\n\t\t\t? narrowSchemaWithData(resolvedSub.resolved, data, resolvedSup.resolved)\n\t\t\t: resolvedSub.resolved;\n\n\t\tconst narrowedSupResolved = canNarrowSup\n\t\t\t? narrowSchemaWithData(resolvedSup.resolved, data, resolvedSub.resolved)\n\t\t\t: resolvedSup.resolved;\n\n\t\t// ── Static subset check ──\n\t\t// Structural incompatibilities are schema-level problems — they are\n\t\t// permanent regardless of the concrete data. Run this before runtime\n\t\t// validation so that static errors always surface with higher priority.\n\t\tconst staticResult = this.checkInternal(\n\t\t\tnarrowedSubResolved,\n\t\t\tnarrowedSupResolved,\n\t\t);\n\n\t\tif (!staticResult.isSubset) {\n\t\t\treturn {\n\t\t\t\t...staticResult,\n\t\t\t\tresolvedSub: { ...resolvedSub, resolved: narrowedSubResolved },\n\t\t\t\tresolvedSup: { ...resolvedSup, resolved: narrowedSupResolved },\n\t\t\t};\n\t\t}\n\n\t\t// ── Runtime validation (opt-in) ──\n\t\t// Runs when `validate` is truthy (boolean or object with sub/sup flags).\n\t\t// Validates the concrete data against the targeted resolved/narrowed\n\t\t// schema(s) via AJV, then runs custom constraint validators if registered.\n\t\tif ((validateSub || validateSup) && data !== undefined) {\n\t\t\tconst runtimeErrors: SchemaError[] = [];\n\n\t\t\t// ── AJV validation ──\n\t\t\t// When partial mode is active for a target, use\n\t\t\t// getPartialRuntimeValidationErrors which strips `required` and\n\t\t\t// `additionalProperties` before AJV compilation so that only\n\t\t\t// the properties present in data are validated.\n\t\t\tif (validateSub) {\n\t\t\t\tconst getErrors = partialSub\n\t\t\t\t\t? getPartialRuntimeValidationErrors\n\t\t\t\t\t: getRuntimeValidationErrors;\n\t\t\t\truntimeErrors.push(\n\t\t\t\t\t...this.prefixRuntimeErrors(\n\t\t\t\t\t\tgetErrors(narrowedSubResolved, data),\n\t\t\t\t\t\t\"$sub\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (validateSup) {\n\t\t\t\tconst getErrors = partialSup\n\t\t\t\t\t? getPartialRuntimeValidationErrors\n\t\t\t\t\t: getRuntimeValidationErrors;\n\t\t\t\truntimeErrors.push(\n\t\t\t\t\t...this.prefixRuntimeErrors(\n\t\t\t\t\t\tgetErrors(narrowedSupResolved, data),\n\t\t\t\t\t\t\"$sup\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// ── Constraint validation ──\n\t\t\t// Validate runtime data against custom constraints in the targeted\n\t\t\t// schema(s). If a schema declares constraints that are not registered\n\t\t\t// in the registry, validateSchemaConstraints will report them as\n\t\t\t// \"unknown constraint (not registered)\" errors.\n\t\t\t// Constraint validators may be async, so we await the results.\n\t\t\tif (validateSub) {\n\t\t\t\truntimeErrors.push(\n\t\t\t\t\t...this.prefixRuntimeErrors(\n\t\t\t\t\t\tawait validateSchemaConstraints(\n\t\t\t\t\t\t\tnarrowedSubResolved,\n\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\tthis.constraintValidators,\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"$sub\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (validateSup) {\n\t\t\t\truntimeErrors.push(\n\t\t\t\t\t...this.prefixRuntimeErrors(\n\t\t\t\t\t\tawait validateSchemaConstraints(\n\t\t\t\t\t\t\tnarrowedSupResolved,\n\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\tthis.constraintValidators,\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"$sup\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (runtimeErrors.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tisSubset: false,\n\t\t\t\t\tmerged: null,\n\t\t\t\t\terrors: runtimeErrors,\n\t\t\t\t\tresolvedSub: { ...resolvedSub, resolved: narrowedSubResolved },\n\t\t\t\t\tresolvedSup: { ...resolvedSup, resolved: narrowedSupResolved },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t...staticResult,\n\t\t\tresolvedSub: { ...resolvedSub, resolved: narrowedSubResolved },\n\t\t\tresolvedSup: { ...resolvedSup, resolved: narrowedSupResolved },\n\t\t};\n\t}\n\n\tprivate prefixRuntimeErrors(\n\t\terrors: SchemaError[],\n\t\trootKey: \"$sub\" | \"$sup\",\n\t): SchemaError[] {\n\t\treturn errors.map((error) => ({\n\t\t\t...error,\n\t\t\tkey: error.key === \"$root\" ? rootKey : `${rootKey}.${error.key}`,\n\t\t}));\n\t}\n\n\t/**\n\t * Internal check logic without condition resolution.\n\t * Factorizes the normalize → branch → atomic pipeline to avoid\n\t * duplication between the two paths of `check()`.\n\t */\n\tprivate checkInternal(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t): SubsetResult {\n\t\t// ── Identity short-circuit ──\n\t\t// Same reference → no errors, no merge needed.\n\t\tif (sub === sup) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\t// ── Pre-normalize structural equality ──\n\t\t// Avoids WeakMap overhead for identical schemas ({} ⊆ {}, etc.).\n\t\tif (deepEqual(sub, sup)) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst nSub = normalize(sub);\n\t\tconst nSup = normalize(sup);\n\n\t\t// ── Post-normalize structural identity ──\n\t\t// Catches semantically equivalent schemas after normalization.\n\t\tif (deepEqual(nSub, nSup)) {\n\t\t\treturn { isSubset: true, merged: nSub, errors: [] };\n\t\t}\n\n\t\tconst { branches: subBranches, type: subBranchType } =\n\t\t\tgetBranchesTyped(nSub);\n\t\tconst { branches: supBranches, type: supBranchType } =\n\t\t\tgetBranchesTyped(nSup);\n\n\t\t// anyOf/oneOf in sub\n\t\tif (subBranches.length > 1 || subBranches[0] !== nSub) {\n\t\t\treturn checkBranchedSub(subBranches, nSup, this.engine, subBranchType);\n\t\t}\n\n\t\t// anyOf/oneOf in sup only\n\t\tif (supBranches.length > 1 || supBranches[0] !== nSup) {\n\t\t\treturn checkBranchedSup(nSub, supBranches, this.engine, supBranchType);\n\t\t}\n\n\t\t// Standard case\n\t\treturn checkAtomic(nSub, nSup, this.engine);\n\t}\n\n\t// ── Cache management ───────────────────────────────────────────────────\n\n\t/**\n\t * Clears all compiled AJV validator caches (WeakMap, LRU, and AJV internal).\n\t *\n\t * Useful for:\n\t * - Long-running processes where schemas evolve over time\n\t * - Test isolation (ensuring no cross-test cache pollution)\n\t * - Memory pressure situations where cached validators are no longer needed\n\t *\n\t * After calling this, the next validation call will recompile validators\n\t * from scratch — there is a one-time performance cost per unique schema.\n\t *\n\t * This is a static method because the AJV instance is a module-level\n\t * singleton shared across all `JsonSchemaCompatibilityChecker` instances.\n\t *\n\t * @example\n\t * ```ts\n\t * JsonSchemaCompatibilityChecker.clearCache();\n\t * ```\n\t */\n\tstatic clearCache(): void {\n\t\tclearAllValidatorCaches();\n\t}\n}\n"],"names":["JsonSchemaCompatibilityChecker","MergeEngine","arePatternsEquivalent","formatResult","isPatternSubset","isTrivialPattern","normalize","resolveConditions","isSubset","sub","sup","deepEqual","nSub","nSup","branches","subBranches","getBranchesTyped","length","every","branch","isAtomicSubsetOf","engine","check","options","checkWithOptions","checkInternal","isEqual","a","b","intersect","nA","nB","merged","merge","def","label","result","schema","data","validateSub","validateSup","partialSub","partialSup","resolveValidateTargets","validate","dataForConditions","isPlainObj","resolvedSub","resolvedSup","canNarrow","undefined","canNarrowSub","resolved","canNarrowSup","narrowedSubResolved","narrowSchemaWithData","narrowedSupResolved","staticResult","runtimeErrors","getErrors","getPartialRuntimeValidationErrors","getRuntimeValidationErrors","push","prefixRuntimeErrors","validateSchemaConstraints","constraintValidators","errors","rootKey","map","error","key","type","subBranchType","supBranches","supBranchType","checkBranchedSub","checkBranchedSup","checkAtomic","clearCache","clearAllValidatorCaches","constraints"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { JSONSchema7Definition } from "json-schema";
1
+ import type { JSONSchema7, JSONSchema7Definition } from "json-schema";
2
2
  import type { SchemaError } from "./types.js";
3
3
  /**
4
4
  * Validates runtime data against a schema using AJV.
@@ -16,6 +16,28 @@ export declare function isDataValidForSchema(schema: JSONSchema7Definition, data
16
16
  * @returns Normalized runtime validation errors
17
17
  */
18
18
  export declare function getRuntimeValidationErrors(schema: JSONSchema7Definition, data: unknown): SchemaError[];
19
+ /**
20
+ * Recursively strips `required` and `additionalProperties` from an
21
+ * object-typed JSON Schema so that AJV validates only the properties
22
+ * present in the data.
23
+ *
24
+ * Recurses into: `properties`, `items` (single + tuple), `oneOf`, `anyOf`,
25
+ * `allOf`, `then`, `else`.
26
+ *
27
+ * @param schema - The schema to strip (not mutated — returns a new object)
28
+ * @returns A new schema without `required` or `additionalProperties` at any level
29
+ */
30
+ export declare function stripRequiredRecursive(schema: JSONSchema7): JSONSchema7;
31
+ /**
32
+ * Returns AJV validation errors for partial data — strips `required` and
33
+ * `additionalProperties` before compilation so that only the properties
34
+ * **present** in `data` are validated.
35
+ *
36
+ * @param schema - The schema to validate against (not mutated)
37
+ * @param data - The partial runtime data
38
+ * @returns Normalized runtime validation errors for present properties only
39
+ */
40
+ export declare function getPartialRuntimeValidationErrors(schema: JSONSchema7Definition, data: unknown): SchemaError[];
19
41
  /**
20
42
  * Clears all compiled validator caches (WeakMap, LRU, and AJV internal).
21
43
  *
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});function _export(target,all){for(var name in all)Object.defineProperty(target,name,{enumerable:true,get:Object.getOwnPropertyDescriptor(all,name).get})}_export(exports,{get clearAllValidatorCaches(){return clearAllValidatorCaches},get getRuntimeValidationErrors(){return getRuntimeValidationErrors},get isDataValidForSchema(){return isDataValidForSchema}});const _ajv=/*#__PURE__*/_interop_require_default(require("ajv"));const _ajvformats=/*#__PURE__*/_interop_require_default(require("ajv-formats"));function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function _interop_require_default(obj){return obj&&obj.__esModule?obj:{default:obj}}const ajv=new _ajv.default({allErrors:true,strict:false,validateFormats:true,allowUnionTypes:true,messages:true});(0,_ajvformats.default)(ajv);const validatorCache=new WeakMap;class LRUCache{get(key){const value=this.cache.get(key);if(value===undefined)return undefined;this.cache.delete(key);this.cache.set(key,value);return value}set(key,value){if(this.cache.has(key)){this.cache.delete(key)}else if(this.cache.size>=this.max){const firstKey=this.cache.keys().next().value;if(firstKey!==undefined){this.cache.delete(firstKey)}}this.cache.set(key,value)}clear(){this.cache.clear()}constructor(maxSize){_define_property(this,"max",void 0);_define_property(this,"cache",new Map);this.max=maxSize}}const validatorStringCache=new LRUCache(500);function isObjectLike(value){return typeof value==="object"&&value!==null}function stableStringify(value){if(value===null||typeof value!=="object"){return JSON.stringify(value)}if(Array.isArray(value)){return`[${value.map(entry=>stableStringify(entry)).join(",")}]`}const entries=Object.entries(value).sort(([a],[b])=>a.localeCompare(b));return`{${entries.map(([key,entryValue])=>`${JSON.stringify(key)}:${stableStringify(entryValue)}`).join(",")}}`}function getSchemaTypeName(schema){if(schema.type===undefined)return"value";if(Array.isArray(schema.type)){return schema.type.join(" | ")}return schema.type}function stringifyValue(value){if(value===undefined)return"undefined";if(typeof value==="string")return value;return JSON.stringify(value)}function normalizeInstancePath(instancePath){if(instancePath==="")return"$root";const parts=instancePath.split("/").filter(Boolean);if(parts.length===0)return"$root";let path="";for(const rawPart of parts){const part=rawPart.replace(/~1/g,"/").replace(/~0/g,"~");const isArrayIndex=/^\d+$/.test(part);if(isArrayIndex){path+="[]";continue}path=path.length===0?part:`${path}.${part}`}return path||"$root"}function formatAllowedValues(values){if(values.length===0)return"no allowed values";const rendered=values.map(value=>typeof value==="string"?value:JSON.stringify(value));if(rendered.length===1)return rendered[0]??"";if(rendered.length===2)return`${rendered[0]} or ${rendered[1]}`;return`${rendered.slice(0,-1).join(", ")}, or ${rendered[rendered.length-1]}`}function formatExpected(error,schema){switch(error.keyword){case"type":{const expectedType=typeof error.params==="object"&&error.params!==null&&"type"in error.params?String(error.params.type):getSchemaTypeName(schema);return expectedType}case"enum":{return Array.isArray(schema.enum)?formatAllowedValues(schema.enum):"allowed enum value"}case"const":{return stringifyValue(schema.const)}case"required":{const missingProperty=typeof error.params==="object"&&error.params!==null&&"missingProperty"in error.params?String(error.params.missingProperty):"unknown";const targetSchema=schema.properties?.[missingProperty]&&typeof schema.properties[missingProperty]!=="boolean"?schema.properties[missingProperty]:undefined;if(targetSchema?.type!==undefined){const prefix=normalizeInstancePath(error.instancePath);const key=prefix==="$root"?missingProperty:`${prefix}.${missingProperty}`;return`${key}: ${getSchemaTypeName(targetSchema)}`}return`required property: ${missingProperty}`}case"minimum":return`>= ${String(schema.minimum)}`;case"maximum":return`<= ${String(schema.maximum)}`;case"exclusiveMinimum":return`> ${String(schema.exclusiveMinimum)}`;case"exclusiveMaximum":return`< ${String(schema.exclusiveMaximum)}`;case"multipleOf":return`multipleOf ${String(schema.multipleOf)}`;case"minLength":return`minLength: ${String(schema.minLength)}`;case"maxLength":return`maxLength: ${String(schema.maxLength)}`;case"pattern":return`pattern: ${String(schema.pattern)}`;case"format":return`format: ${String(schema.format)}`;case"minItems":return`minItems: ${String(schema.minItems)}`;case"maxItems":return`maxItems: ${String(schema.maxItems)}`;case"uniqueItems":return"uniqueItems: true";case"minProperties":return`minProperties: ${String(schema.minProperties)}`;case"maxProperties":return`maxProperties: ${String(schema.maxProperties)}`;case"additionalProperties":return"not allowed (additionalProperties: false)";case"propertyNames":return"valid property names";case"contains":return"contains at least one matching item";case"allOf":return"allOf constraints";case"anyOf":return"anyOf constraints";case"oneOf":return"oneOf constraints";case"not":return"not matching forbidden schema";default:return error.message??error.keyword}}function buildSchemaError(error,schema,data){const baseKey=normalizeInstancePath(error.instancePath);if(error.keyword==="required"){const missingProperty=typeof error.params==="object"&&error.params!==null&&"missingProperty"in error.params?String(error.params.missingProperty):"unknown";return{key:baseKey==="$root"?missingProperty:`${baseKey}.${missingProperty}`,expected:formatExpected(error,schema),received:"undefined"}}if(error.keyword==="additionalProperties"){const additionalProperty=typeof error.params==="object"&&error.params!==null&&"additionalProperty"in error.params?String(error.params.additionalProperty):"unknown";return{key:baseKey==="$root"?additionalProperty:`${baseKey}.${additionalProperty}`,expected:formatExpected(error,schema),received:"present"}}return{key:baseKey,expected:formatExpected(error,schema),received:stringifyValue(data)}}function compileValidator(schema){if(isObjectLike(schema)){const cached=validatorCache.get(schema);if(cached!==undefined)return cached}const serialized=stableStringify(schema);const cachedByString=validatorStringCache.get(serialized);if(cachedByString!==undefined){if(isObjectLike(schema)){validatorCache.set(schema,cachedByString)}return cachedByString}const validate=ajv.compile(schema);if(isObjectLike(schema)){validatorCache.set(schema,validate)}validatorStringCache.set(serialized,validate);return validate}function isDataValidForSchema(schema,data){if(typeof schema==="boolean"){return schema}const validate=compileValidator(schema);return validate(data)===true}function getRuntimeValidationErrors(schema,data){if(typeof schema==="boolean"){if(schema)return[];return[{key:"$root",expected:"never",received:stringifyValue(data)}]}const validate=compileValidator(schema);const isValid=validate(data);if(isValid===true||validate.errors===null||validate.errors===undefined){return[]}return validate.errors.map(error=>buildSchemaError(error,schema,data))}function clearAllValidatorCaches(){validatorStringCache.clear();ajv.removeSchema()}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});function _export(target,all){for(var name in all)Object.defineProperty(target,name,{enumerable:true,get:Object.getOwnPropertyDescriptor(all,name).get})}_export(exports,{get clearAllValidatorCaches(){return clearAllValidatorCaches},get getPartialRuntimeValidationErrors(){return getPartialRuntimeValidationErrors},get getRuntimeValidationErrors(){return getRuntimeValidationErrors},get isDataValidForSchema(){return isDataValidForSchema},get stripRequiredRecursive(){return stripRequiredRecursive}});const _ajv=/*#__PURE__*/_interop_require_default(require("ajv"));const _ajvformats=/*#__PURE__*/_interop_require_default(require("ajv-formats"));const _utilsts=require("./utils.js");function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function _interop_require_default(obj){return obj&&obj.__esModule?obj:{default:obj}}const ajv=new _ajv.default({allErrors:true,strict:false,validateFormats:true,allowUnionTypes:true,messages:true});(0,_ajvformats.default)(ajv);const validatorCache=new WeakMap;class LRUCache{get(key){const value=this.cache.get(key);if(value===undefined)return undefined;this.cache.delete(key);this.cache.set(key,value);return value}set(key,value){if(this.cache.has(key)){this.cache.delete(key)}else if(this.cache.size>=this.max){const firstKey=this.cache.keys().next().value;if(firstKey!==undefined){this.cache.delete(firstKey)}}this.cache.set(key,value)}clear(){this.cache.clear()}constructor(maxSize){_define_property(this,"max",void 0);_define_property(this,"cache",new Map);this.max=maxSize}}const validatorStringCache=new LRUCache(500);function isObjectLike(value){return typeof value==="object"&&value!==null}function stableStringify(value){if(value===null||typeof value!=="object"){return JSON.stringify(value)}if(Array.isArray(value)){return`[${value.map(entry=>stableStringify(entry)).join(",")}]`}const entries=Object.entries(value).sort(([a],[b])=>a.localeCompare(b));return`{${entries.map(([key,entryValue])=>`${JSON.stringify(key)}:${stableStringify(entryValue)}`).join(",")}}`}function getSchemaTypeName(schema){if(schema.type===undefined)return"value";if(Array.isArray(schema.type)){return schema.type.join(" | ")}return schema.type}function stringifyValue(value){if(value===undefined)return"undefined";if(typeof value==="string")return value;return JSON.stringify(value)}function normalizeInstancePath(instancePath){if(instancePath==="")return"$root";const parts=instancePath.split("/").filter(Boolean);if(parts.length===0)return"$root";let path="";for(const rawPart of parts){const part=rawPart.replace(/~1/g,"/").replace(/~0/g,"~");const isArrayIndex=/^\d+$/.test(part);if(isArrayIndex){path+="[]";continue}path=path.length===0?part:`${path}.${part}`}return path||"$root"}function formatAllowedValues(values){if(values.length===0)return"no allowed values";const rendered=values.map(value=>typeof value==="string"?value:JSON.stringify(value));if(rendered.length===1)return rendered[0]??"";if(rendered.length===2)return`${rendered[0]} or ${rendered[1]}`;return`${rendered.slice(0,-1).join(", ")}, or ${rendered[rendered.length-1]}`}function formatExpected(error,schema){switch(error.keyword){case"type":{const expectedType=typeof error.params==="object"&&error.params!==null&&"type"in error.params?String(error.params.type):getSchemaTypeName(schema);return expectedType}case"enum":{return Array.isArray(schema.enum)?formatAllowedValues(schema.enum):"allowed enum value"}case"const":{return stringifyValue(schema.const)}case"required":{const missingProperty=typeof error.params==="object"&&error.params!==null&&"missingProperty"in error.params?String(error.params.missingProperty):"unknown";const targetSchema=schema.properties?.[missingProperty]&&typeof schema.properties[missingProperty]!=="boolean"?schema.properties[missingProperty]:undefined;if(targetSchema?.type!==undefined){const prefix=normalizeInstancePath(error.instancePath);const key=prefix==="$root"?missingProperty:`${prefix}.${missingProperty}`;return`${key}: ${getSchemaTypeName(targetSchema)}`}return`required property: ${missingProperty}`}case"minimum":return`>= ${String(schema.minimum)}`;case"maximum":return`<= ${String(schema.maximum)}`;case"exclusiveMinimum":return`> ${String(schema.exclusiveMinimum)}`;case"exclusiveMaximum":return`< ${String(schema.exclusiveMaximum)}`;case"multipleOf":return`multipleOf ${String(schema.multipleOf)}`;case"minLength":return`minLength: ${String(schema.minLength)}`;case"maxLength":return`maxLength: ${String(schema.maxLength)}`;case"pattern":return`pattern: ${String(schema.pattern)}`;case"format":return`format: ${String(schema.format)}`;case"minItems":return`minItems: ${String(schema.minItems)}`;case"maxItems":return`maxItems: ${String(schema.maxItems)}`;case"uniqueItems":return"uniqueItems: true";case"minProperties":return`minProperties: ${String(schema.minProperties)}`;case"maxProperties":return`maxProperties: ${String(schema.maxProperties)}`;case"additionalProperties":return"not allowed (additionalProperties: false)";case"propertyNames":return"valid property names";case"contains":return"contains at least one matching item";case"allOf":return"allOf constraints";case"anyOf":return"anyOf constraints";case"oneOf":return"oneOf constraints";case"not":return"not matching forbidden schema";default:return error.message??error.keyword}}function buildSchemaError(error,schema,data){const baseKey=normalizeInstancePath(error.instancePath);if(error.keyword==="required"){const missingProperty=typeof error.params==="object"&&error.params!==null&&"missingProperty"in error.params?String(error.params.missingProperty):"unknown";return{key:baseKey==="$root"?missingProperty:`${baseKey}.${missingProperty}`,expected:formatExpected(error,schema),received:"undefined"}}if(error.keyword==="additionalProperties"){const additionalProperty=typeof error.params==="object"&&error.params!==null&&"additionalProperty"in error.params?String(error.params.additionalProperty):"unknown";return{key:baseKey==="$root"?additionalProperty:`${baseKey}.${additionalProperty}`,expected:formatExpected(error,schema),received:"present"}}return{key:baseKey,expected:formatExpected(error,schema),received:stringifyValue(data)}}function compileValidator(schema){if(isObjectLike(schema)){const cached=validatorCache.get(schema);if(cached!==undefined)return cached}const serialized=stableStringify(schema);const cachedByString=validatorStringCache.get(serialized);if(cachedByString!==undefined){if(isObjectLike(schema)){validatorCache.set(schema,cachedByString)}return cachedByString}const validate=ajv.compile(schema);if(isObjectLike(schema)){validatorCache.set(schema,validate)}validatorStringCache.set(serialized,validate);return validate}function isDataValidForSchema(schema,data){if(typeof schema==="boolean"){return schema}const validate=compileValidator(schema);return validate(data)===true}function getRuntimeValidationErrors(schema,data){if(typeof schema==="boolean"){if(schema)return[];return[{key:"$root",expected:"never",received:stringifyValue(data)}]}const validate=compileValidator(schema);const isValid=validate(data);if(isValid===true||validate.errors===null||validate.errors===undefined){return[]}return validate.errors.map(error=>buildSchemaError(error,schema,data))}function stripRequiredRecursive(schema){if(!(0,_utilsts.isPlainObj)(schema))return schema;const result={...schema};delete result.required;delete result.additionalProperties;if((0,_utilsts.isPlainObj)(result.properties)){const props={};for(const[key,value]of Object.entries(result.properties)){props[key]=typeof value==="object"&&value!==null?stripRequiredRecursive(value):value}result.properties=props}if((0,_utilsts.isPlainObj)(result.items)&&!Array.isArray(result.items)){result.items=stripRequiredRecursive(result.items)}if(Array.isArray(result.items)){result.items=result.items.map(item=>typeof item==="object"&&item!==null?stripRequiredRecursive(item):item)}for(const keyword of["oneOf","anyOf","allOf"]){if(Array.isArray(result[keyword])){result[keyword]=result[keyword].map(branch=>typeof branch==="object"&&branch!==null?stripRequiredRecursive(branch):branch)}}if((0,_utilsts.isPlainObj)(result.then)){result.then=stripRequiredRecursive(result.then)}if((0,_utilsts.isPlainObj)(result.else)){result.else=stripRequiredRecursive(result.else)}return result}function getPartialRuntimeValidationErrors(schema,data){if(typeof schema==="boolean"){return getRuntimeValidationErrors(schema,data)}const stripped=stripRequiredRecursive(schema);return getRuntimeValidationErrors(stripped,data)}function clearAllValidatorCaches(){validatorStringCache.clear();ajv.removeSchema()}
2
2
  //# sourceMappingURL=runtime-validator.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime-validator.ts"],"sourcesContent":["import Ajv, { type ErrorObject, type ValidateFunction } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport type { SchemaError } from \"./types.ts\";\n\n/**\n * ─── Runtime Validator ────────────────────────────────────────────────────────\n *\n * Centralizes runtime validation of JSON Schema Draft-07 schemas using AJV.\n *\n * Goals:\n * - Validate concrete runtime data against resolved schemas\n * - Reuse the same runtime engine for `check(..., { data })`\n * - Reuse the same runtime engine for `if/then/else` condition evaluation\n * - Keep the static subset-checking pipeline unchanged when no runtime data is provided\n *\n * Architecture — Singleton AJV instance:\n * The `ajv` constant below is a module-level singleton shared by every\n * `JsonSchemaCompatibilityChecker` instance in the same process. This is\n * intentional:\n * - Compiled validators are reused across checker instances, avoiding\n * redundant schema compilation and reducing memory usage.\n * - The WeakMap and LRU caches for `ValidateFunction` objects are valid\n * only for a single AJV instance; per-instance AJV would break caching.\n * - `ajv-formats` is registered once at module load; all standard Draft-07\n * formats are available globally.\n * - In worker-thread environments, each worker loads its own module scope\n * and gets its own AJV instance — no cross-worker sharing occurs.\n * - Custom AJV configuration or format registration is not supported\n * per-checker-instance. If needed in the future, the singleton could be\n * replaced with a factory, but this is intentionally deferred (YAGNI).\n *\n * Notes:\n * - AJV is configured in non-strict mode because this library intentionally\n * supports partially-specified / pragmatic schemas and some unsupported\n * keywords may appear in user input.\n * - Standard JSON Schema formats are enabled through `ajv-formats` so runtime\n * validation can influence condition resolution and `check(..., { data })`\n * consistently for supported formats.\n * - Unknown formats are still ignored in practice by the non-strict runtime\n * configuration instead of crashing the whole check pipeline.\n */\n\n// Singleton AJV instance — shared across all checker instances (see module JSDoc above)\nconst ajv = new Ajv({\n\tallErrors: true,\n\tstrict: false,\n\tvalidateFormats: true,\n\tallowUnionTypes: true,\n\tmessages: true,\n});\n\naddFormats(ajv);\n\n/**\n * Cache compiled validators by schema object reference.\n *\n * This mirrors the codebase's preference for WeakMap-based caching and avoids\n * recompiling validators for the same resolved schema instances.\n */\nconst validatorCache = new WeakMap<object, ValidateFunction>();\n\n/**\n * Minimal LRU cache using Map insertion-order guarantees for O(1) eviction.\n *\n * On `get`, the entry is moved to the end (most recently used).\n * On `set`, if the cache is full, the first entry (least recently used) is evicted.\n */\nclass LRUCache<K, V> {\n\tprivate readonly max: number;\n\tprivate readonly cache = new Map<K, V>();\n\n\tconstructor(maxSize: number) {\n\t\tthis.max = maxSize;\n\t}\n\n\tget(key: K): V | undefined {\n\t\tconst value = this.cache.get(key);\n\t\tif (value === undefined) return undefined;\n\n\t\t// Move to end (most recently used)\n\t\tthis.cache.delete(key);\n\t\tthis.cache.set(key, value);\n\t\treturn value;\n\t}\n\n\tset(key: K, value: V): void {\n\t\tif (this.cache.has(key)) {\n\t\t\tthis.cache.delete(key);\n\t\t} else if (this.cache.size >= this.max) {\n\t\t\t// Evict least recently used (first key in iteration order)\n\t\t\tconst firstKey = this.cache.keys().next().value;\n\t\t\tif (firstKey !== undefined) {\n\t\t\t\tthis.cache.delete(firstKey);\n\t\t\t}\n\t\t}\n\t\tthis.cache.set(key, value);\n\t}\n\n\tclear(): void {\n\t\tthis.cache.clear();\n\t}\n}\n\n/**\n * LRU cache for compiled validators keyed by deterministic schema serialization.\n *\n * This is a fallback for schemas that are not stable object references (e.g.\n * freshly constructed schemas that are structurally identical to previously\n * seen ones). Bounded to 500 entries to prevent unbounded memory growth in\n * long-running processes. The WeakMap-based `validatorCache` remains the\n * primary cache for the hot path.\n */\nconst validatorStringCache = new LRUCache<string, ValidateFunction>(500);\n\nfunction isObjectLike(value: unknown): value is object {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction stableStringify(value: unknown): string {\n\tif (value === null || typeof value !== \"object\") {\n\t\treturn JSON.stringify(value);\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn `[${value.map((entry) => stableStringify(entry)).join(\",\")}]`;\n\t}\n\n\tconst entries = Object.entries(value as Record<string, unknown>).sort(\n\t\t([a], [b]) => a.localeCompare(b),\n\t);\n\n\treturn `{${entries\n\t\t.map(\n\t\t\t([key, entryValue]) =>\n\t\t\t\t`${JSON.stringify(key)}:${stableStringify(entryValue)}`,\n\t\t)\n\t\t.join(\",\")}}`;\n}\n\nfunction getSchemaTypeName(schema: JSONSchema7): string {\n\tif (schema.type === undefined) return \"value\";\n\n\tif (Array.isArray(schema.type)) {\n\t\treturn schema.type.join(\" | \");\n\t}\n\n\treturn schema.type;\n}\n\nfunction stringifyValue(value: unknown): string {\n\tif (value === undefined) return \"undefined\";\n\tif (typeof value === \"string\") return value;\n\treturn JSON.stringify(value);\n}\n\nfunction normalizeInstancePath(instancePath: string): string {\n\tif (instancePath === \"\") return \"$root\";\n\n\tconst parts = instancePath.split(\"/\").filter(Boolean);\n\tif (parts.length === 0) return \"$root\";\n\n\tlet path = \"\";\n\n\tfor (const rawPart of parts) {\n\t\tconst part = rawPart.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n\t\tconst isArrayIndex = /^\\d+$/.test(part);\n\n\t\tif (isArrayIndex) {\n\t\t\tpath += \"[]\";\n\t\t\tcontinue;\n\t\t}\n\n\t\tpath = path.length === 0 ? part : `${path}.${part}`;\n\t}\n\n\treturn path || \"$root\";\n}\n\nfunction formatAllowedValues(values: unknown[]): string {\n\tif (values.length === 0) return \"no allowed values\";\n\n\tconst rendered = values.map((value) =>\n\t\ttypeof value === \"string\" ? value : JSON.stringify(value),\n\t);\n\n\tif (rendered.length === 1) return rendered[0] ?? \"\";\n\tif (rendered.length === 2) return `${rendered[0]} or ${rendered[1]}`;\n\n\treturn `${rendered.slice(0, -1).join(\", \")}, or ${rendered[rendered.length - 1]}`;\n}\n\nfunction formatExpected(error: ErrorObject, schema: JSONSchema7): string {\n\tswitch (error.keyword) {\n\t\tcase \"type\": {\n\t\t\tconst expectedType =\n\t\t\t\ttypeof error.params === \"object\" &&\n\t\t\t\terror.params !== null &&\n\t\t\t\t\"type\" in error.params\n\t\t\t\t\t? String(error.params.type)\n\t\t\t\t\t: getSchemaTypeName(schema);\n\n\t\t\treturn expectedType;\n\t\t}\n\n\t\tcase \"enum\": {\n\t\t\treturn Array.isArray(schema.enum)\n\t\t\t\t? formatAllowedValues(schema.enum)\n\t\t\t\t: \"allowed enum value\";\n\t\t}\n\n\t\tcase \"const\": {\n\t\t\treturn stringifyValue(schema.const);\n\t\t}\n\n\t\tcase \"required\": {\n\t\t\tconst missingProperty =\n\t\t\t\ttypeof error.params === \"object\" &&\n\t\t\t\terror.params !== null &&\n\t\t\t\t\"missingProperty\" in error.params\n\t\t\t\t\t? String(error.params.missingProperty)\n\t\t\t\t\t: \"unknown\";\n\n\t\t\tconst targetSchema =\n\t\t\t\tschema.properties?.[missingProperty] &&\n\t\t\t\ttypeof schema.properties[missingProperty] !== \"boolean\"\n\t\t\t\t\t? (schema.properties[missingProperty] as JSONSchema7)\n\t\t\t\t\t: undefined;\n\n\t\t\tif (targetSchema?.type !== undefined) {\n\t\t\t\tconst prefix = normalizeInstancePath(error.instancePath);\n\t\t\t\tconst key =\n\t\t\t\t\tprefix === \"$root\" ? missingProperty : `${prefix}.${missingProperty}`;\n\t\t\t\treturn `${key}: ${getSchemaTypeName(targetSchema)}`;\n\t\t\t}\n\n\t\t\treturn `required property: ${missingProperty}`;\n\t\t}\n\n\t\tcase \"minimum\":\n\t\t\treturn `>= ${String((schema as JSONSchema7).minimum)}`;\n\n\t\tcase \"maximum\":\n\t\t\treturn `<= ${String((schema as JSONSchema7).maximum)}`;\n\n\t\tcase \"exclusiveMinimum\":\n\t\t\treturn `> ${String((schema as JSONSchema7).exclusiveMinimum)}`;\n\n\t\tcase \"exclusiveMaximum\":\n\t\t\treturn `< ${String((schema as JSONSchema7).exclusiveMaximum)}`;\n\n\t\tcase \"multipleOf\":\n\t\t\treturn `multipleOf ${String((schema as JSONSchema7).multipleOf)}`;\n\n\t\tcase \"minLength\":\n\t\t\treturn `minLength: ${String((schema as JSONSchema7).minLength)}`;\n\n\t\tcase \"maxLength\":\n\t\t\treturn `maxLength: ${String((schema as JSONSchema7).maxLength)}`;\n\n\t\tcase \"pattern\":\n\t\t\treturn `pattern: ${String((schema as JSONSchema7).pattern)}`;\n\n\t\tcase \"format\":\n\t\t\treturn `format: ${String((schema as JSONSchema7).format)}`;\n\n\t\tcase \"minItems\":\n\t\t\treturn `minItems: ${String((schema as JSONSchema7).minItems)}`;\n\n\t\tcase \"maxItems\":\n\t\t\treturn `maxItems: ${String((schema as JSONSchema7).maxItems)}`;\n\n\t\tcase \"uniqueItems\":\n\t\t\treturn \"uniqueItems: true\";\n\n\t\tcase \"minProperties\":\n\t\t\treturn `minProperties: ${String((schema as JSONSchema7).minProperties)}`;\n\n\t\tcase \"maxProperties\":\n\t\t\treturn `maxProperties: ${String((schema as JSONSchema7).maxProperties)}`;\n\n\t\tcase \"additionalProperties\":\n\t\t\treturn \"not allowed (additionalProperties: false)\";\n\n\t\tcase \"propertyNames\":\n\t\t\treturn \"valid property names\";\n\n\t\tcase \"contains\":\n\t\t\treturn \"contains at least one matching item\";\n\n\t\tcase \"allOf\":\n\t\t\treturn \"allOf constraints\";\n\n\t\tcase \"anyOf\":\n\t\t\treturn \"anyOf constraints\";\n\n\t\tcase \"oneOf\":\n\t\t\treturn \"oneOf constraints\";\n\n\t\tcase \"not\":\n\t\t\treturn \"not matching forbidden schema\";\n\n\t\tdefault:\n\t\t\treturn error.message ?? error.keyword;\n\t}\n}\n\nfunction buildSchemaError(\n\terror: ErrorObject,\n\tschema: JSONSchema7,\n\tdata: unknown,\n): SchemaError {\n\tconst baseKey = normalizeInstancePath(error.instancePath);\n\n\tif (error.keyword === \"required\") {\n\t\tconst missingProperty =\n\t\t\ttypeof error.params === \"object\" &&\n\t\t\terror.params !== null &&\n\t\t\t\"missingProperty\" in error.params\n\t\t\t\t? String(error.params.missingProperty)\n\t\t\t\t: \"unknown\";\n\n\t\treturn {\n\t\t\tkey:\n\t\t\t\tbaseKey === \"$root\" ? missingProperty : `${baseKey}.${missingProperty}`,\n\t\t\texpected: formatExpected(error, schema),\n\t\t\treceived: \"undefined\",\n\t\t};\n\t}\n\n\tif (error.keyword === \"additionalProperties\") {\n\t\tconst additionalProperty =\n\t\t\ttypeof error.params === \"object\" &&\n\t\t\terror.params !== null &&\n\t\t\t\"additionalProperty\" in error.params\n\t\t\t\t? String(error.params.additionalProperty)\n\t\t\t\t: \"unknown\";\n\n\t\treturn {\n\t\t\tkey:\n\t\t\t\tbaseKey === \"$root\"\n\t\t\t\t\t? additionalProperty\n\t\t\t\t\t: `${baseKey}.${additionalProperty}`,\n\t\t\texpected: formatExpected(error, schema),\n\t\t\treceived: \"present\",\n\t\t};\n\t}\n\n\treturn {\n\t\tkey: baseKey,\n\t\texpected: formatExpected(error, schema),\n\t\treceived: stringifyValue(data),\n\t};\n}\n\nfunction compileValidator(schema: JSONSchema7): ValidateFunction {\n\tif (isObjectLike(schema)) {\n\t\tconst cached = validatorCache.get(schema);\n\t\tif (cached !== undefined) return cached;\n\t}\n\n\tconst serialized = stableStringify(schema);\n\tconst cachedByString = validatorStringCache.get(serialized);\n\tif (cachedByString !== undefined) {\n\t\tif (isObjectLike(schema)) {\n\t\t\tvalidatorCache.set(schema, cachedByString);\n\t\t}\n\t\treturn cachedByString;\n\t}\n\n\tconst validate = ajv.compile(schema);\n\n\tif (isObjectLike(schema)) {\n\t\tvalidatorCache.set(schema, validate);\n\t}\n\tvalidatorStringCache.set(serialized, validate);\n\n\treturn validate;\n}\n\n/**\n * Validates runtime data against a schema using AJV.\n *\n * @param schema - The schema to validate against\n * @param data - The runtime data to validate\n * @returns true when valid, false otherwise\n */\nexport function isDataValidForSchema(\n\tschema: JSONSchema7Definition,\n\tdata: unknown,\n): boolean {\n\tif (typeof schema === \"boolean\") {\n\t\treturn schema;\n\t}\n\n\tconst validate = compileValidator(schema);\n\treturn validate(data) === true;\n}\n\n/**\n * Returns AJV validation errors converted to the library's `SchemaError` shape.\n *\n * @param schema - The schema used for validation\n * @param data - The runtime data that failed validation\n * @returns Normalized runtime validation errors\n */\nexport function getRuntimeValidationErrors(\n\tschema: JSONSchema7Definition,\n\tdata: unknown,\n): SchemaError[] {\n\tif (typeof schema === \"boolean\") {\n\t\tif (schema) return [];\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tkey: \"$root\",\n\t\t\t\texpected: \"never\",\n\t\t\t\treceived: stringifyValue(data),\n\t\t\t},\n\t\t];\n\t}\n\n\tconst validate = compileValidator(schema);\n\tconst isValid = validate(data);\n\n\tif (\n\t\tisValid === true ||\n\t\tvalidate.errors === null ||\n\t\tvalidate.errors === undefined\n\t) {\n\t\treturn [];\n\t}\n\n\treturn validate.errors.map((error) => buildSchemaError(error, schema, data));\n}\n\n/**\n * Clears all compiled validator caches (WeakMap, LRU, and AJV internal).\n *\n * Useful for:\n * - Long-running processes where schemas evolve over time\n * - Test isolation (ensuring no cross-test cache pollution)\n * - Memory pressure situations where cached validators are no longer needed\n *\n * After calling this, the next validation call will recompile validators\n * from scratch — there is a one-time performance cost per unique schema.\n */\nexport function clearAllValidatorCaches(): void {\n\t// The WeakMap cannot be \"cleared\" via API — we replace the reference.\n\t// However, since it's a module-level const, we clear it by removing\n\t// AJV's internal schema cache which is the primary memory consumer.\n\t// The WeakMap entries will be garbage-collected when their schema keys\n\t// are no longer referenced.\n\n\t// Clear the LRU string-keyed cache\n\tvalidatorStringCache.clear();\n\n\t// Clear AJV's internal compiled schema cache\n\tajv.removeSchema();\n}\n"],"names":["clearAllValidatorCaches","getRuntimeValidationErrors","isDataValidForSchema","ajv","Ajv","allErrors","strict","validateFormats","allowUnionTypes","messages","addFormats","validatorCache","WeakMap","LRUCache","get","key","value","cache","undefined","delete","set","has","size","max","firstKey","keys","next","clear","maxSize","Map","validatorStringCache","isObjectLike","stableStringify","JSON","stringify","Array","isArray","map","entry","join","entries","Object","sort","a","b","localeCompare","entryValue","getSchemaTypeName","schema","type","stringifyValue","normalizeInstancePath","instancePath","parts","split","filter","Boolean","length","path","rawPart","part","replace","isArrayIndex","test","formatAllowedValues","values","rendered","slice","formatExpected","error","keyword","expectedType","params","String","enum","const","missingProperty","targetSchema","properties","prefix","minimum","maximum","exclusiveMinimum","exclusiveMaximum","multipleOf","minLength","maxLength","pattern","format","minItems","maxItems","minProperties","maxProperties","message","buildSchemaError","data","baseKey","expected","received","additionalProperty","compileValidator","cached","serialized","cachedByString","validate","compile","isValid","errors","removeSchema"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/runtime-validator.ts"],"sourcesContent":["import Ajv, { type ErrorObject, type ValidateFunction } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport type { SchemaError } from \"./types.ts\";\nimport { isPlainObj } from \"./utils.ts\";\n\n/**\n * ─── Runtime Validator ────────────────────────────────────────────────────────\n *\n * Centralizes runtime validation of JSON Schema Draft-07 schemas using AJV.\n *\n * Goals:\n * - Validate concrete runtime data against resolved schemas\n * - Reuse the same runtime engine for `check(..., { data })`\n * - Reuse the same runtime engine for `if/then/else` condition evaluation\n * - Keep the static subset-checking pipeline unchanged when no runtime data is provided\n *\n * Architecture — Singleton AJV instance:\n * The `ajv` constant below is a module-level singleton shared by every\n * `JsonSchemaCompatibilityChecker` instance in the same process. This is\n * intentional:\n * - Compiled validators are reused across checker instances, avoiding\n * redundant schema compilation and reducing memory usage.\n * - The WeakMap and LRU caches for `ValidateFunction` objects are valid\n * only for a single AJV instance; per-instance AJV would break caching.\n * - `ajv-formats` is registered once at module load; all standard Draft-07\n * formats are available globally.\n * - In worker-thread environments, each worker loads its own module scope\n * and gets its own AJV instance — no cross-worker sharing occurs.\n * - Custom AJV configuration or format registration is not supported\n * per-checker-instance. If needed in the future, the singleton could be\n * replaced with a factory, but this is intentionally deferred (YAGNI).\n *\n * Notes:\n * - AJV is configured in non-strict mode because this library intentionally\n * supports partially-specified / pragmatic schemas and some unsupported\n * keywords may appear in user input.\n * - Standard JSON Schema formats are enabled through `ajv-formats` so runtime\n * validation can influence condition resolution and `check(..., { data })`\n * consistently for supported formats.\n * - Unknown formats are still ignored in practice by the non-strict runtime\n * configuration instead of crashing the whole check pipeline.\n */\n\n// Singleton AJV instance — shared across all checker instances (see module JSDoc above)\nconst ajv = new Ajv({\n\tallErrors: true,\n\tstrict: false,\n\tvalidateFormats: true,\n\tallowUnionTypes: true,\n\tmessages: true,\n});\n\naddFormats(ajv);\n\n/**\n * Cache compiled validators by schema object reference.\n *\n * This mirrors the codebase's preference for WeakMap-based caching and avoids\n * recompiling validators for the same resolved schema instances.\n */\nconst validatorCache = new WeakMap<object, ValidateFunction>();\n\n/**\n * Minimal LRU cache using Map insertion-order guarantees for O(1) eviction.\n *\n * On `get`, the entry is moved to the end (most recently used).\n * On `set`, if the cache is full, the first entry (least recently used) is evicted.\n */\nclass LRUCache<K, V> {\n\tprivate readonly max: number;\n\tprivate readonly cache = new Map<K, V>();\n\n\tconstructor(maxSize: number) {\n\t\tthis.max = maxSize;\n\t}\n\n\tget(key: K): V | undefined {\n\t\tconst value = this.cache.get(key);\n\t\tif (value === undefined) return undefined;\n\n\t\t// Move to end (most recently used)\n\t\tthis.cache.delete(key);\n\t\tthis.cache.set(key, value);\n\t\treturn value;\n\t}\n\n\tset(key: K, value: V): void {\n\t\tif (this.cache.has(key)) {\n\t\t\tthis.cache.delete(key);\n\t\t} else if (this.cache.size >= this.max) {\n\t\t\t// Evict least recently used (first key in iteration order)\n\t\t\tconst firstKey = this.cache.keys().next().value;\n\t\t\tif (firstKey !== undefined) {\n\t\t\t\tthis.cache.delete(firstKey);\n\t\t\t}\n\t\t}\n\t\tthis.cache.set(key, value);\n\t}\n\n\tclear(): void {\n\t\tthis.cache.clear();\n\t}\n}\n\n/**\n * LRU cache for compiled validators keyed by deterministic schema serialization.\n *\n * This is a fallback for schemas that are not stable object references (e.g.\n * freshly constructed schemas that are structurally identical to previously\n * seen ones). Bounded to 500 entries to prevent unbounded memory growth in\n * long-running processes. The WeakMap-based `validatorCache` remains the\n * primary cache for the hot path.\n */\nconst validatorStringCache = new LRUCache<string, ValidateFunction>(500);\n\nfunction isObjectLike(value: unknown): value is object {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction stableStringify(value: unknown): string {\n\tif (value === null || typeof value !== \"object\") {\n\t\treturn JSON.stringify(value);\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn `[${value.map((entry) => stableStringify(entry)).join(\",\")}]`;\n\t}\n\n\tconst entries = Object.entries(value as Record<string, unknown>).sort(\n\t\t([a], [b]) => a.localeCompare(b),\n\t);\n\n\treturn `{${entries\n\t\t.map(\n\t\t\t([key, entryValue]) =>\n\t\t\t\t`${JSON.stringify(key)}:${stableStringify(entryValue)}`,\n\t\t)\n\t\t.join(\",\")}}`;\n}\n\nfunction getSchemaTypeName(schema: JSONSchema7): string {\n\tif (schema.type === undefined) return \"value\";\n\n\tif (Array.isArray(schema.type)) {\n\t\treturn schema.type.join(\" | \");\n\t}\n\n\treturn schema.type;\n}\n\nfunction stringifyValue(value: unknown): string {\n\tif (value === undefined) return \"undefined\";\n\tif (typeof value === \"string\") return value;\n\treturn JSON.stringify(value);\n}\n\nfunction normalizeInstancePath(instancePath: string): string {\n\tif (instancePath === \"\") return \"$root\";\n\n\tconst parts = instancePath.split(\"/\").filter(Boolean);\n\tif (parts.length === 0) return \"$root\";\n\n\tlet path = \"\";\n\n\tfor (const rawPart of parts) {\n\t\tconst part = rawPart.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n\t\tconst isArrayIndex = /^\\d+$/.test(part);\n\n\t\tif (isArrayIndex) {\n\t\t\tpath += \"[]\";\n\t\t\tcontinue;\n\t\t}\n\n\t\tpath = path.length === 0 ? part : `${path}.${part}`;\n\t}\n\n\treturn path || \"$root\";\n}\n\nfunction formatAllowedValues(values: unknown[]): string {\n\tif (values.length === 0) return \"no allowed values\";\n\n\tconst rendered = values.map((value) =>\n\t\ttypeof value === \"string\" ? value : JSON.stringify(value),\n\t);\n\n\tif (rendered.length === 1) return rendered[0] ?? \"\";\n\tif (rendered.length === 2) return `${rendered[0]} or ${rendered[1]}`;\n\n\treturn `${rendered.slice(0, -1).join(\", \")}, or ${rendered[rendered.length - 1]}`;\n}\n\nfunction formatExpected(error: ErrorObject, schema: JSONSchema7): string {\n\tswitch (error.keyword) {\n\t\tcase \"type\": {\n\t\t\tconst expectedType =\n\t\t\t\ttypeof error.params === \"object\" &&\n\t\t\t\terror.params !== null &&\n\t\t\t\t\"type\" in error.params\n\t\t\t\t\t? String(error.params.type)\n\t\t\t\t\t: getSchemaTypeName(schema);\n\n\t\t\treturn expectedType;\n\t\t}\n\n\t\tcase \"enum\": {\n\t\t\treturn Array.isArray(schema.enum)\n\t\t\t\t? formatAllowedValues(schema.enum)\n\t\t\t\t: \"allowed enum value\";\n\t\t}\n\n\t\tcase \"const\": {\n\t\t\treturn stringifyValue(schema.const);\n\t\t}\n\n\t\tcase \"required\": {\n\t\t\tconst missingProperty =\n\t\t\t\ttypeof error.params === \"object\" &&\n\t\t\t\terror.params !== null &&\n\t\t\t\t\"missingProperty\" in error.params\n\t\t\t\t\t? String(error.params.missingProperty)\n\t\t\t\t\t: \"unknown\";\n\n\t\t\tconst targetSchema =\n\t\t\t\tschema.properties?.[missingProperty] &&\n\t\t\t\ttypeof schema.properties[missingProperty] !== \"boolean\"\n\t\t\t\t\t? (schema.properties[missingProperty] as JSONSchema7)\n\t\t\t\t\t: undefined;\n\n\t\t\tif (targetSchema?.type !== undefined) {\n\t\t\t\tconst prefix = normalizeInstancePath(error.instancePath);\n\t\t\t\tconst key =\n\t\t\t\t\tprefix === \"$root\" ? missingProperty : `${prefix}.${missingProperty}`;\n\t\t\t\treturn `${key}: ${getSchemaTypeName(targetSchema)}`;\n\t\t\t}\n\n\t\t\treturn `required property: ${missingProperty}`;\n\t\t}\n\n\t\tcase \"minimum\":\n\t\t\treturn `>= ${String((schema as JSONSchema7).minimum)}`;\n\n\t\tcase \"maximum\":\n\t\t\treturn `<= ${String((schema as JSONSchema7).maximum)}`;\n\n\t\tcase \"exclusiveMinimum\":\n\t\t\treturn `> ${String((schema as JSONSchema7).exclusiveMinimum)}`;\n\n\t\tcase \"exclusiveMaximum\":\n\t\t\treturn `< ${String((schema as JSONSchema7).exclusiveMaximum)}`;\n\n\t\tcase \"multipleOf\":\n\t\t\treturn `multipleOf ${String((schema as JSONSchema7).multipleOf)}`;\n\n\t\tcase \"minLength\":\n\t\t\treturn `minLength: ${String((schema as JSONSchema7).minLength)}`;\n\n\t\tcase \"maxLength\":\n\t\t\treturn `maxLength: ${String((schema as JSONSchema7).maxLength)}`;\n\n\t\tcase \"pattern\":\n\t\t\treturn `pattern: ${String((schema as JSONSchema7).pattern)}`;\n\n\t\tcase \"format\":\n\t\t\treturn `format: ${String((schema as JSONSchema7).format)}`;\n\n\t\tcase \"minItems\":\n\t\t\treturn `minItems: ${String((schema as JSONSchema7).minItems)}`;\n\n\t\tcase \"maxItems\":\n\t\t\treturn `maxItems: ${String((schema as JSONSchema7).maxItems)}`;\n\n\t\tcase \"uniqueItems\":\n\t\t\treturn \"uniqueItems: true\";\n\n\t\tcase \"minProperties\":\n\t\t\treturn `minProperties: ${String((schema as JSONSchema7).minProperties)}`;\n\n\t\tcase \"maxProperties\":\n\t\t\treturn `maxProperties: ${String((schema as JSONSchema7).maxProperties)}`;\n\n\t\tcase \"additionalProperties\":\n\t\t\treturn \"not allowed (additionalProperties: false)\";\n\n\t\tcase \"propertyNames\":\n\t\t\treturn \"valid property names\";\n\n\t\tcase \"contains\":\n\t\t\treturn \"contains at least one matching item\";\n\n\t\tcase \"allOf\":\n\t\t\treturn \"allOf constraints\";\n\n\t\tcase \"anyOf\":\n\t\t\treturn \"anyOf constraints\";\n\n\t\tcase \"oneOf\":\n\t\t\treturn \"oneOf constraints\";\n\n\t\tcase \"not\":\n\t\t\treturn \"not matching forbidden schema\";\n\n\t\tdefault:\n\t\t\treturn error.message ?? error.keyword;\n\t}\n}\n\nfunction buildSchemaError(\n\terror: ErrorObject,\n\tschema: JSONSchema7,\n\tdata: unknown,\n): SchemaError {\n\tconst baseKey = normalizeInstancePath(error.instancePath);\n\n\tif (error.keyword === \"required\") {\n\t\tconst missingProperty =\n\t\t\ttypeof error.params === \"object\" &&\n\t\t\terror.params !== null &&\n\t\t\t\"missingProperty\" in error.params\n\t\t\t\t? String(error.params.missingProperty)\n\t\t\t\t: \"unknown\";\n\n\t\treturn {\n\t\t\tkey:\n\t\t\t\tbaseKey === \"$root\" ? missingProperty : `${baseKey}.${missingProperty}`,\n\t\t\texpected: formatExpected(error, schema),\n\t\t\treceived: \"undefined\",\n\t\t};\n\t}\n\n\tif (error.keyword === \"additionalProperties\") {\n\t\tconst additionalProperty =\n\t\t\ttypeof error.params === \"object\" &&\n\t\t\terror.params !== null &&\n\t\t\t\"additionalProperty\" in error.params\n\t\t\t\t? String(error.params.additionalProperty)\n\t\t\t\t: \"unknown\";\n\n\t\treturn {\n\t\t\tkey:\n\t\t\t\tbaseKey === \"$root\"\n\t\t\t\t\t? additionalProperty\n\t\t\t\t\t: `${baseKey}.${additionalProperty}`,\n\t\t\texpected: formatExpected(error, schema),\n\t\t\treceived: \"present\",\n\t\t};\n\t}\n\n\treturn {\n\t\tkey: baseKey,\n\t\texpected: formatExpected(error, schema),\n\t\treceived: stringifyValue(data),\n\t};\n}\n\nfunction compileValidator(schema: JSONSchema7): ValidateFunction {\n\tif (isObjectLike(schema)) {\n\t\tconst cached = validatorCache.get(schema);\n\t\tif (cached !== undefined) return cached;\n\t}\n\n\tconst serialized = stableStringify(schema);\n\tconst cachedByString = validatorStringCache.get(serialized);\n\tif (cachedByString !== undefined) {\n\t\tif (isObjectLike(schema)) {\n\t\t\tvalidatorCache.set(schema, cachedByString);\n\t\t}\n\t\treturn cachedByString;\n\t}\n\n\tconst validate = ajv.compile(schema);\n\n\tif (isObjectLike(schema)) {\n\t\tvalidatorCache.set(schema, validate);\n\t}\n\tvalidatorStringCache.set(serialized, validate);\n\n\treturn validate;\n}\n\n/**\n * Validates runtime data against a schema using AJV.\n *\n * @param schema - The schema to validate against\n * @param data - The runtime data to validate\n * @returns true when valid, false otherwise\n */\nexport function isDataValidForSchema(\n\tschema: JSONSchema7Definition,\n\tdata: unknown,\n): boolean {\n\tif (typeof schema === \"boolean\") {\n\t\treturn schema;\n\t}\n\n\tconst validate = compileValidator(schema);\n\treturn validate(data) === true;\n}\n\n/**\n * Returns AJV validation errors converted to the library's `SchemaError` shape.\n *\n * @param schema - The schema used for validation\n * @param data - The runtime data that failed validation\n * @returns Normalized runtime validation errors\n */\nexport function getRuntimeValidationErrors(\n\tschema: JSONSchema7Definition,\n\tdata: unknown,\n): SchemaError[] {\n\tif (typeof schema === \"boolean\") {\n\t\tif (schema) return [];\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tkey: \"$root\",\n\t\t\t\texpected: \"never\",\n\t\t\t\treceived: stringifyValue(data),\n\t\t\t},\n\t\t];\n\t}\n\n\tconst validate = compileValidator(schema);\n\tconst isValid = validate(data);\n\n\tif (\n\t\tisValid === true ||\n\t\tvalidate.errors === null ||\n\t\tvalidate.errors === undefined\n\t) {\n\t\treturn [];\n\t}\n\n\treturn validate.errors.map((error) => buildSchemaError(error, schema, data));\n}\n\n// ─── Partial Validation ──────────────────────────────────────────────────────\n//\n// Strips `required` and `additionalProperties` from a schema recursively so\n// that AJV only validates the properties **present** in the data — without\n// reporting missing required properties or unexpected additional properties.\n//\n// This is used by the \"partial\" runtime validation mode: the caller has\n// partial data (e.g. only some properties known at design-time) and wants to\n// validate those values against the schema without false negatives for\n// properties that will be provided later by another source.\n\n/**\n * Recursively strips `required` and `additionalProperties` from an\n * object-typed JSON Schema so that AJV validates only the properties\n * present in the data.\n *\n * Recurses into: `properties`, `items` (single + tuple), `oneOf`, `anyOf`,\n * `allOf`, `then`, `else`.\n *\n * @param schema - The schema to strip (not mutated — returns a new object)\n * @returns A new schema without `required` or `additionalProperties` at any level\n */\nexport function stripRequiredRecursive(schema: JSONSchema7): JSONSchema7 {\n\tif (!isPlainObj(schema)) return schema;\n\n\tconst result: JSONSchema7 = { ...schema };\n\tdelete result.required;\n\tdelete result.additionalProperties;\n\n\t// ── Recurse into properties ──\n\tif (isPlainObj(result.properties)) {\n\t\tconst props: Record<string, JSONSchema7Definition> = {};\n\t\tfor (const [key, value] of Object.entries(\n\t\t\tresult.properties as Record<string, JSONSchema7Definition>,\n\t\t)) {\n\t\t\tprops[key] =\n\t\t\t\ttypeof value === \"object\" && value !== null\n\t\t\t\t\t? stripRequiredRecursive(value)\n\t\t\t\t\t: value;\n\t\t}\n\t\tresult.properties = props;\n\t}\n\n\t// ── Recurse into items (single schema) ──\n\tif (isPlainObj(result.items) && !Array.isArray(result.items)) {\n\t\tresult.items = stripRequiredRecursive(result.items as JSONSchema7);\n\t}\n\n\t// ── Recurse into tuple items ──\n\tif (Array.isArray(result.items)) {\n\t\tresult.items = (result.items as JSONSchema7Definition[]).map((item) =>\n\t\t\ttypeof item === \"object\" && item !== null\n\t\t\t\t? stripRequiredRecursive(item)\n\t\t\t\t: item,\n\t\t);\n\t}\n\n\t// ── Recurse into branching keywords ──\n\tfor (const keyword of [\"oneOf\", \"anyOf\", \"allOf\"] as const) {\n\t\tif (Array.isArray(result[keyword])) {\n\t\t\tresult[keyword] = (result[keyword] as JSONSchema7Definition[]).map(\n\t\t\t\t(branch) =>\n\t\t\t\t\ttypeof branch === \"object\" && branch !== null\n\t\t\t\t\t\t? stripRequiredRecursive(branch)\n\t\t\t\t\t\t: branch,\n\t\t\t);\n\t\t}\n\t}\n\n\t// ── Recurse into conditional keywords ──\n\tif (isPlainObj(result.then)) {\n\t\tresult.then = stripRequiredRecursive(result.then as JSONSchema7);\n\t}\n\tif (isPlainObj(result.else)) {\n\t\tresult.else = stripRequiredRecursive(result.else as JSONSchema7);\n\t}\n\n\treturn result;\n}\n\n/**\n * Returns AJV validation errors for partial data — strips `required` and\n * `additionalProperties` before compilation so that only the properties\n * **present** in `data` are validated.\n *\n * @param schema - The schema to validate against (not mutated)\n * @param data - The partial runtime data\n * @returns Normalized runtime validation errors for present properties only\n */\nexport function getPartialRuntimeValidationErrors(\n\tschema: JSONSchema7Definition,\n\tdata: unknown,\n): SchemaError[] {\n\tif (typeof schema === \"boolean\") {\n\t\treturn getRuntimeValidationErrors(schema, data);\n\t}\n\n\tconst stripped = stripRequiredRecursive(schema);\n\treturn getRuntimeValidationErrors(stripped, data);\n}\n\n/**\n * Clears all compiled validator caches (WeakMap, LRU, and AJV internal).\n *\n * Useful for:\n * - Long-running processes where schemas evolve over time\n * - Test isolation (ensuring no cross-test cache pollution)\n * - Memory pressure situations where cached validators are no longer needed\n *\n * After calling this, the next validation call will recompile validators\n * from scratch — there is a one-time performance cost per unique schema.\n */\nexport function clearAllValidatorCaches(): void {\n\t// The WeakMap cannot be \"cleared\" via API — we replace the reference.\n\t// However, since it's a module-level const, we clear it by removing\n\t// AJV's internal schema cache which is the primary memory consumer.\n\t// The WeakMap entries will be garbage-collected when their schema keys\n\t// are no longer referenced.\n\n\t// Clear the LRU string-keyed cache\n\tvalidatorStringCache.clear();\n\n\t// Clear AJV's internal compiled schema cache\n\tajv.removeSchema();\n}\n"],"names":["clearAllValidatorCaches","getPartialRuntimeValidationErrors","getRuntimeValidationErrors","isDataValidForSchema","stripRequiredRecursive","ajv","Ajv","allErrors","strict","validateFormats","allowUnionTypes","messages","addFormats","validatorCache","WeakMap","LRUCache","get","key","value","cache","undefined","delete","set","has","size","max","firstKey","keys","next","clear","maxSize","Map","validatorStringCache","isObjectLike","stableStringify","JSON","stringify","Array","isArray","map","entry","join","entries","Object","sort","a","b","localeCompare","entryValue","getSchemaTypeName","schema","type","stringifyValue","normalizeInstancePath","instancePath","parts","split","filter","Boolean","length","path","rawPart","part","replace","isArrayIndex","test","formatAllowedValues","values","rendered","slice","formatExpected","error","keyword","expectedType","params","String","enum","const","missingProperty","targetSchema","properties","prefix","minimum","maximum","exclusiveMinimum","exclusiveMaximum","multipleOf","minLength","maxLength","pattern","format","minItems","maxItems","minProperties","maxProperties","message","buildSchemaError","data","baseKey","expected","received","additionalProperty","compileValidator","cached","serialized","cachedByString","validate","compile","isValid","errors","isPlainObj","result","required","additionalProperties","props","items","item","branch","then","else","stripped","removeSchema"],"mappings":"mPAqiBgBA,iCAAAA,6BAvBAC,2CAAAA,uCAvHAC,oCAAAA,gCAnBAC,8BAAAA,0BAuEAC,gCAAAA,mFA3c6C,wEACtC,uCAGI,sRAyC3B,MAAMC,IAAM,IAAIC,YAAG,CAAC,CACnBC,UAAW,KACXC,OAAQ,MACRC,gBAAiB,KACjBC,gBAAiB,KACjBC,SAAU,IACX,GAEAC,GAAAA,mBAAU,EAACP,KAQX,MAAMQ,eAAiB,IAAIC,OAQ3B,OAAMC,SAQLC,IAAIC,GAAM,CAAiB,CAC1B,MAAMC,MAAQ,IAAI,CAACC,KAAK,CAACH,GAAG,CAACC,KAC7B,GAAIC,QAAUE,UAAW,OAAOA,UAGhC,IAAI,CAACD,KAAK,CAACE,MAAM,CAACJ,KAClB,IAAI,CAACE,KAAK,CAACG,GAAG,CAACL,IAAKC,OACpB,OAAOA,KACR,CAEAI,IAAIL,GAAM,CAAEC,KAAQ,CAAQ,CAC3B,GAAI,IAAI,CAACC,KAAK,CAACI,GAAG,CAACN,KAAM,CACxB,IAAI,CAACE,KAAK,CAACE,MAAM,CAACJ,IACnB,MAAO,GAAI,IAAI,CAACE,KAAK,CAACK,IAAI,EAAI,IAAI,CAACC,GAAG,CAAE,CAEvC,MAAMC,SAAW,IAAI,CAACP,KAAK,CAACQ,IAAI,GAAGC,IAAI,GAAGV,KAAK,CAC/C,GAAIQ,WAAaN,UAAW,CAC3B,IAAI,CAACD,KAAK,CAACE,MAAM,CAACK,SACnB,CACD,CACA,IAAI,CAACP,KAAK,CAACG,GAAG,CAACL,IAAKC,MACrB,CAEAW,OAAc,CACb,IAAI,CAACV,KAAK,CAACU,KAAK,EACjB,CA7BA,YAAYC,OAAe,CAAE,CAH7B,sBAAiBL,MAAjB,KAAA,GACA,sBAAiBN,QAAQ,IAAIY,IAG5B,CAAA,IAAI,CAACN,GAAG,CAAGK,OACZ,CA4BD,CAWA,MAAME,qBAAuB,IAAIjB,SAAmC,KAEpE,SAASkB,aAAaf,KAAc,EACnC,OAAO,OAAOA,QAAU,UAAYA,QAAU,IAC/C,CAEA,SAASgB,gBAAgBhB,KAAc,EACtC,GAAIA,QAAU,MAAQ,OAAOA,QAAU,SAAU,CAChD,OAAOiB,KAAKC,SAAS,CAAClB,MACvB,CAEA,GAAImB,MAAMC,OAAO,CAACpB,OAAQ,CACzB,MAAO,CAAC,CAAC,EAAEA,MAAMqB,GAAG,CAAC,AAACC,OAAUN,gBAAgBM,QAAQC,IAAI,CAAC,KAAK,CAAC,CAAC,AACrE,CAEA,MAAMC,QAAUC,OAAOD,OAAO,CAACxB,OAAkC0B,IAAI,CACpE,CAAC,CAACC,EAAE,CAAE,CAACC,EAAE,GAAKD,EAAEE,aAAa,CAACD,IAG/B,MAAO,CAAC,CAAC,EAAEJ,QACTH,GAAG,CACH,CAAC,CAACtB,IAAK+B,WAAW,GACjB,CAAC,EAAEb,KAAKC,SAAS,CAACnB,KAAK,CAAC,EAAEiB,gBAAgBc,YAAY,CAAC,EAExDP,IAAI,CAAC,KAAK,CAAC,CAAC,AACf,CAEA,SAASQ,kBAAkBC,MAAmB,EAC7C,GAAIA,OAAOC,IAAI,GAAK/B,UAAW,MAAO,QAEtC,GAAIiB,MAAMC,OAAO,CAACY,OAAOC,IAAI,EAAG,CAC/B,OAAOD,OAAOC,IAAI,CAACV,IAAI,CAAC,MACzB,CAEA,OAAOS,OAAOC,IAAI,AACnB,CAEA,SAASC,eAAelC,KAAc,EACrC,GAAIA,QAAUE,UAAW,MAAO,YAChC,GAAI,OAAOF,QAAU,SAAU,OAAOA,MACtC,OAAOiB,KAAKC,SAAS,CAAClB,MACvB,CAEA,SAASmC,sBAAsBC,YAAoB,EAClD,GAAIA,eAAiB,GAAI,MAAO,QAEhC,MAAMC,MAAQD,aAAaE,KAAK,CAAC,KAAKC,MAAM,CAACC,SAC7C,GAAIH,MAAMI,MAAM,GAAK,EAAG,MAAO,QAE/B,IAAIC,KAAO,GAEX,IAAK,MAAMC,WAAWN,MAAO,CAC5B,MAAMO,KAAOD,QAAQE,OAAO,CAAC,MAAO,KAAKA,OAAO,CAAC,MAAO,KACxD,MAAMC,aAAe,QAAQC,IAAI,CAACH,MAElC,GAAIE,aAAc,CACjBJ,MAAQ,KACR,QACD,CAEAA,KAAOA,KAAKD,MAAM,GAAK,EAAIG,KAAO,CAAC,EAAEF,KAAK,CAAC,EAAEE,KAAK,CAAC,AACpD,CAEA,OAAOF,MAAQ,OAChB,CAEA,SAASM,oBAAoBC,MAAiB,EAC7C,GAAIA,OAAOR,MAAM,GAAK,EAAG,MAAO,oBAEhC,MAAMS,SAAWD,OAAO5B,GAAG,CAAC,AAACrB,OAC5B,OAAOA,QAAU,SAAWA,MAAQiB,KAAKC,SAAS,CAAClB,QAGpD,GAAIkD,SAAST,MAAM,GAAK,EAAG,OAAOS,QAAQ,CAAC,EAAE,EAAI,GACjD,GAAIA,SAAST,MAAM,GAAK,EAAG,MAAO,CAAC,EAAES,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAEA,QAAQ,CAAC,EAAE,CAAC,CAAC,CAEpE,MAAO,CAAC,EAAEA,SAASC,KAAK,CAAC,EAAG,CAAC,GAAG5B,IAAI,CAAC,MAAM,KAAK,EAAE2B,QAAQ,CAACA,SAAST,MAAM,CAAG,EAAE,CAAC,CAAC,AAClF,CAEA,SAASW,eAAeC,KAAkB,CAAErB,MAAmB,EAC9D,OAAQqB,MAAMC,OAAO,EACpB,IAAK,OAAQ,CACZ,MAAMC,aACL,OAAOF,MAAMG,MAAM,GAAK,UACxBH,MAAMG,MAAM,GAAK,MACjB,SAAUH,MAAMG,MAAM,CACnBC,OAAOJ,MAAMG,MAAM,CAACvB,IAAI,EACxBF,kBAAkBC,QAEtB,OAAOuB,YACR,CAEA,IAAK,OAAQ,CACZ,OAAOpC,MAAMC,OAAO,CAACY,OAAO0B,IAAI,EAC7BV,oBAAoBhB,OAAO0B,IAAI,EAC/B,oBACJ,CAEA,IAAK,QAAS,CACb,OAAOxB,eAAeF,OAAO2B,KAAK,CACnC,CAEA,IAAK,WAAY,CAChB,MAAMC,gBACL,OAAOP,MAAMG,MAAM,GAAK,UACxBH,MAAMG,MAAM,GAAK,MACjB,oBAAqBH,MAAMG,MAAM,CAC9BC,OAAOJ,MAAMG,MAAM,CAACI,eAAe,EACnC,UAEJ,MAAMC,aACL7B,OAAO8B,UAAU,EAAE,CAACF,gBAAgB,EACpC,OAAO5B,OAAO8B,UAAU,CAACF,gBAAgB,GAAK,UAC1C5B,OAAO8B,UAAU,CAACF,gBAAgB,CACnC1D,UAEJ,GAAI2D,cAAc5B,OAAS/B,UAAW,CACrC,MAAM6D,OAAS5B,sBAAsBkB,MAAMjB,YAAY,EACvD,MAAMrC,IACLgE,SAAW,QAAUH,gBAAkB,CAAC,EAAEG,OAAO,CAAC,EAAEH,gBAAgB,CAAC,CACtE,MAAO,CAAC,EAAE7D,IAAI,EAAE,EAAEgC,kBAAkB8B,cAAc,CAAC,AACpD,CAEA,MAAO,CAAC,mBAAmB,EAAED,gBAAgB,CAAC,AAC/C,CAEA,IAAK,UACJ,MAAO,CAAC,GAAG,EAAEH,OAAO,AAACzB,OAAuBgC,OAAO,EAAE,CAAC,AAEvD,KAAK,UACJ,MAAO,CAAC,GAAG,EAAEP,OAAO,AAACzB,OAAuBiC,OAAO,EAAE,CAAC,AAEvD,KAAK,mBACJ,MAAO,CAAC,EAAE,EAAER,OAAO,AAACzB,OAAuBkC,gBAAgB,EAAE,CAAC,AAE/D,KAAK,mBACJ,MAAO,CAAC,EAAE,EAAET,OAAO,AAACzB,OAAuBmC,gBAAgB,EAAE,CAAC,AAE/D,KAAK,aACJ,MAAO,CAAC,WAAW,EAAEV,OAAO,AAACzB,OAAuBoC,UAAU,EAAE,CAAC,AAElE,KAAK,YACJ,MAAO,CAAC,WAAW,EAAEX,OAAO,AAACzB,OAAuBqC,SAAS,EAAE,CAAC,AAEjE,KAAK,YACJ,MAAO,CAAC,WAAW,EAAEZ,OAAO,AAACzB,OAAuBsC,SAAS,EAAE,CAAC,AAEjE,KAAK,UACJ,MAAO,CAAC,SAAS,EAAEb,OAAO,AAACzB,OAAuBuC,OAAO,EAAE,CAAC,AAE7D,KAAK,SACJ,MAAO,CAAC,QAAQ,EAAEd,OAAO,AAACzB,OAAuBwC,MAAM,EAAE,CAAC,AAE3D,KAAK,WACJ,MAAO,CAAC,UAAU,EAAEf,OAAO,AAACzB,OAAuByC,QAAQ,EAAE,CAAC,AAE/D,KAAK,WACJ,MAAO,CAAC,UAAU,EAAEhB,OAAO,AAACzB,OAAuB0C,QAAQ,EAAE,CAAC,AAE/D,KAAK,cACJ,MAAO,mBAER,KAAK,gBACJ,MAAO,CAAC,eAAe,EAAEjB,OAAO,AAACzB,OAAuB2C,aAAa,EAAE,CAAC,AAEzE,KAAK,gBACJ,MAAO,CAAC,eAAe,EAAElB,OAAO,AAACzB,OAAuB4C,aAAa,EAAE,CAAC,AAEzE,KAAK,uBACJ,MAAO,2CAER,KAAK,gBACJ,MAAO,sBAER,KAAK,WACJ,MAAO,qCAER,KAAK,QACJ,MAAO,mBAER,KAAK,QACJ,MAAO,mBAER,KAAK,QACJ,MAAO,mBAER,KAAK,MACJ,MAAO,+BAER,SACC,OAAOvB,MAAMwB,OAAO,EAAIxB,MAAMC,OAAO,AACvC,CACD,CAEA,SAASwB,iBACRzB,KAAkB,CAClBrB,MAAmB,CACnB+C,IAAa,EAEb,MAAMC,QAAU7C,sBAAsBkB,MAAMjB,YAAY,EAExD,GAAIiB,MAAMC,OAAO,GAAK,WAAY,CACjC,MAAMM,gBACL,OAAOP,MAAMG,MAAM,GAAK,UACxBH,MAAMG,MAAM,GAAK,MACjB,oBAAqBH,MAAMG,MAAM,CAC9BC,OAAOJ,MAAMG,MAAM,CAACI,eAAe,EACnC,UAEJ,MAAO,CACN7D,IACCiF,UAAY,QAAUpB,gBAAkB,CAAC,EAAEoB,QAAQ,CAAC,EAAEpB,gBAAgB,CAAC,CACxEqB,SAAU7B,eAAeC,MAAOrB,QAChCkD,SAAU,WACX,CACD,CAEA,GAAI7B,MAAMC,OAAO,GAAK,uBAAwB,CAC7C,MAAM6B,mBACL,OAAO9B,MAAMG,MAAM,GAAK,UACxBH,MAAMG,MAAM,GAAK,MACjB,uBAAwBH,MAAMG,MAAM,CACjCC,OAAOJ,MAAMG,MAAM,CAAC2B,kBAAkB,EACtC,UAEJ,MAAO,CACNpF,IACCiF,UAAY,QACTG,mBACA,CAAC,EAAEH,QAAQ,CAAC,EAAEG,mBAAmB,CAAC,CACtCF,SAAU7B,eAAeC,MAAOrB,QAChCkD,SAAU,SACX,CACD,CAEA,MAAO,CACNnF,IAAKiF,QACLC,SAAU7B,eAAeC,MAAOrB,QAChCkD,SAAUhD,eAAe6C,KAC1B,CACD,CAEA,SAASK,iBAAiBpD,MAAmB,EAC5C,GAAIjB,aAAaiB,QAAS,CACzB,MAAMqD,OAAS1F,eAAeG,GAAG,CAACkC,QAClC,GAAIqD,SAAWnF,UAAW,OAAOmF,MAClC,CAEA,MAAMC,WAAatE,gBAAgBgB,QACnC,MAAMuD,eAAiBzE,qBAAqBhB,GAAG,CAACwF,YAChD,GAAIC,iBAAmBrF,UAAW,CACjC,GAAIa,aAAaiB,QAAS,CACzBrC,eAAeS,GAAG,CAAC4B,OAAQuD,eAC5B,CACA,OAAOA,cACR,CAEA,MAAMC,SAAWrG,IAAIsG,OAAO,CAACzD,QAE7B,GAAIjB,aAAaiB,QAAS,CACzBrC,eAAeS,GAAG,CAAC4B,OAAQwD,SAC5B,CACA1E,qBAAqBV,GAAG,CAACkF,WAAYE,UAErC,OAAOA,QACR,CASO,SAASvG,qBACf+C,MAA6B,CAC7B+C,IAAa,EAEb,GAAI,OAAO/C,SAAW,UAAW,CAChC,OAAOA,MACR,CAEA,MAAMwD,SAAWJ,iBAAiBpD,QAClC,OAAOwD,SAAST,QAAU,IAC3B,CASO,SAAS/F,2BACfgD,MAA6B,CAC7B+C,IAAa,EAEb,GAAI,OAAO/C,SAAW,UAAW,CAChC,GAAIA,OAAQ,MAAO,EAAE,CAErB,MAAO,CACN,CACCjC,IAAK,QACLkF,SAAU,QACVC,SAAUhD,eAAe6C,KAC1B,EACA,AACF,CAEA,MAAMS,SAAWJ,iBAAiBpD,QAClC,MAAM0D,QAAUF,SAAST,MAEzB,GACCW,UAAY,MACZF,SAASG,MAAM,GAAK,MACpBH,SAASG,MAAM,GAAKzF,UACnB,CACD,MAAO,EAAE,AACV,CAEA,OAAOsF,SAASG,MAAM,CAACtE,GAAG,CAAC,AAACgC,OAAUyB,iBAAiBzB,MAAOrB,OAAQ+C,MACvE,CAwBO,SAAS7F,uBAAuB8C,MAAmB,EACzD,GAAI,CAAC4D,GAAAA,mBAAU,EAAC5D,QAAS,OAAOA,OAEhC,MAAM6D,OAAsB,CAAE,GAAG7D,MAAM,AAAC,CACxC,QAAO6D,OAAOC,QAAQ,AACtB,QAAOD,OAAOE,oBAAoB,CAGlC,GAAIH,GAAAA,mBAAU,EAACC,OAAO/B,UAAU,EAAG,CAClC,MAAMkC,MAA+C,CAAC,EACtD,IAAK,KAAM,CAACjG,IAAKC,MAAM,GAAIyB,OAAOD,OAAO,CACxCqE,OAAO/B,UAAU,EACf,CACFkC,KAAK,CAACjG,IAAI,CACT,OAAOC,QAAU,UAAYA,QAAU,KACpCd,uBAAuBc,OACvBA,KACL,CACA6F,OAAO/B,UAAU,CAAGkC,KACrB,CAGA,GAAIJ,GAAAA,mBAAU,EAACC,OAAOI,KAAK,GAAK,CAAC9E,MAAMC,OAAO,CAACyE,OAAOI,KAAK,EAAG,CAC7DJ,OAAOI,KAAK,CAAG/G,uBAAuB2G,OAAOI,KAAK,CACnD,CAGA,GAAI9E,MAAMC,OAAO,CAACyE,OAAOI,KAAK,EAAG,CAChCJ,OAAOI,KAAK,CAAG,AAACJ,OAAOI,KAAK,CAA6B5E,GAAG,CAAC,AAAC6E,MAC7D,OAAOA,OAAS,UAAYA,OAAS,KAClChH,uBAAuBgH,MACvBA,KAEL,CAGA,IAAK,MAAM5C,UAAW,CAAC,QAAS,QAAS,QAAQ,CAAW,CAC3D,GAAInC,MAAMC,OAAO,CAACyE,MAAM,CAACvC,QAAQ,EAAG,CACnCuC,MAAM,CAACvC,QAAQ,CAAG,AAACuC,MAAM,CAACvC,QAAQ,CAA6BjC,GAAG,CACjE,AAAC8E,QACA,OAAOA,SAAW,UAAYA,SAAW,KACtCjH,uBAAuBiH,QACvBA,OAEN,CACD,CAGA,GAAIP,GAAAA,mBAAU,EAACC,OAAOO,IAAI,EAAG,CAC5BP,OAAOO,IAAI,CAAGlH,uBAAuB2G,OAAOO,IAAI,CACjD,CACA,GAAIR,GAAAA,mBAAU,EAACC,OAAOQ,IAAI,EAAG,CAC5BR,OAAOQ,IAAI,CAAGnH,uBAAuB2G,OAAOQ,IAAI,CACjD,CAEA,OAAOR,MACR,CAWO,SAAS9G,kCACfiD,MAA6B,CAC7B+C,IAAa,EAEb,GAAI,OAAO/C,SAAW,UAAW,CAChC,OAAOhD,2BAA2BgD,OAAQ+C,KAC3C,CAEA,MAAMuB,SAAWpH,uBAAuB8C,QACxC,OAAOhD,2BAA2BsH,SAAUvB,KAC7C,CAaO,SAASjG,0BAQfgC,qBAAqBH,KAAK,GAG1BxB,IAAIoH,YAAY,EACjB"}