json-schema-compatibility-checker 1.0.10 → 1.0.11
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 _formatvalidator=require("./format-validator.js");const _normalizer=require("./normalizer.js");const _patternsubset=require("./pattern-subset.js");const _semanticerrors=require("./semantic-errors.js");const _utils=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,_utils.hasOwn)(def,"anyOf")&&Array.isArray(def.anyOf)){return{branches:def.anyOf,type:"anyOf"}}if((0,_utils.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,_utils.hasOwn)(sup,"not")&&(0,_utils.isPlainObj)(sup.not)){const notSchema=sup.not;if((0,_utils.isPlainObj)(notSchema.properties)&&Array.isArray(notSchema.required)){const notProps=notSchema.properties;const notRequired=notSchema.required;if((0,_utils.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,_utils.hasOwn)(subProps,key)){return true}if(!(0,_utils.hasOwn)(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return false;const subProp=subPropDef;if((0,_utils.hasOwn)(notProp,"const")&&(0,_utils.hasOwn)(subProp,"const")){if(!(0,_utils.deepEqual)(notProp.const,subProp.const)){return true}}if((0,_utils.hasOwn)(notProp,"enum")&&Array.isArray(notProp.enum)){if((0,_utils.hasOwn)(subProp,"const")){const inNotEnum=notProp.enum.some(v=>(0,_utils.deepEqual)(v,subProp.const));if(!inNotEnum)return true}if((0,_utils.hasOwn)(subProp,"enum")&&Array.isArray(subProp.enum)){const noneInNotEnum=subProp.enum.every(v=>!notProp.enum?.some(nv=>(0,_utils.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,_utils.hasOwn)(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return true;const subProp=subPropDef;if((0,_utils.hasOwn)(notProp,"const")&&(0,_utils.hasOwn)(subProp,"const")){return(0,_utils.deepEqual)(notProp.const,subProp.const)}if((0,_utils.hasOwn)(notProp,"enum")&&Array.isArray(notProp.enum)){if((0,_utils.hasOwn)(subProp,"const")){return notProp.enum.some(v=>(0,_utils.deepEqual)(v,subProp.const))}if((0,_utils.hasOwn)(subProp,"enum")&&Array.isArray(subProp.enum)){return subProp.enum.every(v=>notProp.enum?.some(nv=>(0,_utils.deepEqual)(v,nv)))}}return false});if(allPropsMatch)return false}}if((0,_utils.hasOwn)(notSchema,"const")&&(0,_utils.hasOwn)(sub,"const")){const notConst=notSchema.const;const subConst=sub.const;if((0,_utils.deepEqual)(subConst,notConst))return false;return true}if((0,_utils.hasOwn)(notSchema,"enum")&&Array.isArray(notSchema.enum)&&(0,_utils.hasOwn)(sub,"enum")&&Array.isArray(sub.enum)){const allExcluded=sub.enum.every(val=>!notSchema.enum?.some(notVal=>(0,_utils.deepEqual)(val,notVal)));if(allExcluded)return true}if((0,_utils.hasOwn)(notSchema,"type")&&(0,_utils.hasOwn)(sub,"type")){const notType=notSchema.type;const subType=sub.type;if(typeof notType==="string"&&typeof subType==="string"){if(!(0,_utils.hasOwn)(notSchema,"const")&&!(0,_utils.hasOwn)(notSchema,"enum")&&!(0,_utils.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,_utils.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,_utils.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,_utils.hasOwn)(notSchema,"format")&&(0,_utils.hasOwn)(sub,"format")){const subFormat=sub.format;const notFormat=notSchema.format;if(subFormat===notFormat)return false;return true}}if((0,_utils.hasOwn)(sub,"not")&&(0,_utils.hasOwn)(sup,"not")){if((0,_utils.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,_utils.hasOwn)(result,"not")){result=(0,_utils.omitKeys)(result,["not"])}if((0,_utils.isPlainObj)(result.properties)&&(0,_utils.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,_utils.hasOwn)(supPropDef,"not")){const propNotResult=evaluateNot(subPropDef,supPropDef);if(propNotResult===true){if(!newProps)newProps={...supProps};newProps[key]=(0,_utils.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,_utils.hasOwn)(result,"pattern")&&(0,_utils.hasOwn)(sub,"pattern")&&result.pattern!==sub.pattern){const patResult=(0,_patternsubset.isPatternSubset)(sub.pattern,result.pattern);if(patResult===true){result=(0,_utils.omitKeys)(ensureCopy(),["pattern"]);copied=true}}if((0,_utils.isPlainObj)(result.properties)&&(0,_utils.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,_utils.hasOwn)(supPropDef,"pattern")&&(0,_utils.hasOwn)(subPropDef,"pattern")&&supPropDef.pattern!==subPropDef.pattern){const propPatResult=(0,_patternsubset.isPatternSubset)(subPropDef.pattern,supPropDef.pattern);if(propPatResult===true){if(!newProps)newProps={...supProps};newProps[key]=(0,_utils.omitKeys)(supPropDef,["pattern"]);propsModified=true}}}if(propsModified&&newProps){ensureCopy().properties=newProps}}if((0,_utils.isPlainObj)(result.items)&&typeof result.items!=="boolean"&&(0,_utils.isPlainObj)(sub.items)&&typeof sub.items!=="boolean"){const subItems=sub.items;const supItems=result.items;if((0,_utils.hasOwn)(supItems,"pattern")&&(0,_utils.hasOwn)(subItems,"pattern")&&supItems.pattern!==subItems.pattern){const itemsPatResult=(0,_patternsubset.isPatternSubset)(subItems.pattern,supItems.pattern);if(itemsPatResult===true){ensureCopy().items=(0,_utils.omitKeys)(supItems,["pattern"])}}}return result}function hasNestedBranching(schema){if(typeof schema==="boolean")return false;if((0,_utils.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,_utils.hasOwn)(prop,"oneOf")||(0,_utils.hasOwn)(prop,"anyOf"))return true;if(hasNestedBranching(prop))return true}}if((0,_utils.isPlainObj)(schema.items)&&typeof schema.items!=="boolean"){const items=schema.items;if((0,_utils.hasOwn)(items,"oneOf")||(0,_utils.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,_utils.isPlainObj)(sub.properties);const supIsObj=sup.type==="object"||(0,_utils.isPlainObj)(sup.properties);if(!subIsObj&&!supIsObj){if(sub.type==="array"&&sup.type==="array"&&(0,_utils.isPlainObj)(sub.items)&&(0,_utils.isPlainObj)(sup.items)){return isPropertySubsetOf(sub.items,sup.items,engine)}return false}if(!subIsObj||!supIsObj)return false;if((0,_utils.hasOwn)(sub,"type")&&(0,_utils.hasOwn)(sup,"type")&&sub.type!==sup.type){return false}const subProps=(0,_utils.isPlainObj)(sub.properties)?sub.properties:{};const supProps=(0,_utils.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,_utils.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,_utils.isPlainObj)(sup.additionalProperties)&&typeof sup.additionalProperties!=="boolean"){const addPropSchema=sup.additionalProperties;for(const key of Object.keys(subProps)){if((0,_utils.hasOwn)(supProps,key))continue;const subProp=subProps[key];if(subProp===undefined)continue;if(!isPropertySubsetOf(subProp,addPropSchema,engine)){return false}}}if((0,_utils.isPlainObj)(sub.items)&&(0,_utils.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,_utils.hasOwn)(sub,"format")&&(0,_utils.hasOwn)(sup,"format")&&sub.format!==sup.format){const fmtResult=(0,_formatvalidator.isFormatSubset)(sub.format,sup.format);if(fmtResult!==true)return false}if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&(0,_utils.hasOwn)(sub,"pattern")&&(0,_utils.hasOwn)(sup,"pattern")&&sub.pattern!==sup.pattern){const patResult=(0,_patternsubset.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,_utils.deepEqual)(merged,sub))return true;const normalizedMerged=(0,_normalizer.normalize)(merged);if((0,_utils.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,_utils.hasOwn)(sub,"pattern")&&(0,_utils.hasOwn)(branch,"pattern")&&sub.pattern!==branch.pattern){const patResult=(0,_patternsubset.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,_utils.deepEqual)(merged,sub))return true;const normalizedBranch=(0,_normalizer.normalize)(merged);if((0,_utils.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,_semanticerrors.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,_utils.deepEqual)(merged,sub)){return{isSubset:true,merged,errors:[]}}const normalizedMerged=(0,_normalizer.normalize)(merged);if((0,_utils.deepEqual)(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged,errors:[]}}}}const semanticErrors=(0,_semanticerrors.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,_utils.deepEqual)(merged,sub)){return{isSubset:true,merged,errors:[]}}const normalizedMerged=(0,_normalizer.normalize)(merged);if((0,_utils.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,_semanticerrors.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,_semanticerrors.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 _formatvalidator=require("./format-validator.js");const _normalizer=require("./normalizer.js");const _patternsubset=require("./pattern-subset.js");const _semanticerrors=require("./semantic-errors.js");const _utils=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,_utils.hasOwn)(def,"anyOf")&&Array.isArray(def.anyOf)){return{branches:def.anyOf,type:"anyOf"}}if((0,_utils.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,_utils.hasOwn)(sup,"not")&&(0,_utils.isPlainObj)(sup.not)){const notSchema=sup.not;if((0,_utils.isPlainObj)(notSchema.properties)&&Array.isArray(notSchema.required)){const notProps=notSchema.properties;const notRequired=notSchema.required;if((0,_utils.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,_utils.hasOwn)(subProps,key)){return true}if(!(0,_utils.hasOwn)(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return false;const subProp=subPropDef;if((0,_utils.hasOwn)(notProp,"const")&&(0,_utils.hasOwn)(subProp,"const")){if(!(0,_utils.deepEqual)(notProp.const,subProp.const)){return true}}if((0,_utils.hasOwn)(notProp,"enum")&&Array.isArray(notProp.enum)){if((0,_utils.hasOwn)(subProp,"const")){const inNotEnum=notProp.enum.some(v=>(0,_utils.deepEqual)(v,subProp.const));if(!inNotEnum)return true}if((0,_utils.hasOwn)(subProp,"enum")&&Array.isArray(subProp.enum)){const noneInNotEnum=subProp.enum.every(v=>!notProp.enum?.some(nv=>(0,_utils.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,_utils.hasOwn)(subProps,key))return false;const subPropDef=subProps[key];if(typeof subPropDef==="boolean")return true;const subProp=subPropDef;if((0,_utils.hasOwn)(notProp,"const")&&(0,_utils.hasOwn)(subProp,"const")){return(0,_utils.deepEqual)(notProp.const,subProp.const)}if((0,_utils.hasOwn)(notProp,"enum")&&Array.isArray(notProp.enum)){if((0,_utils.hasOwn)(subProp,"const")){return notProp.enum.some(v=>(0,_utils.deepEqual)(v,subProp.const))}if((0,_utils.hasOwn)(subProp,"enum")&&Array.isArray(subProp.enum)){return subProp.enum.every(v=>notProp.enum?.some(nv=>(0,_utils.deepEqual)(v,nv)))}}return false});if(allPropsMatch)return false}}if((0,_utils.hasOwn)(notSchema,"const")&&(0,_utils.hasOwn)(sub,"const")){const notConst=notSchema.const;const subConst=sub.const;if((0,_utils.deepEqual)(subConst,notConst))return false;return true}if((0,_utils.hasOwn)(notSchema,"enum")&&Array.isArray(notSchema.enum)&&(0,_utils.hasOwn)(sub,"enum")&&Array.isArray(sub.enum)){const allExcluded=sub.enum.every(val=>!notSchema.enum?.some(notVal=>(0,_utils.deepEqual)(val,notVal)));if(allExcluded)return true}if((0,_utils.hasOwn)(notSchema,"type")&&(0,_utils.hasOwn)(sub,"type")){const notType=notSchema.type;const subType=sub.type;if(typeof notType==="string"&&typeof subType==="string"){if(!(0,_utils.hasOwn)(notSchema,"const")&&!(0,_utils.hasOwn)(notSchema,"enum")&&!(0,_utils.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,_utils.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,_utils.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,_utils.hasOwn)(notSchema,"format")&&(0,_utils.hasOwn)(sub,"format")){const subFormat=sub.format;const notFormat=notSchema.format;if(subFormat===notFormat)return false;return true}}if((0,_utils.hasOwn)(sub,"not")&&(0,_utils.hasOwn)(sup,"not")){if((0,_utils.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,_utils.hasOwn)(result,"not")){result=(0,_utils.omitKeys)(result,["not"])}if((0,_utils.isPlainObj)(result.properties)&&(0,_utils.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,_utils.hasOwn)(supPropDef,"not")){const propNotResult=evaluateNot(subPropDef,supPropDef);if(propNotResult===true){if(!newProps)newProps={...supProps};newProps[key]=(0,_utils.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,_utils.hasOwn)(result,"pattern")&&(0,_utils.hasOwn)(sub,"pattern")&&result.pattern!==sub.pattern){const patResult=(0,_patternsubset.isPatternSubset)(sub.pattern,result.pattern);if(patResult===true){result=(0,_utils.omitKeys)(ensureCopy(),["pattern"]);copied=true}}if((0,_utils.isPlainObj)(result.properties)&&(0,_utils.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,_utils.hasOwn)(supPropDef,"pattern")&&(0,_utils.hasOwn)(subPropDef,"pattern")&&supPropDef.pattern!==subPropDef.pattern){const propPatResult=(0,_patternsubset.isPatternSubset)(subPropDef.pattern,supPropDef.pattern);if(propPatResult===true){if(!newProps)newProps={...supProps};newProps[key]=(0,_utils.omitKeys)(supPropDef,["pattern"]);propsModified=true}}}if(propsModified&&newProps){ensureCopy().properties=newProps}}if((0,_utils.isPlainObj)(result.items)&&typeof result.items!=="boolean"&&(0,_utils.isPlainObj)(sub.items)&&typeof sub.items!=="boolean"){const subItems=sub.items;const supItems=result.items;if((0,_utils.hasOwn)(supItems,"pattern")&&(0,_utils.hasOwn)(subItems,"pattern")&&supItems.pattern!==subItems.pattern){const itemsPatResult=(0,_patternsubset.isPatternSubset)(subItems.pattern,supItems.pattern);if(itemsPatResult===true){ensureCopy().items=(0,_utils.omitKeys)(supItems,["pattern"])}}}return result}function stripVacuousFalseProperties(merged,sub){if(typeof merged==="boolean"||typeof sub==="boolean")return merged;if(!(0,_utils.isPlainObj)(merged.properties))return merged;const mergedProps=merged.properties;const subProps=(0,_utils.isPlainObj)(sub.properties)?sub.properties:{};let strippedProps=null;for(const key of Object.keys(mergedProps)){if(mergedProps[key]===false&&!(0,_utils.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,_utils.isPlainObj)(sub.properties)){delete result.properties}return result}function hasNestedBranching(schema){if(typeof schema==="boolean")return false;if((0,_utils.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,_utils.hasOwn)(prop,"oneOf")||(0,_utils.hasOwn)(prop,"anyOf"))return true;if(hasNestedBranching(prop))return true}}if((0,_utils.isPlainObj)(schema.items)&&typeof schema.items!=="boolean"){const items=schema.items;if((0,_utils.hasOwn)(items,"oneOf")||(0,_utils.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,_utils.isPlainObj)(sub.properties);const supIsObj=sup.type==="object"||(0,_utils.isPlainObj)(sup.properties);if(!subIsObj&&!supIsObj){if(sub.type==="array"&&sup.type==="array"&&(0,_utils.isPlainObj)(sub.items)&&(0,_utils.isPlainObj)(sup.items)){return isPropertySubsetOf(sub.items,sup.items,engine)}return false}if(!subIsObj||!supIsObj)return false;if((0,_utils.hasOwn)(sub,"type")&&(0,_utils.hasOwn)(sup,"type")&&sub.type!==sup.type){return false}const subProps=(0,_utils.isPlainObj)(sub.properties)?sub.properties:{};const supProps=(0,_utils.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,_utils.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,_utils.isPlainObj)(sup.additionalProperties)&&typeof sup.additionalProperties!=="boolean"){const addPropSchema=sup.additionalProperties;for(const key of Object.keys(subProps)){if((0,_utils.hasOwn)(supProps,key))continue;const subProp=subProps[key];if(subProp===undefined)continue;if(!isPropertySubsetOf(subProp,addPropSchema,engine)){return false}}}if((0,_utils.isPlainObj)(sub.items)&&(0,_utils.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,_utils.hasOwn)(sub,"format")&&(0,_utils.hasOwn)(sup,"format")&&sub.format!==sup.format){const fmtResult=(0,_formatvalidator.isFormatSubset)(sub.format,sup.format);if(fmtResult!==true)return false}if(typeof sub!=="boolean"&&typeof sup!=="boolean"&&(0,_utils.hasOwn)(sub,"pattern")&&(0,_utils.hasOwn)(sup,"pattern")&&sub.pattern!==sup.pattern){const patResult=(0,_patternsubset.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,_utils.deepEqual)(merged,sub))return true;const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&(0,_utils.deepEqual)(strippedMerged,sub)){return true}const normalizedMerged=(0,_normalizer.normalize)(strippedMerged);if((0,_utils.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,_utils.hasOwn)(sub,"pattern")&&(0,_utils.hasOwn)(branch,"pattern")&&sub.pattern!==branch.pattern){const patResult=(0,_patternsubset.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,_utils.deepEqual)(merged,sub))return true;const strippedBranch=stripVacuousFalseProperties(merged,sub);if(strippedBranch!==merged&&(0,_utils.deepEqual)(strippedBranch,sub)){return true}const normalizedBranch=(0,_normalizer.normalize)(strippedBranch);if((0,_utils.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,_semanticerrors.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,_utils.deepEqual)(merged,sub)){return{isSubset:true,merged,errors:[]}}const normalizedMerged=(0,_normalizer.normalize)(merged);if((0,_utils.deepEqual)(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)){return{isSubset:true,merged,errors:[]}}}}const semanticErrors=(0,_semanticerrors.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,_utils.deepEqual)(merged,sub)){return{isSubset:true,merged,errors:[]}}const strippedMerged=stripVacuousFalseProperties(merged,sub);if(strippedMerged!==merged&&(0,_utils.deepEqual)(strippedMerged,sub)){return{isSubset:true,merged:strippedMerged,errors:[]}}const normalizedMerged=(0,_normalizer.normalize)(strippedMerged);if((0,_utils.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,_semanticerrors.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,_semanticerrors.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\";\nimport type { MergeEngine } from \"./merge-engine\";\nimport { normalize } from \"./normalizer\";\nimport { isPatternSubset } from \"./pattern-subset\";\nimport { computeSemanticErrors } from \"./semantic-errors\";\nimport type { SchemaError, SubsetResult } from \"./types\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys } from \"./utils\";\n\n// ─── Subset Checker ──────────────────────────────────────────────────────────\n//\n// Logique de vérification sub ⊆ sup via l'approche :\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// Gère les cas :\n// - Schemas atomiques (pas de anyOf/oneOf)\n// - anyOf/oneOf dans sub → chaque branche doit être acceptée par sup\n// - anyOf/oneOf dans sup → au moins une branche doit accepter sub\n// - Point 6 : Distinction anyOf / oneOf dans les messages de diff\n// - Point 7 : Raisonnement étendu sur `not` (evaluateNot)\n// - not.type, not.const, not.enum (existants)\n// - not avec properties+required (1.1)\n// - not avec anyOf/oneOf (1.2)\n// - not dans sub (1.3)\n// - not.format (format-vs-format)\n//\n// Utilise des helpers natifs partagés depuis `./utils` pour des performances\n// optimales (deepEqual, hasOwn, isPlainObj, omitKeys).\n\n// ─── Branch type ─────────────────────────────────────────────────────────────\n\n/**\n * Type de branchement détecté dans un schema.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` pour produire des messages\n * de diff plus précis. `\"none\"` indique un schema atomique (pas de branches).\n *\n * Note : la sémantique d'exclusivité de `oneOf` n'est pas vérifiée\n * (ce serait un problème NP-hard en général). Le checker traite `oneOf`\n * comme `anyOf` pour le subset checking, ce qui est correct pour le cas\n * `sub ⊆ sup` mais peut produire des faux-positifs si les branches\n * du sub se chevauchent.\n */\nexport type BranchType = \"anyOf\" | \"oneOf\" | \"none\";\n\nexport interface BranchResult {\n\t/** Les branches extraites du schema */\n\tbranches: JSONSchema7Definition[];\n\t/** Le type de branchement détecté */\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 * Extrait les branches d'un schema et le type de branchement.\n *\n * Retourne les éléments de `anyOf`/`oneOf` s'ils existent, sinon retourne\n * le schema lui-même dans un tableau avec type `\"none\"`.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` dans les paths de diff.\n *\n * Optimisation : réutilise des objets pré-alloués pour les cas boolean\n * (true/false) et un WeakMap cache pour les schemas atomiques afin\n * d'éviter les allocations sur ces chemins fréquents.\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 — étendu) ─────────────────────────────────────\n\n/**\n * Raisonnement étendu sur `not` pour les cas courants.\n *\n * Point 7 — Vérifie la compatibilité quand `sup` et/ou `sub` contiennent `not` :\n *\n * **Cas existants (not dans sup) :**\n * - `not.type` : type exclu vs type de sub\n * - `not.const` : const exclu vs const de sub\n * - `not.enum` : valeurs exclues vs enum de sub\n *\n * **Cas ajoutés :**\n * - 1.1 — `not` avec `properties` + `required` : vérifier que les propriétés\n * de sub sont incompatibles avec celles du `not` (const/enum différents)\n * - 1.2 — `not` avec `anyOf`/`oneOf` : `not(anyOf([A,B]))` ≡ `allOf([not(A), not(B)])`,\n * donc sub doit être incompatible avec CHAQUE branche\n * - 1.3 — `not` dans `sub` (pas seulement dans `sup`) : un sub avec `not`\n * accepte un ensemble trop large pour être un sous-ensemble d'un sup concret\n * - `not.format` : format-vs-format via `isFormatSubset`\n *\n * Contrat ternaire conservateur :\n * - `true` → compatible (certain)\n * - `false` → incompatible (certain)\n * - `null` → indéterminé (laisser le merge engine décider)\n *\n * En cas de doute → `null`. Ne JAMAIS retourner `true` sans certitude.\n *\n * Utilise `_.has`, `_.get`, `_.isEqual`, `_.includes`, `_.every`, `_.some`,\n * `_.keys`, `_.isPlainObject`, `_.isArray` pour des vérifications concises.\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` dans sub (pas dans sup) ──\n\t// Un `not` dans sub est une restriction supplémentaire : il exclut des\n\t// valeurs de l'ensemble accepté par sub, ce qui le rend potentiellement\n\t// plus petit — donc plus susceptible d'être ⊆ sup, pas moins.\n\t// On laisse le merge engine décider : allOf(sub, sup) préservera le `not`\n\t// de sub, et la comparaison merged ≡ sub donnera le bon résultat.\n\t// Exception : si les deux ont `not`, on traite l'identité plus bas.\n\n\t// Vérifier `not` dans sup\n\tif (hasOwn(sup, \"not\") && isPlainObj(sup.not)) {\n\t\tconst notSchema = sup.not as JSONSchema7;\n\n\t\t// ── 1.1 — Cas not avec properties + required ──\n\t\t// IMPORTANT : ce check est placé AVANT le check not.type car quand\n\t\t// le not a à la fois `type` et `properties`, le check not.type seul\n\t\t// produirait un faux négatif (ex: sub type=object et not type=object\n\t\t// retournerait false, mais les properties pourraient être incompatibles\n\t\t// ce qui rendrait sub compatible avec le not).\n\t\t// Si not contient des properties avec const/enum et required,\n\t\t// vérifier que les propriétés de sub sont incompatibles avec celles du not.\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 doit avoir des properties pour qu'on puisse comparer\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// Pour que sub soit compatible avec not(schema),\n\t\t\t\t// il suffit qu'au moins UNE propriété du not soit incompatible avec sub.\n\t\t\t\t// Cela signifie que sub ne peut jamais valider le 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// Si la propriété est required dans not mais PAS dans sub.required\n\t\t\t\t\t// et qu'elle n'existe pas dans sub.properties → sub peut ne pas\n\t\t\t\t\t// avoir cette propriété → le not schema ne matcherait pas → 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; // Propriété absente de sub → not ne matche pas\n\t\t\t\t\t}\n\n\t\t\t\t\t// Comparer les const/enum de la propriété\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 a un const, sub.prop a un const différent → incompatible pour cette 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; // Consts différents → sub ne matche pas le not\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// not.prop a un enum, sub.prop a un const ou enum dont aucune valeur\n\t\t\t\t\t// n'est dans not.enum → incompatible pour cette 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 du 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; // Aucune valeur de sub.enum dans 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// Vérification inverse : si TOUTES les propriétés du not matchent sub\n\t\t\t\t// exactement (même const, sub a les required du not), alors sub VIOLE le 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// La propriété doit être dans sub.required si elle est dans 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// Vérifier 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// Vérifier 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// Toutes les valeurs de sub.enum sont dans 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; // Indéterminé pour cette propriété\n\t\t\t\t});\n\n\t\t\t\tif (allPropsMatch) return false; // sub matche exactement le not → incompatible\n\t\t\t}\n\t\t}\n\n\t\t// ── Cas not.const ──\n\t\t// IMPORTANT : ce check est placé AVANT not.type car quand le not a\n\t\t// à la fois `type` et `const`, le check not.type seul produirait un\n\t\t// faux négatif (ex: sub type=string const=\"active\" et not type=string\n\t\t// const=\"deleted\" → le type check retournerait false car même type,\n\t\t// alors que les consts sont différents → 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// ── Cas not.enum ──\n\t\t// Aussi placé AVANT not.type pour la même raison.\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// Toutes les valeurs de sub.enum doivent être absentes de 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// Certaines valeurs de sub sont dans not.enum → pas automatiquement faux,\n\t\t\t// le merge engine peut encore gérer\n\t\t}\n\n\t\t// ── Cas not.type ──\n\t\t// Placé APRÈS not.const, not.enum et properties+required pour ne pas\n\t\t// court-circuiter les cas où le not a des contraintes plus spécifiques.\n\t\t// Le check type seul est un fallback pour les not schemas simples\n\t\t// (ex: { 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// Si les deux sont des strings simples\n\t\t\tif (typeof notType === \"string\" && typeof subType === \"string\") {\n\t\t\t\t// Ne retourner que si le not n'a PAS de contraintes plus spécifiques\n\t\t\t\t// (const, enum, properties) qui auraient dû être traitées plus haut\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 est exactement le type exclu\n\t\t\t\t\treturn true; // Compatible : sub est un type différent du type exclu\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Si notType est un tableau, sub.type doit ne pas être dedans\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 — Cas not avec anyOf / oneOf ──\n\t\t// not(anyOf([A, B])) ≡ allOf([not(A), not(B)])\n\t\t// Pour que sub ⊆ not(anyOf(...)), sub doit être incompatible avec CHAQUE branche.\n\t\tif (hasOwn(notSchema, \"anyOf\") && Array.isArray(notSchema.anyOf)) {\n\t\t\tconst branches = notSchema.anyOf as JSONSchema7Definition[];\n\t\t\t// Pour chaque branche du not.anyOf, vérifier que sub est incompatible\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch; // not(true) = rien, not(false) = tout\n\t\t\t\t// Créer un sup virtuel { not: branch } et vérifier récursivement\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\t// result = true → sub est compatible avec not(branch) → sub ⊄ branch → OK\n\t\t\t\t// result = false → sub est incompatible avec not(branch) → sub ⊆ branch → pas OK\n\t\t\t\t// result = null → indéterminé\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\t// Vérifier si au moins une branche accepte sub → incompatible avec 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 est incompatible avec not(branch) → sub ⊆ branch\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// Même logique pour oneOf (dans le contexte du not, traité comme 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// ── Cas not.format (format-vs-format uniquement) ──\n\t\t// Si not a un format et sub aussi, vérifier la compatibilité\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 a exactement le format exclu\n\t\t\t// Formats différents → compatible (approximation conservatrice)\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Vérifier `not` dans sub ET dans sup (identité : { 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; // Pas d'avis → laisser le merge engine décider\n}\n\n// ─── Not stripping helper ────────────────────────────────────────────────────\n\n/**\n * Retire le mot-clé `not` d'un schema pour permettre un merge propre\n * quand `evaluateNot` a déjà confirmé la compatibilité.\n *\n * Gère aussi le `not` imbriqué dans les `properties` : si une propriété\n * de `sup` a un `not` qui est compatible avec la propriété correspondante\n * de `sub`, on le retire également.\n *\n * Retourne le schema nettoyé, ou `null` si le schema est vide après retrait.\n *\n * Utilise `_.omit`, `_.has`, `_.keys`, `_.isEmpty`, `_.isPlainObject`.\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// ── Retirer le `not` de niveau supérieur (seulement si confirmé) ──\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// ── Retirer les `not` dans les propriétés communes ──\n\t// Si sup.properties[key] a un `not` et que evaluateNot(sub.prop, sup.prop)\n\t// confirme la compatibilité, on retire le `not` de cette propriété aussi.\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// Vérifier la compatibilité du not au niveau de la propriété\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 * Retire le `pattern` de `sup` quand `isPatternSubset` a confirmé que\n * sub.pattern ⊆ sup.pattern par échantillonnage.\n *\n * Fonctionne comme `stripNotFromSup` : on retire la contrainte de sup\n * qui est déjà satisfaite par sub, pour éviter que le merge engine\n * produise un pattern combiné (lookahead conjunction) structurellement\n * différent du pattern de sub, ce qui causerait un faux négatif.\n *\n * Récurse dans les `properties` pour traiter les patterns imbriqués.\n *\n * @param sub Le schema sub (utilisé pour extraire les patterns à comparer)\n * @param sup Le schema sup dont on retire les patterns confirmés\n * @returns Le schema sup nettoyé\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 dans les propriétés communes ──\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 dans 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// ─── 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 * Vérifie si `sub ⊆ sup` pour deux schemas sans anyOf/oneOf (ou avec\n * anyOf/oneOf uniquement côté sup).\n *\n * Point 7 — Intègre un pré-check `not` étendu (`evaluateNot`) avant le merge.\n *\n * Quand `evaluateNot` confirme la compatibilité (`true`), on retire le `not`\n * de `sup` avant le merge pour éviter que le merge engine ajoute une contrainte\n * `not` que `sub` n'a pas (ce qui ferait échouer `isEqual(merged, sub)`).\n *\n * Pattern pre-check — Quand les deux schemas ont des patterns différents,\n * vérifie l'inclusion par échantillonnage via `isPatternSubset`. Si confirmé,\n * retire le pattern de sup avant le merge (même stratégie que pour `not`).\n *\n * Principe : merge(sub, sup) ≡ sub → sub est un sous-ensemble de 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 *\n * Utilise `_.some`, `_.has`, `_.omit`, `_.keys`, `_.isEmpty` pour la logique.\n */\nexport function isAtomicSubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: supBranches } = getBranchesTyped(sup);\n\n\t// Schema simple → merge direct\n\tif (supBranches.length === 1 && supBranches[0] === sup) {\n\t\t// Point 7 : pré-check `not` étendu\n\t\tconst notResult = evaluateNot(sub, sup);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Format pre-check ──\n\t\t// Si les deux schemas ont un `format` différent, vérifier que\n\t\t// sub.format ⊆ sup.format. Sinon, sub ne peut pas être ⊆ sup.\n\t\t// Cela complète hasFormatConflict (qui gère le merge) en gérant\n\t\t// la direction du subset check que le merge ne peut pas résoudre.\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// Si les deux schemas ont des patterns différents, vérifier l'inclusion\n\t\t// par échantillonnage. Si sub.pattern ⊄ sup.pattern (contre-exemple trouvé),\n\t\t// on retourne false immédiatement. Sinon, on pourra retirer le pattern\n\t\t// de sup pour éviter le faux négatif structurel du 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// Retirer `not` de sup (top-level et/ou dans les properties)\n\t\t// quand evaluateNot confirme la compatibilité au niveau correspondant.\n\t\t// Cela évite que le merge engine ajoute une contrainte `not` que sub n'a pas\n\t\t// (ce qui ferait merged ≠ sub et produirait un faux négatif).\n\t\tlet effectiveSup = sup;\n\t\tif (typeof sup !== \"boolean\") {\n\t\t\t// Si top-level not est confirmé compatible → retirer le not top-level\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, true);\n\t\t\t\t// Si sup n'avait QUE `not` → sub est compatible (le not est résolu)\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// Même si le top-level not n'est pas confirmé (null), on tente\n\t\t\t\t// de retirer les `not` dans les properties individuelles\n\t\t\t\t// sans toucher au `not` top-level\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, false);\n\t\t\t}\n\n\t\t\t// Retirer les patterns de sup confirmés par échantillonnage.\n\t\t\t// Même stratégie que pour `not` : on retire la contrainte déjà\n\t\t\t// satisfaite par sub pour éviter que le merge produise un pattern\n\t\t\t// combiné (lookahead conjunction) structurellement ≠ 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\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(merged);\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 dans sup → au moins une branche doit accepter sub\n\treturn supBranches.some((branch) => {\n\t\t// Point 7 : pré-check `not` étendu par branche\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// Même logique de strip pour les 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 confirmés par échantillonnage\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\t\tconst normalizedBranch = normalize(merged);\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 * Vérifie `sub ⊆ sup` pour un sub qui a des branches (anyOf/oneOf).\n * Chaque branche de sub doit être acceptée par sup.\n *\n * Point 6 — Utilise `getBranchesTyped` pour distinguer `anyOf[i]` de\n * `oneOf[i]` dans les paths de diff.\n *\n * Utilise `_.every` / `_.flatMap` / `_.map` pour une itération idiomatique.\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 * Vérifie `sub ⊆ sup` pour un sup qui a des branches (anyOf/oneOf).\n * Au moins une branche de sup doit accepter sub.\n *\n * Point 6 — Utilise le type de branche de sup pour des messages plus précis.\n *\n * Utilise `_.some` pour trouver la première branche compatible.\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 confirmés par échantillonnage avant le 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// Générer des erreurs sémantiques en comparant sub avec le sup original\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 * Vérifie `sub ⊆ sup` pour deux schemas atomiques (sans anyOf/oneOf).\n * Utilise `mergeOrThrow` pour capturer les erreurs d'incompatibilité.\n *\n * Utilise `deepEqual` pour la comparaison structurelle (avec short-circuit\n * par référence et comptage de clés).\n */\nexport function checkAtomic(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): SubsetResult {\n\t// Strip patterns confirmés par échantillonnage avant le merge,\n\t// même stratégie que dans isAtomicSubsetOf pour éviter les faux négatifs\n\t// structurels causés par la conjonction de patterns en 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\tconst normalizedMerged = normalize(merged);\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","hasNestedBranching","schema","props","prop","isPropertySubsetOf","engine","subBranches","length","isObjectSubsetByProperties","subIsObj","supIsObj","supRequired","additionalProperties","supProp","addPropSchema","tryNestedBranchingFallback","supBranches","notResult","fmtResult","isFormatSubset","effectiveSup","merged","merge","normalizedMerged","normalize","isEqual","effectiveBranch","normalizedBranch","branchType","allErrors","allSubset","i","branchErrors","computeSemanticErrors","push","isSubset","errors","_branchType","semanticErrors","mergeOrThrow","_e"],"mappings":"mPAwkCgBA,qBAAAA,iBAvFAC,0BAAAA,sBAsCAC,0BAAAA,sBAx8BAC,0BAAAA,sBAivBAC,0BAAAA,mDA/zBe,gDAEL,6CACM,kDACM,0CAEkB,WAiDxD,MAAMC,YAA4B,CAAEC,SAAU,CAAC,KAAK,CAAEC,KAAM,MAAO,EACnE,MAAMC,aAA6B,CAAEF,SAAU,CAAC,MAAM,CAAEC,KAAM,MAAO,EAQrE,MAAME,kBAAoB,IAAIC,QAcvB,SAASP,iBAAiBQ,GAA0B,EAC1D,GAAI,OAAOA,MAAQ,UAAW,CAC7B,OAAOA,IAAMN,YAAcG,YAC5B,CACA,GAAII,GAAAA,aAAM,EAACD,IAAK,UAAYE,MAAMC,OAAO,CAACH,IAAII,KAAK,EAAG,CACrD,MAAO,CAAET,SAAUK,IAAII,KAAK,CAAER,KAAM,OAAQ,CAC7C,CACA,GAAIK,GAAAA,aAAM,EAACD,IAAK,UAAYE,MAAMC,OAAO,CAACH,IAAIK,KAAK,EAAG,CACrD,MAAO,CAAEV,SAAUK,IAAIK,KAAK,CAAET,KAAM,OAAQ,CAC7C,CAEA,IAAIU,OAASR,kBAAkBS,GAAG,CAACP,KACnC,GAAIM,SAAWE,UAAW,CACzBF,OAAS,CAAEX,SAAU,CAACK,IAAI,CAAEJ,KAAM,MAAO,EACzCE,kBAAkBW,GAAG,CAACT,IAAKM,OAC5B,CACA,OAAOA,MACR,CAiCA,SAASI,YACRC,GAA0B,CAC1BC,GAA0B,EAE1B,GAAI,OAAOD,MAAQ,WAAa,OAAOC,MAAQ,UAAW,OAAO,KAWjE,GAAIX,GAAAA,aAAM,EAACW,IAAK,QAAUC,GAAAA,iBAAU,EAACD,IAAIE,GAAG,EAAG,CAC9C,MAAMC,UAAYH,IAAIE,GAAG,CAUzB,GAAID,GAAAA,iBAAU,EAACE,UAAUC,UAAU,GAAKd,MAAMC,OAAO,CAACY,UAAUE,QAAQ,EAAG,CAC1E,MAAMC,SAAWH,UAAUC,UAAU,CAIrC,MAAMG,YAAcJ,UAAUE,QAAQ,CAGtC,GAAIJ,GAAAA,iBAAU,EAACF,IAAIK,UAAU,EAAG,CAC/B,MAAMI,SAAWT,IAAIK,UAAU,CAI/B,MAAMK,YAAcnB,MAAMC,OAAO,CAACQ,IAAIM,QAAQ,EAC1CN,IAAIM,QAAQ,CACb,EAAE,CACL,MAAMK,YAAcC,OAAOC,IAAI,CAACN,UAKhC,MAAMO,oBAAsBH,YAAYI,IAAI,CAAC,AAACC,MAC7C,MAAMC,WAAaV,QAAQ,CAACS,IAAI,CAChC,GAAI,OAAOC,aAAe,UAAW,OAAO,MAC5C,MAAMC,QAAUD,WAKhB,GACCT,YAAYW,QAAQ,CAACH,MACrB,CAACN,YAAYS,QAAQ,CAACH,MACtB,CAAC1B,GAAAA,aAAM,EAACmB,SAAUO,KACjB,CACD,OAAO,IACR,CAGA,GAAI,CAAC1B,GAAAA,aAAM,EAACmB,SAAUO,KAAM,OAAO,MACnC,MAAMI,WAAaX,QAAQ,CAACO,IAAI,CAChC,GAAI,OAAOI,aAAe,UAAW,OAAO,MAC5C,MAAMC,QAAUD,WAGhB,GAAI9B,GAAAA,aAAM,EAAC4B,QAAS,UAAY5B,GAAAA,aAAM,EAAC+B,QAAS,SAAU,CACzD,GAAI,CAACC,GAAAA,gBAAS,EAACJ,QAAQK,KAAK,CAAEF,QAAQE,KAAK,EAAG,CAC7C,OAAO,IACR,CACD,CAIA,GAAIjC,GAAAA,aAAM,EAAC4B,QAAS,SAAW3B,MAAMC,OAAO,CAAC0B,QAAQM,IAAI,EAAG,CAC3D,GAAIlC,GAAAA,aAAM,EAAC+B,QAAS,SAAU,CAC7B,MAAMI,UAAYP,QAAQM,IAAI,CAACT,IAAI,CAAC,AAACW,GACpCJ,GAAAA,gBAAS,EAACI,EAAGL,QAAQE,KAAK,GAE3B,GAAI,CAACE,UAAW,OAAO,IACxB,CACA,GAAInC,GAAAA,aAAM,EAAC+B,QAAS,SAAW9B,MAAMC,OAAO,CAAC6B,QAAQG,IAAI,EAAG,CAC3D,MAAMG,cAAgBN,QAAQG,IAAI,CAACI,KAAK,CACvC,AAACF,GAAM,CAACR,QAAQM,IAAI,EAAET,KAAK,AAACc,IAAOP,GAAAA,gBAAS,EAACI,EAAGG,MAEjD,GAAIF,cAAe,OAAO,IAC3B,CACD,CAEA,OAAO,KACR,GAEA,GAAIb,oBAAqB,OAAO,KAIhC,MAAMgB,cAAgBnB,YAAYiB,KAAK,CAAC,AAACZ,MACxC,MAAMC,WAAaV,QAAQ,CAACS,IAAI,CAChC,GAAI,OAAOC,aAAe,UAAW,OAAO,KAC5C,MAAMC,QAAUD,WAGhB,GAAIT,YAAYW,QAAQ,CAACH,MAAQ,CAACN,YAAYS,QAAQ,CAACH,KACtD,OAAO,MACR,GAAI,CAAC1B,GAAAA,aAAM,EAACmB,SAAUO,KAAM,OAAO,MACnC,MAAMI,WAAaX,QAAQ,CAACO,IAAI,CAChC,GAAI,OAAOI,aAAe,UAAW,OAAO,KAC5C,MAAMC,QAAUD,WAGhB,GAAI9B,GAAAA,aAAM,EAAC4B,QAAS,UAAY5B,GAAAA,aAAM,EAAC+B,QAAS,SAAU,CACzD,MAAOC,GAAAA,gBAAS,EAACJ,QAAQK,KAAK,CAAEF,QAAQE,KAAK,CAC9C,CAGA,GAAIjC,GAAAA,aAAM,EAAC4B,QAAS,SAAW3B,MAAMC,OAAO,CAAC0B,QAAQM,IAAI,EAAG,CAC3D,GAAIlC,GAAAA,aAAM,EAAC+B,QAAS,SAAU,CAC7B,OAAOH,QAAQM,IAAI,CAACT,IAAI,CAAC,AAACW,GAAMJ,GAAAA,gBAAS,EAACI,EAAGL,QAAQE,KAAK,EAC3D,CACA,GAAIjC,GAAAA,aAAM,EAAC+B,QAAS,SAAW9B,MAAMC,OAAO,CAAC6B,QAAQG,IAAI,EAAG,CAE3D,OAAOH,QAAQG,IAAI,CAACI,KAAK,CAAC,AAACF,GAC1BR,QAAQM,IAAI,EAAET,KAAK,AAACc,IAAOP,GAAAA,gBAAS,EAACI,EAAGG,KAE1C,CACD,CAEA,OAAO,KACR,GAEA,GAAIC,cAAe,OAAO,KAC3B,CACD,CAQA,GAAIxC,GAAAA,aAAM,EAACc,UAAW,UAAYd,GAAAA,aAAM,EAACU,IAAK,SAAU,CACvD,MAAM+B,SAAW3B,UAAUmB,KAAK,CAChC,MAAMS,SAAWhC,IAAIuB,KAAK,CAC1B,GAAID,GAAAA,gBAAS,EAACU,SAAUD,UAAW,OAAO,MAC1C,OAAO,IACR,CAIA,GACCzC,GAAAA,aAAM,EAACc,UAAW,SAClBb,MAAMC,OAAO,CAACY,UAAUoB,IAAI,GAC5BlC,GAAAA,aAAM,EAACU,IAAK,SACZT,MAAMC,OAAO,CAACQ,IAAIwB,IAAI,EACrB,CAED,MAAMS,YAAcjC,IAAIwB,IAAI,CAACI,KAAK,CACjC,AAACM,KAAQ,CAAC9B,UAAUoB,IAAI,EAAET,KAAK,AAACoB,QAAWb,GAAAA,gBAAS,EAACY,IAAKC,UAE3D,GAAIF,YAAa,OAAO,IAGzB,CAOA,GAAI3C,GAAAA,aAAM,EAACc,UAAW,SAAWd,GAAAA,aAAM,EAACU,IAAK,QAAS,CACrD,MAAMoC,QAAUhC,UAAUnB,IAAI,CAC9B,MAAMoD,QAAUrC,IAAIf,IAAI,CAGxB,GAAI,OAAOmD,UAAY,UAAY,OAAOC,UAAY,SAAU,CAG/D,GACC,CAAC/C,GAAAA,aAAM,EAACc,UAAW,UACnB,CAACd,GAAAA,aAAM,EAACc,UAAW,SACnB,CAACF,GAAAA,iBAAU,EAACE,UAAUC,UAAU,EAC/B,CACD,GAAIgC,UAAYD,QAAS,OAAO,MAChC,OAAO,IACR,CACD,CAGA,GAAI7C,MAAMC,OAAO,CAAC4C,UAAY,OAAOC,UAAY,SAAU,CAC1D,GAAID,QAAQjB,QAAQ,CAACkB,SAAU,OAAO,MACtC,OAAO,IACR,CACD,CAKA,GAAI/C,GAAAA,aAAM,EAACc,UAAW,UAAYb,MAAMC,OAAO,CAACY,UAAUX,KAAK,EAAG,CACjE,MAAMT,SAAWoB,UAAUX,KAAK,CAEhC,MAAM6C,gBAAkBtD,SAAS4C,KAAK,CAAC,AAACW,SACvC,GAAI,OAAOA,SAAW,UAAW,MAAO,CAACA,OAEzC,MAAMC,OAASzC,YAAYC,IAAK,CAAEG,IAAKoC,MAAO,GAI9C,OAAOC,SAAW,IACnB,GACA,GAAIF,gBAAiB,OAAO,KAG5B,MAAMG,iBAAmBzD,SAAS+B,IAAI,CAAC,AAACwB,SACvC,GAAI,OAAOA,SAAW,UAAW,OAAOA,OACxC,MAAMC,OAASzC,YAAYC,IAAK,CAAEG,IAAKoC,MAAO,GAC9C,OAAOC,SAAW,KACnB,GACA,GAAIC,iBAAkB,OAAO,KAC9B,CAGA,GAAInD,GAAAA,aAAM,EAACc,UAAW,UAAYb,MAAMC,OAAO,CAACY,UAAUV,KAAK,EAAG,CACjE,MAAMV,SAAWoB,UAAUV,KAAK,CAChC,MAAM4C,gBAAkBtD,SAAS4C,KAAK,CAAC,AAACW,SACvC,GAAI,OAAOA,SAAW,UAAW,MAAO,CAACA,OACzC,MAAMC,OAASzC,YAAYC,IAAK,CAAEG,IAAKoC,MAAO,GAC9C,OAAOC,SAAW,IACnB,GACA,GAAIF,gBAAiB,OAAO,KAE5B,MAAMG,iBAAmBzD,SAAS+B,IAAI,CAAC,AAACwB,SACvC,GAAI,OAAOA,SAAW,UAAW,OAAOA,OACxC,MAAMC,OAASzC,YAAYC,IAAK,CAAEG,IAAKoC,MAAO,GAC9C,OAAOC,SAAW,KACnB,GACA,GAAIC,iBAAkB,OAAO,KAC9B,CAIA,GAAInD,GAAAA,aAAM,EAACc,UAAW,WAAad,GAAAA,aAAM,EAACU,IAAK,UAAW,CACzD,MAAM0C,UAAY1C,IAAI2C,MAAM,CAC5B,MAAMC,UAAYxC,UAAUuC,MAAM,CAClC,GAAID,YAAcE,UAAW,OAAO,MAEpC,OAAO,IACR,CACD,CAGA,GAAItD,GAAAA,aAAM,EAACU,IAAK,QAAUV,GAAAA,aAAM,EAACW,IAAK,OAAQ,CAC7C,GAAIqB,GAAAA,gBAAS,EAACtB,IAAIG,GAAG,CAAEF,IAAIE,GAAG,EAAG,OAAO,IACzC,CAEA,OAAO,IACR,CAgBA,SAAS0C,gBACR7C,GAA0B,CAC1BC,GAA0B,CAC1B6C,cAAyB,IAAI,EAE7B,GAAI,OAAO7C,MAAQ,WAAa,OAAOD,MAAQ,UAAW,OAAOC,IAEjE,IAAIuC,OAASvC,IAGb,GAAI6C,eAAiBxD,GAAAA,aAAM,EAACkD,OAAQ,OAAQ,CAC3CA,OAASO,GAAAA,eAAQ,EAACP,OAA8C,CAC/D,MACA,CACF,CAKA,GACCtC,GAAAA,iBAAU,EAACsC,OAAOnC,UAAU,GAC5BH,GAAAA,iBAAU,EAAC,AAACF,IAAoBK,UAAU,EACzC,CACD,MAAMI,SAAW,AAACT,IAAoBK,UAAU,CAIhD,MAAM2C,SAAWR,OAAOnC,UAAU,CAClC,IAAI4C,SAEJ,IAAK,MAAMjC,OAAOJ,OAAOC,IAAI,CAACmC,UAAW,CACxC,MAAME,WAAaF,QAAQ,CAAChC,IAAI,CAChC,MAAMI,WAAaX,QAAQ,CAACO,IAAI,CAChC,GACCkC,aAAerD,WACfuB,aAAevB,WACf,OAAOqD,aAAe,WACtB,OAAO9B,aAAe,WACtB9B,GAAAA,aAAM,EAAC4D,WAAY,OAClB,CAED,MAAMC,cAAgBpD,YAAYqB,WAAY8B,YAC9C,GAAIC,gBAAkB,KAAM,CAE3B,GAAI,CAACF,SAAUA,SAAW,CAAE,GAAGD,QAAQ,AAAC,CACxCC,CAAAA,QAAQ,CAACjC,IAAI,CAAG+B,GAAAA,eAAQ,EACvBG,WACA,CAAC,MAAM,CAET,CACD,CACD,CAEA,GAAID,SAAU,CACbT,OAAS,CAAE,GAAGA,MAAM,CAAEnC,WAAY4C,QAAS,CAC5C,CACD,CAEA,OAAOT,MACR,CAmBA,SAASY,oBACRpD,GAA0B,CAC1BC,GAA0B,EAE1B,GAAI,OAAOD,MAAQ,WAAa,OAAOC,MAAQ,UAAW,OAAOA,IAEjE,MAAMoD,OAAsBpD,IAG5B,IAAIuC,OAAsBa,OAC1B,IAAIC,OAAS,MAEb,SAASC,aACR,GAAI,CAACD,OAAQ,CACZd,OAAS,CAAE,GAAGa,MAAM,AAAC,EACrBC,OAAS,IACV,CACA,OAAOd,MACR,CAGA,GACClD,GAAAA,aAAM,EAACkD,OAAQ,YACflD,GAAAA,aAAM,EAACU,IAAK,YACZwC,OAAOgB,OAAO,GAAK,AAACxD,IAAoBwD,OAAO,CAC9C,CACD,MAAMC,UAAYC,GAAAA,8BAAe,EAChC,AAAC1D,IAAoBwD,OAAO,CAC5BhB,OAAOgB,OAAO,EAEf,GAAIC,YAAc,KAAM,CACvBjB,OAASO,GAAAA,eAAQ,EAACQ,aAAoD,CACrE,UACA,EACDD,OAAS,IACV,CACD,CAGA,GACCpD,GAAAA,iBAAU,EAACsC,OAAOnC,UAAU,GAC5BH,GAAAA,iBAAU,EAAC,AAACF,IAAoBK,UAAU,EACzC,CACD,MAAMI,SAAW,AAACT,IAAoBK,UAAU,CAIhD,MAAM2C,SAAWR,OAAOnC,UAAU,CAClC,IAAIsD,cAAgB,MACpB,IAAIV,SAEJ,IAAK,MAAMjC,OAAOJ,OAAOC,IAAI,CAACmC,UAAW,CACxC,MAAME,WAAaF,QAAQ,CAAChC,IAAI,CAChC,MAAMI,WAAaX,QAAQ,CAACO,IAAI,CAChC,GACCkC,aAAerD,WACfuB,aAAevB,WACf,OAAOqD,aAAe,WACtB,OAAO9B,aAAe,WACtB9B,GAAAA,aAAM,EAAC4D,WAAY,YACnB5D,GAAAA,aAAM,EAAC8B,WAAY,YACnB8B,WAAWM,OAAO,GAAKpC,WAAWoC,OAAO,CACxC,CACD,MAAMI,cAAgBF,GAAAA,8BAAe,EACpC,AAACtC,WAA2BoC,OAAO,CACnC,AAACN,WAA2BM,OAAO,EAEpC,GAAII,gBAAkB,KAAM,CAC3B,GAAI,CAACX,SAAUA,SAAW,CAAE,GAAGD,QAAQ,AAAC,CACxCC,CAAAA,QAAQ,CAACjC,IAAI,CAAG+B,GAAAA,eAAQ,EACvBG,WACA,CAAC,UAAU,EAEZS,cAAgB,IACjB,CACD,CACD,CAEA,GAAIA,eAAiBV,SAAU,CAC9BM,aAAalD,UAAU,CAAG4C,QAC3B,CACD,CAGA,GACC/C,GAAAA,iBAAU,EAACsC,OAAOqB,KAAK,GACvB,OAAOrB,OAAOqB,KAAK,GAAK,WACxB3D,GAAAA,iBAAU,EAAC,AAACF,IAAoB6D,KAAK,GACrC,OAAO,AAAC7D,IAAoB6D,KAAK,GAAK,UACrC,CACD,MAAMC,SAAW,AAAC9D,IAAoB6D,KAAK,CAC3C,MAAME,SAAWvB,OAAOqB,KAAK,CAC7B,GACCvE,GAAAA,aAAM,EAACyE,SAAU,YACjBzE,GAAAA,aAAM,EAACwE,SAAU,YACjBC,SAASP,OAAO,GAAKM,SAASN,OAAO,CACpC,CACD,MAAMQ,eAAiBN,GAAAA,8BAAe,EACrCI,SAASN,OAAO,CAChBO,SAASP,OAAO,EAEjB,GAAIQ,iBAAmB,KAAM,CAC5BT,aAAaM,KAAK,CAAGd,GAAAA,eAAQ,EAC5BgB,SACA,CAAC,UAAU,CAEb,CACD,CACD,CAEA,OAAOvB,MACR,CA+BA,SAASyB,mBAAmBC,MAA6B,EACxD,GAAI,OAAOA,SAAW,UAAW,OAAO,MAExC,GAAIhE,GAAAA,iBAAU,EAACgE,OAAO7D,UAAU,EAAG,CAClC,MAAM8D,MAAQD,OAAO7D,UAAU,CAC/B,IAAK,MAAMW,OAAOJ,OAAOC,IAAI,CAACsD,OAAQ,CACrC,MAAMC,KAAOD,KAAK,CAACnD,IAAI,CACvB,GAAIoD,OAASvE,WAAa,OAAOuE,OAAS,UAAW,SACrD,GAAI9E,GAAAA,aAAM,EAAC8E,KAAM,UAAY9E,GAAAA,aAAM,EAAC8E,KAAM,SAAU,OAAO,KAC3D,GAAIH,mBAAmBG,MAAO,OAAO,IACtC,CACD,CAEA,GAAIlE,GAAAA,iBAAU,EAACgE,OAAOL,KAAK,GAAK,OAAOK,OAAOL,KAAK,GAAK,UAAW,CAClE,MAAMA,MAAQK,OAAOL,KAAK,CAC1B,GAAIvE,GAAAA,aAAM,EAACuE,MAAO,UAAYvE,GAAAA,aAAM,EAACuE,MAAO,SAAU,OAAO,KAC7D,GAAII,mBAAmBJ,OAAQ,OAAO,IACvC,CAEA,OAAO,KACR,CAUA,SAASQ,mBACRrE,GAA0B,CAC1BC,GAA0B,CAC1BqE,MAAmB,EAEnB,KAAM,CAAEtF,SAAUuF,WAAW,CAAE,CAAG1F,iBAAiBmB,KAEnD,GAAIuE,YAAYC,MAAM,CAAG,GAAKD,WAAW,CAAC,EAAE,GAAKvE,IAAK,CACrD,IAAK,MAAMuC,UAAUgC,YAAa,CACjC,GAAIhC,SAAW1C,UAAW,SAC1B,GAAI,CAACf,iBAAiByD,OAAQtC,IAAKqE,QAAS,OAAO,KACpD,CACA,OAAO,IACR,CAEA,OAAOxF,iBAAiBkB,IAAKC,IAAKqE,OACnC,CAcA,SAASG,2BACRzE,GAAgB,CAChBC,GAAgB,CAChBqE,MAAmB,EAEnB,MAAMI,SAAW1E,IAAIf,IAAI,GAAK,UAAYiB,GAAAA,iBAAU,EAACF,IAAIK,UAAU,EACnE,MAAMsE,SAAW1E,IAAIhB,IAAI,GAAK,UAAYiB,GAAAA,iBAAU,EAACD,IAAII,UAAU,EAGnE,GAAI,CAACqE,UAAY,CAACC,SAAU,CAC3B,GACC3E,IAAIf,IAAI,GAAK,SACbgB,IAAIhB,IAAI,GAAK,SACbiB,GAAAA,iBAAU,EAACF,IAAI6D,KAAK,GACpB3D,GAAAA,iBAAU,EAACD,IAAI4D,KAAK,EACnB,CACD,OAAOQ,mBACNrE,IAAI6D,KAAK,CACT5D,IAAI4D,KAAK,CACTS,OAEF,CACA,OAAO,KACR,CAGA,GAAI,CAACI,UAAY,CAACC,SAAU,OAAO,MAGnC,GAAIrF,GAAAA,aAAM,EAACU,IAAK,SAAWV,GAAAA,aAAM,EAACW,IAAK,SAAWD,IAAIf,IAAI,GAAKgB,IAAIhB,IAAI,CAAE,CACxE,OAAO,KACR,CAEA,MAAMwB,SAAYP,GAAAA,iBAAU,EAACF,IAAIK,UAAU,EAAIL,IAAIK,UAAU,CAAG,CAAC,EAIjE,MAAM2C,SAAY9C,GAAAA,iBAAU,EAACD,IAAII,UAAU,EAAIJ,IAAII,UAAU,CAAG,CAAC,EAIjE,MAAMK,YAAcnB,MAAMC,OAAO,CAACQ,IAAIM,QAAQ,EAC1CN,IAAIM,QAAQ,CACb,EAAE,CACL,MAAMsE,YAAcrF,MAAMC,OAAO,CAACS,IAAIK,QAAQ,EAC1CL,IAAIK,QAAQ,CACb,EAAE,CAGL,IAAK,MAAMU,OAAO4D,YAAa,CAC9B,GAAI,CAAClE,YAAYS,QAAQ,CAACH,KAAM,OAAO,KACxC,CAGA,GAAIf,IAAI4E,oBAAoB,GAAK,MAAO,CACvC,IAAK,MAAM7D,OAAOJ,OAAOC,IAAI,CAACJ,UAAW,CACxC,GAAI,CAACnB,GAAAA,aAAM,EAAC0D,SAAUhC,KAAM,OAAO,KACpC,CACD,CAGA,IAAK,MAAMA,OAAOJ,OAAOC,IAAI,CAACmC,UAAW,CACxC,MAAM8B,QAAU9B,QAAQ,CAAChC,IAAI,CAC7B,MAAMK,QAAUZ,QAAQ,CAACO,IAAI,CAC7B,GAAI8D,UAAYjF,WAAawB,UAAYxB,UAAW,SAEpD,GAAI,CAACwE,mBAAmBhD,QAASyD,QAASR,QAAS,CAClD,OAAO,KACR,CACD,CAGA,GACCpE,GAAAA,iBAAU,EAACD,IAAI4E,oBAAoB,GACnC,OAAO5E,IAAI4E,oBAAoB,GAAK,UACnC,CACD,MAAME,cAAgB9E,IAAI4E,oBAAoB,CAC9C,IAAK,MAAM7D,OAAOJ,OAAOC,IAAI,CAACJ,UAAW,CACxC,GAAInB,GAAAA,aAAM,EAAC0D,SAAUhC,KAAM,SAC3B,MAAMK,QAAUZ,QAAQ,CAACO,IAAI,CAC7B,GAAIK,UAAYxB,UAAW,SAC3B,GAAI,CAACwE,mBAAmBhD,QAAS0D,cAAeT,QAAS,CACxD,OAAO,KACR,CACD,CACD,CAGA,GAAIpE,GAAAA,iBAAU,EAACF,IAAI6D,KAAK,GAAK3D,GAAAA,iBAAU,EAACD,IAAI4D,KAAK,EAAG,CACnD,GACC,CAACQ,mBACArE,IAAI6D,KAAK,CACT5D,IAAI4D,KAAK,CACTS,QAEA,CACD,OAAO,KACR,CACD,CAEA,OAAO,IACR,CAaA,SAASU,2BACRhF,GAA0B,CAC1BC,GAA0B,CAC1BqE,MAAmB,EAEnB,GAAI,OAAOtE,MAAQ,WAAa,OAAOC,MAAQ,UAAW,OAAO,KACjE,GAAI,CAACgE,mBAAmBjE,MAAQ,CAACiE,mBAAmBhE,KAAM,OAAO,KACjE,OAAOwE,2BAA2BzE,IAAKC,IAAKqE,OAC7C,CA0BO,SAASxF,iBACfkB,GAA0B,CAC1BC,GAA0B,CAC1BqE,MAAmB,EAEnB,KAAM,CAAEtF,SAAUiG,WAAW,CAAE,CAAGpG,iBAAiBoB,KAGnD,GAAIgF,YAAYT,MAAM,GAAK,GAAKS,WAAW,CAAC,EAAE,GAAKhF,IAAK,CAEvD,MAAMiF,UAAYnF,YAAYC,IAAKC,KACnC,GAAIiF,YAAc,MAAO,OAAO,MAOhC,GACC,OAAOlF,MAAQ,WACf,OAAOC,MAAQ,WACfX,GAAAA,aAAM,EAACU,IAAK,WACZV,GAAAA,aAAM,EAACW,IAAK,WACZD,IAAI2C,MAAM,GAAK1C,IAAI0C,MAAM,CACxB,CACD,MAAMwC,UAAYC,GAAAA,+BAAc,EAC/BpF,IAAI2C,MAAM,CACV1C,IAAI0C,MAAM,EAEX,GAAIwC,YAAc,KAAM,OAAO,KAChC,CAOA,GACC,OAAOnF,MAAQ,WACf,OAAOC,MAAQ,WACfX,GAAAA,aAAM,EAACU,IAAK,YACZV,GAAAA,aAAM,EAACW,IAAK,YACZD,IAAIwD,OAAO,GAAKvD,IAAIuD,OAAO,CAC1B,CACD,MAAMC,UAAYC,GAAAA,8BAAe,EAChC1D,IAAIwD,OAAO,CACXvD,IAAIuD,OAAO,EAEZ,GAAIC,YAAc,MAAO,OAAO,KACjC,CAMA,IAAI4B,aAAepF,IACnB,GAAI,OAAOA,MAAQ,UAAW,CAE7B,GAAIiF,YAAc,KAAM,CACvBG,aAAexC,gBAAgB7C,IAAKC,IAAK,MAEzC,GACC,OAAOoF,eAAiB,WACxBzE,OAAOC,IAAI,CAACwE,cAAcb,MAAM,GAAK,EACpC,CACD,OAAO,IACR,CACD,KAAO,CAINa,aAAexC,gBAAgB7C,IAAKC,IAAK,MAC1C,CAMAoF,aAAejC,oBAAoBpD,IAAKqF,aACzC,CAEA,MAAMC,OAAShB,OAAOiB,KAAK,CAACvF,IAAKqF,cACjC,GAAIC,SAAW,KAAM,CAEpB,OAAON,2BAA2BhF,IAAKqF,aAAcf,SAAW,KACjE,CAIA,GAAIhD,GAAAA,gBAAS,EAACgE,OAAQtF,KAAM,OAAO,KAGnC,MAAMwF,iBAAmBC,GAAAA,qBAAS,EAACH,QACnC,GACChE,GAAAA,gBAAS,EAACkE,iBAAkBxF,MAC5BsE,OAAOoB,OAAO,CAACF,iBAAkBxF,KAChC,CACD,OAAO,IACR,CAKA,OAAOgF,2BAA2BhF,IAAKqF,aAAcf,SAAW,KACjE,CAGA,OAAOW,YAAYlE,IAAI,CAAC,AAACwB,SAExB,MAAM2C,UAAYnF,YAAYC,IAAKuC,QACnC,GAAI2C,YAAc,MAAO,OAAO,MAGhC,GACC,OAAOlF,MAAQ,WACf,OAAOuC,SAAW,WAClBjD,GAAAA,aAAM,EAACU,IAAK,YACZV,GAAAA,aAAM,EAACiD,OAAQ,YACfvC,IAAIwD,OAAO,GAAKjB,OAAOiB,OAAO,CAC7B,CACD,MAAMC,UAAYC,GAAAA,8BAAe,EAChC1D,IAAIwD,OAAO,CACXjB,OAAOiB,OAAO,EAEf,GAAIC,YAAc,MAAO,OAAO,KACjC,CAGA,IAAIkC,gBAAkBpD,OACtB,GAAI,OAAOA,SAAW,UAAW,CAChC,GAAI2C,YAAc,KAAM,CACvBS,gBAAkB9C,gBAAgB7C,IAAKuC,OAAQ,MAC/C,GACC,OAAOoD,kBAAoB,WAC3B/E,OAAOC,IAAI,CAAC8E,iBAAiBnB,MAAM,GAAK,EACvC,CACD,OAAO,IACR,CACD,KAAO,CACNmB,gBAAkB9C,gBAAgB7C,IAAKuC,OAAQ,MAChD,CAGAoD,gBAAkBvC,oBAAoBpD,IAAK2F,gBAC5C,CAEA,MAAML,OAAShB,OAAOiB,KAAK,CAACvF,IAAK2F,iBACjC,GAAIL,SAAW,KAAM,CAEpB,OAAON,2BAA2BhF,IAAK2F,gBAAiBrB,UAAY,IACrE,CAEA,GAAIhD,GAAAA,gBAAS,EAACgE,OAAQtF,KAAM,OAAO,KACnC,MAAM4F,iBAAmBH,GAAAA,qBAAS,EAACH,QACnC,GACChE,GAAAA,gBAAS,EAACsE,iBAAkB5F,MAC5BsE,OAAOoB,OAAO,CAACE,iBAAkB5F,KAChC,CACD,OAAO,IACR,CAGA,OAAOgF,2BAA2BhF,IAAK2F,gBAAiBrB,UAAY,IACrE,EACD,CAaO,SAAS3F,iBACf4F,WAAoC,CACpCtE,GAA0B,CAC1BqE,MAAmB,CACnBuB,WAAyB,OAAO,EAEhC,MAAMC,UAA2B,EAAE,CACnC,IAAIC,UAAY,KAEhB,IAAK,IAAIC,EAAI,EAAGA,EAAIzB,YAAYC,MAAM,CAAEwB,IAAK,CAC5C,MAAMzD,OAASgC,WAAW,CAACyB,EAAE,CAC7B,GAAIzD,SAAW1C,UAAW,SAC1B,GAAI,CAACf,iBAAiByD,OAAQtC,IAAKqE,QAAS,CAC3CyB,UAAY,MACZ,MAAME,aAAeC,GAAAA,qCAAqB,EAAC3D,OAAQtC,IAAK,IACxD6F,UAAUK,IAAI,IAAIF,aACnB,CACD,CAEA,MAAO,CACNG,SAAUL,UACVT,OAAQS,UACLF,aAAe,QACd,CAAEnG,MAAO6E,WAAY,EACrB,CAAE9E,MAAO8E,WAAY,EACtB,KACH8B,OAAQP,SACT,CACD,CAUO,SAASlH,iBACfoB,GAA0B,CAC1BiF,WAAoC,CACpCX,MAAmB,CACnBgC,YAA0B,OAAO,EAEjC,IAAK,MAAM/D,UAAU0C,YAAa,CAEjC,IAAIU,gBAAkBpD,OACtB,GAAI,OAAOvC,MAAQ,WAAa,OAAOuC,SAAW,UAAW,CAC5DoD,gBAAkBvC,oBAAoBpD,IAAKuC,OAC5C,CACA,MAAM+C,OAAShB,OAAOiB,KAAK,CAACvF,IAAK2F,iBACjC,GAAIL,SAAW,KAAM,CAEpB,GAAIhE,GAAAA,gBAAS,EAACgE,OAAQtF,KAAM,CAC3B,MAAO,CAAEoG,SAAU,KAAMd,OAAQe,OAAQ,EAAE,AAAC,CAC7C,CACA,MAAMb,iBAAmBC,GAAAA,qBAAS,EAACH,QACnC,GACChE,GAAAA,gBAAS,EAACkE,iBAAkBxF,MAC5BsE,OAAOoB,OAAO,CAACF,iBAAkBxF,KAChC,CACD,MAAO,CAAEoG,SAAU,KAAMd,OAAQe,OAAQ,EAAE,AAAC,CAC7C,CACD,CACD,CAGA,MAAME,eAAiBL,GAAAA,qCAAqB,EAC3ClG,IACA,CAAEP,MAAOwF,WAAY,EACrB,IAGD,MAAO,CACNmB,SAAU,MACVd,OAAQ,KACRe,OAAQE,cACT,CACD,CASO,SAAS7H,YACfsB,GAA0B,CAC1BC,GAA0B,CAC1BqE,MAAmB,EAKnB,IAAIe,aAAepF,IACnB,GAAI,OAAOD,MAAQ,WAAa,OAAOC,MAAQ,UAAW,CACzDoF,aAAejC,oBAAoBpD,IAAKC,IACzC,CAEA,GAAI,CACH,MAAMqF,OAAShB,OAAOkC,YAAY,CAACxG,IAAKqF,cAGxC,GAAI/D,GAAAA,gBAAS,EAACgE,OAAQtF,KAAM,CAC3B,MAAO,CAAEoG,SAAU,KAAMd,OAAQe,OAAQ,EAAE,AAAC,CAC7C,CAEA,MAAMb,iBAAmBC,GAAAA,qBAAS,EAACH,QAEnC,GACChE,GAAAA,gBAAS,EAACkE,iBAAkBxF,MAC5BsE,OAAOoB,OAAO,CAACF,iBAAkBxF,KAChC,CACD,MAAO,CAAEoG,SAAU,KAAMd,OAAQE,iBAAkBa,OAAQ,EAAE,AAAC,CAC/D,CAGA,GAAIrB,2BAA2BhF,IAAKqF,aAAcf,UAAY,KAAM,CACnE,MAAO,CAAE8B,SAAU,KAAMd,OAAQtF,IAAKqG,OAAQ,EAAE,AAAC,CAClD,CAEA,MAAMA,OAASH,GAAAA,qCAAqB,EAAClG,IAAKC,IAAK,IAC/C,MAAO,CAAEmG,SAAU,MAAOd,OAAQE,iBAAkBa,MAAO,CAC5D,CAAE,MAAOI,GAAI,CAEZ,GAAIzB,2BAA2BhF,IAAKqF,aAAcf,UAAY,KAAM,CACnE,MAAO,CAAE8B,SAAU,KAAMd,OAAQtF,IAAKqG,OAAQ,EAAE,AAAC,CAClD,CAEA,MAAMA,OAASH,GAAAA,qCAAqB,EAAClG,IAAKC,IAAK,IAC/C,MAAO,CACNmG,SAAU,MACVd,OAAQ,KACRe,MACD,CACD,CACD"}
|
|
1
|
+
{"version":3,"sources":["../../src/subset-checker.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { isFormatSubset } from \"./format-validator\";\nimport type { MergeEngine } from \"./merge-engine\";\nimport { normalize } from \"./normalizer\";\nimport { isPatternSubset } from \"./pattern-subset\";\nimport { computeSemanticErrors } from \"./semantic-errors\";\nimport type { SchemaError, SubsetResult } from \"./types\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys } from \"./utils\";\n\n// ─── Subset Checker ──────────────────────────────────────────────────────────\n//\n// Logique de vérification sub ⊆ sup via l'approche :\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// Gère les cas :\n// - Schemas atomiques (pas de anyOf/oneOf)\n// - anyOf/oneOf dans sub → chaque branche doit être acceptée par sup\n// - anyOf/oneOf dans sup → au moins une branche doit accepter sub\n// - Point 6 : Distinction anyOf / oneOf dans les messages de diff\n// - Point 7 : Raisonnement étendu sur `not` (evaluateNot)\n// - not.type, not.const, not.enum (existants)\n// - not avec properties+required (1.1)\n// - not avec anyOf/oneOf (1.2)\n// - not dans sub (1.3)\n// - not.format (format-vs-format)\n//\n// Utilise des helpers natifs partagés depuis `./utils` pour des performances\n// optimales (deepEqual, hasOwn, isPlainObj, omitKeys).\n\n// ─── Branch type ─────────────────────────────────────────────────────────────\n\n/**\n * Type de branchement détecté dans un schema.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` pour produire des messages\n * de diff plus précis. `\"none\"` indique un schema atomique (pas de branches).\n *\n * Note : la sémantique d'exclusivité de `oneOf` n'est pas vérifiée\n * (ce serait un problème NP-hard en général). Le checker traite `oneOf`\n * comme `anyOf` pour le subset checking, ce qui est correct pour le cas\n * `sub ⊆ sup` mais peut produire des faux-positifs si les branches\n * du sub se chevauchent.\n */\nexport type BranchType = \"anyOf\" | \"oneOf\" | \"none\";\n\nexport interface BranchResult {\n\t/** Les branches extraites du schema */\n\tbranches: JSONSchema7Definition[];\n\t/** Le type de branchement détecté */\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 * Extrait les branches d'un schema et le type de branchement.\n *\n * Retourne les éléments de `anyOf`/`oneOf` s'ils existent, sinon retourne\n * le schema lui-même dans un tableau avec type `\"none\"`.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` dans les paths de diff.\n *\n * Optimisation : réutilise des objets pré-alloués pour les cas boolean\n * (true/false) et un WeakMap cache pour les schemas atomiques afin\n * d'éviter les allocations sur ces chemins fréquents.\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 — étendu) ─────────────────────────────────────\n\n/**\n * Raisonnement étendu sur `not` pour les cas courants.\n *\n * Point 7 — Vérifie la compatibilité quand `sup` et/ou `sub` contiennent `not` :\n *\n * **Cas existants (not dans sup) :**\n * - `not.type` : type exclu vs type de sub\n * - `not.const` : const exclu vs const de sub\n * - `not.enum` : valeurs exclues vs enum de sub\n *\n * **Cas ajoutés :**\n * - 1.1 — `not` avec `properties` + `required` : vérifier que les propriétés\n * de sub sont incompatibles avec celles du `not` (const/enum différents)\n * - 1.2 — `not` avec `anyOf`/`oneOf` : `not(anyOf([A,B]))` ≡ `allOf([not(A), not(B)])`,\n * donc sub doit être incompatible avec CHAQUE branche\n * - 1.3 — `not` dans `sub` (pas seulement dans `sup`) : un sub avec `not`\n * accepte un ensemble trop large pour être un sous-ensemble d'un sup concret\n * - `not.format` : format-vs-format via `isFormatSubset`\n *\n * Contrat ternaire conservateur :\n * - `true` → compatible (certain)\n * - `false` → incompatible (certain)\n * - `null` → indéterminé (laisser le merge engine décider)\n *\n * En cas de doute → `null`. Ne JAMAIS retourner `true` sans certitude.\n *\n * Utilise `_.has`, `_.get`, `_.isEqual`, `_.includes`, `_.every`, `_.some`,\n * `_.keys`, `_.isPlainObject`, `_.isArray` pour des vérifications concises.\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` dans sub (pas dans sup) ──\n\t// Un `not` dans sub est une restriction supplémentaire : il exclut des\n\t// valeurs de l'ensemble accepté par sub, ce qui le rend potentiellement\n\t// plus petit — donc plus susceptible d'être ⊆ sup, pas moins.\n\t// On laisse le merge engine décider : allOf(sub, sup) préservera le `not`\n\t// de sub, et la comparaison merged ≡ sub donnera le bon résultat.\n\t// Exception : si les deux ont `not`, on traite l'identité plus bas.\n\n\t// Vérifier `not` dans sup\n\tif (hasOwn(sup, \"not\") && isPlainObj(sup.not)) {\n\t\tconst notSchema = sup.not as JSONSchema7;\n\n\t\t// ── 1.1 — Cas not avec properties + required ──\n\t\t// IMPORTANT : ce check est placé AVANT le check not.type car quand\n\t\t// le not a à la fois `type` et `properties`, le check not.type seul\n\t\t// produirait un faux négatif (ex: sub type=object et not type=object\n\t\t// retournerait false, mais les properties pourraient être incompatibles\n\t\t// ce qui rendrait sub compatible avec le not).\n\t\t// Si not contient des properties avec const/enum et required,\n\t\t// vérifier que les propriétés de sub sont incompatibles avec celles du not.\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 doit avoir des properties pour qu'on puisse comparer\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// Pour que sub soit compatible avec not(schema),\n\t\t\t\t// il suffit qu'au moins UNE propriété du not soit incompatible avec sub.\n\t\t\t\t// Cela signifie que sub ne peut jamais valider le 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// Si la propriété est required dans not mais PAS dans sub.required\n\t\t\t\t\t// et qu'elle n'existe pas dans sub.properties → sub peut ne pas\n\t\t\t\t\t// avoir cette propriété → le not schema ne matcherait pas → 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; // Propriété absente de sub → not ne matche pas\n\t\t\t\t\t}\n\n\t\t\t\t\t// Comparer les const/enum de la propriété\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 a un const, sub.prop a un const différent → incompatible pour cette 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; // Consts différents → sub ne matche pas le not\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// not.prop a un enum, sub.prop a un const ou enum dont aucune valeur\n\t\t\t\t\t// n'est dans not.enum → incompatible pour cette 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 du 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; // Aucune valeur de sub.enum dans 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// Vérification inverse : si TOUTES les propriétés du not matchent sub\n\t\t\t\t// exactement (même const, sub a les required du not), alors sub VIOLE le 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// La propriété doit être dans sub.required si elle est dans 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// Vérifier 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// Vérifier 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// Toutes les valeurs de sub.enum sont dans 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; // Indéterminé pour cette propriété\n\t\t\t\t});\n\n\t\t\t\tif (allPropsMatch) return false; // sub matche exactement le not → incompatible\n\t\t\t}\n\t\t}\n\n\t\t// ── Cas not.const ──\n\t\t// IMPORTANT : ce check est placé AVANT not.type car quand le not a\n\t\t// à la fois `type` et `const`, le check not.type seul produirait un\n\t\t// faux négatif (ex: sub type=string const=\"active\" et not type=string\n\t\t// const=\"deleted\" → le type check retournerait false car même type,\n\t\t// alors que les consts sont différents → 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// ── Cas not.enum ──\n\t\t// Aussi placé AVANT not.type pour la même raison.\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// Toutes les valeurs de sub.enum doivent être absentes de 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// Certaines valeurs de sub sont dans not.enum → pas automatiquement faux,\n\t\t\t// le merge engine peut encore gérer\n\t\t}\n\n\t\t// ── Cas not.type ──\n\t\t// Placé APRÈS not.const, not.enum et properties+required pour ne pas\n\t\t// court-circuiter les cas où le not a des contraintes plus spécifiques.\n\t\t// Le check type seul est un fallback pour les not schemas simples\n\t\t// (ex: { 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// Si les deux sont des strings simples\n\t\t\tif (typeof notType === \"string\" && typeof subType === \"string\") {\n\t\t\t\t// Ne retourner que si le not n'a PAS de contraintes plus spécifiques\n\t\t\t\t// (const, enum, properties) qui auraient dû être traitées plus haut\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 est exactement le type exclu\n\t\t\t\t\treturn true; // Compatible : sub est un type différent du type exclu\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Si notType est un tableau, sub.type doit ne pas être dedans\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 — Cas not avec anyOf / oneOf ──\n\t\t// not(anyOf([A, B])) ≡ allOf([not(A), not(B)])\n\t\t// Pour que sub ⊆ not(anyOf(...)), sub doit être incompatible avec CHAQUE branche.\n\t\tif (hasOwn(notSchema, \"anyOf\") && Array.isArray(notSchema.anyOf)) {\n\t\t\tconst branches = notSchema.anyOf as JSONSchema7Definition[];\n\t\t\t// Pour chaque branche du not.anyOf, vérifier que sub est incompatible\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch; // not(true) = rien, not(false) = tout\n\t\t\t\t// Créer un sup virtuel { not: branch } et vérifier récursivement\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\t// result = true → sub est compatible avec not(branch) → sub ⊄ branch → OK\n\t\t\t\t// result = false → sub est incompatible avec not(branch) → sub ⊆ branch → pas OK\n\t\t\t\t// result = null → indéterminé\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\t// Vérifier si au moins une branche accepte sub → incompatible avec 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 est incompatible avec not(branch) → sub ⊆ branch\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// Même logique pour oneOf (dans le contexte du not, traité comme 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// ── Cas not.format (format-vs-format uniquement) ──\n\t\t// Si not a un format et sub aussi, vérifier la compatibilité\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 a exactement le format exclu\n\t\t\t// Formats différents → compatible (approximation conservatrice)\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Vérifier `not` dans sub ET dans sup (identité : { 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; // Pas d'avis → laisser le merge engine décider\n}\n\n// ─── Not stripping helper ────────────────────────────────────────────────────\n\n/**\n * Retire le mot-clé `not` d'un schema pour permettre un merge propre\n * quand `evaluateNot` a déjà confirmé la compatibilité.\n *\n * Gère aussi le `not` imbriqué dans les `properties` : si une propriété\n * de `sup` a un `not` qui est compatible avec la propriété correspondante\n * de `sub`, on le retire également.\n *\n * Retourne le schema nettoyé, ou `null` si le schema est vide après retrait.\n *\n * Utilise `_.omit`, `_.has`, `_.keys`, `_.isEmpty`, `_.isPlainObject`.\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// ── Retirer le `not` de niveau supérieur (seulement si confirmé) ──\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// ── Retirer les `not` dans les propriétés communes ──\n\t// Si sup.properties[key] a un `not` et que evaluateNot(sub.prop, sup.prop)\n\t// confirme la compatibilité, on retire le `not` de cette propriété aussi.\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// Vérifier la compatibilité du not au niveau de la propriété\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 * Retire le `pattern` de `sup` quand `isPatternSubset` a confirmé que\n * sub.pattern ⊆ sup.pattern par échantillonnage.\n *\n * Fonctionne comme `stripNotFromSup` : on retire la contrainte de sup\n * qui est déjà satisfaite par sub, pour éviter que le merge engine\n * produise un pattern combiné (lookahead conjunction) structurellement\n * différent du pattern de sub, ce qui causerait un faux négatif.\n *\n * Récurse dans les `properties` pour traiter les patterns imbriqués.\n *\n * @param sub Le schema sub (utilisé pour extraire les patterns à comparer)\n * @param sup Le schema sup dont on retire les patterns confirmés\n * @returns Le schema sup nettoyé\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 dans les propriétés communes ──\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 dans 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 * Vérifie si `sub ⊆ sup` pour deux schemas sans anyOf/oneOf (ou avec\n * anyOf/oneOf uniquement côté sup).\n *\n * Point 7 — Intègre un pré-check `not` étendu (`evaluateNot`) avant le merge.\n *\n * Quand `evaluateNot` confirme la compatibilité (`true`), on retire le `not`\n * de `sup` avant le merge pour éviter que le merge engine ajoute une contrainte\n * `not` que `sub` n'a pas (ce qui ferait échouer `isEqual(merged, sub)`).\n *\n * Pattern pre-check — Quand les deux schemas ont des patterns différents,\n * vérifie l'inclusion par échantillonnage via `isPatternSubset`. Si confirmé,\n * retire le pattern de sup avant le merge (même stratégie que pour `not`).\n *\n * Principe : merge(sub, sup) ≡ sub → sub est un sous-ensemble de 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 *\n * Utilise `_.some`, `_.has`, `_.omit`, `_.keys`, `_.isEmpty` pour la logique.\n */\nexport function isAtomicSubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: supBranches } = getBranchesTyped(sup);\n\n\t// Schema simple → merge direct\n\tif (supBranches.length === 1 && supBranches[0] === sup) {\n\t\t// Point 7 : pré-check `not` étendu\n\t\tconst notResult = evaluateNot(sub, sup);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Format pre-check ──\n\t\t// Si les deux schemas ont un `format` différent, vérifier que\n\t\t// sub.format ⊆ sup.format. Sinon, sub ne peut pas être ⊆ sup.\n\t\t// Cela complète hasFormatConflict (qui gère le merge) en gérant\n\t\t// la direction du subset check que le merge ne peut pas résoudre.\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// Si les deux schemas ont des patterns différents, vérifier l'inclusion\n\t\t// par échantillonnage. Si sub.pattern ⊄ sup.pattern (contre-exemple trouvé),\n\t\t// on retourne false immédiatement. Sinon, on pourra retirer le pattern\n\t\t// de sup pour éviter le faux négatif structurel du 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// Retirer `not` de sup (top-level et/ou dans les properties)\n\t\t// quand evaluateNot confirme la compatibilité au niveau correspondant.\n\t\t// Cela évite que le merge engine ajoute une contrainte `not` que sub n'a pas\n\t\t// (ce qui ferait merged ≠ sub et produirait un faux négatif).\n\t\tlet effectiveSup = sup;\n\t\tif (typeof sup !== \"boolean\") {\n\t\t\t// Si top-level not est confirmé compatible → retirer le not top-level\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, true);\n\t\t\t\t// Si sup n'avait QUE `not` → sub est compatible (le not est résolu)\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// Même si le top-level not n'est pas confirmé (null), on tente\n\t\t\t\t// de retirer les `not` dans les properties individuelles\n\t\t\t\t// sans toucher au `not` top-level\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, false);\n\t\t\t}\n\n\t\t\t// Retirer les patterns de sup confirmés par échantillonnage.\n\t\t\t// Même stratégie que pour `not` : on retire la contrainte déjà\n\t\t\t// satisfaite par sub pour éviter que le merge produise un pattern\n\t\t\t// combiné (lookahead conjunction) structurellement ≠ 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 dans sup → au moins une branche doit accepter sub\n\treturn supBranches.some((branch) => {\n\t\t// Point 7 : pré-check `not` étendu par branche\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// Même logique de strip pour les 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 confirmés par échantillonnage\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 * Vérifie `sub ⊆ sup` pour un sub qui a des branches (anyOf/oneOf).\n * Chaque branche de sub doit être acceptée par sup.\n *\n * Point 6 — Utilise `getBranchesTyped` pour distinguer `anyOf[i]` de\n * `oneOf[i]` dans les paths de diff.\n *\n * Utilise `_.every` / `_.flatMap` / `_.map` pour une itération idiomatique.\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 * Vérifie `sub ⊆ sup` pour un sup qui a des branches (anyOf/oneOf).\n * Au moins une branche de sup doit accepter sub.\n *\n * Point 6 — Utilise le type de branche de sup pour des messages plus précis.\n *\n * Utilise `_.some` pour trouver la première branche compatible.\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 confirmés par échantillonnage avant le 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// Générer des erreurs sémantiques en comparant sub avec le sup original\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 * Vérifie `sub ⊆ sup` pour deux schemas atomiques (sans anyOf/oneOf).\n * Utilise `mergeOrThrow` pour capturer les erreurs d'incompatibilité.\n *\n * Utilise `deepEqual` pour la comparaison structurelle (avec short-circuit\n * par référence et comptage de clés).\n */\nexport function checkAtomic(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): SubsetResult {\n\t// Strip patterns confirmés par échantillonnage avant le merge,\n\t// même stratégie que dans isAtomicSubsetOf pour éviter les faux négatifs\n\t// structurels causés par la conjonction de patterns en 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,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 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 normalizedMerged=normalize(merged);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 normalizedBranch=normalize(merged);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 normalizedMerged=normalize(merged);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 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}}}
|
|
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\";\nimport type { MergeEngine } from \"./merge-engine\";\nimport { normalize } from \"./normalizer\";\nimport { isPatternSubset } from \"./pattern-subset\";\nimport { computeSemanticErrors } from \"./semantic-errors\";\nimport type { SchemaError, SubsetResult } from \"./types\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys } from \"./utils\";\n\n// ─── Subset Checker ──────────────────────────────────────────────────────────\n//\n// Logique de vérification sub ⊆ sup via l'approche :\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// Gère les cas :\n// - Schemas atomiques (pas de anyOf/oneOf)\n// - anyOf/oneOf dans sub → chaque branche doit être acceptée par sup\n// - anyOf/oneOf dans sup → au moins une branche doit accepter sub\n// - Point 6 : Distinction anyOf / oneOf dans les messages de diff\n// - Point 7 : Raisonnement étendu sur `not` (evaluateNot)\n// - not.type, not.const, not.enum (existants)\n// - not avec properties+required (1.1)\n// - not avec anyOf/oneOf (1.2)\n// - not dans sub (1.3)\n// - not.format (format-vs-format)\n//\n// Utilise des helpers natifs partagés depuis `./utils` pour des performances\n// optimales (deepEqual, hasOwn, isPlainObj, omitKeys).\n\n// ─── Branch type ─────────────────────────────────────────────────────────────\n\n/**\n * Type de branchement détecté dans un schema.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` pour produire des messages\n * de diff plus précis. `\"none\"` indique un schema atomique (pas de branches).\n *\n * Note : la sémantique d'exclusivité de `oneOf` n'est pas vérifiée\n * (ce serait un problème NP-hard en général). Le checker traite `oneOf`\n * comme `anyOf` pour le subset checking, ce qui est correct pour le cas\n * `sub ⊆ sup` mais peut produire des faux-positifs si les branches\n * du sub se chevauchent.\n */\nexport type BranchType = \"anyOf\" | \"oneOf\" | \"none\";\n\nexport interface BranchResult {\n\t/** Les branches extraites du schema */\n\tbranches: JSONSchema7Definition[];\n\t/** Le type de branchement détecté */\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 * Extrait les branches d'un schema et le type de branchement.\n *\n * Retourne les éléments de `anyOf`/`oneOf` s'ils existent, sinon retourne\n * le schema lui-même dans un tableau avec type `\"none\"`.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` dans les paths de diff.\n *\n * Optimisation : réutilise des objets pré-alloués pour les cas boolean\n * (true/false) et un WeakMap cache pour les schemas atomiques afin\n * d'éviter les allocations sur ces chemins fréquents.\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 — étendu) ─────────────────────────────────────\n\n/**\n * Raisonnement étendu sur `not` pour les cas courants.\n *\n * Point 7 — Vérifie la compatibilité quand `sup` et/ou `sub` contiennent `not` :\n *\n * **Cas existants (not dans sup) :**\n * - `not.type` : type exclu vs type de sub\n * - `not.const` : const exclu vs const de sub\n * - `not.enum` : valeurs exclues vs enum de sub\n *\n * **Cas ajoutés :**\n * - 1.1 — `not` avec `properties` + `required` : vérifier que les propriétés\n * de sub sont incompatibles avec celles du `not` (const/enum différents)\n * - 1.2 — `not` avec `anyOf`/`oneOf` : `not(anyOf([A,B]))` ≡ `allOf([not(A), not(B)])`,\n * donc sub doit être incompatible avec CHAQUE branche\n * - 1.3 — `not` dans `sub` (pas seulement dans `sup`) : un sub avec `not`\n * accepte un ensemble trop large pour être un sous-ensemble d'un sup concret\n * - `not.format` : format-vs-format via `isFormatSubset`\n *\n * Contrat ternaire conservateur :\n * - `true` → compatible (certain)\n * - `false` → incompatible (certain)\n * - `null` → indéterminé (laisser le merge engine décider)\n *\n * En cas de doute → `null`. Ne JAMAIS retourner `true` sans certitude.\n *\n * Utilise `_.has`, `_.get`, `_.isEqual`, `_.includes`, `_.every`, `_.some`,\n * `_.keys`, `_.isPlainObject`, `_.isArray` pour des vérifications concises.\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` dans sub (pas dans sup) ──\n\t// Un `not` dans sub est une restriction supplémentaire : il exclut des\n\t// valeurs de l'ensemble accepté par sub, ce qui le rend potentiellement\n\t// plus petit — donc plus susceptible d'être ⊆ sup, pas moins.\n\t// On laisse le merge engine décider : allOf(sub, sup) préservera le `not`\n\t// de sub, et la comparaison merged ≡ sub donnera le bon résultat.\n\t// Exception : si les deux ont `not`, on traite l'identité plus bas.\n\n\t// Vérifier `not` dans sup\n\tif (hasOwn(sup, \"not\") && isPlainObj(sup.not)) {\n\t\tconst notSchema = sup.not as JSONSchema7;\n\n\t\t// ── 1.1 — Cas not avec properties + required ──\n\t\t// IMPORTANT : ce check est placé AVANT le check not.type car quand\n\t\t// le not a à la fois `type` et `properties`, le check not.type seul\n\t\t// produirait un faux négatif (ex: sub type=object et not type=object\n\t\t// retournerait false, mais les properties pourraient être incompatibles\n\t\t// ce qui rendrait sub compatible avec le not).\n\t\t// Si not contient des properties avec const/enum et required,\n\t\t// vérifier que les propriétés de sub sont incompatibles avec celles du not.\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 doit avoir des properties pour qu'on puisse comparer\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// Pour que sub soit compatible avec not(schema),\n\t\t\t\t// il suffit qu'au moins UNE propriété du not soit incompatible avec sub.\n\t\t\t\t// Cela signifie que sub ne peut jamais valider le 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// Si la propriété est required dans not mais PAS dans sub.required\n\t\t\t\t\t// et qu'elle n'existe pas dans sub.properties → sub peut ne pas\n\t\t\t\t\t// avoir cette propriété → le not schema ne matcherait pas → 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; // Propriété absente de sub → not ne matche pas\n\t\t\t\t\t}\n\n\t\t\t\t\t// Comparer les const/enum de la propriété\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 a un const, sub.prop a un const différent → incompatible pour cette 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; // Consts différents → sub ne matche pas le not\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// not.prop a un enum, sub.prop a un const ou enum dont aucune valeur\n\t\t\t\t\t// n'est dans not.enum → incompatible pour cette 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 du 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; // Aucune valeur de sub.enum dans 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// Vérification inverse : si TOUTES les propriétés du not matchent sub\n\t\t\t\t// exactement (même const, sub a les required du not), alors sub VIOLE le 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// La propriété doit être dans sub.required si elle est dans 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// Vérifier 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// Vérifier 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// Toutes les valeurs de sub.enum sont dans 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; // Indéterminé pour cette propriété\n\t\t\t\t});\n\n\t\t\t\tif (allPropsMatch) return false; // sub matche exactement le not → incompatible\n\t\t\t}\n\t\t}\n\n\t\t// ── Cas not.const ──\n\t\t// IMPORTANT : ce check est placé AVANT not.type car quand le not a\n\t\t// à la fois `type` et `const`, le check not.type seul produirait un\n\t\t// faux négatif (ex: sub type=string const=\"active\" et not type=string\n\t\t// const=\"deleted\" → le type check retournerait false car même type,\n\t\t// alors que les consts sont différents → 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// ── Cas not.enum ──\n\t\t// Aussi placé AVANT not.type pour la même raison.\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// Toutes les valeurs de sub.enum doivent être absentes de 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// Certaines valeurs de sub sont dans not.enum → pas automatiquement faux,\n\t\t\t// le merge engine peut encore gérer\n\t\t}\n\n\t\t// ── Cas not.type ──\n\t\t// Placé APRÈS not.const, not.enum et properties+required pour ne pas\n\t\t// court-circuiter les cas où le not a des contraintes plus spécifiques.\n\t\t// Le check type seul est un fallback pour les not schemas simples\n\t\t// (ex: { 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// Si les deux sont des strings simples\n\t\t\tif (typeof notType === \"string\" && typeof subType === \"string\") {\n\t\t\t\t// Ne retourner que si le not n'a PAS de contraintes plus spécifiques\n\t\t\t\t// (const, enum, properties) qui auraient dû être traitées plus haut\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 est exactement le type exclu\n\t\t\t\t\treturn true; // Compatible : sub est un type différent du type exclu\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Si notType est un tableau, sub.type doit ne pas être dedans\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 — Cas not avec anyOf / oneOf ──\n\t\t// not(anyOf([A, B])) ≡ allOf([not(A), not(B)])\n\t\t// Pour que sub ⊆ not(anyOf(...)), sub doit être incompatible avec CHAQUE branche.\n\t\tif (hasOwn(notSchema, \"anyOf\") && Array.isArray(notSchema.anyOf)) {\n\t\t\tconst branches = notSchema.anyOf as JSONSchema7Definition[];\n\t\t\t// Pour chaque branche du not.anyOf, vérifier que sub est incompatible\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch; // not(true) = rien, not(false) = tout\n\t\t\t\t// Créer un sup virtuel { not: branch } et vérifier récursivement\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\t// result = true → sub est compatible avec not(branch) → sub ⊄ branch → OK\n\t\t\t\t// result = false → sub est incompatible avec not(branch) → sub ⊆ branch → pas OK\n\t\t\t\t// result = null → indéterminé\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\t// Vérifier si au moins une branche accepte sub → incompatible avec 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 est incompatible avec not(branch) → sub ⊆ branch\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// Même logique pour oneOf (dans le contexte du not, traité comme 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// ── Cas not.format (format-vs-format uniquement) ──\n\t\t// Si not a un format et sub aussi, vérifier la compatibilité\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 a exactement le format exclu\n\t\t\t// Formats différents → compatible (approximation conservatrice)\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Vérifier `not` dans sub ET dans sup (identité : { 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; // Pas d'avis → laisser le merge engine décider\n}\n\n// ─── Not stripping helper ────────────────────────────────────────────────────\n\n/**\n * Retire le mot-clé `not` d'un schema pour permettre un merge propre\n * quand `evaluateNot` a déjà confirmé la compatibilité.\n *\n * Gère aussi le `not` imbriqué dans les `properties` : si une propriété\n * de `sup` a un `not` qui est compatible avec la propriété correspondante\n * de `sub`, on le retire également.\n *\n * Retourne le schema nettoyé, ou `null` si le schema est vide après retrait.\n *\n * Utilise `_.omit`, `_.has`, `_.keys`, `_.isEmpty`, `_.isPlainObject`.\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// ── Retirer le `not` de niveau supérieur (seulement si confirmé) ──\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// ── Retirer les `not` dans les propriétés communes ──\n\t// Si sup.properties[key] a un `not` et que evaluateNot(sub.prop, sup.prop)\n\t// confirme la compatibilité, on retire le `not` de cette propriété aussi.\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// Vérifier la compatibilité du not au niveau de la propriété\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 * Retire le `pattern` de `sup` quand `isPatternSubset` a confirmé que\n * sub.pattern ⊆ sup.pattern par échantillonnage.\n *\n * Fonctionne comme `stripNotFromSup` : on retire la contrainte de sup\n * qui est déjà satisfaite par sub, pour éviter que le merge engine\n * produise un pattern combiné (lookahead conjunction) structurellement\n * différent du pattern de sub, ce qui causerait un faux négatif.\n *\n * Récurse dans les `properties` pour traiter les patterns imbriqués.\n *\n * @param sub Le schema sub (utilisé pour extraire les patterns à comparer)\n * @param sup Le schema sup dont on retire les patterns confirmés\n * @returns Le schema sup nettoyé\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 dans les propriétés communes ──\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 dans 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// ─── 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 * Vérifie si `sub ⊆ sup` pour deux schemas sans anyOf/oneOf (ou avec\n * anyOf/oneOf uniquement côté sup).\n *\n * Point 7 — Intègre un pré-check `not` étendu (`evaluateNot`) avant le merge.\n *\n * Quand `evaluateNot` confirme la compatibilité (`true`), on retire le `not`\n * de `sup` avant le merge pour éviter que le merge engine ajoute une contrainte\n * `not` que `sub` n'a pas (ce qui ferait échouer `isEqual(merged, sub)`).\n *\n * Pattern pre-check — Quand les deux schemas ont des patterns différents,\n * vérifie l'inclusion par échantillonnage via `isPatternSubset`. Si confirmé,\n * retire le pattern de sup avant le merge (même stratégie que pour `not`).\n *\n * Principe : merge(sub, sup) ≡ sub → sub est un sous-ensemble de 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 *\n * Utilise `_.some`, `_.has`, `_.omit`, `_.keys`, `_.isEmpty` pour la logique.\n */\nexport function isAtomicSubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: supBranches } = getBranchesTyped(sup);\n\n\t// Schema simple → merge direct\n\tif (supBranches.length === 1 && supBranches[0] === sup) {\n\t\t// Point 7 : pré-check `not` étendu\n\t\tconst notResult = evaluateNot(sub, sup);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Format pre-check ──\n\t\t// Si les deux schemas ont un `format` différent, vérifier que\n\t\t// sub.format ⊆ sup.format. Sinon, sub ne peut pas être ⊆ sup.\n\t\t// Cela complète hasFormatConflict (qui gère le merge) en gérant\n\t\t// la direction du subset check que le merge ne peut pas résoudre.\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// Si les deux schemas ont des patterns différents, vérifier l'inclusion\n\t\t// par échantillonnage. Si sub.pattern ⊄ sup.pattern (contre-exemple trouvé),\n\t\t// on retourne false immédiatement. Sinon, on pourra retirer le pattern\n\t\t// de sup pour éviter le faux négatif structurel du 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// Retirer `not` de sup (top-level et/ou dans les properties)\n\t\t// quand evaluateNot confirme la compatibilité au niveau correspondant.\n\t\t// Cela évite que le merge engine ajoute une contrainte `not` que sub n'a pas\n\t\t// (ce qui ferait merged ≠ sub et produirait un faux négatif).\n\t\tlet effectiveSup = sup;\n\t\tif (typeof sup !== \"boolean\") {\n\t\t\t// Si top-level not est confirmé compatible → retirer le not top-level\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, true);\n\t\t\t\t// Si sup n'avait QUE `not` → sub est compatible (le not est résolu)\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// Même si le top-level not n'est pas confirmé (null), on tente\n\t\t\t\t// de retirer les `not` dans les properties individuelles\n\t\t\t\t// sans toucher au `not` top-level\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, false);\n\t\t\t}\n\n\t\t\t// Retirer les patterns de sup confirmés par échantillonnage.\n\t\t\t// Même stratégie que pour `not` : on retire la contrainte déjà\n\t\t\t// satisfaite par sub pour éviter que le merge produise un pattern\n\t\t\t// combiné (lookahead conjunction) structurellement ≠ 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\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(merged);\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 dans sup → au moins une branche doit accepter sub\n\treturn supBranches.some((branch) => {\n\t\t// Point 7 : pré-check `not` étendu par branche\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// Même logique de strip pour les 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 confirmés par échantillonnage\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\t\tconst normalizedBranch = normalize(merged);\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 * Vérifie `sub ⊆ sup` pour un sub qui a des branches (anyOf/oneOf).\n * Chaque branche de sub doit être acceptée par sup.\n *\n * Point 6 — Utilise `getBranchesTyped` pour distinguer `anyOf[i]` de\n * `oneOf[i]` dans les paths de diff.\n *\n * Utilise `_.every` / `_.flatMap` / `_.map` pour une itération idiomatique.\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 * Vérifie `sub ⊆ sup` pour un sup qui a des branches (anyOf/oneOf).\n * Au moins une branche de sup doit accepter sub.\n *\n * Point 6 — Utilise le type de branche de sup pour des messages plus précis.\n *\n * Utilise `_.some` pour trouver la première branche compatible.\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 confirmés par échantillonnage avant le 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// Générer des erreurs sémantiques en comparant sub avec le sup original\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 * Vérifie `sub ⊆ sup` pour deux schemas atomiques (sans anyOf/oneOf).\n * Utilise `mergeOrThrow` pour capturer les erreurs d'incompatibilité.\n *\n * Utilise `deepEqual` pour la comparaison structurelle (avec short-circuit\n * par référence et comptage de clés).\n */\nexport function checkAtomic(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): SubsetResult {\n\t// Strip patterns confirmés par échantillonnage avant le merge,\n\t// même stratégie que dans isAtomicSubsetOf pour éviter les faux négatifs\n\t// structurels causés par la conjonction de patterns en 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\tconst normalizedMerged = normalize(merged);\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","hasNestedBranching","schema","props","prop","isPropertySubsetOf","engine","subBranches","length","isAtomicSubsetOf","isObjectSubsetByProperties","subIsObj","supIsObj","supRequired","additionalProperties","supProp","addPropSchema","tryNestedBranchingFallback","supBranches","notResult","fmtResult","effectiveSup","merged","merge","normalizedMerged","isEqual","effectiveBranch","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\";\nimport type { MergeEngine } from \"./merge-engine\";\nimport { normalize } from \"./normalizer\";\nimport { isPatternSubset } from \"./pattern-subset\";\nimport { computeSemanticErrors } from \"./semantic-errors\";\nimport type { SchemaError, SubsetResult } from \"./types\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys } from \"./utils\";\n\n// ─── Subset Checker ──────────────────────────────────────────────────────────\n//\n// Logique de vérification sub ⊆ sup via l'approche :\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// Gère les cas :\n// - Schemas atomiques (pas de anyOf/oneOf)\n// - anyOf/oneOf dans sub → chaque branche doit être acceptée par sup\n// - anyOf/oneOf dans sup → au moins une branche doit accepter sub\n// - Point 6 : Distinction anyOf / oneOf dans les messages de diff\n// - Point 7 : Raisonnement étendu sur `not` (evaluateNot)\n// - not.type, not.const, not.enum (existants)\n// - not avec properties+required (1.1)\n// - not avec anyOf/oneOf (1.2)\n// - not dans sub (1.3)\n// - not.format (format-vs-format)\n//\n// Utilise des helpers natifs partagés depuis `./utils` pour des performances\n// optimales (deepEqual, hasOwn, isPlainObj, omitKeys).\n\n// ─── Branch type ─────────────────────────────────────────────────────────────\n\n/**\n * Type de branchement détecté dans un schema.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` pour produire des messages\n * de diff plus précis. `\"none\"` indique un schema atomique (pas de branches).\n *\n * Note : la sémantique d'exclusivité de `oneOf` n'est pas vérifiée\n * (ce serait un problème NP-hard en général). Le checker traite `oneOf`\n * comme `anyOf` pour le subset checking, ce qui est correct pour le cas\n * `sub ⊆ sup` mais peut produire des faux-positifs si les branches\n * du sub se chevauchent.\n */\nexport type BranchType = \"anyOf\" | \"oneOf\" | \"none\";\n\nexport interface BranchResult {\n\t/** Les branches extraites du schema */\n\tbranches: JSONSchema7Definition[];\n\t/** Le type de branchement détecté */\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 * Extrait les branches d'un schema et le type de branchement.\n *\n * Retourne les éléments de `anyOf`/`oneOf` s'ils existent, sinon retourne\n * le schema lui-même dans un tableau avec type `\"none\"`.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` dans les paths de diff.\n *\n * Optimisation : réutilise des objets pré-alloués pour les cas boolean\n * (true/false) et un WeakMap cache pour les schemas atomiques afin\n * d'éviter les allocations sur ces chemins fréquents.\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 — étendu) ─────────────────────────────────────\n\n/**\n * Raisonnement étendu sur `not` pour les cas courants.\n *\n * Point 7 — Vérifie la compatibilité quand `sup` et/ou `sub` contiennent `not` :\n *\n * **Cas existants (not dans sup) :**\n * - `not.type` : type exclu vs type de sub\n * - `not.const` : const exclu vs const de sub\n * - `not.enum` : valeurs exclues vs enum de sub\n *\n * **Cas ajoutés :**\n * - 1.1 — `not` avec `properties` + `required` : vérifier que les propriétés\n * de sub sont incompatibles avec celles du `not` (const/enum différents)\n * - 1.2 — `not` avec `anyOf`/`oneOf` : `not(anyOf([A,B]))` ≡ `allOf([not(A), not(B)])`,\n * donc sub doit être incompatible avec CHAQUE branche\n * - 1.3 — `not` dans `sub` (pas seulement dans `sup`) : un sub avec `not`\n * accepte un ensemble trop large pour être un sous-ensemble d'un sup concret\n * - `not.format` : format-vs-format via `isFormatSubset`\n *\n * Contrat ternaire conservateur :\n * - `true` → compatible (certain)\n * - `false` → incompatible (certain)\n * - `null` → indéterminé (laisser le merge engine décider)\n *\n * En cas de doute → `null`. Ne JAMAIS retourner `true` sans certitude.\n *\n * Utilise `_.has`, `_.get`, `_.isEqual`, `_.includes`, `_.every`, `_.some`,\n * `_.keys`, `_.isPlainObject`, `_.isArray` pour des vérifications concises.\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` dans sub (pas dans sup) ──\n\t// Un `not` dans sub est une restriction supplémentaire : il exclut des\n\t// valeurs de l'ensemble accepté par sub, ce qui le rend potentiellement\n\t// plus petit — donc plus susceptible d'être ⊆ sup, pas moins.\n\t// On laisse le merge engine décider : allOf(sub, sup) préservera le `not`\n\t// de sub, et la comparaison merged ≡ sub donnera le bon résultat.\n\t// Exception : si les deux ont `not`, on traite l'identité plus bas.\n\n\t// Vérifier `not` dans sup\n\tif (hasOwn(sup, \"not\") && isPlainObj(sup.not)) {\n\t\tconst notSchema = sup.not as JSONSchema7;\n\n\t\t// ── 1.1 — Cas not avec properties + required ──\n\t\t// IMPORTANT : ce check est placé AVANT le check not.type car quand\n\t\t// le not a à la fois `type` et `properties`, le check not.type seul\n\t\t// produirait un faux négatif (ex: sub type=object et not type=object\n\t\t// retournerait false, mais les properties pourraient être incompatibles\n\t\t// ce qui rendrait sub compatible avec le not).\n\t\t// Si not contient des properties avec const/enum et required,\n\t\t// vérifier que les propriétés de sub sont incompatibles avec celles du not.\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 doit avoir des properties pour qu'on puisse comparer\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// Pour que sub soit compatible avec not(schema),\n\t\t\t\t// il suffit qu'au moins UNE propriété du not soit incompatible avec sub.\n\t\t\t\t// Cela signifie que sub ne peut jamais valider le 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// Si la propriété est required dans not mais PAS dans sub.required\n\t\t\t\t\t// et qu'elle n'existe pas dans sub.properties → sub peut ne pas\n\t\t\t\t\t// avoir cette propriété → le not schema ne matcherait pas → 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; // Propriété absente de sub → not ne matche pas\n\t\t\t\t\t}\n\n\t\t\t\t\t// Comparer les const/enum de la propriété\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 a un const, sub.prop a un const différent → incompatible pour cette 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; // Consts différents → sub ne matche pas le not\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// not.prop a un enum, sub.prop a un const ou enum dont aucune valeur\n\t\t\t\t\t// n'est dans not.enum → incompatible pour cette 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 du 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; // Aucune valeur de sub.enum dans 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// Vérification inverse : si TOUTES les propriétés du not matchent sub\n\t\t\t\t// exactement (même const, sub a les required du not), alors sub VIOLE le 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// La propriété doit être dans sub.required si elle est dans 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// Vérifier 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// Vérifier 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// Toutes les valeurs de sub.enum sont dans 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; // Indéterminé pour cette propriété\n\t\t\t\t});\n\n\t\t\t\tif (allPropsMatch) return false; // sub matche exactement le not → incompatible\n\t\t\t}\n\t\t}\n\n\t\t// ── Cas not.const ──\n\t\t// IMPORTANT : ce check est placé AVANT not.type car quand le not a\n\t\t// à la fois `type` et `const`, le check not.type seul produirait un\n\t\t// faux négatif (ex: sub type=string const=\"active\" et not type=string\n\t\t// const=\"deleted\" → le type check retournerait false car même type,\n\t\t// alors que les consts sont différents → 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// ── Cas not.enum ──\n\t\t// Aussi placé AVANT not.type pour la même raison.\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// Toutes les valeurs de sub.enum doivent être absentes de 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// Certaines valeurs de sub sont dans not.enum → pas automatiquement faux,\n\t\t\t// le merge engine peut encore gérer\n\t\t}\n\n\t\t// ── Cas not.type ──\n\t\t// Placé APRÈS not.const, not.enum et properties+required pour ne pas\n\t\t// court-circuiter les cas où le not a des contraintes plus spécifiques.\n\t\t// Le check type seul est un fallback pour les not schemas simples\n\t\t// (ex: { 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// Si les deux sont des strings simples\n\t\t\tif (typeof notType === \"string\" && typeof subType === \"string\") {\n\t\t\t\t// Ne retourner que si le not n'a PAS de contraintes plus spécifiques\n\t\t\t\t// (const, enum, properties) qui auraient dû être traitées plus haut\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 est exactement le type exclu\n\t\t\t\t\treturn true; // Compatible : sub est un type différent du type exclu\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Si notType est un tableau, sub.type doit ne pas être dedans\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 — Cas not avec anyOf / oneOf ──\n\t\t// not(anyOf([A, B])) ≡ allOf([not(A), not(B)])\n\t\t// Pour que sub ⊆ not(anyOf(...)), sub doit être incompatible avec CHAQUE branche.\n\t\tif (hasOwn(notSchema, \"anyOf\") && Array.isArray(notSchema.anyOf)) {\n\t\t\tconst branches = notSchema.anyOf as JSONSchema7Definition[];\n\t\t\t// Pour chaque branche du not.anyOf, vérifier que sub est incompatible\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch; // not(true) = rien, not(false) = tout\n\t\t\t\t// Créer un sup virtuel { not: branch } et vérifier récursivement\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\t// result = true → sub est compatible avec not(branch) → sub ⊄ branch → OK\n\t\t\t\t// result = false → sub est incompatible avec not(branch) → sub ⊆ branch → pas OK\n\t\t\t\t// result = null → indéterminé\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\t// Vérifier si au moins une branche accepte sub → incompatible avec 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 est incompatible avec not(branch) → sub ⊆ branch\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// Même logique pour oneOf (dans le contexte du not, traité comme 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// ── Cas not.format (format-vs-format uniquement) ──\n\t\t// Si not a un format et sub aussi, vérifier la compatibilité\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 a exactement le format exclu\n\t\t\t// Formats différents → compatible (approximation conservatrice)\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Vérifier `not` dans sub ET dans sup (identité : { 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; // Pas d'avis → laisser le merge engine décider\n}\n\n// ─── Not stripping helper ────────────────────────────────────────────────────\n\n/**\n * Retire le mot-clé `not` d'un schema pour permettre un merge propre\n * quand `evaluateNot` a déjà confirmé la compatibilité.\n *\n * Gère aussi le `not` imbriqué dans les `properties` : si une propriété\n * de `sup` a un `not` qui est compatible avec la propriété correspondante\n * de `sub`, on le retire également.\n *\n * Retourne le schema nettoyé, ou `null` si le schema est vide après retrait.\n *\n * Utilise `_.omit`, `_.has`, `_.keys`, `_.isEmpty`, `_.isPlainObject`.\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// ── Retirer le `not` de niveau supérieur (seulement si confirmé) ──\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// ── Retirer les `not` dans les propriétés communes ──\n\t// Si sup.properties[key] a un `not` et que evaluateNot(sub.prop, sup.prop)\n\t// confirme la compatibilité, on retire le `not` de cette propriété aussi.\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// Vérifier la compatibilité du not au niveau de la propriété\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 * Retire le `pattern` de `sup` quand `isPatternSubset` a confirmé que\n * sub.pattern ⊆ sup.pattern par échantillonnage.\n *\n * Fonctionne comme `stripNotFromSup` : on retire la contrainte de sup\n * qui est déjà satisfaite par sub, pour éviter que le merge engine\n * produise un pattern combiné (lookahead conjunction) structurellement\n * différent du pattern de sub, ce qui causerait un faux négatif.\n *\n * Récurse dans les `properties` pour traiter les patterns imbriqués.\n *\n * @param sub Le schema sub (utilisé pour extraire les patterns à comparer)\n * @param sup Le schema sup dont on retire les patterns confirmés\n * @returns Le schema sup nettoyé\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 dans les propriétés communes ──\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 dans 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 * Vérifie si `sub ⊆ sup` pour deux schemas sans anyOf/oneOf (ou avec\n * anyOf/oneOf uniquement côté sup).\n *\n * Point 7 — Intègre un pré-check `not` étendu (`evaluateNot`) avant le merge.\n *\n * Quand `evaluateNot` confirme la compatibilité (`true`), on retire le `not`\n * de `sup` avant le merge pour éviter que le merge engine ajoute une contrainte\n * `not` que `sub` n'a pas (ce qui ferait échouer `isEqual(merged, sub)`).\n *\n * Pattern pre-check — Quand les deux schemas ont des patterns différents,\n * vérifie l'inclusion par échantillonnage via `isPatternSubset`. Si confirmé,\n * retire le pattern de sup avant le merge (même stratégie que pour `not`).\n *\n * Principe : merge(sub, sup) ≡ sub → sub est un sous-ensemble de 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 *\n * Utilise `_.some`, `_.has`, `_.omit`, `_.keys`, `_.isEmpty` pour la logique.\n */\nexport function isAtomicSubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: supBranches } = getBranchesTyped(sup);\n\n\t// Schema simple → merge direct\n\tif (supBranches.length === 1 && supBranches[0] === sup) {\n\t\t// Point 7 : pré-check `not` étendu\n\t\tconst notResult = evaluateNot(sub, sup);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Format pre-check ──\n\t\t// Si les deux schemas ont un `format` différent, vérifier que\n\t\t// sub.format ⊆ sup.format. Sinon, sub ne peut pas être ⊆ sup.\n\t\t// Cela complète hasFormatConflict (qui gère le merge) en gérant\n\t\t// la direction du subset check que le merge ne peut pas résoudre.\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// Si les deux schemas ont des patterns différents, vérifier l'inclusion\n\t\t// par échantillonnage. Si sub.pattern ⊄ sup.pattern (contre-exemple trouvé),\n\t\t// on retourne false immédiatement. Sinon, on pourra retirer le pattern\n\t\t// de sup pour éviter le faux négatif structurel du 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// Retirer `not` de sup (top-level et/ou dans les properties)\n\t\t// quand evaluateNot confirme la compatibilité au niveau correspondant.\n\t\t// Cela évite que le merge engine ajoute une contrainte `not` que sub n'a pas\n\t\t// (ce qui ferait merged ≠ sub et produirait un faux négatif).\n\t\tlet effectiveSup = sup;\n\t\tif (typeof sup !== \"boolean\") {\n\t\t\t// Si top-level not est confirmé compatible → retirer le not top-level\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, true);\n\t\t\t\t// Si sup n'avait QUE `not` → sub est compatible (le not est résolu)\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// Même si le top-level not n'est pas confirmé (null), on tente\n\t\t\t\t// de retirer les `not` dans les properties individuelles\n\t\t\t\t// sans toucher au `not` top-level\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, false);\n\t\t\t}\n\n\t\t\t// Retirer les patterns de sup confirmés par échantillonnage.\n\t\t\t// Même stratégie que pour `not` : on retire la contrainte déjà\n\t\t\t// satisfaite par sub pour éviter que le merge produise un pattern\n\t\t\t// combiné (lookahead conjunction) structurellement ≠ 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 dans sup → au moins une branche doit accepter sub\n\treturn supBranches.some((branch) => {\n\t\t// Point 7 : pré-check `not` étendu par branche\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// Même logique de strip pour les 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 confirmés par échantillonnage\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 * Vérifie `sub ⊆ sup` pour un sub qui a des branches (anyOf/oneOf).\n * Chaque branche de sub doit être acceptée par sup.\n *\n * Point 6 — Utilise `getBranchesTyped` pour distinguer `anyOf[i]` de\n * `oneOf[i]` dans les paths de diff.\n *\n * Utilise `_.every` / `_.flatMap` / `_.map` pour une itération idiomatique.\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 * Vérifie `sub ⊆ sup` pour un sup qui a des branches (anyOf/oneOf).\n * Au moins une branche de sup doit accepter sub.\n *\n * Point 6 — Utilise le type de branche de sup pour des messages plus précis.\n *\n * Utilise `_.some` pour trouver la première branche compatible.\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 confirmés par échantillonnage avant le 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// Générer des erreurs sémantiques en comparant sub avec le sup original\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 * Vérifie `sub ⊆ sup` pour deux schemas atomiques (sans anyOf/oneOf).\n * Utilise `mergeOrThrow` pour capturer les erreurs d'incompatibilité.\n *\n * Utilise `deepEqual` pour la comparaison structurelle (avec short-circuit\n * par référence et comptage de clés).\n */\nexport function checkAtomic(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): SubsetResult {\n\t// Strip patterns confirmés par échantillonnage avant le merge,\n\t// même stratégie que dans isAtomicSubsetOf pour éviter les faux négatifs\n\t// structurels causés par la conjonction de patterns en 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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"}
|