json-schema-compatibility-checker 1.1.8 → 1.1.9
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.
|
@@ -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 checkAtomic(){return checkAtomic},get checkBranchedSub(){return checkBranchedSub},get checkBranchedSup(){return checkBranchedSup},get getBranchesTyped(){return getBranchesTyped},get isAtomicSubsetOf(){return isAtomicSubsetOf}});const _formatvalidatorts=require("./format-validator.js");const _normalizerts=require("./normalizer.js");const _patternsubsetts=require("./pattern-subset.js");const _semanticerrorsts=require("./semantic-errors.js");const _utilsts=require("./utils.js");const BRANCH_TRUE={branches:[true],type:"none"};const BRANCH_FALSE={branches:[false],type:"none"};const atomicBranchCache=new WeakMap;function getBranchesTyped(def){if(typeof def==="boolean"){return def?BRANCH_TRUE:BRANCH_FALSE}if((0,_utilsts.hasOwn)(def,"anyOf")&&Array.isArray(def.anyOf)){return{branches:def.anyOf,type:"anyOf"}}if((0,_utilsts.hasOwn)(def,"oneOf")&&Array.isArray(def.oneOf)){return{branches:def.oneOf,type:"oneOf"}}let cached=atomicBranchCache.get(def);if(cached===undefined){cached={branches:[def],type:"none"};atomicBranchCache.set(def,cached)}return cached}function evaluateNot(sub,sup){if(typeof sub==="boolean"||typeof sup==="boolean")return null;if((0,_utilsts.hasOwn)(sup,"not")&&(0,_utilsts.isPlainObj)(sup.not)){const notSchema=sup.not;if((0,_utilsts.isPlainObj)(notSchema.properties)&&Array.isArray(notSchema.required)){const notProps=notSchema.properties;const notRequired=notSchema.required;if((0,_utilsts.isPlainObj)(sub.properties)){const subProps=sub.properties;const subRequired=Array.isArray(sub.required)?sub.required:[];const notPropKeys=Object.keys(notProps);const hasIncompatibleProp=notPropKeys.some(key=>{const notPropDef=notProps[key];if(typeof notPropDef==="boolean")return false;const notProp=notPropDef;if(notRequired.includes(key)&&!subRequired.includes(key)&&!(0,_utilsts.hasOwn)(subProps,key)){return true}if(!(0,_utilsts.hasOwn)(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return false;const subProp=subPropDef;if((0,_utilsts.hasOwn)(notProp,"const")&&(0,_utilsts.hasOwn)(subProp,"const")){if(!(0,_utilsts.deepEqual)(notProp.const,subProp.const)){return true}}if((0,_utilsts.hasOwn)(notProp,"enum")&&Array.isArray(notProp.enum)){if((0,_utilsts.hasOwn)(subProp,"const")){const inNotEnum=notProp.enum.some(v=>(0,_utilsts.deepEqual)(v,subProp.const));if(!inNotEnum)return true}if((0,_utilsts.hasOwn)(subProp,"enum")&&Array.isArray(subProp.enum)){const noneInNotEnum=subProp.enum.every(v=>!notProp.enum?.some(nv=>(0,_utilsts.deepEqual)(v,nv)));if(noneInNotEnum)return true}}return false});if(hasIncompatibleProp)return true;const allPropsMatch=notPropKeys.every(key=>{const notPropDef=notProps[key];if(typeof notPropDef==="boolean")return true;const notProp=notPropDef;if(notRequired.includes(key)&&!subRequired.includes(key))return false;if(!(0,_utilsts.hasOwn)(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return true;const subProp=subPropDef;if((0,_utilsts.hasOwn)(notProp,"const")&&(0,_utilsts.hasOwn)(subProp,"const")){return(0,_utilsts.deepEqual)(notProp.const,subProp.const)}if((0,_utilsts.hasOwn)(notProp,"enum")&&Array.isArray(notProp.enum)){if((0,_utilsts.hasOwn)(subProp,"const")){return notProp.enum.some(v=>(0,_utilsts.deepEqual)(v,subProp.const))}if((0,_utilsts.hasOwn)(subProp,"enum")&&Array.isArray(subProp.enum)){return subProp.enum.every(v=>notProp.enum?.some(nv=>(0,_utilsts.deepEqual)(v,nv)))}}return false});if(allPropsMatch)return false}}if((0,_utilsts.hasOwn)(notSchema,"const")&&(0,_utilsts.hasOwn)(sub,"const")){const notConst=notSchema.const;const subConst=sub.const;if((0,_utilsts.deepEqual)(subConst,notConst))return false;return true}if((0,_utilsts.hasOwn)(notSchema,"enum")&&Array.isArray(notSchema.enum)&&(0,_utilsts.hasOwn)(sub,"enum")&&Array.isArray(sub.enum)){const allExcluded=sub.enum.every(val=>!notSchema.enum?.some(notVal=>(0,_utilsts.deepEqual)(val,notVal)));if(allExcluded)return true}if((0,_utilsts.hasOwn)(notSchema,"type")&&(0,_utilsts.hasOwn)(sub,"type")){const notType=notSchema.type;const subType=sub.type;if(typeof notType==="string"&&typeof subType==="string"){if(!(0,_utilsts.hasOwn)(notSchema,"const")&&!(0,_utilsts.hasOwn)(notSchema,"enum")&&!(0,_utilsts.isPlainObj)(notSchema.properties)){if(subType===notType)return false;return true}}if(Array.isArray(notType)&&typeof subType==="string"){if(notType.includes(subType))return false;return true}}if((0,_utilsts.hasOwn)(notSchema,"anyOf")&&Array.isArray(notSchema.anyOf)){const branches=notSchema.anyOf;const allIncompatible=branches.every(branch=>{if(typeof branch==="boolean")return!branch;const result=evaluateNot(sub,{not:branch});return result===true});if(allIncompatible)return true;const anyBranchMatches=branches.some(branch=>{if(typeof branch==="boolean")return branch;const result=evaluateNot(sub,{not:branch});return result===false});if(anyBranchMatches)return false}if((0,_utilsts.hasOwn)(notSchema,"oneOf")&&Array.isArray(notSchema.oneOf)){const branches=notSchema.oneOf;const allIncompatible=branches.every(branch=>{if(typeof branch==="boolean")return!branch;const result=evaluateNot(sub,{not:branch});return result===true});if(allIncompatible)return true;const anyBranchMatches=branches.some(branch=>{if(typeof branch==="boolean")return branch;const result=evaluateNot(sub,{not:branch});return result===false});if(anyBranchMatches)return false}if((0,_utilsts.hasOwn)(notSchema,"format")&&(0,_utilsts.hasOwn)(sub,"format")){const subFormat=sub.format;const notFormat=notSchema.format;if(subFormat===notFormat)return false;return true}}if((0,_utilsts.hasOwn)(sub,"not")&&(0,_utilsts.hasOwn)(sup,"not")){if((0,_utilsts.deepEqual)(sub.not,sup.not))return true}return null}function stripNotFromSup(sub,sup,stripTopLevel=true){if(typeof sup==="boolean"||typeof sub==="boolean")return sup;let result=sup;if(stripTopLevel&&(0,_utilsts.hasOwn)(result,"not")){result=(0,_utilsts.omitKeys)(result,["not"])}if((0,_utilsts.isPlainObj)(result.properties)&&(0,_utilsts.isPlainObj)(sub.properties)){const subProps=sub.properties;const supProps=result.properties;let newProps;for(const key of Object.keys(supProps)){const supPropDef=supProps[key];const subPropDef=subProps[key];if(supPropDef!==undefined&&subPropDef!==undefined&&typeof supPropDef!=="boolean"&&typeof subPropDef!=="boolean"&&(0,_utilsts.hasOwn)(supPropDef,"not")){const propNotResult=evaluateNot(subPropDef,supPropDef);if(propNotResult===true){if(!newProps)newProps={...supProps};newProps[key]=(0,_utilsts.omitKeys)(supPropDef,["not"])}}}if(newProps){result={...result,properties:newProps}}}return result}function stripPatternFromSup(sub,sup){if(typeof sub==="boolean"||typeof sup==="boolean")return sup;const supObj=sup;let result=supObj;let copied=false;function ensureCopy(){if(!copied){result={...supObj};copied=true}return result}if((0,_utilsts.hasOwn)(result,"pattern")&&(0,_utilsts.hasOwn)(sub,"pattern")&&result.pattern!==sub.pattern){const patResult=(0,_patternsubsetts.isPatternSubset)(sub.pattern,result.pattern);if(patResult===true){result=(0,_utilsts.omitKeys)(ensureCopy(),["pattern"]);copied=true}}if((0,_utilsts.isPlainObj)(result.properties)&&(0,_utilsts.isPlainObj)(sub.properties)){const subProps=sub.properties;const supProps=result.properties;let propsModified=false;let newProps;for(const key of Object.keys(supProps)){const supPropDef=supProps[key];const subPropDef=subProps[key];if(supPropDef!==undefined&&subPropDef!==undefined&&typeof supPropDef!=="boolean"&&typeof subPropDef!=="boolean"&&(0,_utilsts.hasOwn)(supPropDef,"pattern")&&(0,_utilsts.hasOwn)(subPropDef,"pattern")&&supPropDef.pattern!==subPropDef.pattern){const propPatResult=(0,_patternsubsetts.isPatternSubset)(subPropDef.pattern,supPropDef.pattern);if(propPatResult===true){if(!newProps)newProps={...supProps};newProps[key]=(0,_utilsts.omitKeys)(supPropDef,["pattern"]);propsModified=true}}}if(propsModified&&newProps){ensureCopy().properties=newProps}}if((0,_utilsts.isPlainObj)(result.items)&&typeof result.items!=="boolean"&&(0,_utilsts.isPlainObj)(sub.items)&&typeof sub.items!=="boolean"){const subItems=sub.items;const supItems=result.items;if((0,_utilsts.hasOwn)(supItems,"pattern")&&(0,_utilsts.hasOwn)(subItems,"pattern")&&supItems.pattern!==subItems.pattern){const itemsPatResult=(0,_patternsubsetts.isPatternSubset)(subItems.pattern,supItems.pattern);if(itemsPatResult===true){ensureCopy().items=(0,_utilsts.omitKeys)(supItems,["pattern"])}}}return result}function stripVacuousFalseProperties(merged,sub){if(typeof merged==="boolean"||typeof sub==="boolean")return merged;if(!(0,_utilsts.isPlainObj)(merged.properties))return merged;const mergedProps=merged.properties;const subProps=(0,_utilsts.isPlainObj)(sub.properties)?sub.properties:{};let strippedProps=null;for(const key of Object.keys(mergedProps)){if(mergedProps[key]===false&&!(0,_utilsts.hasOwn)(subProps,key)){if(strippedProps===null){strippedProps={...mergedProps}}delete strippedProps[key]}}if(strippedProps===null)return merged;const result={...merged,properties:strippedProps};if(Object.keys(strippedProps).length===0&&!(0,_utilsts.isPlainObj)(sub.properties)){delete result.properties}return result}function hasNestedBranching(schema){if(typeof schema==="boolean")return false;if((0,_utilsts.isPlainObj)(schema.properties)){const props=schema.properties;for(const key of Object.keys(props)){const prop=props[key];if(prop===undefined||typeof prop==="boolean")continue;if((0,_utilsts.hasOwn)(prop,"oneOf")||(0,_utilsts.hasOwn)(prop,"anyOf"))return true;if(hasNestedBranching(prop))return true}}if((0,_utilsts.isPlainObj)(schema.items)&&typeof schema.items!=="boolean"){const items=schema.items;if((0,_utilsts.hasOwn)(items,"oneOf")||(0,_utilsts.hasOwn)(items,"anyOf"))return true;if(hasNestedBranching(items))return true}return false}function isPropertySubsetOf(sub,sup,engine){const{branches:subBranches}=getBranchesTyped(sub);if(subBranches.length>1||subBranches[0]!==sub){for(const branch of subBranches){if(branch===undefined)continue;if(!isAtomicSubsetOf(branch,sup,engine))return false}return true}return isAtomicSubsetOf(sub,sup,engine)}function isObjectSubsetByProperties(sub,sup,engine){const subIsObj=sub.type==="object"||(0,_utilsts.isPlainObj)(sub.properties);const supIsObj=sup.type==="object"||(0,_utilsts.isPlainObj)(sup.properties);if(!subIsObj&&!supIsObj){if(sub.type==="array"&&sup.type==="array"&&(0,_utilsts.isPlainObj)(sub.items)&&(0,_utilsts.isPlainObj)(sup.items)){return isPropertySubsetOf(sub.items,sup.items,engine)}return false}if(!subIsObj||!supIsObj)return false;if((0,_utilsts.hasOwn)(sub,"type")&&(0,_utilsts.hasOwn)(sup,"type")&&sub.type!==sup.type){return false}const subProps=(0,_utilsts.isPlainObj)(sub.properties)?sub.properties:{};const supProps=(0,_utilsts.isPlainObj)(sup.properties)?sup.properties:{};const subRequired=Array.isArray(sub.required)?sub.required:[];const supRequired=Array.isArray(sup.required)?sup.required:[];for(const key of supRequired){if(!subRequired.includes(key))return false}if(sup.additionalProperties===false){for(const key of Object.keys(subProps)){if(!(0,_utilsts.hasOwn)(supProps,key))return false}}for(const key of Object.keys(supProps)){const supProp=supProps[key];const subProp=subProps[key];if(supProp===undefined||subProp===undefined)continue;if(!isPropertySubsetOf(subProp,supProp,engine)){return false}}if((0,_utilsts.isPlainObj)(sup.additionalProperties)&&typeof sup.additionalProperties!=="boolean"){const addPropSchema=sup.additionalProperties;for(const key of Object.keys(subProps)){if((0,_utilsts.hasOwn)(supProps,key))continue;const subProp=subProps[key];if(subProp===undefined)continue;if(!isPropertySubsetOf(subProp,addPropSchema,engine)){return false}}}if((0,_utilsts.isPlainObj)(sub.items)&&(0,_utilsts.isPlainObj)(sup.items)){if(!isPropertySubsetOf(sub.items,sup.items,engine)){return false}}return true}function tryNestedBranchingFallback(sub,sup,engine){if(typeof sub==="boolean"||typeof sup==="boolean")return null;if(!hasNestedBranching(sub)&&!hasNestedBranching(sup))return null;return isObjectSubsetByProperties(sub,sup,engine)}function isAtomicSubsetOf(sub,sup,engine){const{branches:supBranches}=getBranchesTyped(sup);if(supBranches.length===1&&supBranches[0]===sup){const notResult=evaluateNot(sub,sup);if(notResult===false)return false;if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&(0,_utilsts.hasOwn)(sub,"format")&&(0,_utilsts.hasOwn)(sup,"format")&&sub.format!==sup.format){const fmtResult=(0,_formatvalidatorts.isFormatSubset)(sub.format,sup.format);if(fmtResult!==true)return false}if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&(0,_utilsts.hasOwn)(sub,"pattern")&&(0,_utilsts.hasOwn)(sup,"pattern")&&sub.pattern!==sup.pattern){const patResult=(0,_patternsubsetts.isPatternSubset)(sub.pattern,sup.pattern);if(patResult===false)return false}let effectiveSup=sup;if(typeof sup!=="boolean"){if(notResult===true){effectiveSup=stripNotFromSup(sub,sup,true);if(typeof effectiveSup!=="boolean"&&Object.keys(effectiveSup).length===0){return true}}else{effectiveSup=stripNotFromSup(sub,sup,false)}effectiveSup=stripPatternFromSup(sub,effectiveSup)}const merged=engine.merge(sub,effectiveSup);if(merged===null){return tryNestedBranchingFallback(sub,effectiveSup,engine)??false}if((0,_utilsts.deepEqual)(merged,sub))return true;const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&(0,_utilsts.deepEqual)(strippedMerged,sub)){return true}const normalizedMerged=(0,_normalizerts.normalize)(strippedMerged);if((0,_utilsts.deepEqual)(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return true}return tryNestedBranchingFallback(sub,effectiveSup,engine)??false}return supBranches.some(branch=>{const notResult=evaluateNot(sub,branch);if(notResult===false)return false;if(typeof sub!=="boolean"&&typeof branch!=="boolean"&&(0,_utilsts.hasOwn)(sub,"pattern")&&(0,_utilsts.hasOwn)(branch,"pattern")&&sub.pattern!==branch.pattern){const patResult=(0,_patternsubsetts.isPatternSubset)(sub.pattern,branch.pattern);if(patResult===false)return false}let effectiveBranch=branch;if(typeof branch!=="boolean"){if(notResult===true){effectiveBranch=stripNotFromSup(sub,branch,true);if(typeof effectiveBranch!=="boolean"&&Object.keys(effectiveBranch).length===0){return true}}else{effectiveBranch=stripNotFromSup(sub,branch,false)}effectiveBranch=stripPatternFromSup(sub,effectiveBranch)}const merged=engine.merge(sub,effectiveBranch);if(merged===null){return tryNestedBranchingFallback(sub,effectiveBranch,engine)===true}if((0,_utilsts.deepEqual)(merged,sub))return true;const strippedBranch=stripVacuousFalseProperties(merged,sub);if(strippedBranch!==merged&&(0,_utilsts.deepEqual)(strippedBranch,sub)){return true}const normalizedBranch=(0,_normalizerts.normalize)(strippedBranch);if((0,_utilsts.deepEqual)(normalizedBranch,sub)||engine.isEqual(normalizedBranch,sub)){return true}return tryNestedBranchingFallback(sub,effectiveBranch,engine)===true})}function checkBranchedSub(subBranches,sup,engine,branchType="anyOf"){const allErrors=[];let allSubset=true;for(let i=0;i<subBranches.length;i++){const branch=subBranches[i];if(branch===undefined)continue;if(!isAtomicSubsetOf(branch,sup,engine)){allSubset=false;const branchErrors=(0,_semanticerrorsts.computeSemanticErrors)(branch,sup,"");allErrors.push(...branchErrors)}}return{isSubset:allSubset,merged:allSubset?branchType==="oneOf"?{oneOf:subBranches}:{anyOf:subBranches}:null,errors:allErrors}}function checkBranchedSup(sub,supBranches,engine,_branchType="anyOf"){for(const branch of supBranches){let effectiveBranch=branch;if(typeof sub!=="boolean"&&typeof branch!=="boolean"){effectiveBranch=stripPatternFromSup(sub,branch)}const merged=engine.merge(sub,effectiveBranch);if(merged!==null){if((0,_utilsts.deepEqual)(merged,sub)){return{isSubset:true,merged,errors:[]}}const normalizedMerged=(0,_normalizerts.normalize)(merged);if((0,_utilsts.deepEqual)(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged,errors:[]}}}}const semanticErrors=(0,_semanticerrorsts.computeSemanticErrors)(sub,{anyOf:supBranches},"");return{isSubset:false,merged:null,errors:semanticErrors}}function checkAtomic(sub,sup,engine){let effectiveSup=sup;if(typeof sub!=="boolean"&&typeof sup!=="boolean"){effectiveSup=stripPatternFromSup(sub,sup)}try{const merged=engine.mergeOrThrow(sub,effectiveSup);if((0,_utilsts.deepEqual)(merged,sub)){return{isSubset:true,merged,errors:[]}}const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&(0,_utilsts.deepEqual)(strippedMerged,sub)){return{isSubset:true,merged:strippedMerged,errors:[]}}const normalizedMerged=(0,_normalizerts.normalize)(strippedMerged);if((0,_utilsts.deepEqual)(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged:normalizedMerged,errors:[]}}if(tryNestedBranchingFallback(sub,effectiveSup,engine)===true){return{isSubset:true,merged:sub,errors:[]}}const errors=(0,_semanticerrorsts.computeSemanticErrors)(sub,sup,"");return{isSubset:false,merged:normalizedMerged,errors}}catch(_e){if(tryNestedBranchingFallback(sub,effectiveSup,engine)===true){return{isSubset:true,merged:sub,errors:[]}}const errors=(0,_semanticerrorsts.computeSemanticErrors)(sub,sup,"");return{isSubset:false,merged:null,errors}}}
|
|
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 checkAtomic(){return checkAtomic},get checkBranchedSub(){return checkBranchedSub},get checkBranchedSup(){return checkBranchedSup},get getBranchesTyped(){return getBranchesTyped},get isAtomicSubsetOf(){return isAtomicSubsetOf}});const _formatvalidatorts=require("./format-validator.js");const _normalizerts=require("./normalizer.js");const _patternsubsetts=require("./pattern-subset.js");const _semanticerrorsts=require("./semantic-errors.js");const _utilsts=require("./utils.js");const BRANCH_TRUE={branches:[true],type:"none"};const BRANCH_FALSE={branches:[false],type:"none"};const atomicBranchCache=new WeakMap;function getBranchesTyped(def){if(typeof def==="boolean"){return def?BRANCH_TRUE:BRANCH_FALSE}if((0,_utilsts.hasOwn)(def,"anyOf")&&Array.isArray(def.anyOf)){return{branches:def.anyOf,type:"anyOf"}}if((0,_utilsts.hasOwn)(def,"oneOf")&&Array.isArray(def.oneOf)){return{branches:def.oneOf,type:"oneOf"}}let cached=atomicBranchCache.get(def);if(cached===undefined){cached={branches:[def],type:"none"};atomicBranchCache.set(def,cached)}return cached}function evaluateNot(sub,sup){if(typeof sub==="boolean"||typeof sup==="boolean")return null;if((0,_utilsts.hasOwn)(sup,"not")&&(0,_utilsts.isPlainObj)(sup.not)){const notSchema=sup.not;if((0,_utilsts.isPlainObj)(notSchema.properties)&&Array.isArray(notSchema.required)){const notProps=notSchema.properties;const notRequired=notSchema.required;if((0,_utilsts.isPlainObj)(sub.properties)){const subProps=sub.properties;const subRequired=Array.isArray(sub.required)?sub.required:[];const notPropKeys=Object.keys(notProps);const hasIncompatibleProp=notPropKeys.some(key=>{const notPropDef=notProps[key];if(typeof notPropDef==="boolean")return false;const notProp=notPropDef;if(notRequired.includes(key)&&!subRequired.includes(key)&&!(0,_utilsts.hasOwn)(subProps,key)){return true}if(!(0,_utilsts.hasOwn)(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return false;const subProp=subPropDef;if((0,_utilsts.hasOwn)(notProp,"const")&&(0,_utilsts.hasOwn)(subProp,"const")){if(!(0,_utilsts.deepEqual)(notProp.const,subProp.const)){return true}}if((0,_utilsts.hasOwn)(notProp,"enum")&&Array.isArray(notProp.enum)){if((0,_utilsts.hasOwn)(subProp,"const")){const inNotEnum=notProp.enum.some(v=>(0,_utilsts.deepEqual)(v,subProp.const));if(!inNotEnum)return true}if((0,_utilsts.hasOwn)(subProp,"enum")&&Array.isArray(subProp.enum)){const noneInNotEnum=subProp.enum.every(v=>!notProp.enum?.some(nv=>(0,_utilsts.deepEqual)(v,nv)));if(noneInNotEnum)return true}}return false});if(hasIncompatibleProp)return true;const allPropsMatch=notPropKeys.every(key=>{const notPropDef=notProps[key];if(typeof notPropDef==="boolean")return true;const notProp=notPropDef;if(notRequired.includes(key)&&!subRequired.includes(key))return false;if(!(0,_utilsts.hasOwn)(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return true;const subProp=subPropDef;if((0,_utilsts.hasOwn)(notProp,"const")&&(0,_utilsts.hasOwn)(subProp,"const")){return(0,_utilsts.deepEqual)(notProp.const,subProp.const)}if((0,_utilsts.hasOwn)(notProp,"enum")&&Array.isArray(notProp.enum)){if((0,_utilsts.hasOwn)(subProp,"const")){return notProp.enum.some(v=>(0,_utilsts.deepEqual)(v,subProp.const))}if((0,_utilsts.hasOwn)(subProp,"enum")&&Array.isArray(subProp.enum)){return subProp.enum.every(v=>notProp.enum?.some(nv=>(0,_utilsts.deepEqual)(v,nv)))}}return false});if(allPropsMatch)return false}}if((0,_utilsts.hasOwn)(notSchema,"const")&&(0,_utilsts.hasOwn)(sub,"const")){const notConst=notSchema.const;const subConst=sub.const;if((0,_utilsts.deepEqual)(subConst,notConst))return false;return true}if((0,_utilsts.hasOwn)(notSchema,"enum")&&Array.isArray(notSchema.enum)&&(0,_utilsts.hasOwn)(sub,"enum")&&Array.isArray(sub.enum)){const allExcluded=sub.enum.every(val=>!notSchema.enum?.some(notVal=>(0,_utilsts.deepEqual)(val,notVal)));if(allExcluded)return true}if((0,_utilsts.hasOwn)(notSchema,"type")&&(0,_utilsts.hasOwn)(sub,"type")){const notType=notSchema.type;const subType=sub.type;if(typeof notType==="string"&&typeof subType==="string"){if(!(0,_utilsts.hasOwn)(notSchema,"const")&&!(0,_utilsts.hasOwn)(notSchema,"enum")&&!(0,_utilsts.isPlainObj)(notSchema.properties)){if(subType===notType)return false;return true}}if(Array.isArray(notType)&&typeof subType==="string"){if(notType.includes(subType))return false;return true}}if((0,_utilsts.hasOwn)(notSchema,"anyOf")&&Array.isArray(notSchema.anyOf)){const branches=notSchema.anyOf;const allIncompatible=branches.every(branch=>{if(typeof branch==="boolean")return!branch;const result=evaluateNot(sub,{not:branch});return result===true});if(allIncompatible)return true;const anyBranchMatches=branches.some(branch=>{if(typeof branch==="boolean")return branch;const result=evaluateNot(sub,{not:branch});return result===false});if(anyBranchMatches)return false}if((0,_utilsts.hasOwn)(notSchema,"oneOf")&&Array.isArray(notSchema.oneOf)){const branches=notSchema.oneOf;const allIncompatible=branches.every(branch=>{if(typeof branch==="boolean")return!branch;const result=evaluateNot(sub,{not:branch});return result===true});if(allIncompatible)return true;const anyBranchMatches=branches.some(branch=>{if(typeof branch==="boolean")return branch;const result=evaluateNot(sub,{not:branch});return result===false});if(anyBranchMatches)return false}if((0,_utilsts.hasOwn)(notSchema,"format")&&(0,_utilsts.hasOwn)(sub,"format")){const subFormat=sub.format;const notFormat=notSchema.format;if(subFormat===notFormat)return false;return true}}if((0,_utilsts.hasOwn)(sub,"not")&&(0,_utilsts.hasOwn)(sup,"not")){if((0,_utilsts.deepEqual)(sub.not,sup.not))return true}return null}function stripNotFromSup(sub,sup,stripTopLevel=true){if(typeof sup==="boolean"||typeof sub==="boolean")return sup;let result=sup;if(stripTopLevel&&(0,_utilsts.hasOwn)(result,"not")){result=(0,_utilsts.omitKeys)(result,["not"])}if((0,_utilsts.isPlainObj)(result.properties)&&(0,_utilsts.isPlainObj)(sub.properties)){const subProps=sub.properties;const supProps=result.properties;let newProps;for(const key of Object.keys(supProps)){const supPropDef=supProps[key];const subPropDef=subProps[key];if(supPropDef!==undefined&&subPropDef!==undefined&&typeof supPropDef!=="boolean"&&typeof subPropDef!=="boolean"&&(0,_utilsts.hasOwn)(supPropDef,"not")){const propNotResult=evaluateNot(subPropDef,supPropDef);if(propNotResult===true){if(!newProps)newProps={...supProps};newProps[key]=(0,_utilsts.omitKeys)(supPropDef,["not"])}}}if(newProps){result={...result,properties:newProps}}}return result}function stripPatternFromSup(sub,sup){if(typeof sub==="boolean"||typeof sup==="boolean")return sup;const supObj=sup;let result=supObj;let copied=false;function ensureCopy(){if(!copied){result={...supObj};copied=true}return result}if((0,_utilsts.hasOwn)(result,"pattern")&&(0,_utilsts.hasOwn)(sub,"pattern")&&result.pattern!==sub.pattern){const patResult=(0,_patternsubsetts.isPatternSubset)(sub.pattern,result.pattern);if(patResult===true){result=(0,_utilsts.omitKeys)(ensureCopy(),["pattern"]);copied=true}}if((0,_utilsts.isPlainObj)(result.properties)&&(0,_utilsts.isPlainObj)(sub.properties)){const subProps=sub.properties;const supProps=result.properties;let propsModified=false;let newProps;for(const key of Object.keys(supProps)){const supPropDef=supProps[key];const subPropDef=subProps[key];if(supPropDef!==undefined&&subPropDef!==undefined&&typeof supPropDef!=="boolean"&&typeof subPropDef!=="boolean"&&(0,_utilsts.hasOwn)(supPropDef,"pattern")&&(0,_utilsts.hasOwn)(subPropDef,"pattern")&&supPropDef.pattern!==subPropDef.pattern){const propPatResult=(0,_patternsubsetts.isPatternSubset)(subPropDef.pattern,supPropDef.pattern);if(propPatResult===true){if(!newProps)newProps={...supProps};newProps[key]=(0,_utilsts.omitKeys)(supPropDef,["pattern"]);propsModified=true}}}if(propsModified&&newProps){ensureCopy().properties=newProps}}if((0,_utilsts.isPlainObj)(result.items)&&typeof result.items!=="boolean"&&(0,_utilsts.isPlainObj)(sub.items)&&typeof sub.items!=="boolean"){const subItems=sub.items;const supItems=result.items;if((0,_utilsts.hasOwn)(supItems,"pattern")&&(0,_utilsts.hasOwn)(subItems,"pattern")&&supItems.pattern!==subItems.pattern){const itemsPatResult=(0,_patternsubsetts.isPatternSubset)(subItems.pattern,supItems.pattern);if(itemsPatResult===true){ensureCopy().items=(0,_utilsts.omitKeys)(supItems,["pattern"])}}}return result}function stripVacuousFalseProperties(merged,sub){if(typeof merged==="boolean"||typeof sub==="boolean")return merged;if(!(0,_utilsts.isPlainObj)(merged.properties))return merged;const mergedProps=merged.properties;const subProps=(0,_utilsts.isPlainObj)(sub.properties)?sub.properties:{};let strippedProps=null;for(const key of Object.keys(mergedProps)){if(mergedProps[key]===false&&!(0,_utilsts.hasOwn)(subProps,key)){if(strippedProps===null){strippedProps={...mergedProps}}delete strippedProps[key]}}if(strippedProps===null)return merged;const result={...merged,properties:strippedProps};if(Object.keys(strippedProps).length===0&&!(0,_utilsts.isPlainObj)(sub.properties)){delete result.properties}return result}function hasNestedBranching(schema){if(typeof schema==="boolean")return false;if((0,_utilsts.isPlainObj)(schema.properties)){const props=schema.properties;for(const key of Object.keys(props)){const prop=props[key];if(prop===undefined||typeof prop==="boolean")continue;if((0,_utilsts.hasOwn)(prop,"oneOf")||(0,_utilsts.hasOwn)(prop,"anyOf"))return true;if(hasNestedBranching(prop))return true}}if((0,_utilsts.isPlainObj)(schema.items)&&typeof schema.items!=="boolean"){const items=schema.items;if((0,_utilsts.hasOwn)(items,"oneOf")||(0,_utilsts.hasOwn)(items,"anyOf"))return true;if(hasNestedBranching(items))return true}return false}function isPropertySubsetOf(sub,sup,engine){const{branches:subBranches}=getBranchesTyped(sub);if(subBranches.length>1||subBranches[0]!==sub){for(const branch of subBranches){if(branch===undefined)continue;if(!isAtomicSubsetOf(branch,sup,engine))return false}return true}return isAtomicSubsetOf(sub,sup,engine)}function isArrayConstraintsSubset(sub,sup){if(sup.minItems!==undefined){if(sub.minItems===undefined||sub.minItems<sup.minItems){return false}}if(sup.maxItems!==undefined){if(sub.maxItems===undefined||sub.maxItems>sup.maxItems){return false}}if(sup.uniqueItems===true&&sub.uniqueItems!==true){return false}return true}function isObjectSubsetByProperties(sub,sup,engine){const subIsObj=sub.type==="object"||(0,_utilsts.isPlainObj)(sub.properties);const supIsObj=sup.type==="object"||(0,_utilsts.isPlainObj)(sup.properties);if(!subIsObj&&!supIsObj){if(sub.type==="array"&&sup.type==="array"&&(0,_utilsts.isPlainObj)(sub.items)&&(0,_utilsts.isPlainObj)(sup.items)){if(!isPropertySubsetOf(sub.items,sup.items,engine)){return false}return isArrayConstraintsSubset(sub,sup)}return false}if(!subIsObj||!supIsObj)return false;if((0,_utilsts.hasOwn)(sub,"type")&&(0,_utilsts.hasOwn)(sup,"type")&&sub.type!==sup.type){return false}const subProps=(0,_utilsts.isPlainObj)(sub.properties)?sub.properties:{};const supProps=(0,_utilsts.isPlainObj)(sup.properties)?sup.properties:{};const subRequired=Array.isArray(sub.required)?sub.required:[];const supRequired=Array.isArray(sup.required)?sup.required:[];for(const key of supRequired){if(!subRequired.includes(key))return false}if(sup.additionalProperties===false){for(const key of Object.keys(subProps)){if(!(0,_utilsts.hasOwn)(supProps,key))return false}}for(const key of Object.keys(supProps)){const supProp=supProps[key];const subProp=subProps[key];if(supProp===undefined||subProp===undefined)continue;if(!isPropertySubsetOf(subProp,supProp,engine)){return false}}if((0,_utilsts.isPlainObj)(sup.additionalProperties)&&typeof sup.additionalProperties!=="boolean"){const addPropSchema=sup.additionalProperties;for(const key of Object.keys(subProps)){if((0,_utilsts.hasOwn)(supProps,key))continue;const subProp=subProps[key];if(subProp===undefined)continue;if(!isPropertySubsetOf(subProp,addPropSchema,engine)){return false}}}if((0,_utilsts.isPlainObj)(sub.items)&&(0,_utilsts.isPlainObj)(sup.items)){if(!isPropertySubsetOf(sub.items,sup.items,engine)){return false}if(!isArrayConstraintsSubset(sub,sup)){return false}}return true}function tryNestedBranchingFallback(sub,sup,engine){if(typeof sub==="boolean"||typeof sup==="boolean")return null;if(!hasNestedBranching(sub)&&!hasNestedBranching(sup))return null;return isObjectSubsetByProperties(sub,sup,engine)}function isAtomicSubsetOf(sub,sup,engine){const{branches:supBranches}=getBranchesTyped(sup);if(supBranches.length===1&&supBranches[0]===sup){const notResult=evaluateNot(sub,sup);if(notResult===false)return false;if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&(0,_utilsts.hasOwn)(sub,"format")&&(0,_utilsts.hasOwn)(sup,"format")&&sub.format!==sup.format){const fmtResult=(0,_formatvalidatorts.isFormatSubset)(sub.format,sup.format);if(fmtResult!==true)return false}if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&(0,_utilsts.hasOwn)(sub,"pattern")&&(0,_utilsts.hasOwn)(sup,"pattern")&&sub.pattern!==sup.pattern){const patResult=(0,_patternsubsetts.isPatternSubset)(sub.pattern,sup.pattern);if(patResult===false)return false}let effectiveSup=sup;if(typeof sup!=="boolean"){if(notResult===true){effectiveSup=stripNotFromSup(sub,sup,true);if(typeof effectiveSup!=="boolean"&&Object.keys(effectiveSup).length===0){return true}}else{effectiveSup=stripNotFromSup(sub,sup,false)}effectiveSup=stripPatternFromSup(sub,effectiveSup)}const merged=engine.merge(sub,effectiveSup);if(merged===null){return tryNestedBranchingFallback(sub,effectiveSup,engine)??false}if((0,_utilsts.deepEqual)(merged,sub))return true;const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&(0,_utilsts.deepEqual)(strippedMerged,sub)){return true}const normalizedMerged=(0,_normalizerts.normalize)(strippedMerged);if((0,_utilsts.deepEqual)(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return true}return tryNestedBranchingFallback(sub,effectiveSup,engine)??false}return supBranches.some(branch=>{const notResult=evaluateNot(sub,branch);if(notResult===false)return false;if(typeof sub!=="boolean"&&typeof branch!=="boolean"&&(0,_utilsts.hasOwn)(sub,"pattern")&&(0,_utilsts.hasOwn)(branch,"pattern")&&sub.pattern!==branch.pattern){const patResult=(0,_patternsubsetts.isPatternSubset)(sub.pattern,branch.pattern);if(patResult===false)return false}let effectiveBranch=branch;if(typeof branch!=="boolean"){if(notResult===true){effectiveBranch=stripNotFromSup(sub,branch,true);if(typeof effectiveBranch!=="boolean"&&Object.keys(effectiveBranch).length===0){return true}}else{effectiveBranch=stripNotFromSup(sub,branch,false)}effectiveBranch=stripPatternFromSup(sub,effectiveBranch)}const merged=engine.merge(sub,effectiveBranch);if(merged===null){return tryNestedBranchingFallback(sub,effectiveBranch,engine)===true}if((0,_utilsts.deepEqual)(merged,sub))return true;const strippedBranch=stripVacuousFalseProperties(merged,sub);if(strippedBranch!==merged&&(0,_utilsts.deepEqual)(strippedBranch,sub)){return true}const normalizedBranch=(0,_normalizerts.normalize)(strippedBranch);if((0,_utilsts.deepEqual)(normalizedBranch,sub)||engine.isEqual(normalizedBranch,sub)){return true}return tryNestedBranchingFallback(sub,effectiveBranch,engine)===true})}function checkBranchedSub(subBranches,sup,engine,branchType="anyOf"){const allErrors=[];let allSubset=true;for(let i=0;i<subBranches.length;i++){const branch=subBranches[i];if(branch===undefined)continue;if(!isAtomicSubsetOf(branch,sup,engine)){allSubset=false;const branchErrors=(0,_semanticerrorsts.computeSemanticErrors)(branch,sup,"");allErrors.push(...branchErrors)}}return{isSubset:allSubset,merged:allSubset?branchType==="oneOf"?{oneOf:subBranches}:{anyOf:subBranches}:null,errors:allErrors}}function checkBranchedSup(sub,supBranches,engine,_branchType="anyOf"){for(const branch of supBranches){let effectiveBranch=branch;if(typeof sub!=="boolean"&&typeof branch!=="boolean"){effectiveBranch=stripPatternFromSup(sub,branch)}const merged=engine.merge(sub,effectiveBranch);if(merged!==null){if((0,_utilsts.deepEqual)(merged,sub)){return{isSubset:true,merged,errors:[]}}const normalizedMerged=(0,_normalizerts.normalize)(merged);if((0,_utilsts.deepEqual)(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged,errors:[]}}}}const semanticErrors=(0,_semanticerrorsts.computeSemanticErrors)(sub,{anyOf:supBranches},"");return{isSubset:false,merged:null,errors:semanticErrors}}function checkAtomic(sub,sup,engine){let effectiveSup=sup;if(typeof sub!=="boolean"&&typeof sup!=="boolean"){effectiveSup=stripPatternFromSup(sub,sup)}try{const merged=engine.mergeOrThrow(sub,effectiveSup);if((0,_utilsts.deepEqual)(merged,sub)){return{isSubset:true,merged,errors:[]}}const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&(0,_utilsts.deepEqual)(strippedMerged,sub)){return{isSubset:true,merged:strippedMerged,errors:[]}}const normalizedMerged=(0,_normalizerts.normalize)(strippedMerged);if((0,_utilsts.deepEqual)(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged:normalizedMerged,errors:[]}}if(tryNestedBranchingFallback(sub,effectiveSup,engine)===true){return{isSubset:true,merged:sub,errors:[]}}const errors=(0,_semanticerrorsts.computeSemanticErrors)(sub,sup,"");return{isSubset:false,merged:normalizedMerged,errors}}catch(_e){if(tryNestedBranchingFallback(sub,effectiveSup,engine)===true){return{isSubset:true,merged:sub,errors:[]}}const errors=(0,_semanticerrorsts.computeSemanticErrors)(sub,sup,"");return{isSubset:false,merged:null,errors}}}
|
|
2
2
|
//# sourceMappingURL=subset-checker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/subset-checker.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { isFormatSubset } from \"./format-validator.ts\";\nimport type { MergeEngine } from \"./merge-engine.ts\";\nimport { normalize } from \"./normalizer.ts\";\nimport { isPatternSubset } from \"./pattern-subset.ts\";\nimport { computeSemanticErrors } from \"./semantic-errors.ts\";\nimport type { SchemaError, SubsetResult } from \"./types.ts\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys } from \"./utils.ts\";\n\n// ─── Subset Checker ──────────────────────────────────────────────────────────\n//\n// Subset verification logic via the approach:\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// Handles:\n// - Atomic schemas (no anyOf/oneOf)\n// - anyOf/oneOf in sub → each branch must be accepted by sup\n// - anyOf/oneOf in sup → at least one branch must accept sub\n// - Point 6: Distinguish anyOf / oneOf in diff messages\n// - Point 7: Extended `not` reasoning (evaluateNot)\n// - not.type, not.const, not.enum (existing)\n// - not with properties+required (1.1)\n// - not with anyOf/oneOf (1.2)\n// - not in sub (1.3)\n// - not.format (format-vs-format)\n//\n// Uses shared native helpers from `./utils` for optimal performance\n// (deepEqual, hasOwn, isPlainObj, omitKeys).\n\n// ─── Branch type ─────────────────────────────────────────────────────────────\n\n/**\n * Branch type detected in a schema.\n *\n * Point 6 — Distinguishes `anyOf` from `oneOf` to produce more precise\n * diff messages. `\"none\"` indicates an atomic schema (no branches).\n *\n * Note: the exclusivity semantics of `oneOf` are not verified\n * (this would be an NP-hard problem in general). The checker treats `oneOf`\n * like `anyOf` for subset checking, which is correct for the `sub ⊆ sup`\n * case but may produce false positives if the sub's branches overlap.\n */\nexport type BranchType = \"anyOf\" | \"oneOf\" | \"none\";\n\nexport interface BranchResult {\n\t/** The branches extracted from the schema */\n\tbranches: JSONSchema7Definition[];\n\t/** The detected branch type */\n\ttype: BranchType;\n}\n\n// ─── Branch extraction ───────────────────────────────────────────────────────\n\n// Pre-allocated singleton results for boolean schemas to avoid per-call allocations.\n// These are safe because the branches arrays are never mutated after creation.\nconst BRANCH_TRUE: BranchResult = { branches: [true], type: \"none\" };\nconst BRANCH_FALSE: BranchResult = { branches: [false], type: \"none\" };\n\n/**\n * WeakMap cache for atomic (no anyOf/oneOf) schema branch results.\n * Avoids allocating `{ branches: [def], type: \"none\" }` on every call\n * for the same schema object. Since normalized schemas are cached and\n * return the same reference, this cache hits frequently.\n */\nconst atomicBranchCache = new WeakMap<object, BranchResult>();\n\n/**\n * Extracts branches from a schema and the branch type.\n *\n * Returns the elements of `anyOf`/`oneOf` if they exist, otherwise returns\n * the schema itself in an array with type `\"none\"`.\n *\n * Point 6 — Distinguishes `anyOf` from `oneOf` in diff paths.\n *\n * Optimization: reuses pre-allocated objects for boolean cases\n * (true/false) and a WeakMap cache for atomic schemas to\n * avoid allocations on these frequent paths.\n */\nexport function getBranchesTyped(def: JSONSchema7Definition): BranchResult {\n\tif (typeof def === \"boolean\") {\n\t\treturn def ? BRANCH_TRUE : BRANCH_FALSE;\n\t}\n\tif (hasOwn(def, \"anyOf\") && Array.isArray(def.anyOf)) {\n\t\treturn { branches: def.anyOf, type: \"anyOf\" };\n\t}\n\tif (hasOwn(def, \"oneOf\") && Array.isArray(def.oneOf)) {\n\t\treturn { branches: def.oneOf, type: \"oneOf\" };\n\t}\n\t// Cache atomic results per schema object to avoid repeated allocations.\n\tlet cached = atomicBranchCache.get(def);\n\tif (cached === undefined) {\n\t\tcached = { branches: [def], type: \"none\" };\n\t\tatomicBranchCache.set(def, cached);\n\t}\n\treturn cached;\n}\n\n// ─── `not` reasoning (Point 7 — extended) ────────────────────────────────────\n\n/**\n * Extended `not` reasoning for common cases.\n *\n * Point 7 — Checks compatibility when `sup` and/or `sub` contain `not`:\n *\n * **Existing cases (not in sup):**\n * - `not.type`: excluded type vs sub's type\n * - `not.const`: excluded const vs sub's const\n * - `not.enum`: excluded values vs sub's enum\n *\n * **Added cases:**\n * - 1.1 — `not` with `properties` + `required`: verify that sub's properties\n * are incompatible with the `not`'s properties (different const/enum)\n * - 1.2 — `not` with `anyOf`/`oneOf`: `not(anyOf([A,B]))` ≡ `allOf([not(A), not(B)])`,\n * so sub must be incompatible with EACH branch\n * - 1.3 — `not` in `sub` (not only in `sup`): a sub with `not`\n * accepts a set too wide to be a subset of a concrete sup\n * - `not.format`: format-vs-format via `isFormatSubset`\n *\n * Conservative ternary contract:\n * - `true` → compatible (certain)\n * - `false` → incompatible (certain)\n * - `null` → undetermined (let the merge engine decide)\n *\n * When in doubt → `null`. NEVER return `true` without certainty.\n */\nfunction evaluateNot(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): boolean | null {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return null;\n\n\t// ── 1.3 — `not` in sub (not in sup) ──\n\t// A `not` in sub is an additional restriction: it excludes values from\n\t// the set accepted by sub, which makes it potentially smaller — thus\n\t// more likely to be ⊆ sup, not less.\n\t// We let the merge engine decide: allOf(sub, sup) will preserve the `not`\n\t// from sub, and the comparison merged ≡ sub will give the correct result.\n\t// Exception: if both have `not`, we handle the identity case below.\n\n\t// Check `not` in sup\n\tif (hasOwn(sup, \"not\") && isPlainObj(sup.not)) {\n\t\tconst notSchema = sup.not as JSONSchema7;\n\n\t\t// ── 1.1 — Case not with properties + required ──\n\t\t// IMPORTANT: this check is placed BEFORE the not.type check because when\n\t\t// the not has both `type` and `properties`, the not.type check alone\n\t\t// would produce a false negative (e.g. sub type=object and not type=object\n\t\t// would return false, but the properties could be incompatible\n\t\t// which would make sub compatible with the not).\n\t\t// If not contains properties with const/enum and required,\n\t\t// verify that sub's properties are incompatible with the not's properties.\n\t\tif (isPlainObj(notSchema.properties) && Array.isArray(notSchema.required)) {\n\t\t\tconst notProps = notSchema.properties as Record<\n\t\t\t\tstring,\n\t\t\t\tJSONSchema7Definition\n\t\t\t>;\n\t\t\tconst notRequired = notSchema.required as string[];\n\n\t\t\t// sub must have properties for us to compare\n\t\t\tif (isPlainObj(sub.properties)) {\n\t\t\t\tconst subProps = sub.properties as Record<\n\t\t\t\t\tstring,\n\t\t\t\t\tJSONSchema7Definition\n\t\t\t\t>;\n\t\t\t\tconst subRequired = Array.isArray(sub.required)\n\t\t\t\t\t? (sub.required as string[])\n\t\t\t\t\t: [];\n\t\t\t\tconst notPropKeys = Object.keys(notProps);\n\n\t\t\t\t// For sub to be compatible with not(schema),\n\t\t\t\t// it suffices that at least ONE property of the not is incompatible with sub.\n\t\t\t\t// This means that sub can never validate the schema inside not.\n\t\t\t\tconst hasIncompatibleProp = notPropKeys.some((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return false;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// If the property is required in not but NOT in sub.required\n\t\t\t\t\t// and it doesn't exist in sub.properties → sub may not\n\t\t\t\t\t// have this property → the not schema wouldn't match → compatible\n\t\t\t\t\tif (\n\t\t\t\t\t\tnotRequired.includes(key) &&\n\t\t\t\t\t\t!subRequired.includes(key) &&\n\t\t\t\t\t\t!hasOwn(subProps, key)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn true; // Property absent from sub → not doesn't match\n\t\t\t\t\t}\n\n\t\t\t\t\t// Compare the const/enum of the property\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return false;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// not.prop has a const, sub.prop has a different const → incompatible for this prop\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\tif (!deepEqual(notProp.const, subProp.const)) {\n\t\t\t\t\t\t\treturn true; // Different consts → sub doesn't match the not\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// not.prop has an enum, sub.prop has a const or enum with no value\n\t\t\t\t\t// in not.enum → incompatible for this prop\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\tconst inNotEnum = notProp.enum.some((v) =>\n\t\t\t\t\t\t\t\tdeepEqual(v, subProp.const),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!inNotEnum) return true; // sub.const absent from not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\tconst noneInNotEnum = subProp.enum.every(\n\t\t\t\t\t\t\t\t(v) => !notProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (noneInNotEnum) return true; // No value from sub.enum in not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\n\t\t\t\tif (hasIncompatibleProp) return true;\n\n\t\t\t\t// Inverse check: if ALL properties of the not match sub\n\t\t\t\t// exactly (same const, sub has the not's required), then sub VIOLATES the not\n\t\t\t\tconst allPropsMatch = notPropKeys.every((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return true;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// The property must be in sub.required if it is in not.required\n\t\t\t\t\tif (notRequired.includes(key) && !subRequired.includes(key))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return true;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// Check const match\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\treturn deepEqual(notProp.const, subProp.const);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check enum inclusion\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\treturn notProp.enum.some((v) => deepEqual(v, subProp.const));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\t// All values of sub.enum are in not.enum\n\t\t\t\t\t\t\treturn subProp.enum.every((v) =>\n\t\t\t\t\t\t\t\tnotProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false; // Undetermined for this property\n\t\t\t\t});\n\n\t\t\t\tif (allPropsMatch) return false; // sub matches the not exactly → incompatible\n\t\t\t}\n\t\t}\n\n\t\t// ── Case not.const ──\n\t\t// IMPORTANT: this check is placed BEFORE not.type because when the not has\n\t\t// both `type` and `const`, the not.type check alone would produce a\n\t\t// false negative (e.g. sub type=string const=\"active\" and not type=string\n\t\t// const=\"deleted\" → the type check would return false due to same type,\n\t\t// even though the consts are different → compatible).\n\t\tif (hasOwn(notSchema, \"const\") && hasOwn(sub, \"const\")) {\n\t\t\tconst notConst = notSchema.const;\n\t\t\tconst subConst = sub.const;\n\t\t\tif (deepEqual(subConst, notConst)) return false;\n\t\t\treturn true;\n\t\t}\n\n\t\t// ── Case not.enum ──\n\t\t// Also placed BEFORE not.type for the same reason.\n\t\tif (\n\t\t\thasOwn(notSchema, \"enum\") &&\n\t\t\tArray.isArray(notSchema.enum) &&\n\t\t\thasOwn(sub, \"enum\") &&\n\t\t\tArray.isArray(sub.enum)\n\t\t) {\n\t\t\t// All values of sub.enum must be absent from not.enum\n\t\t\tconst allExcluded = sub.enum.every(\n\t\t\t\t(val) => !notSchema.enum?.some((notVal) => deepEqual(val, notVal)),\n\t\t\t);\n\t\t\tif (allExcluded) return true;\n\t\t\t// Some values of sub are in not.enum → not automatically false,\n\t\t\t// the merge engine can still handle it\n\t\t}\n\n\t\t// ── Case not.type ──\n\t\t// Placed AFTER not.const, not.enum and properties+required to avoid\n\t\t// short-circuiting cases where the not has more specific constraints.\n\t\t// The type check alone is a fallback for simple not schemas\n\t\t// (e.g. { not: { type: \"string\" } }).\n\t\tif (hasOwn(notSchema, \"type\") && hasOwn(sub, \"type\")) {\n\t\t\tconst notType = notSchema.type;\n\t\t\tconst subType = sub.type;\n\n\t\t\t// If both are simple strings\n\t\t\tif (typeof notType === \"string\" && typeof subType === \"string\") {\n\t\t\t\t// Only return if the not does NOT have more specific constraints\n\t\t\t\t// (const, enum, properties) that should have been handled above\n\t\t\t\tif (\n\t\t\t\t\t!hasOwn(notSchema, \"const\") &&\n\t\t\t\t\t!hasOwn(notSchema, \"enum\") &&\n\t\t\t\t\t!isPlainObj(notSchema.properties)\n\t\t\t\t) {\n\t\t\t\t\tif (subType === notType) return false; // Incompatible: sub is exactly the excluded type\n\t\t\t\t\treturn true; // Compatible: sub is a different type from the excluded type\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If notType is an array, sub.type must not be in it\n\t\t\tif (Array.isArray(notType) && typeof subType === \"string\") {\n\t\t\t\tif (notType.includes(subType)) return false;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// ── 1.2 — Case not with anyOf / oneOf ──\n\t\t// not(anyOf([A, B])) ≡ allOf([not(A), not(B)])\n\t\t// For sub ⊆ not(anyOf(...)), sub must be incompatible with EACH branch.\n\t\tif (hasOwn(notSchema, \"anyOf\") && Array.isArray(notSchema.anyOf)) {\n\t\t\tconst branches = notSchema.anyOf as JSONSchema7Definition[];\n\t\t\t// For each branch of not.anyOf, verify that sub is incompatible\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch; // not(true) = nothing, not(false) = everything\n\t\t\t\t// Create a virtual sup { not: branch } and verify recursively\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\t// result = true → sub is compatible with not(branch) → sub ⊄ branch → OK\n\t\t\t\t// result = false → sub is incompatible with not(branch) → sub ⊆ branch → not OK\n\t\t\t\t// result = null → undetermined\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\t// Check if at least one branch accepts sub → incompatible with not(anyOf)\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false; // sub is incompatible with not(branch) → sub ⊆ branch\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// Same logic for oneOf (in the not context, treated like anyOf)\n\t\tif (hasOwn(notSchema, \"oneOf\") && Array.isArray(notSchema.oneOf)) {\n\t\t\tconst branches = notSchema.oneOf as JSONSchema7Definition[];\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false;\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// ── Case not.format (format-vs-format only) ──\n\t\t// If not has a format and sub also does, check compatibility\n\t\tif (hasOwn(notSchema, \"format\") && hasOwn(sub, \"format\")) {\n\t\t\tconst subFormat = sub.format as string;\n\t\t\tconst notFormat = notSchema.format as string;\n\t\t\tif (subFormat === notFormat) return false; // Incompatible: sub has exactly the excluded format\n\t\t\t// Different formats → compatible (conservative approximation)\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Check `not` in sub AND in sup (identity: { not: X } ⊆ { not: X })\n\tif (hasOwn(sub, \"not\") && hasOwn(sup, \"not\")) {\n\t\tif (deepEqual(sub.not, sup.not)) return true;\n\t}\n\n\treturn null; // No opinion → let the merge engine decide\n}\n\n// ─── Not stripping helper ────────────────────────────────────────────────────\n\n/**\n * Removes the `not` keyword from a schema to allow a clean merge\n * when `evaluateNot` has already confirmed compatibility.\n *\n * Also handles `not` nested in `properties`: if a property of `sup`\n * has a `not` that is compatible with the corresponding property of\n * `sub`, it is removed as well.\n *\n * Returns the cleaned schema, or `null` if the schema is empty after removal.\n */\nfunction stripNotFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tstripTopLevel: boolean = true,\n): JSONSchema7Definition {\n\tif (typeof sup === \"boolean\" || typeof sub === \"boolean\") return sup;\n\n\tlet result = sup as JSONSchema7;\n\n\t// ── Remove top-level `not` (only if confirmed) ──\n\tif (stripTopLevel && hasOwn(result, \"not\")) {\n\t\tresult = omitKeys(result as unknown as Record<string, unknown>, [\n\t\t\t\"not\",\n\t\t]) as JSONSchema7;\n\t}\n\n\t// ── Remove `not` in common properties ──\n\t// If sup.properties[key] has a `not` and evaluateNot(sub.prop, sup.prop)\n\t// confirms compatibility, we remove the `not` from that property as well.\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"not\")\n\t\t\t) {\n\t\t\t\t// Check not compatibility at the property level\n\t\t\t\tconst propNotResult = evaluateNot(subPropDef, supPropDef);\n\t\t\t\tif (propNotResult === true) {\n\t\t\t\t\t// Lazy allocate newProps only on first modification\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"not\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (newProps) {\n\t\t\tresult = { ...result, properties: newProps };\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Pattern stripping helper ────────────────────────────────────────────────\n\n/**\n * Removes the `pattern` from `sup` when `isPatternSubset` has confirmed that\n * sub.pattern ⊆ sup.pattern via sampling.\n *\n * Works like `stripNotFromSup`: we remove the sup constraint that is already\n * satisfied by sub, to prevent the merge engine from producing a combined\n * pattern (lookahead conjunction) structurally different from sub's pattern,\n * which would cause a false negative.\n *\n * Recurses into `properties` to handle nested patterns.\n *\n * @param sub The sub schema (used to extract patterns to compare)\n * @param sup The sup schema from which confirmed patterns are removed\n * @returns The cleaned sup schema\n */\nfunction stripPatternFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): JSONSchema7Definition {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return sup;\n\n\tconst supObj: JSONSchema7 = sup;\n\n\t// Lazy copy-on-write: only create a copy when the first mutation is needed.\n\tlet result: JSONSchema7 = supObj;\n\tlet copied = false;\n\n\tfunction ensureCopy(): JSONSchema7 {\n\t\tif (!copied) {\n\t\t\tresult = { ...supObj };\n\t\t\tcopied = true;\n\t\t}\n\t\treturn result;\n\t}\n\n\t// ── Top-level pattern ──\n\tif (\n\t\thasOwn(result, \"pattern\") &&\n\t\thasOwn(sub, \"pattern\") &&\n\t\tresult.pattern !== (sub as JSONSchema7).pattern\n\t) {\n\t\tconst patResult = isPatternSubset(\n\t\t\t(sub as JSONSchema7).pattern as string,\n\t\t\tresult.pattern as string,\n\t\t);\n\t\tif (patResult === true) {\n\t\t\tresult = omitKeys(ensureCopy() as unknown as Record<string, unknown>, [\n\t\t\t\t\"pattern\",\n\t\t\t]) as JSONSchema7;\n\t\t\tcopied = true;\n\t\t}\n\t}\n\n\t// ── Patterns in common properties ──\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet propsModified = false;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"pattern\") &&\n\t\t\t\thasOwn(subPropDef, \"pattern\") &&\n\t\t\t\tsupPropDef.pattern !== subPropDef.pattern\n\t\t\t) {\n\t\t\t\tconst propPatResult = isPatternSubset(\n\t\t\t\t\t(subPropDef as JSONSchema7).pattern as string,\n\t\t\t\t\t(supPropDef as JSONSchema7).pattern as string,\n\t\t\t\t);\n\t\t\t\tif (propPatResult === true) {\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"pattern\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t\tpropsModified = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (propsModified && newProps) {\n\t\t\tensureCopy().properties = newProps;\n\t\t}\n\t}\n\n\t// ── Pattern in items (single schema) ──\n\tif (\n\t\tisPlainObj(result.items) &&\n\t\ttypeof result.items !== \"boolean\" &&\n\t\tisPlainObj((sub as JSONSchema7).items) &&\n\t\ttypeof (sub as JSONSchema7).items !== \"boolean\"\n\t) {\n\t\tconst subItems = (sub as JSONSchema7).items as JSONSchema7;\n\t\tconst supItems = result.items as JSONSchema7;\n\t\tif (\n\t\t\thasOwn(supItems, \"pattern\") &&\n\t\t\thasOwn(subItems, \"pattern\") &&\n\t\t\tsupItems.pattern !== subItems.pattern\n\t\t) {\n\t\t\tconst itemsPatResult = isPatternSubset(\n\t\t\t\tsubItems.pattern as string,\n\t\t\t\tsupItems.pattern as string,\n\t\t\t);\n\t\t\tif (itemsPatResult === true) {\n\t\t\t\tensureCopy().items = omitKeys(\n\t\t\t\t\tsupItems as unknown as Record<string, unknown>,\n\t\t\t\t\t[\"pattern\"],\n\t\t\t\t) as JSONSchema7Definition;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Vacuous false-property stripping ────────────────────────────────────────\n//\n// In JSON Schema, `properties: { x: false }` means \"if x is present, it must\n// validate against `false` (impossible)\". If x is **absent** from the instance,\n// the constraint is **trivially satisfied** (vacuous truth).\n//\n// After merge(sub, sup), the merge engine may add `false`-schema properties\n// from sup into the merged result even when sub doesn't define those properties.\n// This causes `deepEqual(merged, sub)` to fail — a false negative.\n//\n// `stripVacuousFalseProperties` removes those vacuously-satisfied `false`\n// properties from `merged` so that the structural comparison succeeds.\n\n/**\n * Strips `false`-schema properties from `merged` that are absent in `sub`.\n *\n * A property `{ key: false }` in merged that doesn't exist in sub's properties\n * is vacuously satisfied — sub never produces that key, so the \"impossible\"\n * constraint has no effect. Removing it lets `deepEqual(merged, sub)` succeed.\n *\n * @returns A new schema with vacuous `false` properties removed, or the\n * original `merged` if no stripping was needed.\n */\nfunction stripVacuousFalseProperties(\n\tmerged: JSONSchema7Definition,\n\tsub: JSONSchema7Definition,\n): JSONSchema7Definition {\n\tif (typeof merged === \"boolean\" || typeof sub === \"boolean\") return merged;\n\tif (!isPlainObj(merged.properties)) return merged;\n\n\tconst mergedProps = merged.properties as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst subProps = (isPlainObj(sub.properties) ? sub.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\n\tlet strippedProps: Record<string, JSONSchema7Definition> | null = null;\n\n\tfor (const key of Object.keys(mergedProps)) {\n\t\tif (mergedProps[key] === false && !hasOwn(subProps, key)) {\n\t\t\t// Lazily copy on first strip\n\t\t\tif (strippedProps === null) {\n\t\t\t\tstrippedProps = { ...mergedProps };\n\t\t\t}\n\t\t\tdelete strippedProps[key];\n\t\t}\n\t}\n\n\tif (strippedProps === null) return merged;\n\n\t// Return a new schema with the cleaned properties\n\tconst result = { ...merged, properties: strippedProps };\n\n\t// If properties is now empty and sub doesn't have properties, remove it\n\tif (Object.keys(strippedProps).length === 0 && !isPlainObj(sub.properties)) {\n\t\tdelete (result as Record<string, unknown>).properties;\n\t}\n\n\treturn result;\n}\n\n// ─── Nested branching fallback ───────────────────────────────────────────────\n//\n// The merge engine (`@x0k/json-schema-merge`) cannot resolve `allOf` over\n// `oneOf`/`anyOf` inside properties — it either throws or produces garbage\n// like `{ type: \"string\", oneOf: [...] }`.\n//\n// When the merge-based check fails (null or merged ≠ sub), and either schema\n// contains `oneOf`/`anyOf` inside its properties or items, we fall back to a\n// **property-by-property** comparison that uses the existing branching logic\n// (`getBranchesTyped` / `isAtomicSubsetOf`) on each sub-schema individually.\n//\n// Three helpers:\n// 1. `hasNestedBranching` — guard: does a schema contain oneOf/anyOf in\n// properties or items? Avoids triggering the fallback on normal schemas.\n// 2. `isPropertySubsetOf` — compares a single property sub-schema handling\n// branches on both sides (sub may have oneOf, sup may have oneOf).\n// 3. `isObjectSubsetByProperties` — the fallback itself: iterates over\n// object properties + items and delegates to `isPropertySubsetOf`.\n// 4. `tryNestedBranchingFallback` — the single entry point called from\n// `isAtomicSubsetOf` and `checkAtomic`. Encapsulates the guard check\n// and the call, returning `boolean | null` (null = not applicable).\n\n/**\n * Returns `true` if the schema contains `oneOf`/`anyOf` inside its\n * `properties` or `items`. Recurses into nested object schemas.\n *\n * This is a cheap guard so we only attempt the property-by-property\n * fallback when the merge failure is plausibly caused by nested branching.\n */\nfunction hasNestedBranching(schema: JSONSchema7Definition): boolean {\n\tif (typeof schema === \"boolean\") return false;\n\n\tif (isPlainObj(schema.properties)) {\n\t\tconst props = schema.properties as Record<string, JSONSchema7Definition>;\n\t\tfor (const key of Object.keys(props)) {\n\t\t\tconst prop = props[key];\n\t\t\tif (prop === undefined || typeof prop === \"boolean\") continue;\n\t\t\tif (hasOwn(prop, \"oneOf\") || hasOwn(prop, \"anyOf\")) return true;\n\t\t\tif (hasNestedBranching(prop)) return true;\n\t\t}\n\t}\n\n\tif (isPlainObj(schema.items) && typeof schema.items !== \"boolean\") {\n\t\tconst items = schema.items as JSONSchema7;\n\t\tif (hasOwn(items, \"oneOf\") || hasOwn(items, \"anyOf\")) return true;\n\t\tif (hasNestedBranching(items)) return true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Checks `sub ⊆ sup` for a single property sub-schema, handling branches\n * on **both** sides.\n *\n * `isAtomicSubsetOf` only extracts branches from `sup`. When `sub` also\n * has `oneOf`/`anyOf`, we extract sub's branches and verify that **every**\n * branch is accepted by sup (same semantics as `checkBranchedSub`).\n */\nfunction isPropertySubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: subBranches } = getBranchesTyped(sub);\n\n\tif (subBranches.length > 1 || subBranches[0] !== sub) {\n\t\tfor (const branch of subBranches) {\n\t\t\tif (branch === undefined) continue;\n\t\t\tif (!isAtomicSubsetOf(branch, sup, engine)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\treturn isAtomicSubsetOf(sub, sup, engine);\n}\n\n/**\n * Checks `sub ⊆ sup` by comparing object properties (and array items)\n * individually, using the full branching-aware logic.\n *\n * This is a **fallback** for when the merge-based check fails due to\n * `oneOf`/`anyOf` inside properties. It does NOT check object-level\n * keywords like `minProperties`/`maxProperties` — those are rare in\n * practice and are already handled correctly by the merge when the\n * branching isn't involved.\n *\n * @returns `true` if sub ⊆ sup, `false` otherwise.\n */\nfunction isObjectSubsetByProperties(\n\tsub: JSONSchema7,\n\tsup: JSONSchema7,\n\tengine: MergeEngine,\n): boolean {\n\tconst subIsObj = sub.type === \"object\" || isPlainObj(sub.properties);\n\tconst supIsObj = sup.type === \"object\" || isPlainObj(sup.properties);\n\n\t// ── Array path: both are arrays with items ──\n\tif (!subIsObj && !supIsObj) {\n\t\tif (\n\t\t\tsub.type === \"array\" &&\n\t\t\tsup.type === \"array\" &&\n\t\t\tisPlainObj(sub.items) &&\n\t\t\tisPlainObj(sup.items)\n\t\t) {\n\t\t\treturn isPropertySubsetOf(\n\t\t\t\tsub.items as JSONSchema7Definition,\n\t\t\t\tsup.items as JSONSchema7Definition,\n\t\t\t\tengine,\n\t\t\t);\n\t\t}\n\t\treturn false;\n\t}\n\n\t// Both must look like objects\n\tif (!subIsObj || !supIsObj) return false;\n\n\t// ── Type compatibility ──\n\tif (hasOwn(sub, \"type\") && hasOwn(sup, \"type\") && sub.type !== sup.type) {\n\t\treturn false;\n\t}\n\n\tconst subProps = (isPlainObj(sub.properties) ? sub.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst supProps = (isPlainObj(sup.properties) ? sup.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst subRequired = Array.isArray(sub.required)\n\t\t? (sub.required as string[])\n\t\t: [];\n\tconst supRequired = Array.isArray(sup.required)\n\t\t? (sup.required as string[])\n\t\t: [];\n\n\t// ── Required: every key sup requires, sub must also require ──\n\tfor (const key of supRequired) {\n\t\tif (!subRequired.includes(key)) return false;\n\t}\n\n\t// ── additionalProperties: false on sup ──\n\tif (sup.additionalProperties === false) {\n\t\tfor (const key of Object.keys(subProps)) {\n\t\t\tif (!hasOwn(supProps, key)) return false;\n\t\t}\n\t}\n\n\t// ── Property-by-property check ──\n\tfor (const key of Object.keys(supProps)) {\n\t\tconst supProp = supProps[key];\n\t\tconst subProp = subProps[key];\n\t\tif (supProp === undefined || subProp === undefined) continue;\n\n\t\tif (!isPropertySubsetOf(subProp, supProp, engine)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// ── Sub's extra properties vs sup's additionalProperties schema ──\n\tif (\n\t\tisPlainObj(sup.additionalProperties) &&\n\t\ttypeof sup.additionalProperties !== \"boolean\"\n\t) {\n\t\tconst addPropSchema = sup.additionalProperties as JSONSchema7Definition;\n\t\tfor (const key of Object.keys(subProps)) {\n\t\t\tif (hasOwn(supProps, key)) continue;\n\t\t\tconst subProp = subProps[key];\n\t\t\tif (subProp === undefined) continue;\n\t\t\tif (!isPropertySubsetOf(subProp, addPropSchema, engine)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Items (object schema that also has array items) ──\n\tif (isPlainObj(sub.items) && isPlainObj(sup.items)) {\n\t\tif (\n\t\t\t!isPropertySubsetOf(\n\t\t\t\tsub.items as JSONSchema7Definition,\n\t\t\t\tsup.items as JSONSchema7Definition,\n\t\t\t\tengine,\n\t\t\t)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Attempts the property-by-property fallback when a merge-based check\n * fails and nested branching is detected.\n *\n * Encapsulates the guard (`hasNestedBranching`) and the call to\n * `isObjectSubsetByProperties` so callers don't repeat the pattern.\n *\n * @returns `true` if the fallback confirms sub ⊆ sup, `false` if it\n * confirms sub ⊄ sup, `null` if the fallback is not applicable\n * (neither schema has nested branching, or schemas are booleans).\n */\nfunction tryNestedBranchingFallback(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean | null {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return null;\n\tif (!hasNestedBranching(sub) && !hasNestedBranching(sup)) return null;\n\treturn isObjectSubsetByProperties(sub, sup, engine);\n}\n\n// ─── Atomic subset check ─────────────────────────────────────────────────────\n\n/**\n * Checks whether `sub ⊆ sup` for two schemas without anyOf/oneOf (or with\n * anyOf/oneOf only on the sup side).\n *\n * Point 7 — Integrates an extended `not` pre-check (`evaluateNot`) before the merge.\n *\n * When `evaluateNot` confirms compatibility (`true`), the `not` is removed\n * from `sup` before the merge to prevent the merge engine from adding a `not`\n * constraint that `sub` doesn't have (which would cause `isEqual(merged, sub)` to fail).\n *\n * Pattern pre-check — When both schemas have different patterns, checks\n * inclusion via sampling with `isPatternSubset`. If confirmed, removes the\n * pattern from sup before the merge (same strategy as for `not`).\n *\n * Principle: merge(sub, sup) ≡ sub → sub is a subset of sup.\n *\n * When the merge-based check fails and either sub or sup contains nested\n * `oneOf`/`anyOf` in properties or items, falls back to a property-by-property\n * comparison via `isObjectSubsetByProperties`.\n */\nexport function isAtomicSubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: supBranches } = getBranchesTyped(sup);\n\n\t// Simple schema → direct merge\n\tif (supBranches.length === 1 && supBranches[0] === sup) {\n\t\t// Point 7: extended `not` pre-check\n\t\tconst notResult = evaluateNot(sub, sup);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Format pre-check ──\n\t\t// If both schemas have a different `format`, check that\n\t\t// sub.format ⊆ sup.format. Otherwise, sub cannot be ⊆ sup.\n\t\t// This complements hasFormatConflict (which handles the merge) by handling\n\t\t// the subset check direction that the merge cannot resolve.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"format\") &&\n\t\t\thasOwn(sup, \"format\") &&\n\t\t\tsub.format !== sup.format\n\t\t) {\n\t\t\tconst fmtResult = isFormatSubset(\n\t\t\t\tsub.format as string,\n\t\t\t\tsup.format as string,\n\t\t\t);\n\t\t\tif (fmtResult !== true) return false;\n\t\t}\n\n\t\t// ── Pattern pre-check ──\n\t\t// If both schemas have different patterns, check inclusion\n\t\t// via sampling. If sub.pattern ⊄ sup.pattern (counter-example found),\n\t\t// we return false immediately. Otherwise, we can remove the pattern\n\t\t// from sup to avoid the structural false negative from the merge.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(sup, \"pattern\") &&\n\t\t\tsub.pattern !== sup.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tsup.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Remove `not` from sup (top-level and/or in properties)\n\t\t// when evaluateNot confirms compatibility at the corresponding level.\n\t\t// This prevents the merge engine from adding a `not` constraint that sub doesn't have\n\t\t// (which would cause merged ≠ sub and produce a false negative).\n\t\tlet effectiveSup = sup;\n\t\tif (typeof sup !== \"boolean\") {\n\t\t\t// If top-level not is confirmed compatible → remove top-level not\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, true);\n\t\t\t\t// If sup only had `not` → sub is compatible (the not is resolved)\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveSup !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveSup).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Even if the top-level not is not confirmed (null), we attempt\n\t\t\t\t// to remove `not` in individual properties\n\t\t\t\t// without touching the top-level `not`\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, false);\n\t\t\t}\n\n\t\t\t// Remove patterns from sup confirmed by sampling.\n\t\t\t// Same strategy as for `not`: we remove the constraint already\n\t\t\t// satisfied by sub to prevent the merge from producing a combined\n\t\t\t// pattern (lookahead conjunction) structurally ≠ sub.\n\t\t\teffectiveSup = stripPatternFromSup(sub, effectiveSup);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveSup);\n\t\tif (merged === null) {\n\t\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\t\treturn tryNestedBranchingFallback(sub, effectiveSup, engine) ?? false;\n\t\t}\n\t\t// Fast path: if merged is already structurally equal to sub,\n\t\t// skip normalize entirely. This is the common case when sub ⊆ sup\n\t\t// (A ∩ B = A), saving O(n) normalize traversal on wide schemas.\n\t\tif (deepEqual(merged, sub)) return true;\n\n\t\t// Strip vacuously-satisfied `false` properties added by the merge\n\t\t// from sup but absent in sub (vacuous truth: absent ⊆ forbidden).\n\t\tconst strippedMerged = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedMerged !== merged && deepEqual(strippedMerged, sub)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Slow path: normalize to eliminate merge artifacts (e.g. redundant\n\t\t// enum when const is present), then compare.\n\t\tconst normalizedMerged = normalize(strippedMerged);\n\t\tif (\n\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// ── Fallback: merged ≠ sub but nested branching may explain it ──\n\t\t// The merge engine preserves oneOf/anyOf as-is inside properties\n\t\t// (e.g. merge produces {type:\"string\", oneOf:[...]} ≠ sub).\n\t\treturn tryNestedBranchingFallback(sub, effectiveSup, engine) ?? false;\n\t}\n\n\t// anyOf/oneOf in sup → at least one branch must accept sub\n\treturn supBranches.some((branch) => {\n\t\t// Point 7: extended `not` pre-check per branch\n\t\tconst notResult = evaluateNot(sub, branch);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Pattern pre-check par branche ──\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof branch !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(branch, \"pattern\") &&\n\t\t\tsub.pattern !== branch.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tbranch.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Same strip logic for branches\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof branch !== \"boolean\") {\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, true);\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveBranch !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveBranch).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, false);\n\t\t\t}\n\n\t\t\t// Strip patterns confirmed by sampling\n\t\t\teffectiveBranch = stripPatternFromSup(sub, effectiveBranch);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged === null) {\n\t\t\t// Fallback for nested branching within branches\n\t\t\treturn tryNestedBranchingFallback(sub, effectiveBranch, engine) === true;\n\t\t}\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) return true;\n\n\t\t// Strip vacuously-satisfied `false` properties (see comment above)\n\t\tconst strippedBranch = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedBranch !== merged && deepEqual(strippedBranch, sub)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst normalizedBranch = normalize(strippedBranch);\n\t\tif (\n\t\t\tdeepEqual(normalizedBranch, sub) ||\n\t\t\tengine.isEqual(normalizedBranch, sub)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Fallback: merged ≠ sub but nested branching may explain it\n\t\treturn tryNestedBranchingFallback(sub, effectiveBranch, engine) === true;\n\t});\n}\n\n// ─── Full subset check (with diffs) ─────────────────────────────────────────\n\n/**\n * Checks `sub ⊆ sup` for a sub that has branches (anyOf/oneOf).\n * Each branch of sub must be accepted by sup.\n *\n * Point 6 — Uses `getBranchesTyped` to distinguish `anyOf[i]` from\n * `oneOf[i]` in diff paths.\n */\nexport function checkBranchedSub(\n\tsubBranches: JSONSchema7Definition[],\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n\tbranchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tconst allErrors: SchemaError[] = [];\n\tlet allSubset = true;\n\n\tfor (let i = 0; i < subBranches.length; i++) {\n\t\tconst branch = subBranches[i];\n\t\tif (branch === undefined) continue;\n\t\tif (!isAtomicSubsetOf(branch, sup, engine)) {\n\t\t\tallSubset = false;\n\t\t\tconst branchErrors = computeSemanticErrors(branch, sup, \"\");\n\t\t\tallErrors.push(...branchErrors);\n\t\t}\n\t}\n\n\treturn {\n\t\tisSubset: allSubset,\n\t\tmerged: allSubset\n\t\t\t? branchType === \"oneOf\"\n\t\t\t\t? { oneOf: subBranches }\n\t\t\t\t: { anyOf: subBranches }\n\t\t\t: null,\n\t\terrors: allErrors,\n\t};\n}\n\n/**\n * Checks `sub ⊆ sup` for a sup that has branches (anyOf/oneOf).\n * At least one branch of sup must accept sub.\n *\n * Point 6 — Uses the sup's branch type for more precise messages.\n */\nexport function checkBranchedSup(\n\tsub: JSONSchema7Definition,\n\tsupBranches: JSONSchema7Definition[],\n\tengine: MergeEngine,\n\t_branchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tfor (const branch of supBranches) {\n\t\t// Strip patterns confirmed by sampling before the merge\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof sub !== \"boolean\" && typeof branch !== \"boolean\") {\n\t\t\teffectiveBranch = stripPatternFromSup(sub, branch);\n\t\t}\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged !== null) {\n\t\t\t// Fast path: skip normalize if merged already equals sub\n\t\t\tif (deepEqual(merged, sub)) {\n\t\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t\t}\n\t\t\tconst normalizedMerged = normalize(merged);\n\t\t\tif (\n\t\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t\t) {\n\t\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t\t}\n\t\t}\n\t}\n\n\t// Generate semantic errors by comparing sub with the original sup\n\tconst semanticErrors = computeSemanticErrors(\n\t\tsub,\n\t\t{ anyOf: supBranches } as JSONSchema7,\n\t\t\"\",\n\t);\n\n\treturn {\n\t\tisSubset: false,\n\t\tmerged: null,\n\t\terrors: semanticErrors,\n\t};\n}\n\n/**\n * Checks `sub ⊆ sup` for two atomic schemas (without anyOf/oneOf).\n * Uses `mergeOrThrow` to capture incompatibility errors.\n *\n * Uses `deepEqual` for structural comparison (with short-circuit\n * by reference and key counting).\n */\nexport function checkAtomic(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): SubsetResult {\n\t// Strip patterns confirmed by sampling before the merge,\n\t// same strategy as in isAtomicSubsetOf to avoid structural false negatives\n\t// caused by the conjunction of patterns as lookahead.\n\tlet effectiveSup = sup;\n\tif (typeof sub !== \"boolean\" && typeof sup !== \"boolean\") {\n\t\teffectiveSup = stripPatternFromSup(sub, sup);\n\t}\n\n\ttry {\n\t\tconst merged = engine.mergeOrThrow(sub, effectiveSup);\n\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) {\n\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t}\n\n\t\t// Strip vacuously-satisfied `false` properties added by the merge\n\t\t// from sup but absent in sub (vacuous truth: absent ⊆ forbidden).\n\t\tconst strippedMerged = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedMerged !== merged && deepEqual(strippedMerged, sub)) {\n\t\t\treturn { isSubset: true, merged: strippedMerged, errors: [] };\n\t\t}\n\n\t\tconst normalizedMerged = normalize(strippedMerged);\n\n\t\tif (\n\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t) {\n\t\t\treturn { isSubset: true, merged: normalizedMerged, errors: [] };\n\t\t}\n\n\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\tif (tryNestedBranchingFallback(sub, effectiveSup, engine) === true) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst errors = computeSemanticErrors(sub, sup, \"\");\n\t\treturn { isSubset: false, merged: normalizedMerged, errors };\n\t} catch (_e) {\n\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\tif (tryNestedBranchingFallback(sub, effectiveSup, engine) === true) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst errors = computeSemanticErrors(sub, sup, \"\");\n\t\treturn {\n\t\t\tisSubset: false,\n\t\t\tmerged: null,\n\t\t\terrors,\n\t\t};\n\t}\n}\n"],"names":["checkAtomic","checkBranchedSub","checkBranchedSup","getBranchesTyped","isAtomicSubsetOf","BRANCH_TRUE","branches","type","BRANCH_FALSE","atomicBranchCache","WeakMap","def","hasOwn","Array","isArray","anyOf","oneOf","cached","get","undefined","set","evaluateNot","sub","sup","isPlainObj","not","notSchema","properties","required","notProps","notRequired","subProps","subRequired","notPropKeys","Object","keys","hasIncompatibleProp","some","key","notPropDef","notProp","includes","subPropDef","subProp","deepEqual","const","enum","inNotEnum","v","noneInNotEnum","every","nv","allPropsMatch","notConst","subConst","allExcluded","val","notVal","notType","subType","allIncompatible","branch","result","anyBranchMatches","subFormat","format","notFormat","stripNotFromSup","stripTopLevel","omitKeys","supProps","newProps","supPropDef","propNotResult","stripPatternFromSup","supObj","copied","ensureCopy","pattern","patResult","isPatternSubset","propsModified","propPatResult","items","subItems","supItems","itemsPatResult","stripVacuousFalseProperties","merged","mergedProps","strippedProps","length","hasNestedBranching","schema","props","prop","isPropertySubsetOf","engine","subBranches","isObjectSubsetByProperties","subIsObj","supIsObj","supRequired","additionalProperties","supProp","addPropSchema","tryNestedBranchingFallback","supBranches","notResult","fmtResult","isFormatSubset","effectiveSup","merge","strippedMerged","normalizedMerged","normalize","isEqual","effectiveBranch","strippedBranch","normalizedBranch","branchType","allErrors","allSubset","i","branchErrors","computeSemanticErrors","push","isSubset","errors","_branchType","semanticErrors","mergeOrThrow","_e"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/subset-checker.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { isFormatSubset } from \"./format-validator.ts\";\nimport type { MergeEngine } from \"./merge-engine.ts\";\nimport { normalize } from \"./normalizer.ts\";\nimport { isPatternSubset } from \"./pattern-subset.ts\";\nimport { computeSemanticErrors } from \"./semantic-errors.ts\";\nimport type { SchemaError, SubsetResult } from \"./types.ts\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys } from \"./utils.ts\";\n\n// ─── Subset Checker ──────────────────────────────────────────────────────────\n//\n// Subset verification logic via the approach:\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// Handles:\n// - Atomic schemas (no anyOf/oneOf)\n// - anyOf/oneOf in sub → each branch must be accepted by sup\n// - anyOf/oneOf in sup → at least one branch must accept sub\n// - Point 6: Distinguish anyOf / oneOf in diff messages\n// - Point 7: Extended `not` reasoning (evaluateNot)\n// - not.type, not.const, not.enum (existing)\n// - not with properties+required (1.1)\n// - not with anyOf/oneOf (1.2)\n// - not in sub (1.3)\n// - not.format (format-vs-format)\n//\n// Uses shared native helpers from `./utils` for optimal performance\n// (deepEqual, hasOwn, isPlainObj, omitKeys).\n\n// ─── Branch type ─────────────────────────────────────────────────────────────\n\n/**\n * Branch type detected in a schema.\n *\n * Point 6 — Distinguishes `anyOf` from `oneOf` to produce more precise\n * diff messages. `\"none\"` indicates an atomic schema (no branches).\n *\n * Note: the exclusivity semantics of `oneOf` are not verified\n * (this would be an NP-hard problem in general). The checker treats `oneOf`\n * like `anyOf` for subset checking, which is correct for the `sub ⊆ sup`\n * case but may produce false positives if the sub's branches overlap.\n */\nexport type BranchType = \"anyOf\" | \"oneOf\" | \"none\";\n\nexport interface BranchResult {\n\t/** The branches extracted from the schema */\n\tbranches: JSONSchema7Definition[];\n\t/** The detected branch type */\n\ttype: BranchType;\n}\n\n// ─── Branch extraction ───────────────────────────────────────────────────────\n\n// Pre-allocated singleton results for boolean schemas to avoid per-call allocations.\n// These are safe because the branches arrays are never mutated after creation.\nconst BRANCH_TRUE: BranchResult = { branches: [true], type: \"none\" };\nconst BRANCH_FALSE: BranchResult = { branches: [false], type: \"none\" };\n\n/**\n * WeakMap cache for atomic (no anyOf/oneOf) schema branch results.\n * Avoids allocating `{ branches: [def], type: \"none\" }` on every call\n * for the same schema object. Since normalized schemas are cached and\n * return the same reference, this cache hits frequently.\n */\nconst atomicBranchCache = new WeakMap<object, BranchResult>();\n\n/**\n * Extracts branches from a schema and the branch type.\n *\n * Returns the elements of `anyOf`/`oneOf` if they exist, otherwise returns\n * the schema itself in an array with type `\"none\"`.\n *\n * Point 6 — Distinguishes `anyOf` from `oneOf` in diff paths.\n *\n * Optimization: reuses pre-allocated objects for boolean cases\n * (true/false) and a WeakMap cache for atomic schemas to\n * avoid allocations on these frequent paths.\n */\nexport function getBranchesTyped(def: JSONSchema7Definition): BranchResult {\n\tif (typeof def === \"boolean\") {\n\t\treturn def ? BRANCH_TRUE : BRANCH_FALSE;\n\t}\n\tif (hasOwn(def, \"anyOf\") && Array.isArray(def.anyOf)) {\n\t\treturn { branches: def.anyOf, type: \"anyOf\" };\n\t}\n\tif (hasOwn(def, \"oneOf\") && Array.isArray(def.oneOf)) {\n\t\treturn { branches: def.oneOf, type: \"oneOf\" };\n\t}\n\t// Cache atomic results per schema object to avoid repeated allocations.\n\tlet cached = atomicBranchCache.get(def);\n\tif (cached === undefined) {\n\t\tcached = { branches: [def], type: \"none\" };\n\t\tatomicBranchCache.set(def, cached);\n\t}\n\treturn cached;\n}\n\n// ─── `not` reasoning (Point 7 — extended) ────────────────────────────────────\n\n/**\n * Extended `not` reasoning for common cases.\n *\n * Point 7 — Checks compatibility when `sup` and/or `sub` contain `not`:\n *\n * **Existing cases (not in sup):**\n * - `not.type`: excluded type vs sub's type\n * - `not.const`: excluded const vs sub's const\n * - `not.enum`: excluded values vs sub's enum\n *\n * **Added cases:**\n * - 1.1 — `not` with `properties` + `required`: verify that sub's properties\n * are incompatible with the `not`'s properties (different const/enum)\n * - 1.2 — `not` with `anyOf`/`oneOf`: `not(anyOf([A,B]))` ≡ `allOf([not(A), not(B)])`,\n * so sub must be incompatible with EACH branch\n * - 1.3 — `not` in `sub` (not only in `sup`): a sub with `not`\n * accepts a set too wide to be a subset of a concrete sup\n * - `not.format`: format-vs-format via `isFormatSubset`\n *\n * Conservative ternary contract:\n * - `true` → compatible (certain)\n * - `false` → incompatible (certain)\n * - `null` → undetermined (let the merge engine decide)\n *\n * When in doubt → `null`. NEVER return `true` without certainty.\n */\nfunction evaluateNot(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): boolean | null {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return null;\n\n\t// ── 1.3 — `not` in sub (not in sup) ──\n\t// A `not` in sub is an additional restriction: it excludes values from\n\t// the set accepted by sub, which makes it potentially smaller — thus\n\t// more likely to be ⊆ sup, not less.\n\t// We let the merge engine decide: allOf(sub, sup) will preserve the `not`\n\t// from sub, and the comparison merged ≡ sub will give the correct result.\n\t// Exception: if both have `not`, we handle the identity case below.\n\n\t// Check `not` in sup\n\tif (hasOwn(sup, \"not\") && isPlainObj(sup.not)) {\n\t\tconst notSchema = sup.not as JSONSchema7;\n\n\t\t// ── 1.1 — Case not with properties + required ──\n\t\t// IMPORTANT: this check is placed BEFORE the not.type check because when\n\t\t// the not has both `type` and `properties`, the not.type check alone\n\t\t// would produce a false negative (e.g. sub type=object and not type=object\n\t\t// would return false, but the properties could be incompatible\n\t\t// which would make sub compatible with the not).\n\t\t// If not contains properties with const/enum and required,\n\t\t// verify that sub's properties are incompatible with the not's properties.\n\t\tif (isPlainObj(notSchema.properties) && Array.isArray(notSchema.required)) {\n\t\t\tconst notProps = notSchema.properties as Record<\n\t\t\t\tstring,\n\t\t\t\tJSONSchema7Definition\n\t\t\t>;\n\t\t\tconst notRequired = notSchema.required as string[];\n\n\t\t\t// sub must have properties for us to compare\n\t\t\tif (isPlainObj(sub.properties)) {\n\t\t\t\tconst subProps = sub.properties as Record<\n\t\t\t\t\tstring,\n\t\t\t\t\tJSONSchema7Definition\n\t\t\t\t>;\n\t\t\t\tconst subRequired = Array.isArray(sub.required)\n\t\t\t\t\t? (sub.required as string[])\n\t\t\t\t\t: [];\n\t\t\t\tconst notPropKeys = Object.keys(notProps);\n\n\t\t\t\t// For sub to be compatible with not(schema),\n\t\t\t\t// it suffices that at least ONE property of the not is incompatible with sub.\n\t\t\t\t// This means that sub can never validate the schema inside not.\n\t\t\t\tconst hasIncompatibleProp = notPropKeys.some((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return false;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// If the property is required in not but NOT in sub.required\n\t\t\t\t\t// and it doesn't exist in sub.properties → sub may not\n\t\t\t\t\t// have this property → the not schema wouldn't match → compatible\n\t\t\t\t\tif (\n\t\t\t\t\t\tnotRequired.includes(key) &&\n\t\t\t\t\t\t!subRequired.includes(key) &&\n\t\t\t\t\t\t!hasOwn(subProps, key)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn true; // Property absent from sub → not doesn't match\n\t\t\t\t\t}\n\n\t\t\t\t\t// Compare the const/enum of the property\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return false;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// not.prop has a const, sub.prop has a different const → incompatible for this prop\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\tif (!deepEqual(notProp.const, subProp.const)) {\n\t\t\t\t\t\t\treturn true; // Different consts → sub doesn't match the not\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// not.prop has an enum, sub.prop has a const or enum with no value\n\t\t\t\t\t// in not.enum → incompatible for this prop\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\tconst inNotEnum = notProp.enum.some((v) =>\n\t\t\t\t\t\t\t\tdeepEqual(v, subProp.const),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!inNotEnum) return true; // sub.const absent from not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\tconst noneInNotEnum = subProp.enum.every(\n\t\t\t\t\t\t\t\t(v) => !notProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (noneInNotEnum) return true; // No value from sub.enum in not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\n\t\t\t\tif (hasIncompatibleProp) return true;\n\n\t\t\t\t// Inverse check: if ALL properties of the not match sub\n\t\t\t\t// exactly (same const, sub has the not's required), then sub VIOLATES the not\n\t\t\t\tconst allPropsMatch = notPropKeys.every((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return true;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// The property must be in sub.required if it is in not.required\n\t\t\t\t\tif (notRequired.includes(key) && !subRequired.includes(key))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return true;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// Check const match\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\treturn deepEqual(notProp.const, subProp.const);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check enum inclusion\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\treturn notProp.enum.some((v) => deepEqual(v, subProp.const));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\t// All values of sub.enum are in not.enum\n\t\t\t\t\t\t\treturn subProp.enum.every((v) =>\n\t\t\t\t\t\t\t\tnotProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false; // Undetermined for this property\n\t\t\t\t});\n\n\t\t\t\tif (allPropsMatch) return false; // sub matches the not exactly → incompatible\n\t\t\t}\n\t\t}\n\n\t\t// ── Case not.const ──\n\t\t// IMPORTANT: this check is placed BEFORE not.type because when the not has\n\t\t// both `type` and `const`, the not.type check alone would produce a\n\t\t// false negative (e.g. sub type=string const=\"active\" and not type=string\n\t\t// const=\"deleted\" → the type check would return false due to same type,\n\t\t// even though the consts are different → compatible).\n\t\tif (hasOwn(notSchema, \"const\") && hasOwn(sub, \"const\")) {\n\t\t\tconst notConst = notSchema.const;\n\t\t\tconst subConst = sub.const;\n\t\t\tif (deepEqual(subConst, notConst)) return false;\n\t\t\treturn true;\n\t\t}\n\n\t\t// ── Case not.enum ──\n\t\t// Also placed BEFORE not.type for the same reason.\n\t\tif (\n\t\t\thasOwn(notSchema, \"enum\") &&\n\t\t\tArray.isArray(notSchema.enum) &&\n\t\t\thasOwn(sub, \"enum\") &&\n\t\t\tArray.isArray(sub.enum)\n\t\t) {\n\t\t\t// All values of sub.enum must be absent from not.enum\n\t\t\tconst allExcluded = sub.enum.every(\n\t\t\t\t(val) => !notSchema.enum?.some((notVal) => deepEqual(val, notVal)),\n\t\t\t);\n\t\t\tif (allExcluded) return true;\n\t\t\t// Some values of sub are in not.enum → not automatically false,\n\t\t\t// the merge engine can still handle it\n\t\t}\n\n\t\t// ── Case not.type ──\n\t\t// Placed AFTER not.const, not.enum and properties+required to avoid\n\t\t// short-circuiting cases where the not has more specific constraints.\n\t\t// The type check alone is a fallback for simple not schemas\n\t\t// (e.g. { not: { type: \"string\" } }).\n\t\tif (hasOwn(notSchema, \"type\") && hasOwn(sub, \"type\")) {\n\t\t\tconst notType = notSchema.type;\n\t\t\tconst subType = sub.type;\n\n\t\t\t// If both are simple strings\n\t\t\tif (typeof notType === \"string\" && typeof subType === \"string\") {\n\t\t\t\t// Only return if the not does NOT have more specific constraints\n\t\t\t\t// (const, enum, properties) that should have been handled above\n\t\t\t\tif (\n\t\t\t\t\t!hasOwn(notSchema, \"const\") &&\n\t\t\t\t\t!hasOwn(notSchema, \"enum\") &&\n\t\t\t\t\t!isPlainObj(notSchema.properties)\n\t\t\t\t) {\n\t\t\t\t\tif (subType === notType) return false; // Incompatible: sub is exactly the excluded type\n\t\t\t\t\treturn true; // Compatible: sub is a different type from the excluded type\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If notType is an array, sub.type must not be in it\n\t\t\tif (Array.isArray(notType) && typeof subType === \"string\") {\n\t\t\t\tif (notType.includes(subType)) return false;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// ── 1.2 — Case not with anyOf / oneOf ──\n\t\t// not(anyOf([A, B])) ≡ allOf([not(A), not(B)])\n\t\t// For sub ⊆ not(anyOf(...)), sub must be incompatible with EACH branch.\n\t\tif (hasOwn(notSchema, \"anyOf\") && Array.isArray(notSchema.anyOf)) {\n\t\t\tconst branches = notSchema.anyOf as JSONSchema7Definition[];\n\t\t\t// For each branch of not.anyOf, verify that sub is incompatible\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch; // not(true) = nothing, not(false) = everything\n\t\t\t\t// Create a virtual sup { not: branch } and verify recursively\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\t// result = true → sub is compatible with not(branch) → sub ⊄ branch → OK\n\t\t\t\t// result = false → sub is incompatible with not(branch) → sub ⊆ branch → not OK\n\t\t\t\t// result = null → undetermined\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\t// Check if at least one branch accepts sub → incompatible with not(anyOf)\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false; // sub is incompatible with not(branch) → sub ⊆ branch\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// Same logic for oneOf (in the not context, treated like anyOf)\n\t\tif (hasOwn(notSchema, \"oneOf\") && Array.isArray(notSchema.oneOf)) {\n\t\t\tconst branches = notSchema.oneOf as JSONSchema7Definition[];\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false;\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// ── Case not.format (format-vs-format only) ──\n\t\t// If not has a format and sub also does, check compatibility\n\t\tif (hasOwn(notSchema, \"format\") && hasOwn(sub, \"format\")) {\n\t\t\tconst subFormat = sub.format as string;\n\t\t\tconst notFormat = notSchema.format as string;\n\t\t\tif (subFormat === notFormat) return false; // Incompatible: sub has exactly the excluded format\n\t\t\t// Different formats → compatible (conservative approximation)\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Check `not` in sub AND in sup (identity: { not: X } ⊆ { not: X })\n\tif (hasOwn(sub, \"not\") && hasOwn(sup, \"not\")) {\n\t\tif (deepEqual(sub.not, sup.not)) return true;\n\t}\n\n\treturn null; // No opinion → let the merge engine decide\n}\n\n// ─── Not stripping helper ────────────────────────────────────────────────────\n\n/**\n * Removes the `not` keyword from a schema to allow a clean merge\n * when `evaluateNot` has already confirmed compatibility.\n *\n * Also handles `not` nested in `properties`: if a property of `sup`\n * has a `not` that is compatible with the corresponding property of\n * `sub`, it is removed as well.\n *\n * Returns the cleaned schema, or `null` if the schema is empty after removal.\n */\nfunction stripNotFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tstripTopLevel: boolean = true,\n): JSONSchema7Definition {\n\tif (typeof sup === \"boolean\" || typeof sub === \"boolean\") return sup;\n\n\tlet result = sup as JSONSchema7;\n\n\t// ── Remove top-level `not` (only if confirmed) ──\n\tif (stripTopLevel && hasOwn(result, \"not\")) {\n\t\tresult = omitKeys(result as unknown as Record<string, unknown>, [\n\t\t\t\"not\",\n\t\t]) as JSONSchema7;\n\t}\n\n\t// ── Remove `not` in common properties ──\n\t// If sup.properties[key] has a `not` and evaluateNot(sub.prop, sup.prop)\n\t// confirms compatibility, we remove the `not` from that property as well.\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"not\")\n\t\t\t) {\n\t\t\t\t// Check not compatibility at the property level\n\t\t\t\tconst propNotResult = evaluateNot(subPropDef, supPropDef);\n\t\t\t\tif (propNotResult === true) {\n\t\t\t\t\t// Lazy allocate newProps only on first modification\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"not\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (newProps) {\n\t\t\tresult = { ...result, properties: newProps };\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Pattern stripping helper ────────────────────────────────────────────────\n\n/**\n * Removes the `pattern` from `sup` when `isPatternSubset` has confirmed that\n * sub.pattern ⊆ sup.pattern via sampling.\n *\n * Works like `stripNotFromSup`: we remove the sup constraint that is already\n * satisfied by sub, to prevent the merge engine from producing a combined\n * pattern (lookahead conjunction) structurally different from sub's pattern,\n * which would cause a false negative.\n *\n * Recurses into `properties` to handle nested patterns.\n *\n * @param sub The sub schema (used to extract patterns to compare)\n * @param sup The sup schema from which confirmed patterns are removed\n * @returns The cleaned sup schema\n */\nfunction stripPatternFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): JSONSchema7Definition {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return sup;\n\n\tconst supObj: JSONSchema7 = sup;\n\n\t// Lazy copy-on-write: only create a copy when the first mutation is needed.\n\tlet result: JSONSchema7 = supObj;\n\tlet copied = false;\n\n\tfunction ensureCopy(): JSONSchema7 {\n\t\tif (!copied) {\n\t\t\tresult = { ...supObj };\n\t\t\tcopied = true;\n\t\t}\n\t\treturn result;\n\t}\n\n\t// ── Top-level pattern ──\n\tif (\n\t\thasOwn(result, \"pattern\") &&\n\t\thasOwn(sub, \"pattern\") &&\n\t\tresult.pattern !== (sub as JSONSchema7).pattern\n\t) {\n\t\tconst patResult = isPatternSubset(\n\t\t\t(sub as JSONSchema7).pattern as string,\n\t\t\tresult.pattern as string,\n\t\t);\n\t\tif (patResult === true) {\n\t\t\tresult = omitKeys(ensureCopy() as unknown as Record<string, unknown>, [\n\t\t\t\t\"pattern\",\n\t\t\t]) as JSONSchema7;\n\t\t\tcopied = true;\n\t\t}\n\t}\n\n\t// ── Patterns in common properties ──\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet propsModified = false;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"pattern\") &&\n\t\t\t\thasOwn(subPropDef, \"pattern\") &&\n\t\t\t\tsupPropDef.pattern !== subPropDef.pattern\n\t\t\t) {\n\t\t\t\tconst propPatResult = isPatternSubset(\n\t\t\t\t\t(subPropDef as JSONSchema7).pattern as string,\n\t\t\t\t\t(supPropDef as JSONSchema7).pattern as string,\n\t\t\t\t);\n\t\t\t\tif (propPatResult === true) {\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"pattern\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t\tpropsModified = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (propsModified && newProps) {\n\t\t\tensureCopy().properties = newProps;\n\t\t}\n\t}\n\n\t// ── Pattern in items (single schema) ──\n\tif (\n\t\tisPlainObj(result.items) &&\n\t\ttypeof result.items !== \"boolean\" &&\n\t\tisPlainObj((sub as JSONSchema7).items) &&\n\t\ttypeof (sub as JSONSchema7).items !== \"boolean\"\n\t) {\n\t\tconst subItems = (sub as JSONSchema7).items as JSONSchema7;\n\t\tconst supItems = result.items as JSONSchema7;\n\t\tif (\n\t\t\thasOwn(supItems, \"pattern\") &&\n\t\t\thasOwn(subItems, \"pattern\") &&\n\t\t\tsupItems.pattern !== subItems.pattern\n\t\t) {\n\t\t\tconst itemsPatResult = isPatternSubset(\n\t\t\t\tsubItems.pattern as string,\n\t\t\t\tsupItems.pattern as string,\n\t\t\t);\n\t\t\tif (itemsPatResult === true) {\n\t\t\t\tensureCopy().items = omitKeys(\n\t\t\t\t\tsupItems as unknown as Record<string, unknown>,\n\t\t\t\t\t[\"pattern\"],\n\t\t\t\t) as JSONSchema7Definition;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Vacuous false-property stripping ────────────────────────────────────────\n//\n// In JSON Schema, `properties: { x: false }` means \"if x is present, it must\n// validate against `false` (impossible)\". If x is **absent** from the instance,\n// the constraint is **trivially satisfied** (vacuous truth).\n//\n// After merge(sub, sup), the merge engine may add `false`-schema properties\n// from sup into the merged result even when sub doesn't define those properties.\n// This causes `deepEqual(merged, sub)` to fail — a false negative.\n//\n// `stripVacuousFalseProperties` removes those vacuously-satisfied `false`\n// properties from `merged` so that the structural comparison succeeds.\n\n/**\n * Strips `false`-schema properties from `merged` that are absent in `sub`.\n *\n * A property `{ key: false }` in merged that doesn't exist in sub's properties\n * is vacuously satisfied — sub never produces that key, so the \"impossible\"\n * constraint has no effect. Removing it lets `deepEqual(merged, sub)` succeed.\n *\n * @returns A new schema with vacuous `false` properties removed, or the\n * original `merged` if no stripping was needed.\n */\nfunction stripVacuousFalseProperties(\n\tmerged: JSONSchema7Definition,\n\tsub: JSONSchema7Definition,\n): JSONSchema7Definition {\n\tif (typeof merged === \"boolean\" || typeof sub === \"boolean\") return merged;\n\tif (!isPlainObj(merged.properties)) return merged;\n\n\tconst mergedProps = merged.properties as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst subProps = (isPlainObj(sub.properties) ? sub.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\n\tlet strippedProps: Record<string, JSONSchema7Definition> | null = null;\n\n\tfor (const key of Object.keys(mergedProps)) {\n\t\tif (mergedProps[key] === false && !hasOwn(subProps, key)) {\n\t\t\t// Lazily copy on first strip\n\t\t\tif (strippedProps === null) {\n\t\t\t\tstrippedProps = { ...mergedProps };\n\t\t\t}\n\t\t\tdelete strippedProps[key];\n\t\t}\n\t}\n\n\tif (strippedProps === null) return merged;\n\n\t// Return a new schema with the cleaned properties\n\tconst result = { ...merged, properties: strippedProps };\n\n\t// If properties is now empty and sub doesn't have properties, remove it\n\tif (Object.keys(strippedProps).length === 0 && !isPlainObj(sub.properties)) {\n\t\tdelete (result as Record<string, unknown>).properties;\n\t}\n\n\treturn result;\n}\n\n// ─── Nested branching fallback ───────────────────────────────────────────────\n//\n// The merge engine (`@x0k/json-schema-merge`) cannot resolve `allOf` over\n// `oneOf`/`anyOf` inside properties — it either throws or produces garbage\n// like `{ type: \"string\", oneOf: [...] }`.\n//\n// When the merge-based check fails (null or merged ≠ sub), and either schema\n// contains `oneOf`/`anyOf` inside its properties or items, we fall back to a\n// **property-by-property** comparison that uses the existing branching logic\n// (`getBranchesTyped` / `isAtomicSubsetOf`) on each sub-schema individually.\n//\n// Three helpers:\n// 1. `hasNestedBranching` — guard: does a schema contain oneOf/anyOf in\n// properties or items? Avoids triggering the fallback on normal schemas.\n// 2. `isPropertySubsetOf` — compares a single property sub-schema handling\n// branches on both sides (sub may have oneOf, sup may have oneOf).\n// 3. `isObjectSubsetByProperties` — the fallback itself: iterates over\n// object properties + items and delegates to `isPropertySubsetOf`.\n// 4. `tryNestedBranchingFallback` — the single entry point called from\n// `isAtomicSubsetOf` and `checkAtomic`. Encapsulates the guard check\n// and the call, returning `boolean | null` (null = not applicable).\n\n/**\n * Returns `true` if the schema contains `oneOf`/`anyOf` inside its\n * `properties` or `items`. Recurses into nested object schemas.\n *\n * This is a cheap guard so we only attempt the property-by-property\n * fallback when the merge failure is plausibly caused by nested branching.\n */\nfunction hasNestedBranching(schema: JSONSchema7Definition): boolean {\n\tif (typeof schema === \"boolean\") return false;\n\n\tif (isPlainObj(schema.properties)) {\n\t\tconst props = schema.properties as Record<string, JSONSchema7Definition>;\n\t\tfor (const key of Object.keys(props)) {\n\t\t\tconst prop = props[key];\n\t\t\tif (prop === undefined || typeof prop === \"boolean\") continue;\n\t\t\tif (hasOwn(prop, \"oneOf\") || hasOwn(prop, \"anyOf\")) return true;\n\t\t\tif (hasNestedBranching(prop)) return true;\n\t\t}\n\t}\n\n\tif (isPlainObj(schema.items) && typeof schema.items !== \"boolean\") {\n\t\tconst items = schema.items as JSONSchema7;\n\t\tif (hasOwn(items, \"oneOf\") || hasOwn(items, \"anyOf\")) return true;\n\t\tif (hasNestedBranching(items)) return true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Checks `sub ⊆ sup` for a single property sub-schema, handling branches\n * on **both** sides.\n *\n * `isAtomicSubsetOf` only extracts branches from `sup`. When `sub` also\n * has `oneOf`/`anyOf`, we extract sub's branches and verify that **every**\n * branch is accepted by sup (same semantics as `checkBranchedSub`).\n */\nfunction isPropertySubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: subBranches } = getBranchesTyped(sub);\n\n\tif (subBranches.length > 1 || subBranches[0] !== sub) {\n\t\tfor (const branch of subBranches) {\n\t\t\tif (branch === undefined) continue;\n\t\t\tif (!isAtomicSubsetOf(branch, sup, engine)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\treturn isAtomicSubsetOf(sub, sup, engine);\n}\n\n/**\n * Checks whether the array-level constraints of `sub` are compatible\n * with those of `sup` for subset semantics:\n * - `minItems`: sub.minItems must be >= sup.minItems\n * - `maxItems`: sub.maxItems must be <= sup.maxItems\n * - `uniqueItems`: if sup requires it, sub must too\n */\nfunction isArrayConstraintsSubset(sub: JSONSchema7, sup: JSONSchema7): boolean {\n\t// minItems: sub.minItems must be >= sup.minItems\n\tif (sup.minItems !== undefined) {\n\t\tif (sub.minItems === undefined || sub.minItems < sup.minItems) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// maxItems: sub.maxItems must be <= sup.maxItems\n\tif (sup.maxItems !== undefined) {\n\t\tif (sub.maxItems === undefined || sub.maxItems > sup.maxItems) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// uniqueItems: if sup requires it, sub must also require it\n\tif (sup.uniqueItems === true && sub.uniqueItems !== true) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Checks `sub ⊆ sup` by comparing object properties (and array items)\n * individually, using the full branching-aware logic.\n *\n * This is a **fallback** for when the merge-based check fails due to\n * `oneOf`/`anyOf` inside properties. It does NOT check object-level\n * keywords like `minProperties`/`maxProperties` — those are rare in\n * practice and are already handled correctly by the merge when the\n * branching isn't involved.\n *\n * @returns `true` if sub ⊆ sup, `false` otherwise.\n */\nfunction isObjectSubsetByProperties(\n\tsub: JSONSchema7,\n\tsup: JSONSchema7,\n\tengine: MergeEngine,\n): boolean {\n\tconst subIsObj = sub.type === \"object\" || isPlainObj(sub.properties);\n\tconst supIsObj = sup.type === \"object\" || isPlainObj(sup.properties);\n\n\t// ── Array path: both are arrays with items ──\n\tif (!subIsObj && !supIsObj) {\n\t\tif (\n\t\t\tsub.type === \"array\" &&\n\t\t\tsup.type === \"array\" &&\n\t\t\tisPlainObj(sub.items) &&\n\t\t\tisPlainObj(sup.items)\n\t\t) {\n\t\t\tif (\n\t\t\t\t!isPropertySubsetOf(\n\t\t\t\t\tsub.items as JSONSchema7Definition,\n\t\t\t\t\tsup.items as JSONSchema7Definition,\n\t\t\t\t\tengine,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn isArrayConstraintsSubset(sub, sup);\n\t\t}\n\t\treturn false;\n\t}\n\n\t// Both must look like objects\n\tif (!subIsObj || !supIsObj) return false;\n\n\t// ── Type compatibility ──\n\tif (hasOwn(sub, \"type\") && hasOwn(sup, \"type\") && sub.type !== sup.type) {\n\t\treturn false;\n\t}\n\n\tconst subProps = (isPlainObj(sub.properties) ? sub.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst supProps = (isPlainObj(sup.properties) ? sup.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst subRequired = Array.isArray(sub.required)\n\t\t? (sub.required as string[])\n\t\t: [];\n\tconst supRequired = Array.isArray(sup.required)\n\t\t? (sup.required as string[])\n\t\t: [];\n\n\t// ── Required: every key sup requires, sub must also require ──\n\tfor (const key of supRequired) {\n\t\tif (!subRequired.includes(key)) return false;\n\t}\n\n\t// ── additionalProperties: false on sup ──\n\tif (sup.additionalProperties === false) {\n\t\tfor (const key of Object.keys(subProps)) {\n\t\t\tif (!hasOwn(supProps, key)) return false;\n\t\t}\n\t}\n\n\t// ── Property-by-property check ──\n\tfor (const key of Object.keys(supProps)) {\n\t\tconst supProp = supProps[key];\n\t\tconst subProp = subProps[key];\n\t\tif (supProp === undefined || subProp === undefined) continue;\n\n\t\tif (!isPropertySubsetOf(subProp, supProp, engine)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// ── Sub's extra properties vs sup's additionalProperties schema ──\n\tif (\n\t\tisPlainObj(sup.additionalProperties) &&\n\t\ttypeof sup.additionalProperties !== \"boolean\"\n\t) {\n\t\tconst addPropSchema = sup.additionalProperties as JSONSchema7Definition;\n\t\tfor (const key of Object.keys(subProps)) {\n\t\t\tif (hasOwn(supProps, key)) continue;\n\t\t\tconst subProp = subProps[key];\n\t\t\tif (subProp === undefined) continue;\n\t\t\tif (!isPropertySubsetOf(subProp, addPropSchema, engine)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Items (object schema that also has array items) ──\n\tif (isPlainObj(sub.items) && isPlainObj(sup.items)) {\n\t\tif (\n\t\t\t!isPropertySubsetOf(\n\t\t\t\tsub.items as JSONSchema7Definition,\n\t\t\t\tsup.items as JSONSchema7Definition,\n\t\t\t\tengine,\n\t\t\t)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!isArrayConstraintsSubset(sub, sup)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Attempts the property-by-property fallback when a merge-based check\n * fails and nested branching is detected.\n *\n * Encapsulates the guard (`hasNestedBranching`) and the call to\n * `isObjectSubsetByProperties` so callers don't repeat the pattern.\n *\n * @returns `true` if the fallback confirms sub ⊆ sup, `false` if it\n * confirms sub ⊄ sup, `null` if the fallback is not applicable\n * (neither schema has nested branching, or schemas are booleans).\n */\nfunction tryNestedBranchingFallback(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean | null {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return null;\n\tif (!hasNestedBranching(sub) && !hasNestedBranching(sup)) return null;\n\treturn isObjectSubsetByProperties(sub, sup, engine);\n}\n\n// ─── Atomic subset check ─────────────────────────────────────────────────────\n\n/**\n * Checks whether `sub ⊆ sup` for two schemas without anyOf/oneOf (or with\n * anyOf/oneOf only on the sup side).\n *\n * Point 7 — Integrates an extended `not` pre-check (`evaluateNot`) before the merge.\n *\n * When `evaluateNot` confirms compatibility (`true`), the `not` is removed\n * from `sup` before the merge to prevent the merge engine from adding a `not`\n * constraint that `sub` doesn't have (which would cause `isEqual(merged, sub)` to fail).\n *\n * Pattern pre-check — When both schemas have different patterns, checks\n * inclusion via sampling with `isPatternSubset`. If confirmed, removes the\n * pattern from sup before the merge (same strategy as for `not`).\n *\n * Principle: merge(sub, sup) ≡ sub → sub is a subset of sup.\n *\n * When the merge-based check fails and either sub or sup contains nested\n * `oneOf`/`anyOf` in properties or items, falls back to a property-by-property\n * comparison via `isObjectSubsetByProperties`.\n */\nexport function isAtomicSubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: supBranches } = getBranchesTyped(sup);\n\n\t// Simple schema → direct merge\n\tif (supBranches.length === 1 && supBranches[0] === sup) {\n\t\t// Point 7: extended `not` pre-check\n\t\tconst notResult = evaluateNot(sub, sup);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Format pre-check ──\n\t\t// If both schemas have a different `format`, check that\n\t\t// sub.format ⊆ sup.format. Otherwise, sub cannot be ⊆ sup.\n\t\t// This complements hasFormatConflict (which handles the merge) by handling\n\t\t// the subset check direction that the merge cannot resolve.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"format\") &&\n\t\t\thasOwn(sup, \"format\") &&\n\t\t\tsub.format !== sup.format\n\t\t) {\n\t\t\tconst fmtResult = isFormatSubset(\n\t\t\t\tsub.format as string,\n\t\t\t\tsup.format as string,\n\t\t\t);\n\t\t\tif (fmtResult !== true) return false;\n\t\t}\n\n\t\t// ── Pattern pre-check ──\n\t\t// If both schemas have different patterns, check inclusion\n\t\t// via sampling. If sub.pattern ⊄ sup.pattern (counter-example found),\n\t\t// we return false immediately. Otherwise, we can remove the pattern\n\t\t// from sup to avoid the structural false negative from the merge.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(sup, \"pattern\") &&\n\t\t\tsub.pattern !== sup.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tsup.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Remove `not` from sup (top-level and/or in properties)\n\t\t// when evaluateNot confirms compatibility at the corresponding level.\n\t\t// This prevents the merge engine from adding a `not` constraint that sub doesn't have\n\t\t// (which would cause merged ≠ sub and produce a false negative).\n\t\tlet effectiveSup = sup;\n\t\tif (typeof sup !== \"boolean\") {\n\t\t\t// If top-level not is confirmed compatible → remove top-level not\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, true);\n\t\t\t\t// If sup only had `not` → sub is compatible (the not is resolved)\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveSup !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveSup).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Even if the top-level not is not confirmed (null), we attempt\n\t\t\t\t// to remove `not` in individual properties\n\t\t\t\t// without touching the top-level `not`\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, false);\n\t\t\t}\n\n\t\t\t// Remove patterns from sup confirmed by sampling.\n\t\t\t// Same strategy as for `not`: we remove the constraint already\n\t\t\t// satisfied by sub to prevent the merge from producing a combined\n\t\t\t// pattern (lookahead conjunction) structurally ≠ sub.\n\t\t\teffectiveSup = stripPatternFromSup(sub, effectiveSup);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveSup);\n\t\tif (merged === null) {\n\t\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\t\treturn tryNestedBranchingFallback(sub, effectiveSup, engine) ?? false;\n\t\t}\n\t\t// Fast path: if merged is already structurally equal to sub,\n\t\t// skip normalize entirely. This is the common case when sub ⊆ sup\n\t\t// (A ∩ B = A), saving O(n) normalize traversal on wide schemas.\n\t\tif (deepEqual(merged, sub)) return true;\n\n\t\t// Strip vacuously-satisfied `false` properties added by the merge\n\t\t// from sup but absent in sub (vacuous truth: absent ⊆ forbidden).\n\t\tconst strippedMerged = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedMerged !== merged && deepEqual(strippedMerged, sub)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Slow path: normalize to eliminate merge artifacts (e.g. redundant\n\t\t// enum when const is present), then compare.\n\t\tconst normalizedMerged = normalize(strippedMerged);\n\t\tif (\n\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// ── Fallback: merged ≠ sub but nested branching may explain it ──\n\t\t// The merge engine preserves oneOf/anyOf as-is inside properties\n\t\t// (e.g. merge produces {type:\"string\", oneOf:[...]} ≠ sub).\n\t\treturn tryNestedBranchingFallback(sub, effectiveSup, engine) ?? false;\n\t}\n\n\t// anyOf/oneOf in sup → at least one branch must accept sub\n\treturn supBranches.some((branch) => {\n\t\t// Point 7: extended `not` pre-check per branch\n\t\tconst notResult = evaluateNot(sub, branch);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Pattern pre-check par branche ──\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof branch !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(branch, \"pattern\") &&\n\t\t\tsub.pattern !== branch.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tbranch.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Same strip logic for branches\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof branch !== \"boolean\") {\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, true);\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveBranch !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveBranch).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, false);\n\t\t\t}\n\n\t\t\t// Strip patterns confirmed by sampling\n\t\t\teffectiveBranch = stripPatternFromSup(sub, effectiveBranch);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged === null) {\n\t\t\t// Fallback for nested branching within branches\n\t\t\treturn tryNestedBranchingFallback(sub, effectiveBranch, engine) === true;\n\t\t}\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) return true;\n\n\t\t// Strip vacuously-satisfied `false` properties (see comment above)\n\t\tconst strippedBranch = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedBranch !== merged && deepEqual(strippedBranch, sub)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst normalizedBranch = normalize(strippedBranch);\n\t\tif (\n\t\t\tdeepEqual(normalizedBranch, sub) ||\n\t\t\tengine.isEqual(normalizedBranch, sub)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Fallback: merged ≠ sub but nested branching may explain it\n\t\treturn tryNestedBranchingFallback(sub, effectiveBranch, engine) === true;\n\t});\n}\n\n// ─── Full subset check (with diffs) ─────────────────────────────────────────\n\n/**\n * Checks `sub ⊆ sup` for a sub that has branches (anyOf/oneOf).\n * Each branch of sub must be accepted by sup.\n *\n * Point 6 — Uses `getBranchesTyped` to distinguish `anyOf[i]` from\n * `oneOf[i]` in diff paths.\n */\nexport function checkBranchedSub(\n\tsubBranches: JSONSchema7Definition[],\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n\tbranchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tconst allErrors: SchemaError[] = [];\n\tlet allSubset = true;\n\n\tfor (let i = 0; i < subBranches.length; i++) {\n\t\tconst branch = subBranches[i];\n\t\tif (branch === undefined) continue;\n\t\tif (!isAtomicSubsetOf(branch, sup, engine)) {\n\t\t\tallSubset = false;\n\t\t\tconst branchErrors = computeSemanticErrors(branch, sup, \"\");\n\t\t\tallErrors.push(...branchErrors);\n\t\t}\n\t}\n\n\treturn {\n\t\tisSubset: allSubset,\n\t\tmerged: allSubset\n\t\t\t? branchType === \"oneOf\"\n\t\t\t\t? { oneOf: subBranches }\n\t\t\t\t: { anyOf: subBranches }\n\t\t\t: null,\n\t\terrors: allErrors,\n\t};\n}\n\n/**\n * Checks `sub ⊆ sup` for a sup that has branches (anyOf/oneOf).\n * At least one branch of sup must accept sub.\n *\n * Point 6 — Uses the sup's branch type for more precise messages.\n */\nexport function checkBranchedSup(\n\tsub: JSONSchema7Definition,\n\tsupBranches: JSONSchema7Definition[],\n\tengine: MergeEngine,\n\t_branchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tfor (const branch of supBranches) {\n\t\t// Strip patterns confirmed by sampling before the merge\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof sub !== \"boolean\" && typeof branch !== \"boolean\") {\n\t\t\teffectiveBranch = stripPatternFromSup(sub, branch);\n\t\t}\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged !== null) {\n\t\t\t// Fast path: skip normalize if merged already equals sub\n\t\t\tif (deepEqual(merged, sub)) {\n\t\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t\t}\n\t\t\tconst normalizedMerged = normalize(merged);\n\t\t\tif (\n\t\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t\t) {\n\t\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t\t}\n\t\t}\n\t}\n\n\t// Generate semantic errors by comparing sub with the original sup\n\tconst semanticErrors = computeSemanticErrors(\n\t\tsub,\n\t\t{ anyOf: supBranches } as JSONSchema7,\n\t\t\"\",\n\t);\n\n\treturn {\n\t\tisSubset: false,\n\t\tmerged: null,\n\t\terrors: semanticErrors,\n\t};\n}\n\n/**\n * Checks `sub ⊆ sup` for two atomic schemas (without anyOf/oneOf).\n * Uses `mergeOrThrow` to capture incompatibility errors.\n *\n * Uses `deepEqual` for structural comparison (with short-circuit\n * by reference and key counting).\n */\nexport function checkAtomic(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): SubsetResult {\n\t// Strip patterns confirmed by sampling before the merge,\n\t// same strategy as in isAtomicSubsetOf to avoid structural false negatives\n\t// caused by the conjunction of patterns as lookahead.\n\tlet effectiveSup = sup;\n\tif (typeof sub !== \"boolean\" && typeof sup !== \"boolean\") {\n\t\teffectiveSup = stripPatternFromSup(sub, sup);\n\t}\n\n\ttry {\n\t\tconst merged = engine.mergeOrThrow(sub, effectiveSup);\n\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) {\n\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t}\n\n\t\t// Strip vacuously-satisfied `false` properties added by the merge\n\t\t// from sup but absent in sub (vacuous truth: absent ⊆ forbidden).\n\t\tconst strippedMerged = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedMerged !== merged && deepEqual(strippedMerged, sub)) {\n\t\t\treturn { isSubset: true, merged: strippedMerged, errors: [] };\n\t\t}\n\n\t\tconst normalizedMerged = normalize(strippedMerged);\n\n\t\tif (\n\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t) {\n\t\t\treturn { isSubset: true, merged: normalizedMerged, errors: [] };\n\t\t}\n\n\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\tif (tryNestedBranchingFallback(sub, effectiveSup, engine) === true) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst errors = computeSemanticErrors(sub, sup, \"\");\n\t\treturn { isSubset: false, merged: normalizedMerged, errors };\n\t} catch (_e) {\n\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\tif (tryNestedBranchingFallback(sub, effectiveSup, engine) === true) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst errors = computeSemanticErrors(sub, sup, \"\");\n\t\treturn {\n\t\t\tisSubset: false,\n\t\t\tmerged: null,\n\t\t\terrors,\n\t\t};\n\t}\n}\n"],"names":["checkAtomic","checkBranchedSub","checkBranchedSup","getBranchesTyped","isAtomicSubsetOf","BRANCH_TRUE","branches","type","BRANCH_FALSE","atomicBranchCache","WeakMap","def","hasOwn","Array","isArray","anyOf","oneOf","cached","get","undefined","set","evaluateNot","sub","sup","isPlainObj","not","notSchema","properties","required","notProps","notRequired","subProps","subRequired","notPropKeys","Object","keys","hasIncompatibleProp","some","key","notPropDef","notProp","includes","subPropDef","subProp","deepEqual","const","enum","inNotEnum","v","noneInNotEnum","every","nv","allPropsMatch","notConst","subConst","allExcluded","val","notVal","notType","subType","allIncompatible","branch","result","anyBranchMatches","subFormat","format","notFormat","stripNotFromSup","stripTopLevel","omitKeys","supProps","newProps","supPropDef","propNotResult","stripPatternFromSup","supObj","copied","ensureCopy","pattern","patResult","isPatternSubset","propsModified","propPatResult","items","subItems","supItems","itemsPatResult","stripVacuousFalseProperties","merged","mergedProps","strippedProps","length","hasNestedBranching","schema","props","prop","isPropertySubsetOf","engine","subBranches","isArrayConstraintsSubset","minItems","maxItems","uniqueItems","isObjectSubsetByProperties","subIsObj","supIsObj","supRequired","additionalProperties","supProp","addPropSchema","tryNestedBranchingFallback","supBranches","notResult","fmtResult","isFormatSubset","effectiveSup","merge","strippedMerged","normalizedMerged","normalize","isEqual","effectiveBranch","strippedBranch","normalizedBranch","branchType","allErrors","allSubset","i","branchErrors","computeSemanticErrors","push","isSubset","errors","_branchType","semanticErrors","mergeOrThrow","_e"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{isFormatSubset}from"./format-validator.js";import{normalize}from"./normalizer.js";import{isPatternSubset}from"./pattern-subset.js";import{computeSemanticErrors}from"./semantic-errors.js";import{deepEqual,hasOwn,isPlainObj,omitKeys}from"./utils.js";const BRANCH_TRUE={branches:[true],type:"none"};const BRANCH_FALSE={branches:[false],type:"none"};const atomicBranchCache=new WeakMap;export function getBranchesTyped(def){if(typeof def==="boolean"){return def?BRANCH_TRUE:BRANCH_FALSE}if(hasOwn(def,"anyOf")&&Array.isArray(def.anyOf)){return{branches:def.anyOf,type:"anyOf"}}if(hasOwn(def,"oneOf")&&Array.isArray(def.oneOf)){return{branches:def.oneOf,type:"oneOf"}}let cached=atomicBranchCache.get(def);if(cached===undefined){cached={branches:[def],type:"none"};atomicBranchCache.set(def,cached)}return cached}function evaluateNot(sub,sup){if(typeof sub==="boolean"||typeof sup==="boolean")return null;if(hasOwn(sup,"not")&&isPlainObj(sup.not)){const notSchema=sup.not;if(isPlainObj(notSchema.properties)&&Array.isArray(notSchema.required)){const notProps=notSchema.properties;const notRequired=notSchema.required;if(isPlainObj(sub.properties)){const subProps=sub.properties;const subRequired=Array.isArray(sub.required)?sub.required:[];const notPropKeys=Object.keys(notProps);const hasIncompatibleProp=notPropKeys.some(key=>{const notPropDef=notProps[key];if(typeof notPropDef==="boolean")return false;const notProp=notPropDef;if(notRequired.includes(key)&&!subRequired.includes(key)&&!hasOwn(subProps,key)){return true}if(!hasOwn(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return false;const subProp=subPropDef;if(hasOwn(notProp,"const")&&hasOwn(subProp,"const")){if(!deepEqual(notProp.const,subProp.const)){return true}}if(hasOwn(notProp,"enum")&&Array.isArray(notProp.enum)){if(hasOwn(subProp,"const")){const inNotEnum=notProp.enum.some(v=>deepEqual(v,subProp.const));if(!inNotEnum)return true}if(hasOwn(subProp,"enum")&&Array.isArray(subProp.enum)){const noneInNotEnum=subProp.enum.every(v=>!notProp.enum?.some(nv=>deepEqual(v,nv)));if(noneInNotEnum)return true}}return false});if(hasIncompatibleProp)return true;const allPropsMatch=notPropKeys.every(key=>{const notPropDef=notProps[key];if(typeof notPropDef==="boolean")return true;const notProp=notPropDef;if(notRequired.includes(key)&&!subRequired.includes(key))return false;if(!hasOwn(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return true;const subProp=subPropDef;if(hasOwn(notProp,"const")&&hasOwn(subProp,"const")){return deepEqual(notProp.const,subProp.const)}if(hasOwn(notProp,"enum")&&Array.isArray(notProp.enum)){if(hasOwn(subProp,"const")){return notProp.enum.some(v=>deepEqual(v,subProp.const))}if(hasOwn(subProp,"enum")&&Array.isArray(subProp.enum)){return subProp.enum.every(v=>notProp.enum?.some(nv=>deepEqual(v,nv)))}}return false});if(allPropsMatch)return false}}if(hasOwn(notSchema,"const")&&hasOwn(sub,"const")){const notConst=notSchema.const;const subConst=sub.const;if(deepEqual(subConst,notConst))return false;return true}if(hasOwn(notSchema,"enum")&&Array.isArray(notSchema.enum)&&hasOwn(sub,"enum")&&Array.isArray(sub.enum)){const allExcluded=sub.enum.every(val=>!notSchema.enum?.some(notVal=>deepEqual(val,notVal)));if(allExcluded)return true}if(hasOwn(notSchema,"type")&&hasOwn(sub,"type")){const notType=notSchema.type;const subType=sub.type;if(typeof notType==="string"&&typeof subType==="string"){if(!hasOwn(notSchema,"const")&&!hasOwn(notSchema,"enum")&&!isPlainObj(notSchema.properties)){if(subType===notType)return false;return true}}if(Array.isArray(notType)&&typeof subType==="string"){if(notType.includes(subType))return false;return true}}if(hasOwn(notSchema,"anyOf")&&Array.isArray(notSchema.anyOf)){const branches=notSchema.anyOf;const allIncompatible=branches.every(branch=>{if(typeof branch==="boolean")return!branch;const result=evaluateNot(sub,{not:branch});return result===true});if(allIncompatible)return true;const anyBranchMatches=branches.some(branch=>{if(typeof branch==="boolean")return branch;const result=evaluateNot(sub,{not:branch});return result===false});if(anyBranchMatches)return false}if(hasOwn(notSchema,"oneOf")&&Array.isArray(notSchema.oneOf)){const branches=notSchema.oneOf;const allIncompatible=branches.every(branch=>{if(typeof branch==="boolean")return!branch;const result=evaluateNot(sub,{not:branch});return result===true});if(allIncompatible)return true;const anyBranchMatches=branches.some(branch=>{if(typeof branch==="boolean")return branch;const result=evaluateNot(sub,{not:branch});return result===false});if(anyBranchMatches)return false}if(hasOwn(notSchema,"format")&&hasOwn(sub,"format")){const subFormat=sub.format;const notFormat=notSchema.format;if(subFormat===notFormat)return false;return true}}if(hasOwn(sub,"not")&&hasOwn(sup,"not")){if(deepEqual(sub.not,sup.not))return true}return null}function stripNotFromSup(sub,sup,stripTopLevel=true){if(typeof sup==="boolean"||typeof sub==="boolean")return sup;let result=sup;if(stripTopLevel&&hasOwn(result,"not")){result=omitKeys(result,["not"])}if(isPlainObj(result.properties)&&isPlainObj(sub.properties)){const subProps=sub.properties;const supProps=result.properties;let newProps;for(const key of Object.keys(supProps)){const supPropDef=supProps[key];const subPropDef=subProps[key];if(supPropDef!==undefined&&subPropDef!==undefined&&typeof supPropDef!=="boolean"&&typeof subPropDef!=="boolean"&&hasOwn(supPropDef,"not")){const propNotResult=evaluateNot(subPropDef,supPropDef);if(propNotResult===true){if(!newProps)newProps={...supProps};newProps[key]=omitKeys(supPropDef,["not"])}}}if(newProps){result={...result,properties:newProps}}}return result}function stripPatternFromSup(sub,sup){if(typeof sub==="boolean"||typeof sup==="boolean")return sup;const supObj=sup;let result=supObj;let copied=false;function ensureCopy(){if(!copied){result={...supObj};copied=true}return result}if(hasOwn(result,"pattern")&&hasOwn(sub,"pattern")&&result.pattern!==sub.pattern){const patResult=isPatternSubset(sub.pattern,result.pattern);if(patResult===true){result=omitKeys(ensureCopy(),["pattern"]);copied=true}}if(isPlainObj(result.properties)&&isPlainObj(sub.properties)){const subProps=sub.properties;const supProps=result.properties;let propsModified=false;let newProps;for(const key of Object.keys(supProps)){const supPropDef=supProps[key];const subPropDef=subProps[key];if(supPropDef!==undefined&&subPropDef!==undefined&&typeof supPropDef!=="boolean"&&typeof subPropDef!=="boolean"&&hasOwn(supPropDef,"pattern")&&hasOwn(subPropDef,"pattern")&&supPropDef.pattern!==subPropDef.pattern){const propPatResult=isPatternSubset(subPropDef.pattern,supPropDef.pattern);if(propPatResult===true){if(!newProps)newProps={...supProps};newProps[key]=omitKeys(supPropDef,["pattern"]);propsModified=true}}}if(propsModified&&newProps){ensureCopy().properties=newProps}}if(isPlainObj(result.items)&&typeof result.items!=="boolean"&&isPlainObj(sub.items)&&typeof sub.items!=="boolean"){const subItems=sub.items;const supItems=result.items;if(hasOwn(supItems,"pattern")&&hasOwn(subItems,"pattern")&&supItems.pattern!==subItems.pattern){const itemsPatResult=isPatternSubset(subItems.pattern,supItems.pattern);if(itemsPatResult===true){ensureCopy().items=omitKeys(supItems,["pattern"])}}}return result}function stripVacuousFalseProperties(merged,sub){if(typeof merged==="boolean"||typeof sub==="boolean")return merged;if(!isPlainObj(merged.properties))return merged;const mergedProps=merged.properties;const subProps=isPlainObj(sub.properties)?sub.properties:{};let strippedProps=null;for(const key of Object.keys(mergedProps)){if(mergedProps[key]===false&&!hasOwn(subProps,key)){if(strippedProps===null){strippedProps={...mergedProps}}delete strippedProps[key]}}if(strippedProps===null)return merged;const result={...merged,properties:strippedProps};if(Object.keys(strippedProps).length===0&&!isPlainObj(sub.properties)){delete result.properties}return result}function hasNestedBranching(schema){if(typeof schema==="boolean")return false;if(isPlainObj(schema.properties)){const props=schema.properties;for(const key of Object.keys(props)){const prop=props[key];if(prop===undefined||typeof prop==="boolean")continue;if(hasOwn(prop,"oneOf")||hasOwn(prop,"anyOf"))return true;if(hasNestedBranching(prop))return true}}if(isPlainObj(schema.items)&&typeof schema.items!=="boolean"){const items=schema.items;if(hasOwn(items,"oneOf")||hasOwn(items,"anyOf"))return true;if(hasNestedBranching(items))return true}return false}function isPropertySubsetOf(sub,sup,engine){const{branches:subBranches}=getBranchesTyped(sub);if(subBranches.length>1||subBranches[0]!==sub){for(const branch of subBranches){if(branch===undefined)continue;if(!isAtomicSubsetOf(branch,sup,engine))return false}return true}return isAtomicSubsetOf(sub,sup,engine)}function isObjectSubsetByProperties(sub,sup,engine){const subIsObj=sub.type==="object"||isPlainObj(sub.properties);const supIsObj=sup.type==="object"||isPlainObj(sup.properties);if(!subIsObj&&!supIsObj){if(sub.type==="array"&&sup.type==="array"&&isPlainObj(sub.items)&&isPlainObj(sup.items)){return isPropertySubsetOf(sub.items,sup.items,engine)}return false}if(!subIsObj||!supIsObj)return false;if(hasOwn(sub,"type")&&hasOwn(sup,"type")&&sub.type!==sup.type){return false}const subProps=isPlainObj(sub.properties)?sub.properties:{};const supProps=isPlainObj(sup.properties)?sup.properties:{};const subRequired=Array.isArray(sub.required)?sub.required:[];const supRequired=Array.isArray(sup.required)?sup.required:[];for(const key of supRequired){if(!subRequired.includes(key))return false}if(sup.additionalProperties===false){for(const key of Object.keys(subProps)){if(!hasOwn(supProps,key))return false}}for(const key of Object.keys(supProps)){const supProp=supProps[key];const subProp=subProps[key];if(supProp===undefined||subProp===undefined)continue;if(!isPropertySubsetOf(subProp,supProp,engine)){return false}}if(isPlainObj(sup.additionalProperties)&&typeof sup.additionalProperties!=="boolean"){const addPropSchema=sup.additionalProperties;for(const key of Object.keys(subProps)){if(hasOwn(supProps,key))continue;const subProp=subProps[key];if(subProp===undefined)continue;if(!isPropertySubsetOf(subProp,addPropSchema,engine)){return false}}}if(isPlainObj(sub.items)&&isPlainObj(sup.items)){if(!isPropertySubsetOf(sub.items,sup.items,engine)){return false}}return true}function tryNestedBranchingFallback(sub,sup,engine){if(typeof sub==="boolean"||typeof sup==="boolean")return null;if(!hasNestedBranching(sub)&&!hasNestedBranching(sup))return null;return isObjectSubsetByProperties(sub,sup,engine)}export function isAtomicSubsetOf(sub,sup,engine){const{branches:supBranches}=getBranchesTyped(sup);if(supBranches.length===1&&supBranches[0]===sup){const notResult=evaluateNot(sub,sup);if(notResult===false)return false;if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&hasOwn(sub,"format")&&hasOwn(sup,"format")&&sub.format!==sup.format){const fmtResult=isFormatSubset(sub.format,sup.format);if(fmtResult!==true)return false}if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&hasOwn(sub,"pattern")&&hasOwn(sup,"pattern")&&sub.pattern!==sup.pattern){const patResult=isPatternSubset(sub.pattern,sup.pattern);if(patResult===false)return false}let effectiveSup=sup;if(typeof sup!=="boolean"){if(notResult===true){effectiveSup=stripNotFromSup(sub,sup,true);if(typeof effectiveSup!=="boolean"&&Object.keys(effectiveSup).length===0){return true}}else{effectiveSup=stripNotFromSup(sub,sup,false)}effectiveSup=stripPatternFromSup(sub,effectiveSup)}const merged=engine.merge(sub,effectiveSup);if(merged===null){return tryNestedBranchingFallback(sub,effectiveSup,engine)??false}if(deepEqual(merged,sub))return true;const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&deepEqual(strippedMerged,sub)){return true}const normalizedMerged=normalize(strippedMerged);if(deepEqual(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return true}return tryNestedBranchingFallback(sub,effectiveSup,engine)??false}return supBranches.some(branch=>{const notResult=evaluateNot(sub,branch);if(notResult===false)return false;if(typeof sub!=="boolean"&&typeof branch!=="boolean"&&hasOwn(sub,"pattern")&&hasOwn(branch,"pattern")&&sub.pattern!==branch.pattern){const patResult=isPatternSubset(sub.pattern,branch.pattern);if(patResult===false)return false}let effectiveBranch=branch;if(typeof branch!=="boolean"){if(notResult===true){effectiveBranch=stripNotFromSup(sub,branch,true);if(typeof effectiveBranch!=="boolean"&&Object.keys(effectiveBranch).length===0){return true}}else{effectiveBranch=stripNotFromSup(sub,branch,false)}effectiveBranch=stripPatternFromSup(sub,effectiveBranch)}const merged=engine.merge(sub,effectiveBranch);if(merged===null){return tryNestedBranchingFallback(sub,effectiveBranch,engine)===true}if(deepEqual(merged,sub))return true;const strippedBranch=stripVacuousFalseProperties(merged,sub);if(strippedBranch!==merged&&deepEqual(strippedBranch,sub)){return true}const normalizedBranch=normalize(strippedBranch);if(deepEqual(normalizedBranch,sub)||engine.isEqual(normalizedBranch,sub)){return true}return tryNestedBranchingFallback(sub,effectiveBranch,engine)===true})}export function checkBranchedSub(subBranches,sup,engine,branchType="anyOf"){const allErrors=[];let allSubset=true;for(let i=0;i<subBranches.length;i++){const branch=subBranches[i];if(branch===undefined)continue;if(!isAtomicSubsetOf(branch,sup,engine)){allSubset=false;const branchErrors=computeSemanticErrors(branch,sup,"");allErrors.push(...branchErrors)}}return{isSubset:allSubset,merged:allSubset?branchType==="oneOf"?{oneOf:subBranches}:{anyOf:subBranches}:null,errors:allErrors}}export function checkBranchedSup(sub,supBranches,engine,_branchType="anyOf"){for(const branch of supBranches){let effectiveBranch=branch;if(typeof sub!=="boolean"&&typeof branch!=="boolean"){effectiveBranch=stripPatternFromSup(sub,branch)}const merged=engine.merge(sub,effectiveBranch);if(merged!==null){if(deepEqual(merged,sub)){return{isSubset:true,merged,errors:[]}}const normalizedMerged=normalize(merged);if(deepEqual(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged,errors:[]}}}}const semanticErrors=computeSemanticErrors(sub,{anyOf:supBranches},"");return{isSubset:false,merged:null,errors:semanticErrors}}export function checkAtomic(sub,sup,engine){let effectiveSup=sup;if(typeof sub!=="boolean"&&typeof sup!=="boolean"){effectiveSup=stripPatternFromSup(sub,sup)}try{const merged=engine.mergeOrThrow(sub,effectiveSup);if(deepEqual(merged,sub)){return{isSubset:true,merged,errors:[]}}const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&deepEqual(strippedMerged,sub)){return{isSubset:true,merged:strippedMerged,errors:[]}}const normalizedMerged=normalize(strippedMerged);if(deepEqual(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged:normalizedMerged,errors:[]}}if(tryNestedBranchingFallback(sub,effectiveSup,engine)===true){return{isSubset:true,merged:sub,errors:[]}}const errors=computeSemanticErrors(sub,sup,"");return{isSubset:false,merged:normalizedMerged,errors}}catch(_e){if(tryNestedBranchingFallback(sub,effectiveSup,engine)===true){return{isSubset:true,merged:sub,errors:[]}}const errors=computeSemanticErrors(sub,sup,"");return{isSubset:false,merged:null,errors}}}
|
|
1
|
+
import{isFormatSubset}from"./format-validator.js";import{normalize}from"./normalizer.js";import{isPatternSubset}from"./pattern-subset.js";import{computeSemanticErrors}from"./semantic-errors.js";import{deepEqual,hasOwn,isPlainObj,omitKeys}from"./utils.js";const BRANCH_TRUE={branches:[true],type:"none"};const BRANCH_FALSE={branches:[false],type:"none"};const atomicBranchCache=new WeakMap;export function getBranchesTyped(def){if(typeof def==="boolean"){return def?BRANCH_TRUE:BRANCH_FALSE}if(hasOwn(def,"anyOf")&&Array.isArray(def.anyOf)){return{branches:def.anyOf,type:"anyOf"}}if(hasOwn(def,"oneOf")&&Array.isArray(def.oneOf)){return{branches:def.oneOf,type:"oneOf"}}let cached=atomicBranchCache.get(def);if(cached===undefined){cached={branches:[def],type:"none"};atomicBranchCache.set(def,cached)}return cached}function evaluateNot(sub,sup){if(typeof sub==="boolean"||typeof sup==="boolean")return null;if(hasOwn(sup,"not")&&isPlainObj(sup.not)){const notSchema=sup.not;if(isPlainObj(notSchema.properties)&&Array.isArray(notSchema.required)){const notProps=notSchema.properties;const notRequired=notSchema.required;if(isPlainObj(sub.properties)){const subProps=sub.properties;const subRequired=Array.isArray(sub.required)?sub.required:[];const notPropKeys=Object.keys(notProps);const hasIncompatibleProp=notPropKeys.some(key=>{const notPropDef=notProps[key];if(typeof notPropDef==="boolean")return false;const notProp=notPropDef;if(notRequired.includes(key)&&!subRequired.includes(key)&&!hasOwn(subProps,key)){return true}if(!hasOwn(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return false;const subProp=subPropDef;if(hasOwn(notProp,"const")&&hasOwn(subProp,"const")){if(!deepEqual(notProp.const,subProp.const)){return true}}if(hasOwn(notProp,"enum")&&Array.isArray(notProp.enum)){if(hasOwn(subProp,"const")){const inNotEnum=notProp.enum.some(v=>deepEqual(v,subProp.const));if(!inNotEnum)return true}if(hasOwn(subProp,"enum")&&Array.isArray(subProp.enum)){const noneInNotEnum=subProp.enum.every(v=>!notProp.enum?.some(nv=>deepEqual(v,nv)));if(noneInNotEnum)return true}}return false});if(hasIncompatibleProp)return true;const allPropsMatch=notPropKeys.every(key=>{const notPropDef=notProps[key];if(typeof notPropDef==="boolean")return true;const notProp=notPropDef;if(notRequired.includes(key)&&!subRequired.includes(key))return false;if(!hasOwn(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return true;const subProp=subPropDef;if(hasOwn(notProp,"const")&&hasOwn(subProp,"const")){return deepEqual(notProp.const,subProp.const)}if(hasOwn(notProp,"enum")&&Array.isArray(notProp.enum)){if(hasOwn(subProp,"const")){return notProp.enum.some(v=>deepEqual(v,subProp.const))}if(hasOwn(subProp,"enum")&&Array.isArray(subProp.enum)){return subProp.enum.every(v=>notProp.enum?.some(nv=>deepEqual(v,nv)))}}return false});if(allPropsMatch)return false}}if(hasOwn(notSchema,"const")&&hasOwn(sub,"const")){const notConst=notSchema.const;const subConst=sub.const;if(deepEqual(subConst,notConst))return false;return true}if(hasOwn(notSchema,"enum")&&Array.isArray(notSchema.enum)&&hasOwn(sub,"enum")&&Array.isArray(sub.enum)){const allExcluded=sub.enum.every(val=>!notSchema.enum?.some(notVal=>deepEqual(val,notVal)));if(allExcluded)return true}if(hasOwn(notSchema,"type")&&hasOwn(sub,"type")){const notType=notSchema.type;const subType=sub.type;if(typeof notType==="string"&&typeof subType==="string"){if(!hasOwn(notSchema,"const")&&!hasOwn(notSchema,"enum")&&!isPlainObj(notSchema.properties)){if(subType===notType)return false;return true}}if(Array.isArray(notType)&&typeof subType==="string"){if(notType.includes(subType))return false;return true}}if(hasOwn(notSchema,"anyOf")&&Array.isArray(notSchema.anyOf)){const branches=notSchema.anyOf;const allIncompatible=branches.every(branch=>{if(typeof branch==="boolean")return!branch;const result=evaluateNot(sub,{not:branch});return result===true});if(allIncompatible)return true;const anyBranchMatches=branches.some(branch=>{if(typeof branch==="boolean")return branch;const result=evaluateNot(sub,{not:branch});return result===false});if(anyBranchMatches)return false}if(hasOwn(notSchema,"oneOf")&&Array.isArray(notSchema.oneOf)){const branches=notSchema.oneOf;const allIncompatible=branches.every(branch=>{if(typeof branch==="boolean")return!branch;const result=evaluateNot(sub,{not:branch});return result===true});if(allIncompatible)return true;const anyBranchMatches=branches.some(branch=>{if(typeof branch==="boolean")return branch;const result=evaluateNot(sub,{not:branch});return result===false});if(anyBranchMatches)return false}if(hasOwn(notSchema,"format")&&hasOwn(sub,"format")){const subFormat=sub.format;const notFormat=notSchema.format;if(subFormat===notFormat)return false;return true}}if(hasOwn(sub,"not")&&hasOwn(sup,"not")){if(deepEqual(sub.not,sup.not))return true}return null}function stripNotFromSup(sub,sup,stripTopLevel=true){if(typeof sup==="boolean"||typeof sub==="boolean")return sup;let result=sup;if(stripTopLevel&&hasOwn(result,"not")){result=omitKeys(result,["not"])}if(isPlainObj(result.properties)&&isPlainObj(sub.properties)){const subProps=sub.properties;const supProps=result.properties;let newProps;for(const key of Object.keys(supProps)){const supPropDef=supProps[key];const subPropDef=subProps[key];if(supPropDef!==undefined&&subPropDef!==undefined&&typeof supPropDef!=="boolean"&&typeof subPropDef!=="boolean"&&hasOwn(supPropDef,"not")){const propNotResult=evaluateNot(subPropDef,supPropDef);if(propNotResult===true){if(!newProps)newProps={...supProps};newProps[key]=omitKeys(supPropDef,["not"])}}}if(newProps){result={...result,properties:newProps}}}return result}function stripPatternFromSup(sub,sup){if(typeof sub==="boolean"||typeof sup==="boolean")return sup;const supObj=sup;let result=supObj;let copied=false;function ensureCopy(){if(!copied){result={...supObj};copied=true}return result}if(hasOwn(result,"pattern")&&hasOwn(sub,"pattern")&&result.pattern!==sub.pattern){const patResult=isPatternSubset(sub.pattern,result.pattern);if(patResult===true){result=omitKeys(ensureCopy(),["pattern"]);copied=true}}if(isPlainObj(result.properties)&&isPlainObj(sub.properties)){const subProps=sub.properties;const supProps=result.properties;let propsModified=false;let newProps;for(const key of Object.keys(supProps)){const supPropDef=supProps[key];const subPropDef=subProps[key];if(supPropDef!==undefined&&subPropDef!==undefined&&typeof supPropDef!=="boolean"&&typeof subPropDef!=="boolean"&&hasOwn(supPropDef,"pattern")&&hasOwn(subPropDef,"pattern")&&supPropDef.pattern!==subPropDef.pattern){const propPatResult=isPatternSubset(subPropDef.pattern,supPropDef.pattern);if(propPatResult===true){if(!newProps)newProps={...supProps};newProps[key]=omitKeys(supPropDef,["pattern"]);propsModified=true}}}if(propsModified&&newProps){ensureCopy().properties=newProps}}if(isPlainObj(result.items)&&typeof result.items!=="boolean"&&isPlainObj(sub.items)&&typeof sub.items!=="boolean"){const subItems=sub.items;const supItems=result.items;if(hasOwn(supItems,"pattern")&&hasOwn(subItems,"pattern")&&supItems.pattern!==subItems.pattern){const itemsPatResult=isPatternSubset(subItems.pattern,supItems.pattern);if(itemsPatResult===true){ensureCopy().items=omitKeys(supItems,["pattern"])}}}return result}function stripVacuousFalseProperties(merged,sub){if(typeof merged==="boolean"||typeof sub==="boolean")return merged;if(!isPlainObj(merged.properties))return merged;const mergedProps=merged.properties;const subProps=isPlainObj(sub.properties)?sub.properties:{};let strippedProps=null;for(const key of Object.keys(mergedProps)){if(mergedProps[key]===false&&!hasOwn(subProps,key)){if(strippedProps===null){strippedProps={...mergedProps}}delete strippedProps[key]}}if(strippedProps===null)return merged;const result={...merged,properties:strippedProps};if(Object.keys(strippedProps).length===0&&!isPlainObj(sub.properties)){delete result.properties}return result}function hasNestedBranching(schema){if(typeof schema==="boolean")return false;if(isPlainObj(schema.properties)){const props=schema.properties;for(const key of Object.keys(props)){const prop=props[key];if(prop===undefined||typeof prop==="boolean")continue;if(hasOwn(prop,"oneOf")||hasOwn(prop,"anyOf"))return true;if(hasNestedBranching(prop))return true}}if(isPlainObj(schema.items)&&typeof schema.items!=="boolean"){const items=schema.items;if(hasOwn(items,"oneOf")||hasOwn(items,"anyOf"))return true;if(hasNestedBranching(items))return true}return false}function isPropertySubsetOf(sub,sup,engine){const{branches:subBranches}=getBranchesTyped(sub);if(subBranches.length>1||subBranches[0]!==sub){for(const branch of subBranches){if(branch===undefined)continue;if(!isAtomicSubsetOf(branch,sup,engine))return false}return true}return isAtomicSubsetOf(sub,sup,engine)}function isArrayConstraintsSubset(sub,sup){if(sup.minItems!==undefined){if(sub.minItems===undefined||sub.minItems<sup.minItems){return false}}if(sup.maxItems!==undefined){if(sub.maxItems===undefined||sub.maxItems>sup.maxItems){return false}}if(sup.uniqueItems===true&&sub.uniqueItems!==true){return false}return true}function isObjectSubsetByProperties(sub,sup,engine){const subIsObj=sub.type==="object"||isPlainObj(sub.properties);const supIsObj=sup.type==="object"||isPlainObj(sup.properties);if(!subIsObj&&!supIsObj){if(sub.type==="array"&&sup.type==="array"&&isPlainObj(sub.items)&&isPlainObj(sup.items)){if(!isPropertySubsetOf(sub.items,sup.items,engine)){return false}return isArrayConstraintsSubset(sub,sup)}return false}if(!subIsObj||!supIsObj)return false;if(hasOwn(sub,"type")&&hasOwn(sup,"type")&&sub.type!==sup.type){return false}const subProps=isPlainObj(sub.properties)?sub.properties:{};const supProps=isPlainObj(sup.properties)?sup.properties:{};const subRequired=Array.isArray(sub.required)?sub.required:[];const supRequired=Array.isArray(sup.required)?sup.required:[];for(const key of supRequired){if(!subRequired.includes(key))return false}if(sup.additionalProperties===false){for(const key of Object.keys(subProps)){if(!hasOwn(supProps,key))return false}}for(const key of Object.keys(supProps)){const supProp=supProps[key];const subProp=subProps[key];if(supProp===undefined||subProp===undefined)continue;if(!isPropertySubsetOf(subProp,supProp,engine)){return false}}if(isPlainObj(sup.additionalProperties)&&typeof sup.additionalProperties!=="boolean"){const addPropSchema=sup.additionalProperties;for(const key of Object.keys(subProps)){if(hasOwn(supProps,key))continue;const subProp=subProps[key];if(subProp===undefined)continue;if(!isPropertySubsetOf(subProp,addPropSchema,engine)){return false}}}if(isPlainObj(sub.items)&&isPlainObj(sup.items)){if(!isPropertySubsetOf(sub.items,sup.items,engine)){return false}if(!isArrayConstraintsSubset(sub,sup)){return false}}return true}function tryNestedBranchingFallback(sub,sup,engine){if(typeof sub==="boolean"||typeof sup==="boolean")return null;if(!hasNestedBranching(sub)&&!hasNestedBranching(sup))return null;return isObjectSubsetByProperties(sub,sup,engine)}export function isAtomicSubsetOf(sub,sup,engine){const{branches:supBranches}=getBranchesTyped(sup);if(supBranches.length===1&&supBranches[0]===sup){const notResult=evaluateNot(sub,sup);if(notResult===false)return false;if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&hasOwn(sub,"format")&&hasOwn(sup,"format")&&sub.format!==sup.format){const fmtResult=isFormatSubset(sub.format,sup.format);if(fmtResult!==true)return false}if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&hasOwn(sub,"pattern")&&hasOwn(sup,"pattern")&&sub.pattern!==sup.pattern){const patResult=isPatternSubset(sub.pattern,sup.pattern);if(patResult===false)return false}let effectiveSup=sup;if(typeof sup!=="boolean"){if(notResult===true){effectiveSup=stripNotFromSup(sub,sup,true);if(typeof effectiveSup!=="boolean"&&Object.keys(effectiveSup).length===0){return true}}else{effectiveSup=stripNotFromSup(sub,sup,false)}effectiveSup=stripPatternFromSup(sub,effectiveSup)}const merged=engine.merge(sub,effectiveSup);if(merged===null){return tryNestedBranchingFallback(sub,effectiveSup,engine)??false}if(deepEqual(merged,sub))return true;const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&deepEqual(strippedMerged,sub)){return true}const normalizedMerged=normalize(strippedMerged);if(deepEqual(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return true}return tryNestedBranchingFallback(sub,effectiveSup,engine)??false}return supBranches.some(branch=>{const notResult=evaluateNot(sub,branch);if(notResult===false)return false;if(typeof sub!=="boolean"&&typeof branch!=="boolean"&&hasOwn(sub,"pattern")&&hasOwn(branch,"pattern")&&sub.pattern!==branch.pattern){const patResult=isPatternSubset(sub.pattern,branch.pattern);if(patResult===false)return false}let effectiveBranch=branch;if(typeof branch!=="boolean"){if(notResult===true){effectiveBranch=stripNotFromSup(sub,branch,true);if(typeof effectiveBranch!=="boolean"&&Object.keys(effectiveBranch).length===0){return true}}else{effectiveBranch=stripNotFromSup(sub,branch,false)}effectiveBranch=stripPatternFromSup(sub,effectiveBranch)}const merged=engine.merge(sub,effectiveBranch);if(merged===null){return tryNestedBranchingFallback(sub,effectiveBranch,engine)===true}if(deepEqual(merged,sub))return true;const strippedBranch=stripVacuousFalseProperties(merged,sub);if(strippedBranch!==merged&&deepEqual(strippedBranch,sub)){return true}const normalizedBranch=normalize(strippedBranch);if(deepEqual(normalizedBranch,sub)||engine.isEqual(normalizedBranch,sub)){return true}return tryNestedBranchingFallback(sub,effectiveBranch,engine)===true})}export function checkBranchedSub(subBranches,sup,engine,branchType="anyOf"){const allErrors=[];let allSubset=true;for(let i=0;i<subBranches.length;i++){const branch=subBranches[i];if(branch===undefined)continue;if(!isAtomicSubsetOf(branch,sup,engine)){allSubset=false;const branchErrors=computeSemanticErrors(branch,sup,"");allErrors.push(...branchErrors)}}return{isSubset:allSubset,merged:allSubset?branchType==="oneOf"?{oneOf:subBranches}:{anyOf:subBranches}:null,errors:allErrors}}export function checkBranchedSup(sub,supBranches,engine,_branchType="anyOf"){for(const branch of supBranches){let effectiveBranch=branch;if(typeof sub!=="boolean"&&typeof branch!=="boolean"){effectiveBranch=stripPatternFromSup(sub,branch)}const merged=engine.merge(sub,effectiveBranch);if(merged!==null){if(deepEqual(merged,sub)){return{isSubset:true,merged,errors:[]}}const normalizedMerged=normalize(merged);if(deepEqual(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged,errors:[]}}}}const semanticErrors=computeSemanticErrors(sub,{anyOf:supBranches},"");return{isSubset:false,merged:null,errors:semanticErrors}}export function checkAtomic(sub,sup,engine){let effectiveSup=sup;if(typeof sub!=="boolean"&&typeof sup!=="boolean"){effectiveSup=stripPatternFromSup(sub,sup)}try{const merged=engine.mergeOrThrow(sub,effectiveSup);if(deepEqual(merged,sub)){return{isSubset:true,merged,errors:[]}}const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&deepEqual(strippedMerged,sub)){return{isSubset:true,merged:strippedMerged,errors:[]}}const normalizedMerged=normalize(strippedMerged);if(deepEqual(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged:normalizedMerged,errors:[]}}if(tryNestedBranchingFallback(sub,effectiveSup,engine)===true){return{isSubset:true,merged:sub,errors:[]}}const errors=computeSemanticErrors(sub,sup,"");return{isSubset:false,merged:normalizedMerged,errors}}catch(_e){if(tryNestedBranchingFallback(sub,effectiveSup,engine)===true){return{isSubset:true,merged:sub,errors:[]}}const errors=computeSemanticErrors(sub,sup,"");return{isSubset:false,merged:null,errors}}}
|
|
2
2
|
//# sourceMappingURL=subset-checker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/subset-checker.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { isFormatSubset } from \"./format-validator.ts\";\nimport type { MergeEngine } from \"./merge-engine.ts\";\nimport { normalize } from \"./normalizer.ts\";\nimport { isPatternSubset } from \"./pattern-subset.ts\";\nimport { computeSemanticErrors } from \"./semantic-errors.ts\";\nimport type { SchemaError, SubsetResult } from \"./types.ts\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys } from \"./utils.ts\";\n\n// ─── Subset Checker ──────────────────────────────────────────────────────────\n//\n// Subset verification logic via the approach:\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// Handles:\n// - Atomic schemas (no anyOf/oneOf)\n// - anyOf/oneOf in sub → each branch must be accepted by sup\n// - anyOf/oneOf in sup → at least one branch must accept sub\n// - Point 6: Distinguish anyOf / oneOf in diff messages\n// - Point 7: Extended `not` reasoning (evaluateNot)\n// - not.type, not.const, not.enum (existing)\n// - not with properties+required (1.1)\n// - not with anyOf/oneOf (1.2)\n// - not in sub (1.3)\n// - not.format (format-vs-format)\n//\n// Uses shared native helpers from `./utils` for optimal performance\n// (deepEqual, hasOwn, isPlainObj, omitKeys).\n\n// ─── Branch type ─────────────────────────────────────────────────────────────\n\n/**\n * Branch type detected in a schema.\n *\n * Point 6 — Distinguishes `anyOf` from `oneOf` to produce more precise\n * diff messages. `\"none\"` indicates an atomic schema (no branches).\n *\n * Note: the exclusivity semantics of `oneOf` are not verified\n * (this would be an NP-hard problem in general). The checker treats `oneOf`\n * like `anyOf` for subset checking, which is correct for the `sub ⊆ sup`\n * case but may produce false positives if the sub's branches overlap.\n */\nexport type BranchType = \"anyOf\" | \"oneOf\" | \"none\";\n\nexport interface BranchResult {\n\t/** The branches extracted from the schema */\n\tbranches: JSONSchema7Definition[];\n\t/** The detected branch type */\n\ttype: BranchType;\n}\n\n// ─── Branch extraction ───────────────────────────────────────────────────────\n\n// Pre-allocated singleton results for boolean schemas to avoid per-call allocations.\n// These are safe because the branches arrays are never mutated after creation.\nconst BRANCH_TRUE: BranchResult = { branches: [true], type: \"none\" };\nconst BRANCH_FALSE: BranchResult = { branches: [false], type: \"none\" };\n\n/**\n * WeakMap cache for atomic (no anyOf/oneOf) schema branch results.\n * Avoids allocating `{ branches: [def], type: \"none\" }` on every call\n * for the same schema object. Since normalized schemas are cached and\n * return the same reference, this cache hits frequently.\n */\nconst atomicBranchCache = new WeakMap<object, BranchResult>();\n\n/**\n * Extracts branches from a schema and the branch type.\n *\n * Returns the elements of `anyOf`/`oneOf` if they exist, otherwise returns\n * the schema itself in an array with type `\"none\"`.\n *\n * Point 6 — Distinguishes `anyOf` from `oneOf` in diff paths.\n *\n * Optimization: reuses pre-allocated objects for boolean cases\n * (true/false) and a WeakMap cache for atomic schemas to\n * avoid allocations on these frequent paths.\n */\nexport function getBranchesTyped(def: JSONSchema7Definition): BranchResult {\n\tif (typeof def === \"boolean\") {\n\t\treturn def ? BRANCH_TRUE : BRANCH_FALSE;\n\t}\n\tif (hasOwn(def, \"anyOf\") && Array.isArray(def.anyOf)) {\n\t\treturn { branches: def.anyOf, type: \"anyOf\" };\n\t}\n\tif (hasOwn(def, \"oneOf\") && Array.isArray(def.oneOf)) {\n\t\treturn { branches: def.oneOf, type: \"oneOf\" };\n\t}\n\t// Cache atomic results per schema object to avoid repeated allocations.\n\tlet cached = atomicBranchCache.get(def);\n\tif (cached === undefined) {\n\t\tcached = { branches: [def], type: \"none\" };\n\t\tatomicBranchCache.set(def, cached);\n\t}\n\treturn cached;\n}\n\n// ─── `not` reasoning (Point 7 — extended) ────────────────────────────────────\n\n/**\n * Extended `not` reasoning for common cases.\n *\n * Point 7 — Checks compatibility when `sup` and/or `sub` contain `not`:\n *\n * **Existing cases (not in sup):**\n * - `not.type`: excluded type vs sub's type\n * - `not.const`: excluded const vs sub's const\n * - `not.enum`: excluded values vs sub's enum\n *\n * **Added cases:**\n * - 1.1 — `not` with `properties` + `required`: verify that sub's properties\n * are incompatible with the `not`'s properties (different const/enum)\n * - 1.2 — `not` with `anyOf`/`oneOf`: `not(anyOf([A,B]))` ≡ `allOf([not(A), not(B)])`,\n * so sub must be incompatible with EACH branch\n * - 1.3 — `not` in `sub` (not only in `sup`): a sub with `not`\n * accepts a set too wide to be a subset of a concrete sup\n * - `not.format`: format-vs-format via `isFormatSubset`\n *\n * Conservative ternary contract:\n * - `true` → compatible (certain)\n * - `false` → incompatible (certain)\n * - `null` → undetermined (let the merge engine decide)\n *\n * When in doubt → `null`. NEVER return `true` without certainty.\n */\nfunction evaluateNot(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): boolean | null {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return null;\n\n\t// ── 1.3 — `not` in sub (not in sup) ──\n\t// A `not` in sub is an additional restriction: it excludes values from\n\t// the set accepted by sub, which makes it potentially smaller — thus\n\t// more likely to be ⊆ sup, not less.\n\t// We let the merge engine decide: allOf(sub, sup) will preserve the `not`\n\t// from sub, and the comparison merged ≡ sub will give the correct result.\n\t// Exception: if both have `not`, we handle the identity case below.\n\n\t// Check `not` in sup\n\tif (hasOwn(sup, \"not\") && isPlainObj(sup.not)) {\n\t\tconst notSchema = sup.not as JSONSchema7;\n\n\t\t// ── 1.1 — Case not with properties + required ──\n\t\t// IMPORTANT: this check is placed BEFORE the not.type check because when\n\t\t// the not has both `type` and `properties`, the not.type check alone\n\t\t// would produce a false negative (e.g. sub type=object and not type=object\n\t\t// would return false, but the properties could be incompatible\n\t\t// which would make sub compatible with the not).\n\t\t// If not contains properties with const/enum and required,\n\t\t// verify that sub's properties are incompatible with the not's properties.\n\t\tif (isPlainObj(notSchema.properties) && Array.isArray(notSchema.required)) {\n\t\t\tconst notProps = notSchema.properties as Record<\n\t\t\t\tstring,\n\t\t\t\tJSONSchema7Definition\n\t\t\t>;\n\t\t\tconst notRequired = notSchema.required as string[];\n\n\t\t\t// sub must have properties for us to compare\n\t\t\tif (isPlainObj(sub.properties)) {\n\t\t\t\tconst subProps = sub.properties as Record<\n\t\t\t\t\tstring,\n\t\t\t\t\tJSONSchema7Definition\n\t\t\t\t>;\n\t\t\t\tconst subRequired = Array.isArray(sub.required)\n\t\t\t\t\t? (sub.required as string[])\n\t\t\t\t\t: [];\n\t\t\t\tconst notPropKeys = Object.keys(notProps);\n\n\t\t\t\t// For sub to be compatible with not(schema),\n\t\t\t\t// it suffices that at least ONE property of the not is incompatible with sub.\n\t\t\t\t// This means that sub can never validate the schema inside not.\n\t\t\t\tconst hasIncompatibleProp = notPropKeys.some((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return false;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// If the property is required in not but NOT in sub.required\n\t\t\t\t\t// and it doesn't exist in sub.properties → sub may not\n\t\t\t\t\t// have this property → the not schema wouldn't match → compatible\n\t\t\t\t\tif (\n\t\t\t\t\t\tnotRequired.includes(key) &&\n\t\t\t\t\t\t!subRequired.includes(key) &&\n\t\t\t\t\t\t!hasOwn(subProps, key)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn true; // Property absent from sub → not doesn't match\n\t\t\t\t\t}\n\n\t\t\t\t\t// Compare the const/enum of the property\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return false;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// not.prop has a const, sub.prop has a different const → incompatible for this prop\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\tif (!deepEqual(notProp.const, subProp.const)) {\n\t\t\t\t\t\t\treturn true; // Different consts → sub doesn't match the not\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// not.prop has an enum, sub.prop has a const or enum with no value\n\t\t\t\t\t// in not.enum → incompatible for this prop\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\tconst inNotEnum = notProp.enum.some((v) =>\n\t\t\t\t\t\t\t\tdeepEqual(v, subProp.const),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!inNotEnum) return true; // sub.const absent from not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\tconst noneInNotEnum = subProp.enum.every(\n\t\t\t\t\t\t\t\t(v) => !notProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (noneInNotEnum) return true; // No value from sub.enum in not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\n\t\t\t\tif (hasIncompatibleProp) return true;\n\n\t\t\t\t// Inverse check: if ALL properties of the not match sub\n\t\t\t\t// exactly (same const, sub has the not's required), then sub VIOLATES the not\n\t\t\t\tconst allPropsMatch = notPropKeys.every((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return true;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// The property must be in sub.required if it is in not.required\n\t\t\t\t\tif (notRequired.includes(key) && !subRequired.includes(key))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return true;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// Check const match\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\treturn deepEqual(notProp.const, subProp.const);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check enum inclusion\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\treturn notProp.enum.some((v) => deepEqual(v, subProp.const));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\t// All values of sub.enum are in not.enum\n\t\t\t\t\t\t\treturn subProp.enum.every((v) =>\n\t\t\t\t\t\t\t\tnotProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false; // Undetermined for this property\n\t\t\t\t});\n\n\t\t\t\tif (allPropsMatch) return false; // sub matches the not exactly → incompatible\n\t\t\t}\n\t\t}\n\n\t\t// ── Case not.const ──\n\t\t// IMPORTANT: this check is placed BEFORE not.type because when the not has\n\t\t// both `type` and `const`, the not.type check alone would produce a\n\t\t// false negative (e.g. sub type=string const=\"active\" and not type=string\n\t\t// const=\"deleted\" → the type check would return false due to same type,\n\t\t// even though the consts are different → compatible).\n\t\tif (hasOwn(notSchema, \"const\") && hasOwn(sub, \"const\")) {\n\t\t\tconst notConst = notSchema.const;\n\t\t\tconst subConst = sub.const;\n\t\t\tif (deepEqual(subConst, notConst)) return false;\n\t\t\treturn true;\n\t\t}\n\n\t\t// ── Case not.enum ──\n\t\t// Also placed BEFORE not.type for the same reason.\n\t\tif (\n\t\t\thasOwn(notSchema, \"enum\") &&\n\t\t\tArray.isArray(notSchema.enum) &&\n\t\t\thasOwn(sub, \"enum\") &&\n\t\t\tArray.isArray(sub.enum)\n\t\t) {\n\t\t\t// All values of sub.enum must be absent from not.enum\n\t\t\tconst allExcluded = sub.enum.every(\n\t\t\t\t(val) => !notSchema.enum?.some((notVal) => deepEqual(val, notVal)),\n\t\t\t);\n\t\t\tif (allExcluded) return true;\n\t\t\t// Some values of sub are in not.enum → not automatically false,\n\t\t\t// the merge engine can still handle it\n\t\t}\n\n\t\t// ── Case not.type ──\n\t\t// Placed AFTER not.const, not.enum and properties+required to avoid\n\t\t// short-circuiting cases where the not has more specific constraints.\n\t\t// The type check alone is a fallback for simple not schemas\n\t\t// (e.g. { not: { type: \"string\" } }).\n\t\tif (hasOwn(notSchema, \"type\") && hasOwn(sub, \"type\")) {\n\t\t\tconst notType = notSchema.type;\n\t\t\tconst subType = sub.type;\n\n\t\t\t// If both are simple strings\n\t\t\tif (typeof notType === \"string\" && typeof subType === \"string\") {\n\t\t\t\t// Only return if the not does NOT have more specific constraints\n\t\t\t\t// (const, enum, properties) that should have been handled above\n\t\t\t\tif (\n\t\t\t\t\t!hasOwn(notSchema, \"const\") &&\n\t\t\t\t\t!hasOwn(notSchema, \"enum\") &&\n\t\t\t\t\t!isPlainObj(notSchema.properties)\n\t\t\t\t) {\n\t\t\t\t\tif (subType === notType) return false; // Incompatible: sub is exactly the excluded type\n\t\t\t\t\treturn true; // Compatible: sub is a different type from the excluded type\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If notType is an array, sub.type must not be in it\n\t\t\tif (Array.isArray(notType) && typeof subType === \"string\") {\n\t\t\t\tif (notType.includes(subType)) return false;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// ── 1.2 — Case not with anyOf / oneOf ──\n\t\t// not(anyOf([A, B])) ≡ allOf([not(A), not(B)])\n\t\t// For sub ⊆ not(anyOf(...)), sub must be incompatible with EACH branch.\n\t\tif (hasOwn(notSchema, \"anyOf\") && Array.isArray(notSchema.anyOf)) {\n\t\t\tconst branches = notSchema.anyOf as JSONSchema7Definition[];\n\t\t\t// For each branch of not.anyOf, verify that sub is incompatible\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch; // not(true) = nothing, not(false) = everything\n\t\t\t\t// Create a virtual sup { not: branch } and verify recursively\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\t// result = true → sub is compatible with not(branch) → sub ⊄ branch → OK\n\t\t\t\t// result = false → sub is incompatible with not(branch) → sub ⊆ branch → not OK\n\t\t\t\t// result = null → undetermined\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\t// Check if at least one branch accepts sub → incompatible with not(anyOf)\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false; // sub is incompatible with not(branch) → sub ⊆ branch\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// Same logic for oneOf (in the not context, treated like anyOf)\n\t\tif (hasOwn(notSchema, \"oneOf\") && Array.isArray(notSchema.oneOf)) {\n\t\t\tconst branches = notSchema.oneOf as JSONSchema7Definition[];\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false;\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// ── Case not.format (format-vs-format only) ──\n\t\t// If not has a format and sub also does, check compatibility\n\t\tif (hasOwn(notSchema, \"format\") && hasOwn(sub, \"format\")) {\n\t\t\tconst subFormat = sub.format as string;\n\t\t\tconst notFormat = notSchema.format as string;\n\t\t\tif (subFormat === notFormat) return false; // Incompatible: sub has exactly the excluded format\n\t\t\t// Different formats → compatible (conservative approximation)\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Check `not` in sub AND in sup (identity: { not: X } ⊆ { not: X })\n\tif (hasOwn(sub, \"not\") && hasOwn(sup, \"not\")) {\n\t\tif (deepEqual(sub.not, sup.not)) return true;\n\t}\n\n\treturn null; // No opinion → let the merge engine decide\n}\n\n// ─── Not stripping helper ────────────────────────────────────────────────────\n\n/**\n * Removes the `not` keyword from a schema to allow a clean merge\n * when `evaluateNot` has already confirmed compatibility.\n *\n * Also handles `not` nested in `properties`: if a property of `sup`\n * has a `not` that is compatible with the corresponding property of\n * `sub`, it is removed as well.\n *\n * Returns the cleaned schema, or `null` if the schema is empty after removal.\n */\nfunction stripNotFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tstripTopLevel: boolean = true,\n): JSONSchema7Definition {\n\tif (typeof sup === \"boolean\" || typeof sub === \"boolean\") return sup;\n\n\tlet result = sup as JSONSchema7;\n\n\t// ── Remove top-level `not` (only if confirmed) ──\n\tif (stripTopLevel && hasOwn(result, \"not\")) {\n\t\tresult = omitKeys(result as unknown as Record<string, unknown>, [\n\t\t\t\"not\",\n\t\t]) as JSONSchema7;\n\t}\n\n\t// ── Remove `not` in common properties ──\n\t// If sup.properties[key] has a `not` and evaluateNot(sub.prop, sup.prop)\n\t// confirms compatibility, we remove the `not` from that property as well.\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"not\")\n\t\t\t) {\n\t\t\t\t// Check not compatibility at the property level\n\t\t\t\tconst propNotResult = evaluateNot(subPropDef, supPropDef);\n\t\t\t\tif (propNotResult === true) {\n\t\t\t\t\t// Lazy allocate newProps only on first modification\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"not\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (newProps) {\n\t\t\tresult = { ...result, properties: newProps };\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Pattern stripping helper ────────────────────────────────────────────────\n\n/**\n * Removes the `pattern` from `sup` when `isPatternSubset` has confirmed that\n * sub.pattern ⊆ sup.pattern via sampling.\n *\n * Works like `stripNotFromSup`: we remove the sup constraint that is already\n * satisfied by sub, to prevent the merge engine from producing a combined\n * pattern (lookahead conjunction) structurally different from sub's pattern,\n * which would cause a false negative.\n *\n * Recurses into `properties` to handle nested patterns.\n *\n * @param sub The sub schema (used to extract patterns to compare)\n * @param sup The sup schema from which confirmed patterns are removed\n * @returns The cleaned sup schema\n */\nfunction stripPatternFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): JSONSchema7Definition {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return sup;\n\n\tconst supObj: JSONSchema7 = sup;\n\n\t// Lazy copy-on-write: only create a copy when the first mutation is needed.\n\tlet result: JSONSchema7 = supObj;\n\tlet copied = false;\n\n\tfunction ensureCopy(): JSONSchema7 {\n\t\tif (!copied) {\n\t\t\tresult = { ...supObj };\n\t\t\tcopied = true;\n\t\t}\n\t\treturn result;\n\t}\n\n\t// ── Top-level pattern ──\n\tif (\n\t\thasOwn(result, \"pattern\") &&\n\t\thasOwn(sub, \"pattern\") &&\n\t\tresult.pattern !== (sub as JSONSchema7).pattern\n\t) {\n\t\tconst patResult = isPatternSubset(\n\t\t\t(sub as JSONSchema7).pattern as string,\n\t\t\tresult.pattern as string,\n\t\t);\n\t\tif (patResult === true) {\n\t\t\tresult = omitKeys(ensureCopy() as unknown as Record<string, unknown>, [\n\t\t\t\t\"pattern\",\n\t\t\t]) as JSONSchema7;\n\t\t\tcopied = true;\n\t\t}\n\t}\n\n\t// ── Patterns in common properties ──\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet propsModified = false;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"pattern\") &&\n\t\t\t\thasOwn(subPropDef, \"pattern\") &&\n\t\t\t\tsupPropDef.pattern !== subPropDef.pattern\n\t\t\t) {\n\t\t\t\tconst propPatResult = isPatternSubset(\n\t\t\t\t\t(subPropDef as JSONSchema7).pattern as string,\n\t\t\t\t\t(supPropDef as JSONSchema7).pattern as string,\n\t\t\t\t);\n\t\t\t\tif (propPatResult === true) {\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"pattern\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t\tpropsModified = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (propsModified && newProps) {\n\t\t\tensureCopy().properties = newProps;\n\t\t}\n\t}\n\n\t// ── Pattern in items (single schema) ──\n\tif (\n\t\tisPlainObj(result.items) &&\n\t\ttypeof result.items !== \"boolean\" &&\n\t\tisPlainObj((sub as JSONSchema7).items) &&\n\t\ttypeof (sub as JSONSchema7).items !== \"boolean\"\n\t) {\n\t\tconst subItems = (sub as JSONSchema7).items as JSONSchema7;\n\t\tconst supItems = result.items as JSONSchema7;\n\t\tif (\n\t\t\thasOwn(supItems, \"pattern\") &&\n\t\t\thasOwn(subItems, \"pattern\") &&\n\t\t\tsupItems.pattern !== subItems.pattern\n\t\t) {\n\t\t\tconst itemsPatResult = isPatternSubset(\n\t\t\t\tsubItems.pattern as string,\n\t\t\t\tsupItems.pattern as string,\n\t\t\t);\n\t\t\tif (itemsPatResult === true) {\n\t\t\t\tensureCopy().items = omitKeys(\n\t\t\t\t\tsupItems as unknown as Record<string, unknown>,\n\t\t\t\t\t[\"pattern\"],\n\t\t\t\t) as JSONSchema7Definition;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Vacuous false-property stripping ────────────────────────────────────────\n//\n// In JSON Schema, `properties: { x: false }` means \"if x is present, it must\n// validate against `false` (impossible)\". If x is **absent** from the instance,\n// the constraint is **trivially satisfied** (vacuous truth).\n//\n// After merge(sub, sup), the merge engine may add `false`-schema properties\n// from sup into the merged result even when sub doesn't define those properties.\n// This causes `deepEqual(merged, sub)` to fail — a false negative.\n//\n// `stripVacuousFalseProperties` removes those vacuously-satisfied `false`\n// properties from `merged` so that the structural comparison succeeds.\n\n/**\n * Strips `false`-schema properties from `merged` that are absent in `sub`.\n *\n * A property `{ key: false }` in merged that doesn't exist in sub's properties\n * is vacuously satisfied — sub never produces that key, so the \"impossible\"\n * constraint has no effect. Removing it lets `deepEqual(merged, sub)` succeed.\n *\n * @returns A new schema with vacuous `false` properties removed, or the\n * original `merged` if no stripping was needed.\n */\nfunction stripVacuousFalseProperties(\n\tmerged: JSONSchema7Definition,\n\tsub: JSONSchema7Definition,\n): JSONSchema7Definition {\n\tif (typeof merged === \"boolean\" || typeof sub === \"boolean\") return merged;\n\tif (!isPlainObj(merged.properties)) return merged;\n\n\tconst mergedProps = merged.properties as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst subProps = (isPlainObj(sub.properties) ? sub.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\n\tlet strippedProps: Record<string, JSONSchema7Definition> | null = null;\n\n\tfor (const key of Object.keys(mergedProps)) {\n\t\tif (mergedProps[key] === false && !hasOwn(subProps, key)) {\n\t\t\t// Lazily copy on first strip\n\t\t\tif (strippedProps === null) {\n\t\t\t\tstrippedProps = { ...mergedProps };\n\t\t\t}\n\t\t\tdelete strippedProps[key];\n\t\t}\n\t}\n\n\tif (strippedProps === null) return merged;\n\n\t// Return a new schema with the cleaned properties\n\tconst result = { ...merged, properties: strippedProps };\n\n\t// If properties is now empty and sub doesn't have properties, remove it\n\tif (Object.keys(strippedProps).length === 0 && !isPlainObj(sub.properties)) {\n\t\tdelete (result as Record<string, unknown>).properties;\n\t}\n\n\treturn result;\n}\n\n// ─── Nested branching fallback ───────────────────────────────────────────────\n//\n// The merge engine (`@x0k/json-schema-merge`) cannot resolve `allOf` over\n// `oneOf`/`anyOf` inside properties — it either throws or produces garbage\n// like `{ type: \"string\", oneOf: [...] }`.\n//\n// When the merge-based check fails (null or merged ≠ sub), and either schema\n// contains `oneOf`/`anyOf` inside its properties or items, we fall back to a\n// **property-by-property** comparison that uses the existing branching logic\n// (`getBranchesTyped` / `isAtomicSubsetOf`) on each sub-schema individually.\n//\n// Three helpers:\n// 1. `hasNestedBranching` — guard: does a schema contain oneOf/anyOf in\n// properties or items? Avoids triggering the fallback on normal schemas.\n// 2. `isPropertySubsetOf` — compares a single property sub-schema handling\n// branches on both sides (sub may have oneOf, sup may have oneOf).\n// 3. `isObjectSubsetByProperties` — the fallback itself: iterates over\n// object properties + items and delegates to `isPropertySubsetOf`.\n// 4. `tryNestedBranchingFallback` — the single entry point called from\n// `isAtomicSubsetOf` and `checkAtomic`. Encapsulates the guard check\n// and the call, returning `boolean | null` (null = not applicable).\n\n/**\n * Returns `true` if the schema contains `oneOf`/`anyOf` inside its\n * `properties` or `items`. Recurses into nested object schemas.\n *\n * This is a cheap guard so we only attempt the property-by-property\n * fallback when the merge failure is plausibly caused by nested branching.\n */\nfunction hasNestedBranching(schema: JSONSchema7Definition): boolean {\n\tif (typeof schema === \"boolean\") return false;\n\n\tif (isPlainObj(schema.properties)) {\n\t\tconst props = schema.properties as Record<string, JSONSchema7Definition>;\n\t\tfor (const key of Object.keys(props)) {\n\t\t\tconst prop = props[key];\n\t\t\tif (prop === undefined || typeof prop === \"boolean\") continue;\n\t\t\tif (hasOwn(prop, \"oneOf\") || hasOwn(prop, \"anyOf\")) return true;\n\t\t\tif (hasNestedBranching(prop)) return true;\n\t\t}\n\t}\n\n\tif (isPlainObj(schema.items) && typeof schema.items !== \"boolean\") {\n\t\tconst items = schema.items as JSONSchema7;\n\t\tif (hasOwn(items, \"oneOf\") || hasOwn(items, \"anyOf\")) return true;\n\t\tif (hasNestedBranching(items)) return true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Checks `sub ⊆ sup` for a single property sub-schema, handling branches\n * on **both** sides.\n *\n * `isAtomicSubsetOf` only extracts branches from `sup`. When `sub` also\n * has `oneOf`/`anyOf`, we extract sub's branches and verify that **every**\n * branch is accepted by sup (same semantics as `checkBranchedSub`).\n */\nfunction isPropertySubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: subBranches } = getBranchesTyped(sub);\n\n\tif (subBranches.length > 1 || subBranches[0] !== sub) {\n\t\tfor (const branch of subBranches) {\n\t\t\tif (branch === undefined) continue;\n\t\t\tif (!isAtomicSubsetOf(branch, sup, engine)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\treturn isAtomicSubsetOf(sub, sup, engine);\n}\n\n/**\n * Checks `sub ⊆ sup` by comparing object properties (and array items)\n * individually, using the full branching-aware logic.\n *\n * This is a **fallback** for when the merge-based check fails due to\n * `oneOf`/`anyOf` inside properties. It does NOT check object-level\n * keywords like `minProperties`/`maxProperties` — those are rare in\n * practice and are already handled correctly by the merge when the\n * branching isn't involved.\n *\n * @returns `true` if sub ⊆ sup, `false` otherwise.\n */\nfunction isObjectSubsetByProperties(\n\tsub: JSONSchema7,\n\tsup: JSONSchema7,\n\tengine: MergeEngine,\n): boolean {\n\tconst subIsObj = sub.type === \"object\" || isPlainObj(sub.properties);\n\tconst supIsObj = sup.type === \"object\" || isPlainObj(sup.properties);\n\n\t// ── Array path: both are arrays with items ──\n\tif (!subIsObj && !supIsObj) {\n\t\tif (\n\t\t\tsub.type === \"array\" &&\n\t\t\tsup.type === \"array\" &&\n\t\t\tisPlainObj(sub.items) &&\n\t\t\tisPlainObj(sup.items)\n\t\t) {\n\t\t\treturn isPropertySubsetOf(\n\t\t\t\tsub.items as JSONSchema7Definition,\n\t\t\t\tsup.items as JSONSchema7Definition,\n\t\t\t\tengine,\n\t\t\t);\n\t\t}\n\t\treturn false;\n\t}\n\n\t// Both must look like objects\n\tif (!subIsObj || !supIsObj) return false;\n\n\t// ── Type compatibility ──\n\tif (hasOwn(sub, \"type\") && hasOwn(sup, \"type\") && sub.type !== sup.type) {\n\t\treturn false;\n\t}\n\n\tconst subProps = (isPlainObj(sub.properties) ? sub.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst supProps = (isPlainObj(sup.properties) ? sup.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst subRequired = Array.isArray(sub.required)\n\t\t? (sub.required as string[])\n\t\t: [];\n\tconst supRequired = Array.isArray(sup.required)\n\t\t? (sup.required as string[])\n\t\t: [];\n\n\t// ── Required: every key sup requires, sub must also require ──\n\tfor (const key of supRequired) {\n\t\tif (!subRequired.includes(key)) return false;\n\t}\n\n\t// ── additionalProperties: false on sup ──\n\tif (sup.additionalProperties === false) {\n\t\tfor (const key of Object.keys(subProps)) {\n\t\t\tif (!hasOwn(supProps, key)) return false;\n\t\t}\n\t}\n\n\t// ── Property-by-property check ──\n\tfor (const key of Object.keys(supProps)) {\n\t\tconst supProp = supProps[key];\n\t\tconst subProp = subProps[key];\n\t\tif (supProp === undefined || subProp === undefined) continue;\n\n\t\tif (!isPropertySubsetOf(subProp, supProp, engine)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// ── Sub's extra properties vs sup's additionalProperties schema ──\n\tif (\n\t\tisPlainObj(sup.additionalProperties) &&\n\t\ttypeof sup.additionalProperties !== \"boolean\"\n\t) {\n\t\tconst addPropSchema = sup.additionalProperties as JSONSchema7Definition;\n\t\tfor (const key of Object.keys(subProps)) {\n\t\t\tif (hasOwn(supProps, key)) continue;\n\t\t\tconst subProp = subProps[key];\n\t\t\tif (subProp === undefined) continue;\n\t\t\tif (!isPropertySubsetOf(subProp, addPropSchema, engine)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Items (object schema that also has array items) ──\n\tif (isPlainObj(sub.items) && isPlainObj(sup.items)) {\n\t\tif (\n\t\t\t!isPropertySubsetOf(\n\t\t\t\tsub.items as JSONSchema7Definition,\n\t\t\t\tsup.items as JSONSchema7Definition,\n\t\t\t\tengine,\n\t\t\t)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Attempts the property-by-property fallback when a merge-based check\n * fails and nested branching is detected.\n *\n * Encapsulates the guard (`hasNestedBranching`) and the call to\n * `isObjectSubsetByProperties` so callers don't repeat the pattern.\n *\n * @returns `true` if the fallback confirms sub ⊆ sup, `false` if it\n * confirms sub ⊄ sup, `null` if the fallback is not applicable\n * (neither schema has nested branching, or schemas are booleans).\n */\nfunction tryNestedBranchingFallback(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean | null {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return null;\n\tif (!hasNestedBranching(sub) && !hasNestedBranching(sup)) return null;\n\treturn isObjectSubsetByProperties(sub, sup, engine);\n}\n\n// ─── Atomic subset check ─────────────────────────────────────────────────────\n\n/**\n * Checks whether `sub ⊆ sup` for two schemas without anyOf/oneOf (or with\n * anyOf/oneOf only on the sup side).\n *\n * Point 7 — Integrates an extended `not` pre-check (`evaluateNot`) before the merge.\n *\n * When `evaluateNot` confirms compatibility (`true`), the `not` is removed\n * from `sup` before the merge to prevent the merge engine from adding a `not`\n * constraint that `sub` doesn't have (which would cause `isEqual(merged, sub)` to fail).\n *\n * Pattern pre-check — When both schemas have different patterns, checks\n * inclusion via sampling with `isPatternSubset`. If confirmed, removes the\n * pattern from sup before the merge (same strategy as for `not`).\n *\n * Principle: merge(sub, sup) ≡ sub → sub is a subset of sup.\n *\n * When the merge-based check fails and either sub or sup contains nested\n * `oneOf`/`anyOf` in properties or items, falls back to a property-by-property\n * comparison via `isObjectSubsetByProperties`.\n */\nexport function isAtomicSubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: supBranches } = getBranchesTyped(sup);\n\n\t// Simple schema → direct merge\n\tif (supBranches.length === 1 && supBranches[0] === sup) {\n\t\t// Point 7: extended `not` pre-check\n\t\tconst notResult = evaluateNot(sub, sup);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Format pre-check ──\n\t\t// If both schemas have a different `format`, check that\n\t\t// sub.format ⊆ sup.format. Otherwise, sub cannot be ⊆ sup.\n\t\t// This complements hasFormatConflict (which handles the merge) by handling\n\t\t// the subset check direction that the merge cannot resolve.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"format\") &&\n\t\t\thasOwn(sup, \"format\") &&\n\t\t\tsub.format !== sup.format\n\t\t) {\n\t\t\tconst fmtResult = isFormatSubset(\n\t\t\t\tsub.format as string,\n\t\t\t\tsup.format as string,\n\t\t\t);\n\t\t\tif (fmtResult !== true) return false;\n\t\t}\n\n\t\t// ── Pattern pre-check ──\n\t\t// If both schemas have different patterns, check inclusion\n\t\t// via sampling. If sub.pattern ⊄ sup.pattern (counter-example found),\n\t\t// we return false immediately. Otherwise, we can remove the pattern\n\t\t// from sup to avoid the structural false negative from the merge.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(sup, \"pattern\") &&\n\t\t\tsub.pattern !== sup.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tsup.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Remove `not` from sup (top-level and/or in properties)\n\t\t// when evaluateNot confirms compatibility at the corresponding level.\n\t\t// This prevents the merge engine from adding a `not` constraint that sub doesn't have\n\t\t// (which would cause merged ≠ sub and produce a false negative).\n\t\tlet effectiveSup = sup;\n\t\tif (typeof sup !== \"boolean\") {\n\t\t\t// If top-level not is confirmed compatible → remove top-level not\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, true);\n\t\t\t\t// If sup only had `not` → sub is compatible (the not is resolved)\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveSup !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveSup).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Even if the top-level not is not confirmed (null), we attempt\n\t\t\t\t// to remove `not` in individual properties\n\t\t\t\t// without touching the top-level `not`\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, false);\n\t\t\t}\n\n\t\t\t// Remove patterns from sup confirmed by sampling.\n\t\t\t// Same strategy as for `not`: we remove the constraint already\n\t\t\t// satisfied by sub to prevent the merge from producing a combined\n\t\t\t// pattern (lookahead conjunction) structurally ≠ sub.\n\t\t\teffectiveSup = stripPatternFromSup(sub, effectiveSup);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveSup);\n\t\tif (merged === null) {\n\t\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\t\treturn tryNestedBranchingFallback(sub, effectiveSup, engine) ?? false;\n\t\t}\n\t\t// Fast path: if merged is already structurally equal to sub,\n\t\t// skip normalize entirely. This is the common case when sub ⊆ sup\n\t\t// (A ∩ B = A), saving O(n) normalize traversal on wide schemas.\n\t\tif (deepEqual(merged, sub)) return true;\n\n\t\t// Strip vacuously-satisfied `false` properties added by the merge\n\t\t// from sup but absent in sub (vacuous truth: absent ⊆ forbidden).\n\t\tconst strippedMerged = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedMerged !== merged && deepEqual(strippedMerged, sub)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Slow path: normalize to eliminate merge artifacts (e.g. redundant\n\t\t// enum when const is present), then compare.\n\t\tconst normalizedMerged = normalize(strippedMerged);\n\t\tif (\n\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// ── Fallback: merged ≠ sub but nested branching may explain it ──\n\t\t// The merge engine preserves oneOf/anyOf as-is inside properties\n\t\t// (e.g. merge produces {type:\"string\", oneOf:[...]} ≠ sub).\n\t\treturn tryNestedBranchingFallback(sub, effectiveSup, engine) ?? false;\n\t}\n\n\t// anyOf/oneOf in sup → at least one branch must accept sub\n\treturn supBranches.some((branch) => {\n\t\t// Point 7: extended `not` pre-check per branch\n\t\tconst notResult = evaluateNot(sub, branch);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Pattern pre-check par branche ──\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof branch !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(branch, \"pattern\") &&\n\t\t\tsub.pattern !== branch.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tbranch.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Same strip logic for branches\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof branch !== \"boolean\") {\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, true);\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveBranch !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveBranch).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, false);\n\t\t\t}\n\n\t\t\t// Strip patterns confirmed by sampling\n\t\t\teffectiveBranch = stripPatternFromSup(sub, effectiveBranch);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged === null) {\n\t\t\t// Fallback for nested branching within branches\n\t\t\treturn tryNestedBranchingFallback(sub, effectiveBranch, engine) === true;\n\t\t}\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) return true;\n\n\t\t// Strip vacuously-satisfied `false` properties (see comment above)\n\t\tconst strippedBranch = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedBranch !== merged && deepEqual(strippedBranch, sub)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst normalizedBranch = normalize(strippedBranch);\n\t\tif (\n\t\t\tdeepEqual(normalizedBranch, sub) ||\n\t\t\tengine.isEqual(normalizedBranch, sub)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Fallback: merged ≠ sub but nested branching may explain it\n\t\treturn tryNestedBranchingFallback(sub, effectiveBranch, engine) === true;\n\t});\n}\n\n// ─── Full subset check (with diffs) ─────────────────────────────────────────\n\n/**\n * Checks `sub ⊆ sup` for a sub that has branches (anyOf/oneOf).\n * Each branch of sub must be accepted by sup.\n *\n * Point 6 — Uses `getBranchesTyped` to distinguish `anyOf[i]` from\n * `oneOf[i]` in diff paths.\n */\nexport function checkBranchedSub(\n\tsubBranches: JSONSchema7Definition[],\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n\tbranchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tconst allErrors: SchemaError[] = [];\n\tlet allSubset = true;\n\n\tfor (let i = 0; i < subBranches.length; i++) {\n\t\tconst branch = subBranches[i];\n\t\tif (branch === undefined) continue;\n\t\tif (!isAtomicSubsetOf(branch, sup, engine)) {\n\t\t\tallSubset = false;\n\t\t\tconst branchErrors = computeSemanticErrors(branch, sup, \"\");\n\t\t\tallErrors.push(...branchErrors);\n\t\t}\n\t}\n\n\treturn {\n\t\tisSubset: allSubset,\n\t\tmerged: allSubset\n\t\t\t? branchType === \"oneOf\"\n\t\t\t\t? { oneOf: subBranches }\n\t\t\t\t: { anyOf: subBranches }\n\t\t\t: null,\n\t\terrors: allErrors,\n\t};\n}\n\n/**\n * Checks `sub ⊆ sup` for a sup that has branches (anyOf/oneOf).\n * At least one branch of sup must accept sub.\n *\n * Point 6 — Uses the sup's branch type for more precise messages.\n */\nexport function checkBranchedSup(\n\tsub: JSONSchema7Definition,\n\tsupBranches: JSONSchema7Definition[],\n\tengine: MergeEngine,\n\t_branchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tfor (const branch of supBranches) {\n\t\t// Strip patterns confirmed by sampling before the merge\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof sub !== \"boolean\" && typeof branch !== \"boolean\") {\n\t\t\teffectiveBranch = stripPatternFromSup(sub, branch);\n\t\t}\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged !== null) {\n\t\t\t// Fast path: skip normalize if merged already equals sub\n\t\t\tif (deepEqual(merged, sub)) {\n\t\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t\t}\n\t\t\tconst normalizedMerged = normalize(merged);\n\t\t\tif (\n\t\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t\t) {\n\t\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t\t}\n\t\t}\n\t}\n\n\t// Generate semantic errors by comparing sub with the original sup\n\tconst semanticErrors = computeSemanticErrors(\n\t\tsub,\n\t\t{ anyOf: supBranches } as JSONSchema7,\n\t\t\"\",\n\t);\n\n\treturn {\n\t\tisSubset: false,\n\t\tmerged: null,\n\t\terrors: semanticErrors,\n\t};\n}\n\n/**\n * Checks `sub ⊆ sup` for two atomic schemas (without anyOf/oneOf).\n * Uses `mergeOrThrow` to capture incompatibility errors.\n *\n * Uses `deepEqual` for structural comparison (with short-circuit\n * by reference and key counting).\n */\nexport function checkAtomic(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): SubsetResult {\n\t// Strip patterns confirmed by sampling before the merge,\n\t// same strategy as in isAtomicSubsetOf to avoid structural false negatives\n\t// caused by the conjunction of patterns as lookahead.\n\tlet effectiveSup = sup;\n\tif (typeof sub !== \"boolean\" && typeof sup !== \"boolean\") {\n\t\teffectiveSup = stripPatternFromSup(sub, sup);\n\t}\n\n\ttry {\n\t\tconst merged = engine.mergeOrThrow(sub, effectiveSup);\n\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) {\n\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t}\n\n\t\t// Strip vacuously-satisfied `false` properties added by the merge\n\t\t// from sup but absent in sub (vacuous truth: absent ⊆ forbidden).\n\t\tconst strippedMerged = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedMerged !== merged && deepEqual(strippedMerged, sub)) {\n\t\t\treturn { isSubset: true, merged: strippedMerged, errors: [] };\n\t\t}\n\n\t\tconst normalizedMerged = normalize(strippedMerged);\n\n\t\tif (\n\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t) {\n\t\t\treturn { isSubset: true, merged: normalizedMerged, errors: [] };\n\t\t}\n\n\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\tif (tryNestedBranchingFallback(sub, effectiveSup, engine) === true) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst errors = computeSemanticErrors(sub, sup, \"\");\n\t\treturn { isSubset: false, merged: normalizedMerged, errors };\n\t} catch (_e) {\n\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\tif (tryNestedBranchingFallback(sub, effectiveSup, engine) === true) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst errors = computeSemanticErrors(sub, sup, \"\");\n\t\treturn {\n\t\t\tisSubset: false,\n\t\t\tmerged: null,\n\t\t\terrors,\n\t\t};\n\t}\n}\n"],"names":["isFormatSubset","normalize","isPatternSubset","computeSemanticErrors","deepEqual","hasOwn","isPlainObj","omitKeys","BRANCH_TRUE","branches","type","BRANCH_FALSE","atomicBranchCache","WeakMap","getBranchesTyped","def","Array","isArray","anyOf","oneOf","cached","get","undefined","set","evaluateNot","sub","sup","not","notSchema","properties","required","notProps","notRequired","subProps","subRequired","notPropKeys","Object","keys","hasIncompatibleProp","some","key","notPropDef","notProp","includes","subPropDef","subProp","const","enum","inNotEnum","v","noneInNotEnum","every","nv","allPropsMatch","notConst","subConst","allExcluded","val","notVal","notType","subType","allIncompatible","branch","result","anyBranchMatches","subFormat","format","notFormat","stripNotFromSup","stripTopLevel","supProps","newProps","supPropDef","propNotResult","stripPatternFromSup","supObj","copied","ensureCopy","pattern","patResult","propsModified","propPatResult","items","subItems","supItems","itemsPatResult","stripVacuousFalseProperties","merged","mergedProps","strippedProps","length","hasNestedBranching","schema","props","prop","isPropertySubsetOf","engine","subBranches","isAtomicSubsetOf","isObjectSubsetByProperties","subIsObj","supIsObj","supRequired","additionalProperties","supProp","addPropSchema","tryNestedBranchingFallback","supBranches","notResult","fmtResult","effectiveSup","merge","strippedMerged","normalizedMerged","isEqual","effectiveBranch","strippedBranch","normalizedBranch","checkBranchedSub","branchType","allErrors","allSubset","i","branchErrors","push","isSubset","errors","checkBranchedSup","_branchType","semanticErrors","checkAtomic","mergeOrThrow","_e"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/subset-checker.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { isFormatSubset } from \"./format-validator.ts\";\nimport type { MergeEngine } from \"./merge-engine.ts\";\nimport { normalize } from \"./normalizer.ts\";\nimport { isPatternSubset } from \"./pattern-subset.ts\";\nimport { computeSemanticErrors } from \"./semantic-errors.ts\";\nimport type { SchemaError, SubsetResult } from \"./types.ts\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys } from \"./utils.ts\";\n\n// ─── Subset Checker ──────────────────────────────────────────────────────────\n//\n// Subset verification logic via the approach:\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// Handles:\n// - Atomic schemas (no anyOf/oneOf)\n// - anyOf/oneOf in sub → each branch must be accepted by sup\n// - anyOf/oneOf in sup → at least one branch must accept sub\n// - Point 6: Distinguish anyOf / oneOf in diff messages\n// - Point 7: Extended `not` reasoning (evaluateNot)\n// - not.type, not.const, not.enum (existing)\n// - not with properties+required (1.1)\n// - not with anyOf/oneOf (1.2)\n// - not in sub (1.3)\n// - not.format (format-vs-format)\n//\n// Uses shared native helpers from `./utils` for optimal performance\n// (deepEqual, hasOwn, isPlainObj, omitKeys).\n\n// ─── Branch type ─────────────────────────────────────────────────────────────\n\n/**\n * Branch type detected in a schema.\n *\n * Point 6 — Distinguishes `anyOf` from `oneOf` to produce more precise\n * diff messages. `\"none\"` indicates an atomic schema (no branches).\n *\n * Note: the exclusivity semantics of `oneOf` are not verified\n * (this would be an NP-hard problem in general). The checker treats `oneOf`\n * like `anyOf` for subset checking, which is correct for the `sub ⊆ sup`\n * case but may produce false positives if the sub's branches overlap.\n */\nexport type BranchType = \"anyOf\" | \"oneOf\" | \"none\";\n\nexport interface BranchResult {\n\t/** The branches extracted from the schema */\n\tbranches: JSONSchema7Definition[];\n\t/** The detected branch type */\n\ttype: BranchType;\n}\n\n// ─── Branch extraction ───────────────────────────────────────────────────────\n\n// Pre-allocated singleton results for boolean schemas to avoid per-call allocations.\n// These are safe because the branches arrays are never mutated after creation.\nconst BRANCH_TRUE: BranchResult = { branches: [true], type: \"none\" };\nconst BRANCH_FALSE: BranchResult = { branches: [false], type: \"none\" };\n\n/**\n * WeakMap cache for atomic (no anyOf/oneOf) schema branch results.\n * Avoids allocating `{ branches: [def], type: \"none\" }` on every call\n * for the same schema object. Since normalized schemas are cached and\n * return the same reference, this cache hits frequently.\n */\nconst atomicBranchCache = new WeakMap<object, BranchResult>();\n\n/**\n * Extracts branches from a schema and the branch type.\n *\n * Returns the elements of `anyOf`/`oneOf` if they exist, otherwise returns\n * the schema itself in an array with type `\"none\"`.\n *\n * Point 6 — Distinguishes `anyOf` from `oneOf` in diff paths.\n *\n * Optimization: reuses pre-allocated objects for boolean cases\n * (true/false) and a WeakMap cache for atomic schemas to\n * avoid allocations on these frequent paths.\n */\nexport function getBranchesTyped(def: JSONSchema7Definition): BranchResult {\n\tif (typeof def === \"boolean\") {\n\t\treturn def ? BRANCH_TRUE : BRANCH_FALSE;\n\t}\n\tif (hasOwn(def, \"anyOf\") && Array.isArray(def.anyOf)) {\n\t\treturn { branches: def.anyOf, type: \"anyOf\" };\n\t}\n\tif (hasOwn(def, \"oneOf\") && Array.isArray(def.oneOf)) {\n\t\treturn { branches: def.oneOf, type: \"oneOf\" };\n\t}\n\t// Cache atomic results per schema object to avoid repeated allocations.\n\tlet cached = atomicBranchCache.get(def);\n\tif (cached === undefined) {\n\t\tcached = { branches: [def], type: \"none\" };\n\t\tatomicBranchCache.set(def, cached);\n\t}\n\treturn cached;\n}\n\n// ─── `not` reasoning (Point 7 — extended) ────────────────────────────────────\n\n/**\n * Extended `not` reasoning for common cases.\n *\n * Point 7 — Checks compatibility when `sup` and/or `sub` contain `not`:\n *\n * **Existing cases (not in sup):**\n * - `not.type`: excluded type vs sub's type\n * - `not.const`: excluded const vs sub's const\n * - `not.enum`: excluded values vs sub's enum\n *\n * **Added cases:**\n * - 1.1 — `not` with `properties` + `required`: verify that sub's properties\n * are incompatible with the `not`'s properties (different const/enum)\n * - 1.2 — `not` with `anyOf`/`oneOf`: `not(anyOf([A,B]))` ≡ `allOf([not(A), not(B)])`,\n * so sub must be incompatible with EACH branch\n * - 1.3 — `not` in `sub` (not only in `sup`): a sub with `not`\n * accepts a set too wide to be a subset of a concrete sup\n * - `not.format`: format-vs-format via `isFormatSubset`\n *\n * Conservative ternary contract:\n * - `true` → compatible (certain)\n * - `false` → incompatible (certain)\n * - `null` → undetermined (let the merge engine decide)\n *\n * When in doubt → `null`. NEVER return `true` without certainty.\n */\nfunction evaluateNot(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): boolean | null {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return null;\n\n\t// ── 1.3 — `not` in sub (not in sup) ──\n\t// A `not` in sub is an additional restriction: it excludes values from\n\t// the set accepted by sub, which makes it potentially smaller — thus\n\t// more likely to be ⊆ sup, not less.\n\t// We let the merge engine decide: allOf(sub, sup) will preserve the `not`\n\t// from sub, and the comparison merged ≡ sub will give the correct result.\n\t// Exception: if both have `not`, we handle the identity case below.\n\n\t// Check `not` in sup\n\tif (hasOwn(sup, \"not\") && isPlainObj(sup.not)) {\n\t\tconst notSchema = sup.not as JSONSchema7;\n\n\t\t// ── 1.1 — Case not with properties + required ──\n\t\t// IMPORTANT: this check is placed BEFORE the not.type check because when\n\t\t// the not has both `type` and `properties`, the not.type check alone\n\t\t// would produce a false negative (e.g. sub type=object and not type=object\n\t\t// would return false, but the properties could be incompatible\n\t\t// which would make sub compatible with the not).\n\t\t// If not contains properties with const/enum and required,\n\t\t// verify that sub's properties are incompatible with the not's properties.\n\t\tif (isPlainObj(notSchema.properties) && Array.isArray(notSchema.required)) {\n\t\t\tconst notProps = notSchema.properties as Record<\n\t\t\t\tstring,\n\t\t\t\tJSONSchema7Definition\n\t\t\t>;\n\t\t\tconst notRequired = notSchema.required as string[];\n\n\t\t\t// sub must have properties for us to compare\n\t\t\tif (isPlainObj(sub.properties)) {\n\t\t\t\tconst subProps = sub.properties as Record<\n\t\t\t\t\tstring,\n\t\t\t\t\tJSONSchema7Definition\n\t\t\t\t>;\n\t\t\t\tconst subRequired = Array.isArray(sub.required)\n\t\t\t\t\t? (sub.required as string[])\n\t\t\t\t\t: [];\n\t\t\t\tconst notPropKeys = Object.keys(notProps);\n\n\t\t\t\t// For sub to be compatible with not(schema),\n\t\t\t\t// it suffices that at least ONE property of the not is incompatible with sub.\n\t\t\t\t// This means that sub can never validate the schema inside not.\n\t\t\t\tconst hasIncompatibleProp = notPropKeys.some((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return false;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// If the property is required in not but NOT in sub.required\n\t\t\t\t\t// and it doesn't exist in sub.properties → sub may not\n\t\t\t\t\t// have this property → the not schema wouldn't match → compatible\n\t\t\t\t\tif (\n\t\t\t\t\t\tnotRequired.includes(key) &&\n\t\t\t\t\t\t!subRequired.includes(key) &&\n\t\t\t\t\t\t!hasOwn(subProps, key)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn true; // Property absent from sub → not doesn't match\n\t\t\t\t\t}\n\n\t\t\t\t\t// Compare the const/enum of the property\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return false;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// not.prop has a const, sub.prop has a different const → incompatible for this prop\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\tif (!deepEqual(notProp.const, subProp.const)) {\n\t\t\t\t\t\t\treturn true; // Different consts → sub doesn't match the not\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// not.prop has an enum, sub.prop has a const or enum with no value\n\t\t\t\t\t// in not.enum → incompatible for this prop\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\tconst inNotEnum = notProp.enum.some((v) =>\n\t\t\t\t\t\t\t\tdeepEqual(v, subProp.const),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!inNotEnum) return true; // sub.const absent from not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\tconst noneInNotEnum = subProp.enum.every(\n\t\t\t\t\t\t\t\t(v) => !notProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (noneInNotEnum) return true; // No value from sub.enum in not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\n\t\t\t\tif (hasIncompatibleProp) return true;\n\n\t\t\t\t// Inverse check: if ALL properties of the not match sub\n\t\t\t\t// exactly (same const, sub has the not's required), then sub VIOLATES the not\n\t\t\t\tconst allPropsMatch = notPropKeys.every((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return true;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// The property must be in sub.required if it is in not.required\n\t\t\t\t\tif (notRequired.includes(key) && !subRequired.includes(key))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return true;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// Check const match\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\treturn deepEqual(notProp.const, subProp.const);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check enum inclusion\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\treturn notProp.enum.some((v) => deepEqual(v, subProp.const));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\t// All values of sub.enum are in not.enum\n\t\t\t\t\t\t\treturn subProp.enum.every((v) =>\n\t\t\t\t\t\t\t\tnotProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false; // Undetermined for this property\n\t\t\t\t});\n\n\t\t\t\tif (allPropsMatch) return false; // sub matches the not exactly → incompatible\n\t\t\t}\n\t\t}\n\n\t\t// ── Case not.const ──\n\t\t// IMPORTANT: this check is placed BEFORE not.type because when the not has\n\t\t// both `type` and `const`, the not.type check alone would produce a\n\t\t// false negative (e.g. sub type=string const=\"active\" and not type=string\n\t\t// const=\"deleted\" → the type check would return false due to same type,\n\t\t// even though the consts are different → compatible).\n\t\tif (hasOwn(notSchema, \"const\") && hasOwn(sub, \"const\")) {\n\t\t\tconst notConst = notSchema.const;\n\t\t\tconst subConst = sub.const;\n\t\t\tif (deepEqual(subConst, notConst)) return false;\n\t\t\treturn true;\n\t\t}\n\n\t\t// ── Case not.enum ──\n\t\t// Also placed BEFORE not.type for the same reason.\n\t\tif (\n\t\t\thasOwn(notSchema, \"enum\") &&\n\t\t\tArray.isArray(notSchema.enum) &&\n\t\t\thasOwn(sub, \"enum\") &&\n\t\t\tArray.isArray(sub.enum)\n\t\t) {\n\t\t\t// All values of sub.enum must be absent from not.enum\n\t\t\tconst allExcluded = sub.enum.every(\n\t\t\t\t(val) => !notSchema.enum?.some((notVal) => deepEqual(val, notVal)),\n\t\t\t);\n\t\t\tif (allExcluded) return true;\n\t\t\t// Some values of sub are in not.enum → not automatically false,\n\t\t\t// the merge engine can still handle it\n\t\t}\n\n\t\t// ── Case not.type ──\n\t\t// Placed AFTER not.const, not.enum and properties+required to avoid\n\t\t// short-circuiting cases where the not has more specific constraints.\n\t\t// The type check alone is a fallback for simple not schemas\n\t\t// (e.g. { not: { type: \"string\" } }).\n\t\tif (hasOwn(notSchema, \"type\") && hasOwn(sub, \"type\")) {\n\t\t\tconst notType = notSchema.type;\n\t\t\tconst subType = sub.type;\n\n\t\t\t// If both are simple strings\n\t\t\tif (typeof notType === \"string\" && typeof subType === \"string\") {\n\t\t\t\t// Only return if the not does NOT have more specific constraints\n\t\t\t\t// (const, enum, properties) that should have been handled above\n\t\t\t\tif (\n\t\t\t\t\t!hasOwn(notSchema, \"const\") &&\n\t\t\t\t\t!hasOwn(notSchema, \"enum\") &&\n\t\t\t\t\t!isPlainObj(notSchema.properties)\n\t\t\t\t) {\n\t\t\t\t\tif (subType === notType) return false; // Incompatible: sub is exactly the excluded type\n\t\t\t\t\treturn true; // Compatible: sub is a different type from the excluded type\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If notType is an array, sub.type must not be in it\n\t\t\tif (Array.isArray(notType) && typeof subType === \"string\") {\n\t\t\t\tif (notType.includes(subType)) return false;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// ── 1.2 — Case not with anyOf / oneOf ──\n\t\t// not(anyOf([A, B])) ≡ allOf([not(A), not(B)])\n\t\t// For sub ⊆ not(anyOf(...)), sub must be incompatible with EACH branch.\n\t\tif (hasOwn(notSchema, \"anyOf\") && Array.isArray(notSchema.anyOf)) {\n\t\t\tconst branches = notSchema.anyOf as JSONSchema7Definition[];\n\t\t\t// For each branch of not.anyOf, verify that sub is incompatible\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch; // not(true) = nothing, not(false) = everything\n\t\t\t\t// Create a virtual sup { not: branch } and verify recursively\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\t// result = true → sub is compatible with not(branch) → sub ⊄ branch → OK\n\t\t\t\t// result = false → sub is incompatible with not(branch) → sub ⊆ branch → not OK\n\t\t\t\t// result = null → undetermined\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\t// Check if at least one branch accepts sub → incompatible with not(anyOf)\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false; // sub is incompatible with not(branch) → sub ⊆ branch\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// Same logic for oneOf (in the not context, treated like anyOf)\n\t\tif (hasOwn(notSchema, \"oneOf\") && Array.isArray(notSchema.oneOf)) {\n\t\t\tconst branches = notSchema.oneOf as JSONSchema7Definition[];\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false;\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// ── Case not.format (format-vs-format only) ──\n\t\t// If not has a format and sub also does, check compatibility\n\t\tif (hasOwn(notSchema, \"format\") && hasOwn(sub, \"format\")) {\n\t\t\tconst subFormat = sub.format as string;\n\t\t\tconst notFormat = notSchema.format as string;\n\t\t\tif (subFormat === notFormat) return false; // Incompatible: sub has exactly the excluded format\n\t\t\t// Different formats → compatible (conservative approximation)\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Check `not` in sub AND in sup (identity: { not: X } ⊆ { not: X })\n\tif (hasOwn(sub, \"not\") && hasOwn(sup, \"not\")) {\n\t\tif (deepEqual(sub.not, sup.not)) return true;\n\t}\n\n\treturn null; // No opinion → let the merge engine decide\n}\n\n// ─── Not stripping helper ────────────────────────────────────────────────────\n\n/**\n * Removes the `not` keyword from a schema to allow a clean merge\n * when `evaluateNot` has already confirmed compatibility.\n *\n * Also handles `not` nested in `properties`: if a property of `sup`\n * has a `not` that is compatible with the corresponding property of\n * `sub`, it is removed as well.\n *\n * Returns the cleaned schema, or `null` if the schema is empty after removal.\n */\nfunction stripNotFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tstripTopLevel: boolean = true,\n): JSONSchema7Definition {\n\tif (typeof sup === \"boolean\" || typeof sub === \"boolean\") return sup;\n\n\tlet result = sup as JSONSchema7;\n\n\t// ── Remove top-level `not` (only if confirmed) ──\n\tif (stripTopLevel && hasOwn(result, \"not\")) {\n\t\tresult = omitKeys(result as unknown as Record<string, unknown>, [\n\t\t\t\"not\",\n\t\t]) as JSONSchema7;\n\t}\n\n\t// ── Remove `not` in common properties ──\n\t// If sup.properties[key] has a `not` and evaluateNot(sub.prop, sup.prop)\n\t// confirms compatibility, we remove the `not` from that property as well.\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"not\")\n\t\t\t) {\n\t\t\t\t// Check not compatibility at the property level\n\t\t\t\tconst propNotResult = evaluateNot(subPropDef, supPropDef);\n\t\t\t\tif (propNotResult === true) {\n\t\t\t\t\t// Lazy allocate newProps only on first modification\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"not\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (newProps) {\n\t\t\tresult = { ...result, properties: newProps };\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Pattern stripping helper ────────────────────────────────────────────────\n\n/**\n * Removes the `pattern` from `sup` when `isPatternSubset` has confirmed that\n * sub.pattern ⊆ sup.pattern via sampling.\n *\n * Works like `stripNotFromSup`: we remove the sup constraint that is already\n * satisfied by sub, to prevent the merge engine from producing a combined\n * pattern (lookahead conjunction) structurally different from sub's pattern,\n * which would cause a false negative.\n *\n * Recurses into `properties` to handle nested patterns.\n *\n * @param sub The sub schema (used to extract patterns to compare)\n * @param sup The sup schema from which confirmed patterns are removed\n * @returns The cleaned sup schema\n */\nfunction stripPatternFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): JSONSchema7Definition {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return sup;\n\n\tconst supObj: JSONSchema7 = sup;\n\n\t// Lazy copy-on-write: only create a copy when the first mutation is needed.\n\tlet result: JSONSchema7 = supObj;\n\tlet copied = false;\n\n\tfunction ensureCopy(): JSONSchema7 {\n\t\tif (!copied) {\n\t\t\tresult = { ...supObj };\n\t\t\tcopied = true;\n\t\t}\n\t\treturn result;\n\t}\n\n\t// ── Top-level pattern ──\n\tif (\n\t\thasOwn(result, \"pattern\") &&\n\t\thasOwn(sub, \"pattern\") &&\n\t\tresult.pattern !== (sub as JSONSchema7).pattern\n\t) {\n\t\tconst patResult = isPatternSubset(\n\t\t\t(sub as JSONSchema7).pattern as string,\n\t\t\tresult.pattern as string,\n\t\t);\n\t\tif (patResult === true) {\n\t\t\tresult = omitKeys(ensureCopy() as unknown as Record<string, unknown>, [\n\t\t\t\t\"pattern\",\n\t\t\t]) as JSONSchema7;\n\t\t\tcopied = true;\n\t\t}\n\t}\n\n\t// ── Patterns in common properties ──\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet propsModified = false;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"pattern\") &&\n\t\t\t\thasOwn(subPropDef, \"pattern\") &&\n\t\t\t\tsupPropDef.pattern !== subPropDef.pattern\n\t\t\t) {\n\t\t\t\tconst propPatResult = isPatternSubset(\n\t\t\t\t\t(subPropDef as JSONSchema7).pattern as string,\n\t\t\t\t\t(supPropDef as JSONSchema7).pattern as string,\n\t\t\t\t);\n\t\t\t\tif (propPatResult === true) {\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"pattern\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t\tpropsModified = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (propsModified && newProps) {\n\t\t\tensureCopy().properties = newProps;\n\t\t}\n\t}\n\n\t// ── Pattern in items (single schema) ──\n\tif (\n\t\tisPlainObj(result.items) &&\n\t\ttypeof result.items !== \"boolean\" &&\n\t\tisPlainObj((sub as JSONSchema7).items) &&\n\t\ttypeof (sub as JSONSchema7).items !== \"boolean\"\n\t) {\n\t\tconst subItems = (sub as JSONSchema7).items as JSONSchema7;\n\t\tconst supItems = result.items as JSONSchema7;\n\t\tif (\n\t\t\thasOwn(supItems, \"pattern\") &&\n\t\t\thasOwn(subItems, \"pattern\") &&\n\t\t\tsupItems.pattern !== subItems.pattern\n\t\t) {\n\t\t\tconst itemsPatResult = isPatternSubset(\n\t\t\t\tsubItems.pattern as string,\n\t\t\t\tsupItems.pattern as string,\n\t\t\t);\n\t\t\tif (itemsPatResult === true) {\n\t\t\t\tensureCopy().items = omitKeys(\n\t\t\t\t\tsupItems as unknown as Record<string, unknown>,\n\t\t\t\t\t[\"pattern\"],\n\t\t\t\t) as JSONSchema7Definition;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Vacuous false-property stripping ────────────────────────────────────────\n//\n// In JSON Schema, `properties: { x: false }` means \"if x is present, it must\n// validate against `false` (impossible)\". If x is **absent** from the instance,\n// the constraint is **trivially satisfied** (vacuous truth).\n//\n// After merge(sub, sup), the merge engine may add `false`-schema properties\n// from sup into the merged result even when sub doesn't define those properties.\n// This causes `deepEqual(merged, sub)` to fail — a false negative.\n//\n// `stripVacuousFalseProperties` removes those vacuously-satisfied `false`\n// properties from `merged` so that the structural comparison succeeds.\n\n/**\n * Strips `false`-schema properties from `merged` that are absent in `sub`.\n *\n * A property `{ key: false }` in merged that doesn't exist in sub's properties\n * is vacuously satisfied — sub never produces that key, so the \"impossible\"\n * constraint has no effect. Removing it lets `deepEqual(merged, sub)` succeed.\n *\n * @returns A new schema with vacuous `false` properties removed, or the\n * original `merged` if no stripping was needed.\n */\nfunction stripVacuousFalseProperties(\n\tmerged: JSONSchema7Definition,\n\tsub: JSONSchema7Definition,\n): JSONSchema7Definition {\n\tif (typeof merged === \"boolean\" || typeof sub === \"boolean\") return merged;\n\tif (!isPlainObj(merged.properties)) return merged;\n\n\tconst mergedProps = merged.properties as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst subProps = (isPlainObj(sub.properties) ? sub.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\n\tlet strippedProps: Record<string, JSONSchema7Definition> | null = null;\n\n\tfor (const key of Object.keys(mergedProps)) {\n\t\tif (mergedProps[key] === false && !hasOwn(subProps, key)) {\n\t\t\t// Lazily copy on first strip\n\t\t\tif (strippedProps === null) {\n\t\t\t\tstrippedProps = { ...mergedProps };\n\t\t\t}\n\t\t\tdelete strippedProps[key];\n\t\t}\n\t}\n\n\tif (strippedProps === null) return merged;\n\n\t// Return a new schema with the cleaned properties\n\tconst result = { ...merged, properties: strippedProps };\n\n\t// If properties is now empty and sub doesn't have properties, remove it\n\tif (Object.keys(strippedProps).length === 0 && !isPlainObj(sub.properties)) {\n\t\tdelete (result as Record<string, unknown>).properties;\n\t}\n\n\treturn result;\n}\n\n// ─── Nested branching fallback ───────────────────────────────────────────────\n//\n// The merge engine (`@x0k/json-schema-merge`) cannot resolve `allOf` over\n// `oneOf`/`anyOf` inside properties — it either throws or produces garbage\n// like `{ type: \"string\", oneOf: [...] }`.\n//\n// When the merge-based check fails (null or merged ≠ sub), and either schema\n// contains `oneOf`/`anyOf` inside its properties or items, we fall back to a\n// **property-by-property** comparison that uses the existing branching logic\n// (`getBranchesTyped` / `isAtomicSubsetOf`) on each sub-schema individually.\n//\n// Three helpers:\n// 1. `hasNestedBranching` — guard: does a schema contain oneOf/anyOf in\n// properties or items? Avoids triggering the fallback on normal schemas.\n// 2. `isPropertySubsetOf` — compares a single property sub-schema handling\n// branches on both sides (sub may have oneOf, sup may have oneOf).\n// 3. `isObjectSubsetByProperties` — the fallback itself: iterates over\n// object properties + items and delegates to `isPropertySubsetOf`.\n// 4. `tryNestedBranchingFallback` — the single entry point called from\n// `isAtomicSubsetOf` and `checkAtomic`. Encapsulates the guard check\n// and the call, returning `boolean | null` (null = not applicable).\n\n/**\n * Returns `true` if the schema contains `oneOf`/`anyOf` inside its\n * `properties` or `items`. Recurses into nested object schemas.\n *\n * This is a cheap guard so we only attempt the property-by-property\n * fallback when the merge failure is plausibly caused by nested branching.\n */\nfunction hasNestedBranching(schema: JSONSchema7Definition): boolean {\n\tif (typeof schema === \"boolean\") return false;\n\n\tif (isPlainObj(schema.properties)) {\n\t\tconst props = schema.properties as Record<string, JSONSchema7Definition>;\n\t\tfor (const key of Object.keys(props)) {\n\t\t\tconst prop = props[key];\n\t\t\tif (prop === undefined || typeof prop === \"boolean\") continue;\n\t\t\tif (hasOwn(prop, \"oneOf\") || hasOwn(prop, \"anyOf\")) return true;\n\t\t\tif (hasNestedBranching(prop)) return true;\n\t\t}\n\t}\n\n\tif (isPlainObj(schema.items) && typeof schema.items !== \"boolean\") {\n\t\tconst items = schema.items as JSONSchema7;\n\t\tif (hasOwn(items, \"oneOf\") || hasOwn(items, \"anyOf\")) return true;\n\t\tif (hasNestedBranching(items)) return true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Checks `sub ⊆ sup` for a single property sub-schema, handling branches\n * on **both** sides.\n *\n * `isAtomicSubsetOf` only extracts branches from `sup`. When `sub` also\n * has `oneOf`/`anyOf`, we extract sub's branches and verify that **every**\n * branch is accepted by sup (same semantics as `checkBranchedSub`).\n */\nfunction isPropertySubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: subBranches } = getBranchesTyped(sub);\n\n\tif (subBranches.length > 1 || subBranches[0] !== sub) {\n\t\tfor (const branch of subBranches) {\n\t\t\tif (branch === undefined) continue;\n\t\t\tif (!isAtomicSubsetOf(branch, sup, engine)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\treturn isAtomicSubsetOf(sub, sup, engine);\n}\n\n/**\n * Checks whether the array-level constraints of `sub` are compatible\n * with those of `sup` for subset semantics:\n * - `minItems`: sub.minItems must be >= sup.minItems\n * - `maxItems`: sub.maxItems must be <= sup.maxItems\n * - `uniqueItems`: if sup requires it, sub must too\n */\nfunction isArrayConstraintsSubset(sub: JSONSchema7, sup: JSONSchema7): boolean {\n\t// minItems: sub.minItems must be >= sup.minItems\n\tif (sup.minItems !== undefined) {\n\t\tif (sub.minItems === undefined || sub.minItems < sup.minItems) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// maxItems: sub.maxItems must be <= sup.maxItems\n\tif (sup.maxItems !== undefined) {\n\t\tif (sub.maxItems === undefined || sub.maxItems > sup.maxItems) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// uniqueItems: if sup requires it, sub must also require it\n\tif (sup.uniqueItems === true && sub.uniqueItems !== true) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Checks `sub ⊆ sup` by comparing object properties (and array items)\n * individually, using the full branching-aware logic.\n *\n * This is a **fallback** for when the merge-based check fails due to\n * `oneOf`/`anyOf` inside properties. It does NOT check object-level\n * keywords like `minProperties`/`maxProperties` — those are rare in\n * practice and are already handled correctly by the merge when the\n * branching isn't involved.\n *\n * @returns `true` if sub ⊆ sup, `false` otherwise.\n */\nfunction isObjectSubsetByProperties(\n\tsub: JSONSchema7,\n\tsup: JSONSchema7,\n\tengine: MergeEngine,\n): boolean {\n\tconst subIsObj = sub.type === \"object\" || isPlainObj(sub.properties);\n\tconst supIsObj = sup.type === \"object\" || isPlainObj(sup.properties);\n\n\t// ── Array path: both are arrays with items ──\n\tif (!subIsObj && !supIsObj) {\n\t\tif (\n\t\t\tsub.type === \"array\" &&\n\t\t\tsup.type === \"array\" &&\n\t\t\tisPlainObj(sub.items) &&\n\t\t\tisPlainObj(sup.items)\n\t\t) {\n\t\t\tif (\n\t\t\t\t!isPropertySubsetOf(\n\t\t\t\t\tsub.items as JSONSchema7Definition,\n\t\t\t\t\tsup.items as JSONSchema7Definition,\n\t\t\t\t\tengine,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn isArrayConstraintsSubset(sub, sup);\n\t\t}\n\t\treturn false;\n\t}\n\n\t// Both must look like objects\n\tif (!subIsObj || !supIsObj) return false;\n\n\t// ── Type compatibility ──\n\tif (hasOwn(sub, \"type\") && hasOwn(sup, \"type\") && sub.type !== sup.type) {\n\t\treturn false;\n\t}\n\n\tconst subProps = (isPlainObj(sub.properties) ? sub.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst supProps = (isPlainObj(sup.properties) ? sup.properties : {}) as Record<\n\t\tstring,\n\t\tJSONSchema7Definition\n\t>;\n\tconst subRequired = Array.isArray(sub.required)\n\t\t? (sub.required as string[])\n\t\t: [];\n\tconst supRequired = Array.isArray(sup.required)\n\t\t? (sup.required as string[])\n\t\t: [];\n\n\t// ── Required: every key sup requires, sub must also require ──\n\tfor (const key of supRequired) {\n\t\tif (!subRequired.includes(key)) return false;\n\t}\n\n\t// ── additionalProperties: false on sup ──\n\tif (sup.additionalProperties === false) {\n\t\tfor (const key of Object.keys(subProps)) {\n\t\t\tif (!hasOwn(supProps, key)) return false;\n\t\t}\n\t}\n\n\t// ── Property-by-property check ──\n\tfor (const key of Object.keys(supProps)) {\n\t\tconst supProp = supProps[key];\n\t\tconst subProp = subProps[key];\n\t\tif (supProp === undefined || subProp === undefined) continue;\n\n\t\tif (!isPropertySubsetOf(subProp, supProp, engine)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// ── Sub's extra properties vs sup's additionalProperties schema ──\n\tif (\n\t\tisPlainObj(sup.additionalProperties) &&\n\t\ttypeof sup.additionalProperties !== \"boolean\"\n\t) {\n\t\tconst addPropSchema = sup.additionalProperties as JSONSchema7Definition;\n\t\tfor (const key of Object.keys(subProps)) {\n\t\t\tif (hasOwn(supProps, key)) continue;\n\t\t\tconst subProp = subProps[key];\n\t\t\tif (subProp === undefined) continue;\n\t\t\tif (!isPropertySubsetOf(subProp, addPropSchema, engine)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Items (object schema that also has array items) ──\n\tif (isPlainObj(sub.items) && isPlainObj(sup.items)) {\n\t\tif (\n\t\t\t!isPropertySubsetOf(\n\t\t\t\tsub.items as JSONSchema7Definition,\n\t\t\t\tsup.items as JSONSchema7Definition,\n\t\t\t\tengine,\n\t\t\t)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!isArrayConstraintsSubset(sub, sup)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Attempts the property-by-property fallback when a merge-based check\n * fails and nested branching is detected.\n *\n * Encapsulates the guard (`hasNestedBranching`) and the call to\n * `isObjectSubsetByProperties` so callers don't repeat the pattern.\n *\n * @returns `true` if the fallback confirms sub ⊆ sup, `false` if it\n * confirms sub ⊄ sup, `null` if the fallback is not applicable\n * (neither schema has nested branching, or schemas are booleans).\n */\nfunction tryNestedBranchingFallback(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean | null {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return null;\n\tif (!hasNestedBranching(sub) && !hasNestedBranching(sup)) return null;\n\treturn isObjectSubsetByProperties(sub, sup, engine);\n}\n\n// ─── Atomic subset check ─────────────────────────────────────────────────────\n\n/**\n * Checks whether `sub ⊆ sup` for two schemas without anyOf/oneOf (or with\n * anyOf/oneOf only on the sup side).\n *\n * Point 7 — Integrates an extended `not` pre-check (`evaluateNot`) before the merge.\n *\n * When `evaluateNot` confirms compatibility (`true`), the `not` is removed\n * from `sup` before the merge to prevent the merge engine from adding a `not`\n * constraint that `sub` doesn't have (which would cause `isEqual(merged, sub)` to fail).\n *\n * Pattern pre-check — When both schemas have different patterns, checks\n * inclusion via sampling with `isPatternSubset`. If confirmed, removes the\n * pattern from sup before the merge (same strategy as for `not`).\n *\n * Principle: merge(sub, sup) ≡ sub → sub is a subset of sup.\n *\n * When the merge-based check fails and either sub or sup contains nested\n * `oneOf`/`anyOf` in properties or items, falls back to a property-by-property\n * comparison via `isObjectSubsetByProperties`.\n */\nexport function isAtomicSubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: supBranches } = getBranchesTyped(sup);\n\n\t// Simple schema → direct merge\n\tif (supBranches.length === 1 && supBranches[0] === sup) {\n\t\t// Point 7: extended `not` pre-check\n\t\tconst notResult = evaluateNot(sub, sup);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Format pre-check ──\n\t\t// If both schemas have a different `format`, check that\n\t\t// sub.format ⊆ sup.format. Otherwise, sub cannot be ⊆ sup.\n\t\t// This complements hasFormatConflict (which handles the merge) by handling\n\t\t// the subset check direction that the merge cannot resolve.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"format\") &&\n\t\t\thasOwn(sup, \"format\") &&\n\t\t\tsub.format !== sup.format\n\t\t) {\n\t\t\tconst fmtResult = isFormatSubset(\n\t\t\t\tsub.format as string,\n\t\t\t\tsup.format as string,\n\t\t\t);\n\t\t\tif (fmtResult !== true) return false;\n\t\t}\n\n\t\t// ── Pattern pre-check ──\n\t\t// If both schemas have different patterns, check inclusion\n\t\t// via sampling. If sub.pattern ⊄ sup.pattern (counter-example found),\n\t\t// we return false immediately. Otherwise, we can remove the pattern\n\t\t// from sup to avoid the structural false negative from the merge.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(sup, \"pattern\") &&\n\t\t\tsub.pattern !== sup.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tsup.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Remove `not` from sup (top-level and/or in properties)\n\t\t// when evaluateNot confirms compatibility at the corresponding level.\n\t\t// This prevents the merge engine from adding a `not` constraint that sub doesn't have\n\t\t// (which would cause merged ≠ sub and produce a false negative).\n\t\tlet effectiveSup = sup;\n\t\tif (typeof sup !== \"boolean\") {\n\t\t\t// If top-level not is confirmed compatible → remove top-level not\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, true);\n\t\t\t\t// If sup only had `not` → sub is compatible (the not is resolved)\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveSup !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveSup).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Even if the top-level not is not confirmed (null), we attempt\n\t\t\t\t// to remove `not` in individual properties\n\t\t\t\t// without touching the top-level `not`\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, false);\n\t\t\t}\n\n\t\t\t// Remove patterns from sup confirmed by sampling.\n\t\t\t// Same strategy as for `not`: we remove the constraint already\n\t\t\t// satisfied by sub to prevent the merge from producing a combined\n\t\t\t// pattern (lookahead conjunction) structurally ≠ sub.\n\t\t\teffectiveSup = stripPatternFromSup(sub, effectiveSup);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveSup);\n\t\tif (merged === null) {\n\t\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\t\treturn tryNestedBranchingFallback(sub, effectiveSup, engine) ?? false;\n\t\t}\n\t\t// Fast path: if merged is already structurally equal to sub,\n\t\t// skip normalize entirely. This is the common case when sub ⊆ sup\n\t\t// (A ∩ B = A), saving O(n) normalize traversal on wide schemas.\n\t\tif (deepEqual(merged, sub)) return true;\n\n\t\t// Strip vacuously-satisfied `false` properties added by the merge\n\t\t// from sup but absent in sub (vacuous truth: absent ⊆ forbidden).\n\t\tconst strippedMerged = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedMerged !== merged && deepEqual(strippedMerged, sub)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Slow path: normalize to eliminate merge artifacts (e.g. redundant\n\t\t// enum when const is present), then compare.\n\t\tconst normalizedMerged = normalize(strippedMerged);\n\t\tif (\n\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// ── Fallback: merged ≠ sub but nested branching may explain it ──\n\t\t// The merge engine preserves oneOf/anyOf as-is inside properties\n\t\t// (e.g. merge produces {type:\"string\", oneOf:[...]} ≠ sub).\n\t\treturn tryNestedBranchingFallback(sub, effectiveSup, engine) ?? false;\n\t}\n\n\t// anyOf/oneOf in sup → at least one branch must accept sub\n\treturn supBranches.some((branch) => {\n\t\t// Point 7: extended `not` pre-check per branch\n\t\tconst notResult = evaluateNot(sub, branch);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Pattern pre-check par branche ──\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof branch !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(branch, \"pattern\") &&\n\t\t\tsub.pattern !== branch.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tbranch.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Same strip logic for branches\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof branch !== \"boolean\") {\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, true);\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveBranch !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveBranch).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, false);\n\t\t\t}\n\n\t\t\t// Strip patterns confirmed by sampling\n\t\t\teffectiveBranch = stripPatternFromSup(sub, effectiveBranch);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged === null) {\n\t\t\t// Fallback for nested branching within branches\n\t\t\treturn tryNestedBranchingFallback(sub, effectiveBranch, engine) === true;\n\t\t}\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) return true;\n\n\t\t// Strip vacuously-satisfied `false` properties (see comment above)\n\t\tconst strippedBranch = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedBranch !== merged && deepEqual(strippedBranch, sub)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst normalizedBranch = normalize(strippedBranch);\n\t\tif (\n\t\t\tdeepEqual(normalizedBranch, sub) ||\n\t\t\tengine.isEqual(normalizedBranch, sub)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Fallback: merged ≠ sub but nested branching may explain it\n\t\treturn tryNestedBranchingFallback(sub, effectiveBranch, engine) === true;\n\t});\n}\n\n// ─── Full subset check (with diffs) ─────────────────────────────────────────\n\n/**\n * Checks `sub ⊆ sup` for a sub that has branches (anyOf/oneOf).\n * Each branch of sub must be accepted by sup.\n *\n * Point 6 — Uses `getBranchesTyped` to distinguish `anyOf[i]` from\n * `oneOf[i]` in diff paths.\n */\nexport function checkBranchedSub(\n\tsubBranches: JSONSchema7Definition[],\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n\tbranchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tconst allErrors: SchemaError[] = [];\n\tlet allSubset = true;\n\n\tfor (let i = 0; i < subBranches.length; i++) {\n\t\tconst branch = subBranches[i];\n\t\tif (branch === undefined) continue;\n\t\tif (!isAtomicSubsetOf(branch, sup, engine)) {\n\t\t\tallSubset = false;\n\t\t\tconst branchErrors = computeSemanticErrors(branch, sup, \"\");\n\t\t\tallErrors.push(...branchErrors);\n\t\t}\n\t}\n\n\treturn {\n\t\tisSubset: allSubset,\n\t\tmerged: allSubset\n\t\t\t? branchType === \"oneOf\"\n\t\t\t\t? { oneOf: subBranches }\n\t\t\t\t: { anyOf: subBranches }\n\t\t\t: null,\n\t\terrors: allErrors,\n\t};\n}\n\n/**\n * Checks `sub ⊆ sup` for a sup that has branches (anyOf/oneOf).\n * At least one branch of sup must accept sub.\n *\n * Point 6 — Uses the sup's branch type for more precise messages.\n */\nexport function checkBranchedSup(\n\tsub: JSONSchema7Definition,\n\tsupBranches: JSONSchema7Definition[],\n\tengine: MergeEngine,\n\t_branchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tfor (const branch of supBranches) {\n\t\t// Strip patterns confirmed by sampling before the merge\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof sub !== \"boolean\" && typeof branch !== \"boolean\") {\n\t\t\teffectiveBranch = stripPatternFromSup(sub, branch);\n\t\t}\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged !== null) {\n\t\t\t// Fast path: skip normalize if merged already equals sub\n\t\t\tif (deepEqual(merged, sub)) {\n\t\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t\t}\n\t\t\tconst normalizedMerged = normalize(merged);\n\t\t\tif (\n\t\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t\t) {\n\t\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t\t}\n\t\t}\n\t}\n\n\t// Generate semantic errors by comparing sub with the original sup\n\tconst semanticErrors = computeSemanticErrors(\n\t\tsub,\n\t\t{ anyOf: supBranches } as JSONSchema7,\n\t\t\"\",\n\t);\n\n\treturn {\n\t\tisSubset: false,\n\t\tmerged: null,\n\t\terrors: semanticErrors,\n\t};\n}\n\n/**\n * Checks `sub ⊆ sup` for two atomic schemas (without anyOf/oneOf).\n * Uses `mergeOrThrow` to capture incompatibility errors.\n *\n * Uses `deepEqual` for structural comparison (with short-circuit\n * by reference and key counting).\n */\nexport function checkAtomic(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): SubsetResult {\n\t// Strip patterns confirmed by sampling before the merge,\n\t// same strategy as in isAtomicSubsetOf to avoid structural false negatives\n\t// caused by the conjunction of patterns as lookahead.\n\tlet effectiveSup = sup;\n\tif (typeof sub !== \"boolean\" && typeof sup !== \"boolean\") {\n\t\teffectiveSup = stripPatternFromSup(sub, sup);\n\t}\n\n\ttry {\n\t\tconst merged = engine.mergeOrThrow(sub, effectiveSup);\n\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) {\n\t\t\treturn { isSubset: true, merged, errors: [] };\n\t\t}\n\n\t\t// Strip vacuously-satisfied `false` properties added by the merge\n\t\t// from sup but absent in sub (vacuous truth: absent ⊆ forbidden).\n\t\tconst strippedMerged = stripVacuousFalseProperties(merged, sub);\n\t\tif (strippedMerged !== merged && deepEqual(strippedMerged, sub)) {\n\t\t\treturn { isSubset: true, merged: strippedMerged, errors: [] };\n\t\t}\n\n\t\tconst normalizedMerged = normalize(strippedMerged);\n\n\t\tif (\n\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t) {\n\t\t\treturn { isSubset: true, merged: normalizedMerged, errors: [] };\n\t\t}\n\n\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\tif (tryNestedBranchingFallback(sub, effectiveSup, engine) === true) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst errors = computeSemanticErrors(sub, sup, \"\");\n\t\treturn { isSubset: false, merged: normalizedMerged, errors };\n\t} catch (_e) {\n\t\t// ── Fallback: property-by-property for nested oneOf/anyOf ──\n\t\tif (tryNestedBranchingFallback(sub, effectiveSup, engine) === true) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst errors = computeSemanticErrors(sub, sup, \"\");\n\t\treturn {\n\t\t\tisSubset: false,\n\t\t\tmerged: null,\n\t\t\terrors,\n\t\t};\n\t}\n}\n"],"names":["isFormatSubset","normalize","isPatternSubset","computeSemanticErrors","deepEqual","hasOwn","isPlainObj","omitKeys","BRANCH_TRUE","branches","type","BRANCH_FALSE","atomicBranchCache","WeakMap","getBranchesTyped","def","Array","isArray","anyOf","oneOf","cached","get","undefined","set","evaluateNot","sub","sup","not","notSchema","properties","required","notProps","notRequired","subProps","subRequired","notPropKeys","Object","keys","hasIncompatibleProp","some","key","notPropDef","notProp","includes","subPropDef","subProp","const","enum","inNotEnum","v","noneInNotEnum","every","nv","allPropsMatch","notConst","subConst","allExcluded","val","notVal","notType","subType","allIncompatible","branch","result","anyBranchMatches","subFormat","format","notFormat","stripNotFromSup","stripTopLevel","supProps","newProps","supPropDef","propNotResult","stripPatternFromSup","supObj","copied","ensureCopy","pattern","patResult","propsModified","propPatResult","items","subItems","supItems","itemsPatResult","stripVacuousFalseProperties","merged","mergedProps","strippedProps","length","hasNestedBranching","schema","props","prop","isPropertySubsetOf","engine","subBranches","isAtomicSubsetOf","isArrayConstraintsSubset","minItems","maxItems","uniqueItems","isObjectSubsetByProperties","subIsObj","supIsObj","supRequired","additionalProperties","supProp","addPropSchema","tryNestedBranchingFallback","supBranches","notResult","fmtResult","effectiveSup","merge","strippedMerged","normalizedMerged","isEqual","effectiveBranch","strippedBranch","normalizedBranch","checkBranchedSub","branchType","allErrors","allSubset","i","branchErrors","push","isSubset","errors","checkBranchedSup","_branchType","semanticErrors","checkAtomic","mergeOrThrow","_e"],"mappings":"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"}
|