json-schema-compatibility-checker 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/{condition-resolver.d.ts → cjs/condition-resolver.d.ts} +2 -2
  2. package/dist/cjs/condition-resolver.js +2 -0
  3. package/dist/cjs/condition-resolver.js.map +1 -0
  4. package/dist/cjs/format-validator.js +2 -0
  5. package/dist/cjs/format-validator.js.map +1 -0
  6. package/dist/{formatter.d.ts → cjs/formatter.d.ts} +5 -5
  7. package/dist/cjs/formatter.js +2 -0
  8. package/dist/cjs/formatter.js.map +1 -0
  9. package/dist/cjs/index.d.ts +5 -0
  10. package/dist/cjs/index.js +2 -0
  11. package/dist/cjs/index.js.map +1 -0
  12. package/dist/{json-schema-compatibility-checker.d.ts → cjs/json-schema-compatibility-checker.d.ts} +10 -10
  13. package/dist/cjs/json-schema-compatibility-checker.js +2 -0
  14. package/dist/cjs/json-schema-compatibility-checker.js.map +1 -0
  15. package/dist/cjs/merge-engine.js +2 -0
  16. package/dist/cjs/merge-engine.js.map +1 -0
  17. package/dist/cjs/normalizer.js +2 -0
  18. package/dist/cjs/normalizer.js.map +1 -0
  19. package/dist/cjs/package.json +3 -0
  20. package/dist/cjs/pattern-subset.js +2 -0
  21. package/dist/cjs/pattern-subset.js.map +1 -0
  22. package/dist/cjs/semantic-errors.d.ts +24 -0
  23. package/dist/cjs/semantic-errors.js +2 -0
  24. package/dist/cjs/semantic-errors.js.map +1 -0
  25. package/dist/{subset-checker.d.ts → cjs/subset-checker.d.ts} +3 -3
  26. package/dist/cjs/subset-checker.js +2 -0
  27. package/dist/cjs/subset-checker.js.map +1 -0
  28. package/dist/{types.d.ts → cjs/types.d.ts} +9 -11
  29. package/dist/cjs/types.js +2 -0
  30. package/dist/cjs/types.js.map +1 -0
  31. package/dist/cjs/utils.js +2 -0
  32. package/dist/cjs/utils.js.map +1 -0
  33. package/dist/esm/condition-resolver.d.ts +26 -0
  34. package/dist/esm/condition-resolver.js +2 -0
  35. package/dist/esm/condition-resolver.js.map +1 -0
  36. package/dist/esm/format-validator.d.ts +78 -0
  37. package/dist/esm/format-validator.js +2 -0
  38. package/dist/esm/format-validator.js.map +1 -0
  39. package/dist/esm/formatter.d.ts +22 -0
  40. package/dist/esm/formatter.js +2 -0
  41. package/dist/esm/formatter.js.map +1 -0
  42. package/dist/esm/index.d.ts +5 -0
  43. package/dist/esm/index.js +2 -0
  44. package/dist/esm/index.js.map +1 -0
  45. package/dist/esm/json-schema-compatibility-checker.d.ts +73 -0
  46. package/dist/esm/json-schema-compatibility-checker.js +2 -0
  47. package/dist/esm/json-schema-compatibility-checker.js.map +1 -0
  48. package/dist/esm/merge-engine.d.ts +30 -0
  49. package/dist/esm/merge-engine.js +2 -0
  50. package/dist/esm/merge-engine.js.map +1 -0
  51. package/dist/esm/normalizer.d.ts +24 -0
  52. package/dist/esm/normalizer.js +2 -0
  53. package/dist/esm/normalizer.js.map +1 -0
  54. package/dist/esm/pattern-subset.d.ts +59 -0
  55. package/dist/esm/pattern-subset.js +2 -0
  56. package/dist/esm/pattern-subset.js.map +1 -0
  57. package/dist/esm/semantic-errors.d.ts +24 -0
  58. package/dist/esm/semantic-errors.js +2 -0
  59. package/dist/esm/semantic-errors.js.map +1 -0
  60. package/dist/esm/subset-checker.d.ts +81 -0
  61. package/dist/esm/subset-checker.js +2 -0
  62. package/dist/esm/subset-checker.js.map +1 -0
  63. package/dist/esm/types.d.ts +29 -0
  64. package/dist/esm/types.js +2 -0
  65. package/dist/esm/types.js.map +1 -0
  66. package/dist/esm/utils.d.ts +43 -0
  67. package/dist/esm/utils.js +2 -0
  68. package/dist/esm/utils.js.map +1 -0
  69. package/package.json +26 -11
  70. package/dist/chunk-07z7fc5q.js +0 -5
  71. package/dist/chunk-07z7fc5q.js.map +0 -10
  72. package/dist/chunk-2ddbnbyq.js +0 -5
  73. package/dist/chunk-2ddbnbyq.js.map +0 -10
  74. package/dist/chunk-b55zsn5n.js +0 -5
  75. package/dist/chunk-b55zsn5n.js.map +0 -10
  76. package/dist/chunk-jkdzdb3r.js +0 -5
  77. package/dist/chunk-jkdzdb3r.js.map +0 -10
  78. package/dist/chunk-jybaxgmh.js +0 -5
  79. package/dist/chunk-jybaxgmh.js.map +0 -10
  80. package/dist/chunk-pyrx217p.js +0 -5
  81. package/dist/chunk-pyrx217p.js.map +0 -10
  82. package/dist/chunk-q7kq4fgq.js +0 -5
  83. package/dist/chunk-q7kq4fgq.js.map +0 -10
  84. package/dist/chunk-y8c2z1m3.js +0 -6
  85. package/dist/chunk-y8c2z1m3.js.map +0 -10
  86. package/dist/chunk-yg81ax5m.js +0 -5
  87. package/dist/chunk-yg81ax5m.js.map +0 -10
  88. package/dist/chunk-yqhv3py7.js +0 -5
  89. package/dist/chunk-yqhv3py7.js.map +0 -10
  90. package/dist/condition-resolver.js +0 -4
  91. package/dist/condition-resolver.js.map +0 -9
  92. package/dist/differ.d.ts +0 -14
  93. package/dist/differ.js +0 -4
  94. package/dist/differ.js.map +0 -9
  95. package/dist/format-validator.js +0 -4
  96. package/dist/format-validator.js.map +0 -9
  97. package/dist/formatter.js +0 -4
  98. package/dist/formatter.js.map +0 -9
  99. package/dist/index.d.ts +0 -4
  100. package/dist/index.js +0 -4
  101. package/dist/index.js.map +0 -9
  102. package/dist/json-schema-compatibility-checker.js +0 -4
  103. package/dist/json-schema-compatibility-checker.js.map +0 -9
  104. package/dist/merge-engine.js +0 -4
  105. package/dist/merge-engine.js.map +0 -9
  106. package/dist/normalizer.js +0 -4
  107. package/dist/normalizer.js.map +0 -9
  108. package/dist/pattern-subset.js +0 -4
  109. package/dist/pattern-subset.js.map +0 -9
  110. package/dist/subset-checker.js +0 -4
  111. package/dist/subset-checker.js.map +0 -9
  112. package/dist/types.js +0 -3
  113. package/dist/types.js.map +0 -9
  114. package/dist/utils.js +0 -4
  115. package/dist/utils.js.map +0 -9
  116. /package/dist/{format-validator.d.ts → cjs/format-validator.d.ts} +0 -0
  117. /package/dist/{merge-engine.d.ts → cjs/merge-engine.d.ts} +0 -0
  118. /package/dist/{normalizer.d.ts → cjs/normalizer.d.ts} +0 -0
  119. /package/dist/{pattern-subset.d.ts → cjs/pattern-subset.d.ts} +0 -0
  120. /package/dist/{utils.d.ts → cjs/utils.d.ts} +0 -0
@@ -0,0 +1,24 @@
1
+ import type { JSONSchema7Definition } from "json-schema";
2
+ import type { SchemaError } from "./types.js";
3
+ /**
4
+ * Formate un schema en représentation de type lisible.
5
+ *
6
+ * Exemples :
7
+ * - `{ type: "string" }` → `"string"`
8
+ * - `{ type: "array", items: { type: "string" } }` → `"string[]"`
9
+ * - `{ type: "array", items: { type: ["string","number"] }` → `"string[] | number[]"`
10
+ * - `{ enum: [1, 2, 3] }` → `"1, 2, or 3"`
11
+ * - `{ const: "hello" }` → `"hello"`
12
+ * - `{ anyOf: [{type:"string"},{type:"number"}] }` → `"string | number"`
13
+ * - `undefined` → `"undefined"`
14
+ */
15
+ export declare function formatSchemaType(def: JSONSchema7Definition | undefined): string;
16
+ /**
17
+ * Compare deux schemas et produit des erreurs sémantiques.
18
+ *
19
+ * @param sub Le schema source (ce qui est produit / received)
20
+ * @param sup Le schema cible (ce qui est attendu / expected)
21
+ * @param path Le chemin normalisé courant
22
+ * @returns Liste d'erreurs sémantiques
23
+ */
24
+ export declare function computeSemanticErrors(sub: JSONSchema7Definition, sup: JSONSchema7Definition, path?: string): SchemaError[];
@@ -0,0 +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 computeSemanticErrors(){return computeSemanticErrors},get formatSchemaType(){return formatSchemaType}});const _utils=require("./utils.js");function formatEnumValues(values){const parts=values.map(v=>typeof v==="string"?v:JSON.stringify(v));if(parts.length===0)return"never";if(parts.length===1)return parts[0];if(parts.length===2)return`${parts[0]} or ${parts[1]}`;const last=parts.pop();return`${parts.join(", ")}, or ${last}`}function formatSchemaType(def){if(def===undefined)return"undefined";if(typeof def==="boolean")return def?"any":"never";const schema=def;if((0,_utils.hasOwn)(schema,"const")){const v=schema.const;return typeof v==="string"?v:JSON.stringify(v)}if(Array.isArray(schema.enum)){return formatEnumValues(schema.enum)}const branches=schema.anyOf??schema.oneOf;if(Array.isArray(branches)&&branches.length>0){const parts=branches.map(b=>formatSchemaType(b));return parts.join(" | ")}if(schema.type==="array"){if(schema.items!==undefined&&typeof schema.items!=="boolean"){const itemSchema=schema.items;const itemBranches=itemSchema.anyOf??itemSchema.oneOf;if(Array.isArray(itemBranches)&&itemBranches.length>0){const parts=itemBranches.map(b=>`${formatSchemaType(b)}[]`);return parts.join(" | ")}if(Array.isArray(itemSchema.type)){const parts=itemSchema.type.map(t=>`${t}[]`);return parts.join(" | ")}const itemType=formatSchemaType(itemSchema);return`${itemType}[]`}return"array"}if(typeof schema.type==="string"){return schema.type}if(Array.isArray(schema.type)){return schema.type.join(" | ")}if((0,_utils.hasOwn)(schema,"not")&&!schema.type&&!(0,_utils.isPlainObj)(schema.properties)&&schema.items===undefined&&!Array.isArray(schema.enum)&&!(0,_utils.hasOwn)(schema,"const")){return`not ${formatSchemaType(schema.not)}`}if((0,_utils.isPlainObj)(schema.properties))return"object";if(schema.items!==undefined)return"array";return"unknown"}function joinPath(parent,key){if(!parent)return key;return`${parent}.${key}`}function arrayPath(parent){if(!parent)return"[]";return`${parent}[]`}function getProperties(schema){if((0,_utils.isPlainObj)(schema.properties)){return schema.properties}return null}function getRequired(schema){if(Array.isArray(schema.required)){return schema.required}return[]}function getEffectiveType(schema){if(schema.type!==undefined)return schema.type;if((0,_utils.hasOwn)(schema,"const")){const v=schema.const;if(v===null)return"null";if(Array.isArray(v))return"array";return typeof v}if((0,_utils.isPlainObj)(schema.properties))return"object";if(schema.items!==undefined)return"array";return undefined}function typeIncludes(schemaType,target){if(schemaType===undefined)return false;if(typeof schemaType==="string"){if(target==="number"&&schemaType==="integer")return true;if(target==="integer"&&schemaType==="number")return true;return schemaType===target}return schemaType.includes(target)}function typesAreCompatible(subType,supType){if(supType===undefined)return true;if(subType===undefined)return true;if(typeof subType==="string"&&typeof supType==="string"){if(subType===supType)return true;if(subType==="integer"&&supType==="number")return true;return false}if(typeof subType==="string"&&Array.isArray(supType)){return supType.some(t=>t===subType||subType==="integer"&&t==="number")}if(Array.isArray(subType)&&typeof supType==="string"){return subType.every(t=>t===supType||t==="integer"&&supType==="number")}if(Array.isArray(subType)&&Array.isArray(supType)){return subType.every(st=>supType.some(supt=>supt===st||st==="integer"&&supt==="number"))}return true}function fmtConstraint(name,value){if(value===undefined)return`${name}: not set`;if(typeof value==="boolean")return`${name}: ${value}`;if(typeof value==="number"||typeof value==="string")return`${name}: ${value}`;return`${name}: ${JSON.stringify(value)}`}function checkMinConstraint(subVal,supVal,name,path,errors){if(supVal!==undefined){if(subVal===undefined||subVal<supVal){errors.push({key:path||"$root",expected:fmtConstraint(name,supVal),received:fmtConstraint(name,subVal)})}}}function checkMaxConstraint(subVal,supVal,name,path,errors){if(supVal!==undefined){if(subVal===undefined||subVal>supVal){errors.push({key:path||"$root",expected:fmtConstraint(name,supVal),received:fmtConstraint(name,subVal)})}}}function checkNumericConstraints(sub,sup,path,errors){checkMinConstraint(sub.minimum,sup.minimum,"minimum",path,errors);checkMaxConstraint(sub.maximum,sup.maximum,"maximum",path,errors);checkMinConstraint(sub.exclusiveMinimum,sup.exclusiveMinimum,"exclusiveMinimum",path,errors);checkMaxConstraint(sub.exclusiveMaximum,sup.exclusiveMaximum,"exclusiveMaximum",path,errors);if(sup.multipleOf!==undefined){if(sub.multipleOf===undefined){errors.push({key:path||"$root",expected:fmtConstraint("multipleOf",sup.multipleOf),received:fmtConstraint("multipleOf",sub.multipleOf)})}else if(sub.multipleOf!==sup.multipleOf){if(sub.multipleOf%sup.multipleOf!==0){errors.push({key:path||"$root",expected:fmtConstraint("multipleOf",sup.multipleOf),received:fmtConstraint("multipleOf",sub.multipleOf)})}}}}function checkStringConstraints(sub,sup,path,errors){checkMinConstraint(sub.minLength,sup.minLength,"minLength",path,errors);checkMaxConstraint(sub.maxLength,sup.maxLength,"maxLength",path,errors);if(sup.pattern!==undefined){if(sub.pattern===undefined){errors.push({key:path||"$root",expected:fmtConstraint("pattern",sup.pattern),received:"no pattern constraint"})}else if(sub.pattern!==sup.pattern){errors.push({key:path||"$root",expected:fmtConstraint("pattern",sup.pattern),received:fmtConstraint("pattern",sub.pattern)})}}if(sup.format!==undefined&&sub.format!==sup.format){if(sub.format===undefined){errors.push({key:path||"$root",expected:fmtConstraint("format",sup.format),received:"no format constraint"})}else{errors.push({key:path||"$root",expected:fmtConstraint("format",sup.format),received:fmtConstraint("format",sub.format)})}}}function checkObjectConstraints(sub,sup,path,errors){if(sup.additionalProperties!==undefined){if(sup.additionalProperties===false){if(sub.additionalProperties===undefined||sub.additionalProperties===true){errors.push({key:path||"$root",expected:"additionalProperties: false",received:"additional properties allowed"})}else if(typeof sub.additionalProperties==="object"&&sub.additionalProperties!==null){errors.push({key:path||"$root",expected:"additionalProperties: false",received:"additionalProperties: schema"})}}else if(typeof sup.additionalProperties==="object"&&sup.additionalProperties!==null){if(sub.additionalProperties===undefined||sub.additionalProperties===true){errors.push({key:path||"$root",expected:`additionalProperties: ${formatSchemaType(sup.additionalProperties)}`,received:"additional properties allowed"})}else if(typeof sub.additionalProperties==="object"&&sub.additionalProperties!==null){const apPath=path?`${path}.<additionalProperties>`:"<additionalProperties>";const apErrors=computeSemanticErrors(sub.additionalProperties,sup.additionalProperties,apPath);errors.push(...apErrors)}}}checkMinConstraint(sub.minProperties,sup.minProperties,"minProperties",path,errors);checkMaxConstraint(sub.maxProperties,sup.maxProperties,"maxProperties",path,errors);if(sup.propertyNames!==undefined){if(sub.propertyNames===undefined){errors.push({key:path||"$root",expected:`propertyNames: ${formatSchemaType(sup.propertyNames)}`,received:"no propertyNames constraint"})}else{const pnErrors=computeSemanticErrors(sub.propertyNames,sup.propertyNames,path?`${path}.<propertyNames>`:"<propertyNames>");errors.push(...pnErrors)}}if((0,_utils.isPlainObj)(sup.dependencies)){const supDeps=sup.dependencies;const subDeps=(0,_utils.isPlainObj)(sub.dependencies)?sub.dependencies:null;for(const key of Object.keys(supDeps)){const supDep=supDeps[key];const subDep=subDeps?.[key];if(subDep===undefined){if(Array.isArray(supDep)){errors.push({key:path||"$root",expected:`dependency: ${key} requires ${supDep.join(", ")}`,received:`no dependency for ${key}`})}else{errors.push({key:path||"$root",expected:`dependency: ${key} requires schema`,received:`no dependency for ${key}`})}}else if(Array.isArray(supDep)&&Array.isArray(subDep)){const missing=supDep.filter(d=>!subDep.includes(d));if(missing.length>0){errors.push({key:path||"$root",expected:`dependency: ${key} requires ${supDep.join(", ")}`,received:`dependency: ${key} requires ${subDep.join(", ")}`})}}else if(!Array.isArray(supDep)&&!Array.isArray(subDep)){const depPath=path?`${path}.<dependency:${key}>`:`<dependency:${key}>`;const depErrors=computeSemanticErrors(subDep,supDep,depPath);errors.push(...depErrors)}else{errors.push({key:path||"$root",expected:Array.isArray(supDep)?`dependency: ${key} requires ${supDep.join(", ")}`:`dependency: ${key} requires schema`,received:Array.isArray(subDep)?`dependency: ${key} requires ${subDep.join(", ")}`:`dependency: ${key} requires schema`})}}}if((0,_utils.isPlainObj)(sup.patternProperties)){const supPP=sup.patternProperties;const subPP=(0,_utils.isPlainObj)(sub.patternProperties)?sub.patternProperties:null;for(const pattern of Object.keys(supPP)){const supPropDef=supPP[pattern];if(supPropDef===undefined)continue;const subPropDef=subPP?.[pattern];const ppPath=path?`${path}.<patternProperties:${pattern}>`:`<patternProperties:${pattern}>`;if(subPropDef===undefined){errors.push({key:ppPath,expected:formatSchemaType(supPropDef),received:"no constraint for this pattern"})}else{const ppErrors=computeSemanticErrors(subPropDef,supPropDef,ppPath);errors.push(...ppErrors)}}}}function checkArrayConstraints(sub,sup,path,errors){checkMinConstraint(sub.minItems,sup.minItems,"minItems",path,errors);checkMaxConstraint(sub.maxItems,sup.maxItems,"maxItems",path,errors);if(sup.uniqueItems===true&&sub.uniqueItems!==true){errors.push({key:path||"$root",expected:"uniqueItems: true",received:fmtConstraint("uniqueItems",sub.uniqueItems??false)})}if(sup.contains!==undefined){if(sub.contains===undefined){errors.push({key:path||"$root",expected:`contains: ${formatSchemaType(sup.contains)}`,received:"no contains constraint"})}else{const containsPath=path?`${path}.<contains>`:"<contains>";const containsErrors=computeSemanticErrors(sub.contains,sup.contains,containsPath);errors.push(...containsErrors)}}}function isNumericType(t){if(t===undefined)return false;if(typeof t==="string")return t==="number"||t==="integer";return t.some(v=>v==="number"||v==="integer")}function isStringType(t){if(t===undefined)return false;if(typeof t==="string")return t==="string";return t.includes("string")}function isObjectType(t){if(t===undefined)return false;if(typeof t==="string")return t==="object";return t.includes("object")}function isArrayType(t){if(t===undefined)return false;if(typeof t==="string")return t==="array";return t.includes("array")}function hasNumericKeywords(s){return s.minimum!==undefined||s.maximum!==undefined||s.exclusiveMinimum!==undefined||s.exclusiveMaximum!==undefined||s.multipleOf!==undefined}function hasStringKeywords(s){return s.minLength!==undefined||s.maxLength!==undefined||s.pattern!==undefined||s.format!==undefined}function hasObjectKeywords(s){return s.minProperties!==undefined||s.maxProperties!==undefined||s.propertyNames!==undefined||s.additionalProperties!==undefined||(0,_utils.isPlainObj)(s.patternProperties)||(0,_utils.isPlainObj)(s.dependencies)}function hasArrayKeywords(s){return s.minItems!==undefined||s.maxItems!==undefined||s.uniqueItems!==undefined||s.contains!==undefined}function computeSemanticErrors(sub,sup,path=""){if(typeof sup==="boolean"){if(sup===false){return[{key:path||"$root",expected:"never",received:formatSchemaType(sub)}]}return[]}if(typeof sub==="boolean"){if(sub===true){return[{key:path||"$root",expected:formatSchemaType(sup),received:"any"}]}return[]}const subSchema=sub;const supSchema=sup;const errors=[];if((0,_utils.hasOwn)(supSchema,"not")&&(0,_utils.isPlainObj)(supSchema.not)&&typeof supSchema.not!=="boolean"){const notSchema=supSchema.not;const notFormatted=formatSchemaType(notSchema);if(!(0,_utils.hasOwn)(subSchema,"not")){errors.push({key:path||"$root",expected:`not ${notFormatted}`,received:formatSchemaType(subSchema)})}else if((0,_utils.isPlainObj)(subSchema.not)&&typeof subSchema.not!=="boolean"){const subNotSchema=subSchema.not;if(!deepEqualPrimitive(subNotSchema,notSchema)){errors.push({key:path||"$root",expected:`not ${notFormatted}`,received:`not ${formatSchemaType(subNotSchema)}`})}}}const subType=getEffectiveType(subSchema);const supType=getEffectiveType(supSchema);const supBranches=supSchema.anyOf??supSchema.oneOf;if(Array.isArray(supBranches)&&supBranches.length>0&&!supSchema.type){return computeErrorsAgainstBranches(subSchema,supBranches,path)}const subBranches=subSchema.anyOf??subSchema.oneOf;if(Array.isArray(subBranches)&&subBranches.length>0&&!subSchema.type){const branchErrors=[];for(const branch of subBranches){const errs=computeSemanticErrors(branch,sup,path);branchErrors.push(...errs)}return branchErrors}const supProps=getProperties(supSchema);const subProps=getProperties(subSchema);if(supProps!==null||isObjectType(supType)){if(subType!==undefined&&!typeIncludes(subType,"object")){errors.push({key:path||"$root",expected:formatSchemaType(supSchema),received:formatSchemaType(subSchema)});return errors}if(supProps!==null){const supRequired=getRequired(supSchema);const subRequired=getRequired(subSchema);for(const key of Object.keys(supProps)){const propPath=joinPath(path,key);const supPropDef=supProps[key];const subPropDef=subProps?.[key];if(supPropDef===undefined)continue;const isRequiredInSup=supRequired.includes(key);if(subPropDef===undefined){if(isRequiredInSup){errors.push({key:propPath,expected:formatSchemaType(supPropDef),received:"undefined"})}continue}if(isRequiredInSup&&!subRequired.includes(key)){errors.push({key:propPath,expected:"not optional",received:"optional"});continue}const propErrors=comparePropertySchemas(subPropDef,supPropDef,propPath);errors.push(...propErrors)}}checkObjectConstraints(subSchema,supSchema,path,errors);return errors}if((supType==="array"||supSchema.items!==undefined)&&(subType==="array"||subSchema.items!==undefined)){if(supSchema.items!==undefined&&typeof supSchema.items!=="boolean"){if(subSchema.items!==undefined&&typeof subSchema.items!=="boolean"){if(Array.isArray(supSchema.items)&&Array.isArray(subSchema.items)){const maxLen=Math.max(supSchema.items.length,subSchema.items.length);for(let i=0;i<maxLen;i++){const supItem=supSchema.items[i];const subItem=subSchema.items[i];const itemPath=joinPath(path,`[${i}]`);if(supItem!==undefined&&subItem===undefined){errors.push({key:itemPath,expected:formatSchemaType(supItem),received:"undefined"})}else if(supItem!==undefined&&subItem!==undefined){errors.push(...computeSemanticErrors(subItem,supItem,itemPath))}}}else if(!Array.isArray(supSchema.items)&&!Array.isArray(subSchema.items)){const itemPath=arrayPath(path);const itemErrors=computeSemanticErrors(subSchema.items,supSchema.items,itemPath);errors.push(...itemErrors)}}else{errors.push({key:path||"$root",expected:formatSchemaType(supSchema),received:formatSchemaType(subSchema)})}}checkArrayConstraints(subSchema,supSchema,path,errors);return errors}if(subType!==undefined&&supType!==undefined){if(!typesAreCompatible(subType,supType)){errors.push({key:path||"$root",expected:formatSchemaType(supSchema),received:formatSchemaType(subSchema)});return errors}}if(Array.isArray(supSchema.enum)){if(Array.isArray(subSchema.enum)){const subExtra=subSchema.enum.filter(v=>!supSchema.enum?.some(sv=>deepEqualPrimitive(v,sv)));if(subExtra.length>0){errors.push({key:path||"$root",expected:formatEnumValues(supSchema.enum),received:formatEnumValues(subSchema.enum)})}}else if((0,_utils.hasOwn)(subSchema,"const")){const constInEnum=supSchema.enum.some(v=>deepEqualPrimitive(v,subSchema.const));if(!constInEnum){errors.push({key:path||"$root",expected:formatEnumValues(supSchema.enum),received:formatSchemaType(subSchema)})}}else{errors.push({key:path||"$root",expected:formatEnumValues(supSchema.enum),received:formatSchemaType(subSchema)})}return errors}if((0,_utils.hasOwn)(supSchema,"const")&&(0,_utils.hasOwn)(subSchema,"const")){if(!deepEqualPrimitive(supSchema.const,subSchema.const)){errors.push({key:path||"$root",expected:formatSchemaType(supSchema),received:formatSchemaType(subSchema)})}return errors}if(isNumericType(subType)||isNumericType(supType)||hasNumericKeywords(supSchema)||hasNumericKeywords(subSchema)){checkNumericConstraints(subSchema,supSchema,path,errors)}if(isStringType(subType)||isStringType(supType)||hasStringKeywords(supSchema)||hasStringKeywords(subSchema)){checkStringConstraints(subSchema,supSchema,path,errors)}if(isObjectType(subType)||isObjectType(supType)||hasObjectKeywords(supSchema)||hasObjectKeywords(subSchema)){checkObjectConstraints(subSchema,supSchema,path,errors)}if(isArrayType(subType)||isArrayType(supType)||hasArrayKeywords(supSchema)||hasArrayKeywords(subSchema)){checkArrayConstraints(subSchema,supSchema,path,errors)}if(errors.length>0){return errors}const expectedStr=formatSchemaType(supSchema);const receivedStr=formatSchemaType(subSchema);if(expectedStr!==receivedStr){errors.push({key:path||"$root",expected:expectedStr,received:receivedStr})}return errors}function comparePropertySchemas(subDef,supDef,path){if(typeof subDef==="boolean"||typeof supDef==="boolean"){if(subDef!==supDef){return[{key:path,expected:formatSchemaType(supDef),received:formatSchemaType(subDef)}]}return[]}const subSchema=subDef;const supSchema=supDef;const subType=getEffectiveType(subSchema);const supType=getEffectiveType(supSchema);if(Array.isArray(supSchema.enum)){if(Array.isArray(subSchema.enum)){const subExtra=subSchema.enum.filter(v=>!supSchema.enum?.some(sv=>deepEqualPrimitive(v,sv)));if(subExtra.length>0){return[{key:path,expected:formatEnumValues(supSchema.enum),received:formatEnumValues(subSchema.enum)}]}return[]}if((0,_utils.hasOwn)(subSchema,"const")){const constInEnum=supSchema.enum.some(v=>deepEqualPrimitive(v,subSchema.const));if(!constInEnum){return[{key:path,expected:formatEnumValues(supSchema.enum),received:formatSchemaType(subSchema)}]}return[]}return[{key:path,expected:formatEnumValues(supSchema.enum),received:formatSchemaType(subSchema)}]}if((0,_utils.hasOwn)(supSchema,"const")&&(0,_utils.hasOwn)(subSchema,"const")){if(!deepEqualPrimitive(supSchema.const,subSchema.const)){return[{key:path,expected:formatSchemaType(supSchema),received:formatSchemaType(subSchema)}]}return[]}if(subType!==undefined&&supType!==undefined){if(!typesAreCompatible(subType,supType)){return[{key:path,expected:formatSchemaType(supSchema),received:formatSchemaType(subSchema)}]}}return computeSemanticErrors(subDef,supDef,path)}function computeErrorsAgainstBranches(sub,branches,path){let bestErrors=null;for(const branch of branches){const errors=computeSemanticErrors(sub,branch,path);if(errors.length===0)return[];if(bestErrors===null||errors.length<bestErrors.length){bestErrors=errors}}return bestErrors??[{key:path||"$root",expected:formatSchemaType({anyOf:branches}),received:formatSchemaType(sub)}]}function deepEqualPrimitive(a,b){if(a===b)return true;if(a===null||b===null)return false;if(typeof a!==typeof b)return false;if(typeof a==="object"){if(Array.isArray(a)){if(!Array.isArray(b))return false;if(a.length!==b.length)return false;for(let i=0;i<a.length;i++){if(!deepEqualPrimitive(a[i],b[i]))return false}return true}if(Array.isArray(b))return false;const aObj=a;const bObj=b;const aKeys=Object.keys(aObj);if(aKeys.length!==Object.keys(bObj).length)return false;for(const key of aKeys){if(!deepEqualPrimitive(aObj[key],bObj[key]))return false}return true}return false}
2
+ //# sourceMappingURL=semantic-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/semantic-errors.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport type { SchemaError } from \"./types\";\nimport { hasOwn, isPlainObj } from \"./utils\";\n\n// ─── Semantic Error Generator ────────────────────────────────────────────────\n//\n// Génère des erreurs sémantiques lisibles en comparant directement deux schemas.\n//\n// Contrairement au differ structurel (qui comparait sub vs merged), ce module\n// compare directement sub (source/received) et sup (target/expected) pour\n// produire des messages d'erreur orientés métier.\n//\n// Les chemins de propriétés sont normalisés :\n// - `accountId` (propriété top-level)\n// - `user.name` (propriété imbriquée)\n// - `users[].name` (propriété dans les items d'un tableau)\n//\n// Convention :\n// - `expected` = ce que le schema cible (sup) attend\n// - `received` = ce que le schema source (sub) fournit\n\n// ─── Type Formatting ─────────────────────────────────────────────────────────\n\n/**\n * Formate les valeurs d'un enum en chaîne lisible.\n *\n * Exemples :\n * - 1 valeur : `\"123\"`\n * - 2 valeurs : `\"123 or salut\"`\n * - 3 valeurs : `\"10, 20, or 30\"`\n */\nfunction formatEnumValues(values: unknown[]): string {\n\tconst parts = values.map((v) =>\n\t\ttypeof v === \"string\" ? v : JSON.stringify(v),\n\t);\n\tif (parts.length === 0) return \"never\";\n\tif (parts.length === 1) return parts[0] as string;\n\tif (parts.length === 2) return `${parts[0]} or ${parts[1]}`;\n\tconst last = parts.pop();\n\treturn `${parts.join(\", \")}, or ${last}`;\n}\n\n/**\n * Formate un schema en représentation de type lisible.\n *\n * Exemples :\n * - `{ type: \"string\" }` → `\"string\"`\n * - `{ type: \"array\", items: { type: \"string\" } }` → `\"string[]\"`\n * - `{ type: \"array\", items: { type: [\"string\",\"number\"] }` → `\"string[] | number[]\"`\n * - `{ enum: [1, 2, 3] }` → `\"1, 2, or 3\"`\n * - `{ const: \"hello\" }` → `\"hello\"`\n * - `{ anyOf: [{type:\"string\"},{type:\"number\"}] }` → `\"string | number\"`\n * - `undefined` → `\"undefined\"`\n */\nexport function formatSchemaType(\n\tdef: JSONSchema7Definition | undefined,\n): string {\n\tif (def === undefined) return \"undefined\";\n\tif (typeof def === \"boolean\") return def ? \"any\" : \"never\";\n\n\tconst schema = def as JSONSchema7;\n\n\t// ── Const ──\n\tif (hasOwn(schema, \"const\")) {\n\t\tconst v = schema.const;\n\t\treturn typeof v === \"string\" ? v : JSON.stringify(v);\n\t}\n\n\t// ── Enum ──\n\tif (Array.isArray(schema.enum)) {\n\t\treturn formatEnumValues(schema.enum);\n\t}\n\n\t// ── anyOf / oneOf (union types) ──\n\tconst branches = schema.anyOf ?? schema.oneOf;\n\tif (Array.isArray(branches) && branches.length > 0) {\n\t\tconst parts = branches.map((b) => formatSchemaType(b));\n\t\treturn parts.join(\" | \");\n\t}\n\n\t// ── Array type ──\n\tif (schema.type === \"array\") {\n\t\tif (schema.items !== undefined && typeof schema.items !== \"boolean\") {\n\t\t\tconst itemSchema = schema.items as JSONSchema7;\n\n\t\t\t// Items with anyOf/oneOf → \"string[] | number[]\"\n\t\t\tconst itemBranches = itemSchema.anyOf ?? itemSchema.oneOf;\n\t\t\tif (Array.isArray(itemBranches) && itemBranches.length > 0) {\n\t\t\t\tconst parts = itemBranches.map((b) => `${formatSchemaType(b)}[]`);\n\t\t\t\treturn parts.join(\" | \");\n\t\t\t}\n\n\t\t\t// Items with multiple types → \"string[] | number[]\"\n\t\t\tif (Array.isArray(itemSchema.type)) {\n\t\t\t\tconst parts = itemSchema.type.map((t) => `${t}[]`);\n\t\t\t\treturn parts.join(\" | \");\n\t\t\t}\n\n\t\t\tconst itemType = formatSchemaType(itemSchema);\n\t\t\treturn `${itemType}[]`;\n\t\t}\n\t\t// items is boolean true or missing\n\t\treturn \"array\";\n\t}\n\n\t// ── Simple type ──\n\tif (typeof schema.type === \"string\") {\n\t\treturn schema.type;\n\t}\n\n\t// ── Multiple types (type: [\"string\", \"number\"]) ──\n\tif (Array.isArray(schema.type)) {\n\t\treturn schema.type.join(\" | \");\n\t}\n\n\t// ── not (pure-not schema, no other significant keywords) ──\n\tif (\n\t\thasOwn(schema, \"not\") &&\n\t\t!schema.type &&\n\t\t!isPlainObj(schema.properties) &&\n\t\tschema.items === undefined &&\n\t\t!Array.isArray(schema.enum) &&\n\t\t!hasOwn(schema, \"const\")\n\t) {\n\t\treturn `not ${formatSchemaType(schema.not as JSONSchema7Definition)}`;\n\t}\n\n\t// ── Fallback ──\n\t// Schema without explicit type — try to infer from structure\n\tif (isPlainObj(schema.properties)) return \"object\";\n\tif (schema.items !== undefined) return \"array\";\n\n\treturn \"unknown\";\n}\n\n// ─── Path Helpers ────────────────────────────────────────────────────────────\n\n/**\n * Construit un chemin de propriété normalisé.\n * - Racine + clé → `\"accountId\"`\n * - Parent + clé → `\"user.name\"`\n * - Parent[] + clé → `\"users[].name\"`\n */\nfunction joinPath(parent: string, key: string): string {\n\tif (!parent) return key;\n\treturn `${parent}.${key}`;\n}\n\n/**\n * Ajoute le suffixe `[]` pour indiquer qu'on entre dans les items d'un array.\n */\nfunction arrayPath(parent: string): string {\n\tif (!parent) return \"[]\";\n\treturn `${parent}[]`;\n}\n\n// ─── Schema Accessors ────────────────────────────────────────────────────────\n\n/**\n * Extrait les propriétés d'un schema de manière sûre.\n */\nfunction getProperties(\n\tschema: JSONSchema7,\n): Record<string, JSONSchema7Definition> | null {\n\tif (isPlainObj(schema.properties)) {\n\t\treturn schema.properties as Record<string, JSONSchema7Definition>;\n\t}\n\treturn null;\n}\n\n/**\n * Extrait les champs required d'un schema de manière sûre.\n */\nfunction getRequired(schema: JSONSchema7): string[] {\n\tif (Array.isArray(schema.required)) {\n\t\treturn schema.required as string[];\n\t}\n\treturn [];\n}\n\n/**\n * Détermine le type effectif d'un schema (string ou tableau de types).\n */\nfunction getEffectiveType(schema: JSONSchema7): string | string[] | undefined {\n\tif (schema.type !== undefined) return schema.type as string | string[];\n\n\t// Infer from const\n\tif (hasOwn(schema, \"const\")) {\n\t\tconst v = schema.const;\n\t\tif (v === null) return \"null\";\n\t\tif (Array.isArray(v)) return \"array\";\n\t\treturn typeof v;\n\t}\n\n\t// Infer from properties\n\tif (isPlainObj(schema.properties)) return \"object\";\n\n\t// Infer from items\n\tif (schema.items !== undefined) return \"array\";\n\n\treturn undefined;\n}\n\n/**\n * Vérifie si un type (string) est inclus dans un type ou un tableau de types.\n */\nfunction typeIncludes(\n\tschemaType: string | string[] | undefined,\n\ttarget: string,\n): boolean {\n\tif (schemaType === undefined) return false;\n\tif (typeof schemaType === \"string\") {\n\t\t// integer is a subset of number\n\t\tif (target === \"number\" && schemaType === \"integer\") return true;\n\t\tif (target === \"integer\" && schemaType === \"number\") return true;\n\t\treturn schemaType === target;\n\t}\n\treturn schemaType.includes(target);\n}\n\n/**\n * Vérifie si deux types sont compatibles.\n * Un type est compatible si le type de sub est inclus dans le type de sup.\n */\nfunction typesAreCompatible(\n\tsubType: string | string[] | undefined,\n\tsupType: string | string[] | undefined,\n): boolean {\n\tif (supType === undefined) return true; // sup accepte tout\n\tif (subType === undefined) return true; // sub indéterminé, on ne peut pas conclure\n\n\tif (typeof subType === \"string\" && typeof supType === \"string\") {\n\t\tif (subType === supType) return true;\n\t\t// integer ⊆ number\n\t\tif (subType === \"integer\" && supType === \"number\") return true;\n\t\treturn false;\n\t}\n\n\tif (typeof subType === \"string\" && Array.isArray(supType)) {\n\t\treturn supType.some(\n\t\t\t(t) => t === subType || (subType === \"integer\" && t === \"number\"),\n\t\t);\n\t}\n\n\tif (Array.isArray(subType) && typeof supType === \"string\") {\n\t\treturn subType.every(\n\t\t\t(t) => t === supType || (t === \"integer\" && supType === \"number\"),\n\t\t);\n\t}\n\n\tif (Array.isArray(subType) && Array.isArray(supType)) {\n\t\treturn subType.every((st) =>\n\t\t\tsupType.some(\n\t\t\t\t(supt) => supt === st || (st === \"integer\" && supt === \"number\"),\n\t\t\t),\n\t\t);\n\t}\n\n\treturn true;\n}\n\n// ─── Constraint Helpers ──────────────────────────────────────────────────────\n\n/**\n * Formate une valeur de contrainte en string lisible.\n */\nfunction fmtConstraint(name: string, value: unknown): string {\n\tif (value === undefined) return `${name}: not set`;\n\tif (typeof value === \"boolean\") return `${name}: ${value}`;\n\tif (typeof value === \"number\" || typeof value === \"string\")\n\t\treturn `${name}: ${value}`;\n\treturn `${name}: ${JSON.stringify(value)}`;\n}\n\n/**\n * Compare une contrainte numérique \"minimum-like\" (sub.X doit être >= sup.X pour sub ⊆ sup).\n * Exemples : minimum, exclusiveMinimum, minLength, minItems, minProperties\n */\nfunction checkMinConstraint(\n\tsubVal: number | undefined,\n\tsupVal: number | undefined,\n\tname: string,\n\tpath: string,\n\terrors: SchemaError[],\n): void {\n\tif (supVal !== undefined) {\n\t\tif (subVal === undefined || subVal < supVal) {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: fmtConstraint(name, supVal),\n\t\t\t\treceived: fmtConstraint(name, subVal),\n\t\t\t});\n\t\t}\n\t}\n}\n\n/**\n * Compare une contrainte numérique \"maximum-like\" (sub.X doit être <= sup.X pour sub ⊆ sup).\n * Exemples : maximum, exclusiveMaximum, maxLength, maxItems, maxProperties\n */\nfunction checkMaxConstraint(\n\tsubVal: number | undefined,\n\tsupVal: number | undefined,\n\tname: string,\n\tpath: string,\n\terrors: SchemaError[],\n): void {\n\tif (supVal !== undefined) {\n\t\tif (subVal === undefined || subVal > supVal) {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: fmtConstraint(name, supVal),\n\t\t\t\treceived: fmtConstraint(name, subVal),\n\t\t\t});\n\t\t}\n\t}\n}\n\n/**\n * Compare les contraintes numériques entre sub et sup.\n */\nfunction checkNumericConstraints(\n\tsub: JSONSchema7,\n\tsup: JSONSchema7,\n\tpath: string,\n\terrors: SchemaError[],\n): void {\n\tcheckMinConstraint(sub.minimum, sup.minimum, \"minimum\", path, errors);\n\tcheckMaxConstraint(sub.maximum, sup.maximum, \"maximum\", path, errors);\n\tcheckMinConstraint(\n\t\tsub.exclusiveMinimum as number | undefined,\n\t\tsup.exclusiveMinimum as number | undefined,\n\t\t\"exclusiveMinimum\",\n\t\tpath,\n\t\terrors,\n\t);\n\tcheckMaxConstraint(\n\t\tsub.exclusiveMaximum as number | undefined,\n\t\tsup.exclusiveMaximum as number | undefined,\n\t\t\"exclusiveMaximum\",\n\t\tpath,\n\t\terrors,\n\t);\n\n\tif (sup.multipleOf !== undefined) {\n\t\tif (sub.multipleOf === undefined) {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: fmtConstraint(\"multipleOf\", sup.multipleOf),\n\t\t\t\treceived: fmtConstraint(\"multipleOf\", sub.multipleOf),\n\t\t\t});\n\t\t} else if (sub.multipleOf !== sup.multipleOf) {\n\t\t\t// sub.multipleOf must be a multiple of sup.multipleOf for sub ⊆ sup\n\t\t\tif (sub.multipleOf % sup.multipleOf !== 0) {\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: fmtConstraint(\"multipleOf\", sup.multipleOf),\n\t\t\t\t\treceived: fmtConstraint(\"multipleOf\", sub.multipleOf),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Compare les contraintes de string entre sub et sup.\n */\nfunction checkStringConstraints(\n\tsub: JSONSchema7,\n\tsup: JSONSchema7,\n\tpath: string,\n\terrors: SchemaError[],\n): void {\n\tcheckMinConstraint(sub.minLength, sup.minLength, \"minLength\", path, errors);\n\tcheckMaxConstraint(sub.maxLength, sup.maxLength, \"maxLength\", path, errors);\n\n\t// ── Pattern ──\n\tif (sup.pattern !== undefined) {\n\t\tif (sub.pattern === undefined) {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: fmtConstraint(\"pattern\", sup.pattern),\n\t\t\t\treceived: \"no pattern constraint\",\n\t\t\t});\n\t\t} else if (sub.pattern !== sup.pattern) {\n\t\t\t// Different patterns — we can't statically determine subset relationship\n\t\t\t// without sampling, so report it as a potential mismatch.\n\t\t\t// The subset checker may have already stripped equivalent patterns,\n\t\t\t// so if we get here, they're genuinely different.\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: fmtConstraint(\"pattern\", sup.pattern),\n\t\t\t\treceived: fmtConstraint(\"pattern\", sub.pattern),\n\t\t\t});\n\t\t}\n\t}\n\n\t// ── Format ──\n\tif (sup.format !== undefined && sub.format !== sup.format) {\n\t\tif (sub.format === undefined) {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: fmtConstraint(\"format\", sup.format),\n\t\t\t\treceived: \"no format constraint\",\n\t\t\t});\n\t\t} else {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: fmtConstraint(\"format\", sup.format),\n\t\t\t\treceived: fmtConstraint(\"format\", sub.format),\n\t\t\t});\n\t\t}\n\t}\n}\n\n/**\n * Compare les contraintes d'objet (hors properties/required) entre sub et sup.\n */\nfunction checkObjectConstraints(\n\tsub: JSONSchema7,\n\tsup: JSONSchema7,\n\tpath: string,\n\terrors: SchemaError[],\n): void {\n\t// ── additionalProperties ──\n\tif (sup.additionalProperties !== undefined) {\n\t\tif (sup.additionalProperties === false) {\n\t\t\t// sup interdit les propriétés additionnelles\n\t\t\tif (\n\t\t\t\tsub.additionalProperties === undefined ||\n\t\t\t\tsub.additionalProperties === true\n\t\t\t) {\n\t\t\t\t// sub les autorise → incompatible\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: \"additionalProperties: false\",\n\t\t\t\t\treceived: \"additional properties allowed\",\n\t\t\t\t});\n\t\t\t} else if (\n\t\t\t\ttypeof sub.additionalProperties === \"object\" &&\n\t\t\t\tsub.additionalProperties !== null\n\t\t\t) {\n\t\t\t\t// sub has a schema for additional properties → still allows them\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: \"additionalProperties: false\",\n\t\t\t\t\treceived: \"additionalProperties: schema\",\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (\n\t\t\ttypeof sup.additionalProperties === \"object\" &&\n\t\t\tsup.additionalProperties !== null\n\t\t) {\n\t\t\t// sup has a schema for additionalProperties\n\t\t\tif (\n\t\t\t\tsub.additionalProperties === undefined ||\n\t\t\t\tsub.additionalProperties === true\n\t\t\t) {\n\t\t\t\t// sub allows anything → more permissive\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: `additionalProperties: ${formatSchemaType(sup.additionalProperties as JSONSchema7Definition)}`,\n\t\t\t\t\treceived: \"additional properties allowed\",\n\t\t\t\t});\n\t\t\t} else if (\n\t\t\t\ttypeof sub.additionalProperties === \"object\" &&\n\t\t\t\tsub.additionalProperties !== null\n\t\t\t) {\n\t\t\t\t// Both have schema-form additionalProperties — recurse\n\t\t\t\tconst apPath = path\n\t\t\t\t\t? `${path}.<additionalProperties>`\n\t\t\t\t\t: \"<additionalProperties>\";\n\t\t\t\tconst apErrors = computeSemanticErrors(\n\t\t\t\t\tsub.additionalProperties as JSONSchema7Definition,\n\t\t\t\t\tsup.additionalProperties as JSONSchema7Definition,\n\t\t\t\t\tapPath,\n\t\t\t\t);\n\t\t\t\terrors.push(...apErrors);\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── minProperties / maxProperties ──\n\tcheckMinConstraint(\n\t\tsub.minProperties,\n\t\tsup.minProperties,\n\t\t\"minProperties\",\n\t\tpath,\n\t\terrors,\n\t);\n\tcheckMaxConstraint(\n\t\tsub.maxProperties,\n\t\tsup.maxProperties,\n\t\t\"maxProperties\",\n\t\tpath,\n\t\terrors,\n\t);\n\n\t// ── propertyNames ──\n\tif (sup.propertyNames !== undefined) {\n\t\tif (sub.propertyNames === undefined) {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: `propertyNames: ${formatSchemaType(sup.propertyNames)}`,\n\t\t\t\treceived: \"no propertyNames constraint\",\n\t\t\t});\n\t\t} else {\n\t\t\t// Both have propertyNames — recurse\n\t\t\tconst pnErrors = computeSemanticErrors(\n\t\t\t\tsub.propertyNames as JSONSchema7Definition,\n\t\t\t\tsup.propertyNames as JSONSchema7Definition,\n\t\t\t\tpath ? `${path}.<propertyNames>` : \"<propertyNames>\",\n\t\t\t);\n\t\t\terrors.push(...pnErrors);\n\t\t}\n\t}\n\n\t// ── dependencies ──\n\tif (isPlainObj(sup.dependencies)) {\n\t\tconst supDeps = sup.dependencies as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition | string[]\n\t\t>;\n\t\tconst subDeps = isPlainObj(sub.dependencies)\n\t\t\t? (sub.dependencies as Record<string, JSONSchema7Definition | string[]>)\n\t\t\t: null;\n\n\t\tfor (const key of Object.keys(supDeps)) {\n\t\t\tconst supDep = supDeps[key];\n\t\t\tconst subDep = subDeps?.[key];\n\n\t\t\tif (subDep === undefined) {\n\t\t\t\t// sup requires a dependency that sub doesn't have\n\t\t\t\tif (Array.isArray(supDep)) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\t\texpected: `dependency: ${key} requires ${supDep.join(\", \")}`,\n\t\t\t\t\t\treceived: `no dependency for ${key}`,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\t\texpected: `dependency: ${key} requires schema`,\n\t\t\t\t\t\treceived: `no dependency for ${key}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (Array.isArray(supDep) && Array.isArray(subDep)) {\n\t\t\t\t// Both are array form — check if sub includes all required props from sup\n\t\t\t\tconst missing = supDep.filter((d) => !subDep.includes(d));\n\t\t\t\tif (missing.length > 0) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\t\texpected: `dependency: ${key} requires ${supDep.join(\", \")}`,\n\t\t\t\t\t\treceived: `dependency: ${key} requires ${subDep.join(\", \")}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (!Array.isArray(supDep) && !Array.isArray(subDep)) {\n\t\t\t\t// Both are schema form — recurse\n\t\t\t\tconst depPath = path\n\t\t\t\t\t? `${path}.<dependency:${key}>`\n\t\t\t\t\t: `<dependency:${key}>`;\n\t\t\t\tconst depErrors = computeSemanticErrors(\n\t\t\t\t\tsubDep as JSONSchema7Definition,\n\t\t\t\t\tsupDep as JSONSchema7Definition,\n\t\t\t\t\tdepPath,\n\t\t\t\t);\n\t\t\t\terrors.push(...depErrors);\n\t\t\t} else {\n\t\t\t\t// Mixed forms (one array, one schema) — report mismatch\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: Array.isArray(supDep)\n\t\t\t\t\t\t? `dependency: ${key} requires ${supDep.join(\", \")}`\n\t\t\t\t\t\t: `dependency: ${key} requires schema`,\n\t\t\t\t\treceived: Array.isArray(subDep)\n\t\t\t\t\t\t? `dependency: ${key} requires ${subDep.join(\", \")}`\n\t\t\t\t\t\t: `dependency: ${key} requires schema`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── patternProperties ──\n\tif (isPlainObj(sup.patternProperties)) {\n\t\tconst supPP = sup.patternProperties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst subPP = isPlainObj(sub.patternProperties)\n\t\t\t? (sub.patternProperties as Record<string, JSONSchema7Definition>)\n\t\t\t: null;\n\n\t\tfor (const pattern of Object.keys(supPP)) {\n\t\t\tconst supPropDef = supPP[pattern];\n\t\t\tif (supPropDef === undefined) continue;\n\n\t\t\tconst subPropDef = subPP?.[pattern];\n\t\t\tconst ppPath = path\n\t\t\t\t? `${path}.<patternProperties:${pattern}>`\n\t\t\t\t: `<patternProperties:${pattern}>`;\n\n\t\t\tif (subPropDef === undefined) {\n\t\t\t\t// sub doesn't constrain this pattern at all — more permissive\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: ppPath,\n\t\t\t\t\texpected: formatSchemaType(supPropDef),\n\t\t\t\t\treceived: \"no constraint for this pattern\",\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Both define the same pattern — recurse\n\t\t\t\tconst ppErrors = computeSemanticErrors(subPropDef, supPropDef, ppPath);\n\t\t\t\terrors.push(...ppErrors);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Compare les contraintes d'array (hors items) entre sub et sup.\n */\nfunction checkArrayConstraints(\n\tsub: JSONSchema7,\n\tsup: JSONSchema7,\n\tpath: string,\n\terrors: SchemaError[],\n): void {\n\tcheckMinConstraint(sub.minItems, sup.minItems, \"minItems\", path, errors);\n\tcheckMaxConstraint(sub.maxItems, sup.maxItems, \"maxItems\", path, errors);\n\n\t// ── uniqueItems ──\n\tif (sup.uniqueItems === true && sub.uniqueItems !== true) {\n\t\terrors.push({\n\t\t\tkey: path || \"$root\",\n\t\t\texpected: \"uniqueItems: true\",\n\t\t\treceived: fmtConstraint(\"uniqueItems\", sub.uniqueItems ?? false),\n\t\t});\n\t}\n\n\t// ── contains ──\n\tif (sup.contains !== undefined) {\n\t\tif (sub.contains === undefined) {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: `contains: ${formatSchemaType(sup.contains as JSONSchema7Definition)}`,\n\t\t\t\treceived: \"no contains constraint\",\n\t\t\t});\n\t\t} else {\n\t\t\t// Both have contains — recurse to compare the contained schemas\n\t\t\tconst containsPath = path ? `${path}.<contains>` : \"<contains>\";\n\t\t\tconst containsErrors = computeSemanticErrors(\n\t\t\t\tsub.contains as JSONSchema7Definition,\n\t\t\t\tsup.contains as JSONSchema7Definition,\n\t\t\t\tcontainsPath,\n\t\t\t);\n\t\t\terrors.push(...containsErrors);\n\t\t}\n\t}\n}\n\n/**\n * Détecte si un schema a un type numérique.\n */\nfunction isNumericType(t: string | string[] | undefined): boolean {\n\tif (t === undefined) return false;\n\tif (typeof t === \"string\") return t === \"number\" || t === \"integer\";\n\treturn t.some((v) => v === \"number\" || v === \"integer\");\n}\n\n/**\n * Détecte si un schema a un type string.\n */\nfunction isStringType(t: string | string[] | undefined): boolean {\n\tif (t === undefined) return false;\n\tif (typeof t === \"string\") return t === \"string\";\n\treturn t.includes(\"string\");\n}\n\n/**\n * Détecte si un schema a un type object.\n */\nfunction isObjectType(t: string | string[] | undefined): boolean {\n\tif (t === undefined) return false;\n\tif (typeof t === \"string\") return t === \"object\";\n\treturn t.includes(\"object\");\n}\n\n/**\n * Détecte si un schema a un type array.\n */\nfunction isArrayType(t: string | string[] | undefined): boolean {\n\tif (t === undefined) return false;\n\tif (typeof t === \"string\") return t === \"array\";\n\treturn t.includes(\"array\");\n}\n\n// ─── Keyword-based implicit type detection ───────────────────────────────────\n//\n// propertyNames schemas (e.g. { minLength: 1 }) don't always carry an explicit\n// `type`, yet their keywords unambiguously imply a type family. These helpers\n// let us trigger the right constraint checks even when `getEffectiveType`\n// returns `undefined`.\n\nfunction hasNumericKeywords(s: JSONSchema7): boolean {\n\treturn (\n\t\ts.minimum !== undefined ||\n\t\ts.maximum !== undefined ||\n\t\ts.exclusiveMinimum !== undefined ||\n\t\ts.exclusiveMaximum !== undefined ||\n\t\ts.multipleOf !== undefined\n\t);\n}\n\nfunction hasStringKeywords(s: JSONSchema7): boolean {\n\treturn (\n\t\ts.minLength !== undefined ||\n\t\ts.maxLength !== undefined ||\n\t\ts.pattern !== undefined ||\n\t\ts.format !== undefined\n\t);\n}\n\nfunction hasObjectKeywords(s: JSONSchema7): boolean {\n\treturn (\n\t\ts.minProperties !== undefined ||\n\t\ts.maxProperties !== undefined ||\n\t\ts.propertyNames !== undefined ||\n\t\ts.additionalProperties !== undefined ||\n\t\tisPlainObj(s.patternProperties) ||\n\t\tisPlainObj(s.dependencies)\n\t);\n}\n\nfunction hasArrayKeywords(s: JSONSchema7): boolean {\n\treturn (\n\t\ts.minItems !== undefined ||\n\t\ts.maxItems !== undefined ||\n\t\ts.uniqueItems !== undefined ||\n\t\ts.contains !== undefined\n\t);\n}\n\n// ─── Core Comparison ─────────────────────────────────────────────────────────\n\n/**\n * Compare deux schemas et produit des erreurs sémantiques.\n *\n * @param sub Le schema source (ce qui est produit / received)\n * @param sup Le schema cible (ce qui est attendu / expected)\n * @param path Le chemin normalisé courant\n * @returns Liste d'erreurs sémantiques\n */\nexport function computeSemanticErrors(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tpath = \"\",\n): SchemaError[] {\n\t// ── Boolean schemas ──\n\tif (typeof sup === \"boolean\") {\n\t\tif (sup === false) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: \"never\",\n\t\t\t\t\treceived: formatSchemaType(sub),\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\treturn []; // sup = true accepts everything\n\t}\n\tif (typeof sub === \"boolean\") {\n\t\tif (sub === true) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: formatSchemaType(sup),\n\t\t\t\t\treceived: \"any\",\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\treturn []; // sub = false produces nothing, trivially subset\n\t}\n\n\tconst subSchema = sub as JSONSchema7;\n\tconst supSchema = sup as JSONSchema7;\n\n\tconst errors: SchemaError[] = [];\n\n\t// ── Handle `not` keyword ──\n\t// Check sup.not: sub must not satisfy the not-schema for sub ⊆ sup.\n\t// Check sub.not: if sub has a not that sup doesn't, sub is more constrained (OK).\n\t// if sup has a not that sub doesn't, sub may be too permissive.\n\tif (\n\t\thasOwn(supSchema, \"not\") &&\n\t\tisPlainObj(supSchema.not) &&\n\t\ttypeof supSchema.not !== \"boolean\"\n\t) {\n\t\tconst notSchema = supSchema.not as JSONSchema7;\n\t\tconst notFormatted = formatSchemaType(notSchema);\n\n\t\tif (!hasOwn(subSchema, \"not\")) {\n\t\t\t// sup excludes something, sub doesn't → sub is more permissive\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: `not ${notFormatted}`,\n\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t});\n\t\t} else if (\n\t\t\tisPlainObj(subSchema.not) &&\n\t\t\ttypeof subSchema.not !== \"boolean\"\n\t\t) {\n\t\t\t// Both have not — compare the not schemas\n\t\t\t// For sub ⊆ sup, sub.not must be at least as broad as sup.not\n\t\t\t// (i.e. sub excludes at least as much). We report if they differ.\n\t\t\tconst subNotSchema = subSchema.not as JSONSchema7;\n\t\t\tif (!deepEqualPrimitive(subNotSchema, notSchema)) {\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: `not ${notFormatted}`,\n\t\t\t\t\treceived: `not ${formatSchemaType(subNotSchema)}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Get effective types ──\n\tconst subType = getEffectiveType(subSchema);\n\tconst supType = getEffectiveType(supSchema);\n\n\t// ── Handle anyOf/oneOf in sup ──\n\t// If sup has branches, try to find the best matching one for error reporting\n\tconst supBranches = supSchema.anyOf ?? supSchema.oneOf;\n\tif (Array.isArray(supBranches) && supBranches.length > 0 && !supSchema.type) {\n\t\treturn computeErrorsAgainstBranches(subSchema, supBranches, path);\n\t}\n\n\t// ── Handle anyOf/oneOf in sub ──\n\tconst subBranches = subSchema.anyOf ?? subSchema.oneOf;\n\tif (Array.isArray(subBranches) && subBranches.length > 0 && !subSchema.type) {\n\t\tconst branchErrors: SchemaError[] = [];\n\t\tfor (const branch of subBranches) {\n\t\t\tconst errs = computeSemanticErrors(branch, sup, path);\n\t\t\tbranchErrors.push(...errs);\n\t\t}\n\t\treturn branchErrors;\n\t}\n\n\t// ── Both are object types → compare properties + object constraints ──\n\tconst supProps = getProperties(supSchema);\n\tconst subProps = getProperties(subSchema);\n\n\tif (supProps !== null || isObjectType(supType)) {\n\t\t// sup is an object schema\n\t\tif (subType !== undefined && !typeIncludes(subType, \"object\")) {\n\t\t\t// sub is not an object at all\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: formatSchemaType(supSchema),\n\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t});\n\t\t\treturn errors;\n\t\t}\n\n\t\tif (supProps !== null) {\n\t\t\tconst supRequired = getRequired(supSchema);\n\t\t\tconst subRequired = getRequired(subSchema);\n\n\t\t\tfor (const key of Object.keys(supProps)) {\n\t\t\t\tconst propPath = joinPath(path, key);\n\t\t\t\tconst supPropDef = supProps[key];\n\t\t\t\tconst subPropDef = subProps?.[key];\n\n\t\t\t\tif (supPropDef === undefined) continue;\n\n\t\t\t\tconst isRequiredInSup = supRequired.includes(key);\n\n\t\t\t\t// ── Missing property (required in sup, absent in sub) ──\n\t\t\t\tif (subPropDef === undefined) {\n\t\t\t\t\tif (isRequiredInSup) {\n\t\t\t\t\t\terrors.push({\n\t\t\t\t\t\t\tkey: propPath,\n\t\t\t\t\t\t\texpected: formatSchemaType(supPropDef),\n\t\t\t\t\t\t\treceived: \"undefined\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// ── Optionality mismatch (required in sup, optional in sub) ──\n\t\t\t\tif (isRequiredInSup && !subRequired.includes(key)) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tkey: propPath,\n\t\t\t\t\t\texpected: \"not optional\",\n\t\t\t\t\t\treceived: \"optional\",\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// ── Recurse into the property schemas ──\n\t\t\t\tconst propErrors = comparePropertySchemas(\n\t\t\t\t\tsubPropDef,\n\t\t\t\t\tsupPropDef,\n\t\t\t\t\tpropPath,\n\t\t\t\t);\n\t\t\t\terrors.push(...propErrors);\n\t\t\t}\n\t\t}\n\n\t\t// ── Object-level constraints ──\n\t\tcheckObjectConstraints(subSchema, supSchema, path, errors);\n\n\t\treturn errors;\n\t}\n\n\t// ── Both are array types → compare items + array constraints ──\n\tif (\n\t\t(supType === \"array\" || supSchema.items !== undefined) &&\n\t\t(subType === \"array\" || subSchema.items !== undefined)\n\t) {\n\t\t// Check items compatibility\n\t\tif (supSchema.items !== undefined && typeof supSchema.items !== \"boolean\") {\n\t\t\tif (\n\t\t\t\tsubSchema.items !== undefined &&\n\t\t\t\ttypeof subSchema.items !== \"boolean\"\n\t\t\t) {\n\t\t\t\t// Both have items schemas — recurse\n\t\t\t\tif (Array.isArray(supSchema.items) && Array.isArray(subSchema.items)) {\n\t\t\t\t\t// Tuple comparison\n\t\t\t\t\tconst maxLen = Math.max(\n\t\t\t\t\t\tsupSchema.items.length,\n\t\t\t\t\t\tsubSchema.items.length,\n\t\t\t\t\t);\n\t\t\t\t\tfor (let i = 0; i < maxLen; i++) {\n\t\t\t\t\t\tconst supItem = supSchema.items[i];\n\t\t\t\t\t\tconst subItem = subSchema.items[i];\n\t\t\t\t\t\tconst itemPath = joinPath(path, `[${i}]`);\n\t\t\t\t\t\tif (supItem !== undefined && subItem === undefined) {\n\t\t\t\t\t\t\terrors.push({\n\t\t\t\t\t\t\t\tkey: itemPath,\n\t\t\t\t\t\t\t\texpected: formatSchemaType(supItem),\n\t\t\t\t\t\t\t\treceived: \"undefined\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (supItem !== undefined && subItem !== undefined) {\n\t\t\t\t\t\t\terrors.push(...computeSemanticErrors(subItem, supItem, itemPath));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (\n\t\t\t\t\t!Array.isArray(supSchema.items) &&\n\t\t\t\t\t!Array.isArray(subSchema.items)\n\t\t\t\t) {\n\t\t\t\t\t// Single items schema — recurse with [] path\n\t\t\t\t\tconst itemPath = arrayPath(path);\n\t\t\t\t\tconst itemErrors = computeSemanticErrors(\n\t\t\t\t\t\tsubSchema.items as JSONSchema7Definition,\n\t\t\t\t\t\tsupSchema.items as JSONSchema7Definition,\n\t\t\t\t\t\titemPath,\n\t\t\t\t\t);\n\t\t\t\t\terrors.push(...itemErrors);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// sup has items schema but sub doesn't\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: formatSchemaType(supSchema),\n\t\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// ── Array-level constraints ──\n\t\tcheckArrayConstraints(subSchema, supSchema, path, errors);\n\n\t\treturn errors;\n\t}\n\n\t// ── Type mismatch at current level ──\n\tif (subType !== undefined && supType !== undefined) {\n\t\tif (!typesAreCompatible(subType, supType)) {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: formatSchemaType(supSchema),\n\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t});\n\t\t\treturn errors;\n\t\t}\n\t}\n\n\t// ── Enum comparison ──\n\tif (Array.isArray(supSchema.enum)) {\n\t\tif (Array.isArray(subSchema.enum)) {\n\t\t\t// Both have enums — check if sub.enum ⊆ sup.enum\n\t\t\tconst subExtra = subSchema.enum.filter(\n\t\t\t\t(v) => !supSchema.enum?.some((sv) => deepEqualPrimitive(v, sv)),\n\t\t\t);\n\t\t\tif (subExtra.length > 0) {\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: formatEnumValues(supSchema.enum),\n\t\t\t\t\treceived: formatEnumValues(subSchema.enum),\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (hasOwn(subSchema, \"const\")) {\n\t\t\t// sub has const, sup has enum — check inclusion\n\t\t\tconst constInEnum = supSchema.enum.some((v) =>\n\t\t\t\tdeepEqualPrimitive(v, subSchema.const),\n\t\t\t);\n\t\t\tif (!constInEnum) {\n\t\t\t\terrors.push({\n\t\t\t\t\tkey: path || \"$root\",\n\t\t\t\t\texpected: formatEnumValues(supSchema.enum),\n\t\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\t// sup has enum but sub is a plain type (no enum restriction)\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: formatEnumValues(supSchema.enum),\n\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t});\n\t\t}\n\t\treturn errors;\n\t}\n\n\t// ── Const comparison ──\n\tif (hasOwn(supSchema, \"const\") && hasOwn(subSchema, \"const\")) {\n\t\tif (!deepEqualPrimitive(supSchema.const, subSchema.const)) {\n\t\t\terrors.push({\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: formatSchemaType(supSchema),\n\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t});\n\t\t}\n\t\treturn errors;\n\t}\n\n\t// ── Same-type constraint comparison ──\n\t// Types are compatible (or unspecified), now check individual keywords.\n\n\tif (\n\t\tisNumericType(subType) ||\n\t\tisNumericType(supType) ||\n\t\thasNumericKeywords(supSchema) ||\n\t\thasNumericKeywords(subSchema)\n\t) {\n\t\tcheckNumericConstraints(subSchema, supSchema, path, errors);\n\t}\n\n\tif (\n\t\tisStringType(subType) ||\n\t\tisStringType(supType) ||\n\t\thasStringKeywords(supSchema) ||\n\t\thasStringKeywords(subSchema)\n\t) {\n\t\tcheckStringConstraints(subSchema, supSchema, path, errors);\n\t}\n\n\t// Object-level constraints when sup doesn't have explicit properties\n\t// but still has object constraints (e.g., just { type: \"object\", minProperties: 3 })\n\tif (\n\t\tisObjectType(subType) ||\n\t\tisObjectType(supType) ||\n\t\thasObjectKeywords(supSchema) ||\n\t\thasObjectKeywords(subSchema)\n\t) {\n\t\tcheckObjectConstraints(subSchema, supSchema, path, errors);\n\t}\n\n\t// Array-level constraints when sup doesn't have explicit items\n\t// but still has array constraints (e.g., just { type: \"array\", minItems: 2 })\n\tif (\n\t\tisArrayType(subType) ||\n\t\tisArrayType(supType) ||\n\t\thasArrayKeywords(supSchema) ||\n\t\thasArrayKeywords(subSchema)\n\t) {\n\t\tcheckArrayConstraints(subSchema, supSchema, path, errors);\n\t}\n\n\tif (errors.length > 0) {\n\t\treturn errors;\n\t}\n\n\t// ── Fallback: generic incompatibility ──\n\t// If we get here, there's an incompatibility we couldn't pinpoint precisely.\n\t// Produce a root-level error with the formatted types.\n\tconst expectedStr = formatSchemaType(supSchema);\n\tconst receivedStr = formatSchemaType(subSchema);\n\tif (expectedStr !== receivedStr) {\n\t\terrors.push({\n\t\t\tkey: path || \"$root\",\n\t\t\texpected: expectedStr,\n\t\t\treceived: receivedStr,\n\t\t});\n\t}\n\n\treturn errors;\n}\n\n// ─── Property Schema Comparison ──────────────────────────────────────────────\n\n/**\n * Compare deux schemas de propriété et produit des erreurs.\n * Gère la récursion dans les objets imbriqués et les tableaux.\n */\nfunction comparePropertySchemas(\n\tsubDef: JSONSchema7Definition,\n\tsupDef: JSONSchema7Definition,\n\tpath: string,\n): SchemaError[] {\n\tif (typeof subDef === \"boolean\" || typeof supDef === \"boolean\") {\n\t\tif (subDef !== supDef) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tkey: path,\n\t\t\t\t\texpected: formatSchemaType(supDef),\n\t\t\t\t\treceived: formatSchemaType(subDef),\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\treturn [];\n\t}\n\n\tconst subSchema = subDef as JSONSchema7;\n\tconst supSchema = supDef as JSONSchema7;\n\n\tconst subType = getEffectiveType(subSchema);\n\tconst supType = getEffectiveType(supSchema);\n\n\t// ── Enum comparison (before type check, as enums can cross types) ──\n\tif (Array.isArray(supSchema.enum)) {\n\t\tif (Array.isArray(subSchema.enum)) {\n\t\t\tconst subExtra = subSchema.enum.filter(\n\t\t\t\t(v) => !supSchema.enum?.some((sv) => deepEqualPrimitive(v, sv)),\n\t\t\t);\n\t\t\tif (subExtra.length > 0) {\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: path,\n\t\t\t\t\t\texpected: formatEnumValues(supSchema.enum),\n\t\t\t\t\t\treceived: formatEnumValues(subSchema.enum),\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\t\tif (hasOwn(subSchema, \"const\")) {\n\t\t\tconst constInEnum = supSchema.enum.some((v) =>\n\t\t\t\tdeepEqualPrimitive(v, subSchema.const),\n\t\t\t);\n\t\t\tif (!constInEnum) {\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: path,\n\t\t\t\t\t\texpected: formatEnumValues(supSchema.enum),\n\t\t\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\t\t// sup has enum, sub is a plain type\n\t\treturn [\n\t\t\t{\n\t\t\t\tkey: path,\n\t\t\t\texpected: formatEnumValues(supSchema.enum),\n\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t},\n\t\t];\n\t}\n\n\t// ── Const comparison ──\n\tif (hasOwn(supSchema, \"const\") && hasOwn(subSchema, \"const\")) {\n\t\tif (!deepEqualPrimitive(supSchema.const, subSchema.const)) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tkey: path,\n\t\t\t\t\texpected: formatSchemaType(supSchema),\n\t\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\treturn [];\n\t}\n\n\t// ── Type mismatch ──\n\tif (subType !== undefined && supType !== undefined) {\n\t\tif (!typesAreCompatible(subType, supType)) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tkey: path,\n\t\t\t\t\texpected: formatSchemaType(supSchema),\n\t\t\t\t\treceived: formatSchemaType(subSchema),\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t}\n\n\t// ── If same types, recurse deeper ──\n\treturn computeSemanticErrors(subDef, supDef, path);\n}\n\n// ─── Branch Error Computation ────────────────────────────────────────────────\n\n/**\n * Quand sup a des branches (anyOf/oneOf), tente de trouver la branche\n * la plus proche et génère les erreurs contre celle-ci.\n *\n * Stratégie : calculer les erreurs pour chaque branche et retourner\n * celles de la branche avec le moins d'erreurs (meilleur match).\n */\nfunction computeErrorsAgainstBranches(\n\tsub: JSONSchema7,\n\tbranches: JSONSchema7Definition[],\n\tpath: string,\n): SchemaError[] {\n\tlet bestErrors: SchemaError[] | null = null;\n\n\tfor (const branch of branches) {\n\t\tconst errors = computeSemanticErrors(sub, branch, path);\n\t\tif (errors.length === 0) return [];\n\t\tif (bestErrors === null || errors.length < bestErrors.length) {\n\t\t\tbestErrors = errors;\n\t\t}\n\t}\n\n\treturn (\n\t\tbestErrors ?? [\n\t\t\t{\n\t\t\t\tkey: path || \"$root\",\n\t\t\t\texpected: formatSchemaType({ anyOf: branches } as JSONSchema7),\n\t\t\t\treceived: formatSchemaType(sub),\n\t\t\t},\n\t\t]\n\t);\n}\n\n// ─── Primitive Deep Equal ────────────────────────────────────────────────────\n\n/**\n * Comparaison d'égalité profonde pour des valeurs JSON primitives et tableaux.\n * Utilisé pour la comparaison d'enums et de consts.\n */\nfunction deepEqualPrimitive(a: unknown, b: unknown): boolean {\n\tif (a === b) return true;\n\tif (a === null || b === null) return false;\n\tif (typeof a !== typeof b) return false;\n\tif (typeof a === \"object\") {\n\t\tif (Array.isArray(a)) {\n\t\t\tif (!Array.isArray(b)) return false;\n\t\t\tif (a.length !== b.length) return false;\n\t\t\tfor (let i = 0; i < a.length; i++) {\n\t\t\t\tif (!deepEqualPrimitive(a[i], b[i])) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (Array.isArray(b)) return false;\n\t\tconst aObj = a as Record<string, unknown>;\n\t\tconst bObj = b as Record<string, unknown>;\n\t\tconst aKeys = Object.keys(aObj);\n\t\tif (aKeys.length !== Object.keys(bObj).length) return false;\n\t\tfor (const key of aKeys) {\n\t\t\tif (!deepEqualPrimitive(aObj[key], bObj[key])) return false;\n\t\t}\n\t\treturn true;\n\t}\n\treturn false;\n}\n"],"names":["computeSemanticErrors","formatSchemaType","formatEnumValues","values","parts","map","v","JSON","stringify","length","last","pop","join","def","undefined","schema","hasOwn","const","Array","isArray","enum","branches","anyOf","oneOf","b","type","items","itemSchema","itemBranches","t","itemType","isPlainObj","properties","not","joinPath","parent","key","arrayPath","getProperties","getRequired","required","getEffectiveType","typeIncludes","schemaType","target","includes","typesAreCompatible","subType","supType","some","every","st","supt","fmtConstraint","name","value","checkMinConstraint","subVal","supVal","path","errors","push","expected","received","checkMaxConstraint","checkNumericConstraints","sub","sup","minimum","maximum","exclusiveMinimum","exclusiveMaximum","multipleOf","checkStringConstraints","minLength","maxLength","pattern","format","checkObjectConstraints","additionalProperties","apPath","apErrors","minProperties","maxProperties","propertyNames","pnErrors","dependencies","supDeps","subDeps","Object","keys","supDep","subDep","missing","filter","d","depPath","depErrors","patternProperties","supPP","subPP","supPropDef","subPropDef","ppPath","ppErrors","checkArrayConstraints","minItems","maxItems","uniqueItems","contains","containsPath","containsErrors","isNumericType","isStringType","isObjectType","isArrayType","hasNumericKeywords","s","hasStringKeywords","hasObjectKeywords","hasArrayKeywords","subSchema","supSchema","notSchema","notFormatted","subNotSchema","deepEqualPrimitive","supBranches","computeErrorsAgainstBranches","subBranches","branchErrors","branch","errs","supProps","subProps","supRequired","subRequired","propPath","isRequiredInSup","propErrors","comparePropertySchemas","maxLen","Math","max","i","supItem","subItem","itemPath","itemErrors","subExtra","sv","constInEnum","expectedStr","receivedStr","subDef","supDef","bestErrors","a","aObj","bObj","aKeys"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { JSONSchema7Definition } from "json-schema";
2
- import type { MergeEngine } from "./merge-engine";
3
- import type { SubsetResult } from "./types";
2
+ import type { MergeEngine } from "./merge-engine.js";
3
+ import type { SubsetResult } from "./types.js";
4
4
  /**
5
5
  * Type de branchement détecté dans un schema.
6
6
  *
@@ -70,7 +70,7 @@ export declare function checkBranchedSub(subBranches: JSONSchema7Definition[], s
70
70
  *
71
71
  * Utilise `_.some` pour trouver la première branche compatible.
72
72
  */
73
- export declare function checkBranchedSup(sub: JSONSchema7Definition, supBranches: JSONSchema7Definition[], engine: MergeEngine, branchType?: BranchType): SubsetResult;
73
+ export declare function checkBranchedSup(sub: JSONSchema7Definition, supBranches: JSONSchema7Definition[], engine: MergeEngine, _branchType?: BranchType): SubsetResult;
74
74
  /**
75
75
  * Vérifie `sub ⊆ sup` pour deux schemas atomiques (sans anyOf/oneOf).
76
76
  * Utilise `mergeOrThrow` pour capturer les erreurs d'incompatibilité.
@@ -0,0 +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 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 false;if((0,_utils.deepEqual)(merged,sub))return true;const normalizedMerged=(0,_normalizer.normalize)(merged);return(0,_utils.deepEqual)(normalizedMerged,sub)||engine.isEqual(normalizedMerged,sub)}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 false;if((0,_utils.deepEqual)(merged,sub))return true;const normalizedBranch=(0,_normalizer.normalize)(merged);return(0,_utils.deepEqual)(normalizedBranch,sub)||engine.isEqual(normalizedBranch,sub)})}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:[]}}const errors=(0,_semanticerrors.computeSemanticErrors)(sub,sup,"");return{isSubset:false,merged:normalizedMerged,errors}}catch(_e){const errors=(0,_semanticerrors.computeSemanticErrors)(sub,sup,"");return{isSubset:false,merged:null,errors}}}
2
+ //# sourceMappingURL=subset-checker.js.map
@@ -0,0 +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// ─── 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 * 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) return false;\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\treturn (\n\t\t\tdeepEqual(normalizedMerged, sub) || engine.isEqual(normalizedMerged, sub)\n\t\t);\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) return false;\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\treturn (\n\t\t\tdeepEqual(normalizedBranch, sub) || engine.isEqual(normalizedBranch, sub)\n\t\t);\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\tconst errors = computeSemanticErrors(sub, sup, \"\");\n\t\treturn { isSubset: false, merged: normalizedMerged, errors };\n\t} catch (_e) {\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","engine","supBranches","length","notResult","fmtResult","isFormatSubset","effectiveSup","merged","merge","normalizedMerged","normalize","isEqual","effectiveBranch","normalizedBranch","subBranches","branchType","allErrors","allSubset","i","branchErrors","computeSemanticErrors","push","isSubset","errors","_branchType","semanticErrors","mergeOrThrow","_e"],"mappings":"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"}
@@ -1,21 +1,19 @@
1
1
  import type { JSONSchema7, JSONSchema7Definition } from "json-schema";
2
- export interface SchemaDiff {
3
- /** Chemin JSON-path-like vers la divergence (ex: "properties.user.required") */
4
- path: string;
5
- /** Type de divergence */
6
- type: "added" | "removed" | "changed";
7
- /** Valeur dans le schema original (sub) */
8
- expected: unknown;
9
- /** Valeur dans le schema mergé (intersection) */
10
- actual: unknown;
2
+ export interface SchemaError {
3
+ /** Chemin normalisé vers la propriété concernée (ex: "user.name", "users[].name", "accountId") */
4
+ key: string;
5
+ /** Type ou valeur attendu(e) par le schema cible (sup) */
6
+ expected: string;
7
+ /** Type ou valeur reçu(e) depuis le schema source (sub) */
8
+ received: string;
11
9
  }
12
10
  export interface SubsetResult {
13
11
  /** true si sub ⊆ sup (toute valeur valide pour sub est valide pour sup) */
14
12
  isSubset: boolean;
15
13
  /** Le schema résultant de l'intersection allOf(sub, sup), ou null si incompatible */
16
14
  merged: JSONSchema7Definition | null;
17
- /** Différences structurelles détectées entre sub et l'intersection */
18
- diffs: SchemaDiff[];
15
+ /** Erreurs sémantiques décrivant les incompatibilités entre les deux schemas */
16
+ errors: SchemaError[];
19
17
  }
20
18
  export interface ConnectionResult extends SubsetResult {
21
19
  /** Direction lisible du check */
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +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 deepEqual(){return deepEqual},get hasOwn(){return hasOwn},get isPlainObj(){return isPlainObj},get omitKeys(){return omitKeys},get schemaDeepEqual(){return schemaDeepEqual},get unionStrings(){return unionStrings}});function isPlainObj(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function hasOwn(obj,key){return Object.hasOwn(obj,key)}function deepEqual(a,b){if(a===b)return true;if(a===null||b===null)return false;if(typeof a!==typeof b)return false;if(typeof a==="object"){if(Array.isArray(a)){if(!Array.isArray(b))return false;const len=a.length;if(len!==b.length)return false;for(let i=0;i<len;i++){if(!deepEqual(a[i],b[i]))return false}return true}if(Array.isArray(b))return false;const aObj=a;const bObj=b;const aKeys=Object.keys(aObj);const bKeys=Object.keys(bObj);if(aKeys.length!==bKeys.length)return false;for(const key of aKeys){if(!(key in bObj)||!deepEqual(aObj[key],bObj[key]))return false}return true}return false}function omitKeys(obj,keysToOmit){if(keysToOmit.length<=2){const k0=keysToOmit[0];const k1=keysToOmit[1];const has0=k0!==undefined&&k0 in obj;const has1=k1!==undefined&&k1 in obj;if(!has0&&!has1)return obj;const result={};for(const key of Object.keys(obj)){if(key!==k0&&key!==k1){result[key]=obj[key]}}return result}const omitSet=new Set(keysToOmit);let hasAny=false;for(const key of keysToOmit){if(key in obj){hasAny=true;break}}if(!hasAny)return obj;const result={};for(const key of Object.keys(obj)){if(!omitSet.has(key)){result[key]=obj[key]}}return result}function unionStrings(a,b){const aLen=a.length;const bLen=b.length;if(bLen===0)return a;if(aLen===0)return b;if(aLen+bLen<=8){const result=a.slice();for(let i=0;i<bLen;i++){const item=b[i];if(item!==undefined&&!result.includes(item)){result.push(item)}}return result.length===aLen?a:result}const set=new Set(a);const initialSize=set.size;for(let i=0;i<bLen;i++){const item=b[i];if(item!==undefined)set.add(item)}if(set.size===initialSize&&initialSize===aLen)return a;return Array.from(set)}function schemaDeepEqual(a,b){return deepEqual(a,b)}
2
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["import type { JSONSchema7Definition } from \"json-schema\";\n\n// ─── Shared Utilities ────────────────────────────────────────────────────────\n//\n// Fonctions utilitaires natives partagées entre tous les modules.\n// Centralisées ici pour éviter la duplication et permettre à V8\n// d'optimiser une seule instance de chaque fonction hot-path.\n\n/**\n * Vérifie si une valeur est un plain object (pas null, pas un array).\n */\nexport function isPlainObj(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Vérifie si un objet possède une propriété propre.\n */\nexport function hasOwn(obj: object, key: string): boolean {\n\treturn Object.hasOwn(obj, key);\n}\n\n/**\n * Compare deux valeurs en profondeur (deep equality).\n *\n * Optimisations :\n * - Reference equality short-circuit (a === b)\n * - Length checks avant l'itération (arrays et objects)\n * - Pas de support pour Date, RegExp, Map, Set (pas nécessaire pour JSON Schema)\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n\tif (a === b) return true;\n\tif (a === null || b === null) return false;\n\tif (typeof a !== typeof b) return false;\n\n\tif (typeof a === \"object\") {\n\t\tif (Array.isArray(a)) {\n\t\t\tif (!Array.isArray(b)) return false;\n\t\t\tconst len = a.length;\n\t\t\tif (len !== b.length) return false;\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (!deepEqual(a[i], b[i])) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (Array.isArray(b)) return false;\n\n\t\tconst aObj = a as Record<string, unknown>;\n\t\tconst bObj = b as Record<string, unknown>;\n\t\tconst aKeys = Object.keys(aObj);\n\t\tconst bKeys = Object.keys(bObj);\n\t\tif (aKeys.length !== bKeys.length) return false;\n\t\tfor (const key of aKeys) {\n\t\t\tif (!(key in bObj) || !deepEqual(aObj[key], bObj[key])) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Crée une copie d'un objet sans les clés spécifiées.\n *\n * Optimisé pour le cas courant (1-2 clés à omettre) :\n * - Utilise un Set uniquement si > 2 clés\n * - Itère une seule fois sur l'objet source\n * - Retourne l'original si aucune clé à omettre n'est présente dans l'objet\n */\nexport function omitKeys<T extends Record<string, unknown>>(\n\tobj: T,\n\tkeysToOmit: string[],\n): T {\n\t// Fast path: check if any key to omit actually exists in the object\n\tif (keysToOmit.length <= 2) {\n\t\tconst k0 = keysToOmit[0];\n\t\tconst k1 = keysToOmit[1];\n\t\tconst has0 = k0 !== undefined && k0 in obj;\n\t\tconst has1 = k1 !== undefined && k1 in obj;\n\t\tif (!has0 && !has1) return obj;\n\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const key of Object.keys(obj)) {\n\t\t\tif (key !== k0 && key !== k1) {\n\t\t\t\tresult[key] = obj[key];\n\t\t\t}\n\t\t}\n\t\treturn result as T;\n\t}\n\n\tconst omitSet = new Set(keysToOmit);\n\n\t// Check if any key to omit exists\n\tlet hasAny = false;\n\tfor (const key of keysToOmit) {\n\t\tif (key in obj) {\n\t\t\thasAny = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!hasAny) return obj;\n\n\tconst result: Record<string, unknown> = {};\n\tfor (const key of Object.keys(obj)) {\n\t\tif (!omitSet.has(key)) {\n\t\t\tresult[key] = obj[key];\n\t\t}\n\t}\n\treturn result as T;\n}\n\n/**\n * Fusionne deux tableaux de strings en éliminant les doublons.\n * Retourne un tableau avec les éléments uniques des deux sources.\n *\n * Optimisé avec fast paths pour les cas courants :\n * - Si b est vide → retourne a directement\n * - Si a est vide → retourne b directement\n * - Pour les petits tableaux (≤ 8 éléments total), utilise\n * une boucle avec includes au lieu de créer un Set\n */\nexport function unionStrings(a: string[], b: string[]): string[] {\n\tconst aLen = a.length;\n\tconst bLen = b.length;\n\n\t// Fast paths for empty arrays\n\tif (bLen === 0) return a;\n\tif (aLen === 0) return b;\n\n\t// Fast path for small arrays: avoid Set allocation overhead\n\tif (aLen + bLen <= 8) {\n\t\tconst result = a.slice();\n\t\tfor (let i = 0; i < bLen; i++) {\n\t\t\tconst item = b[i];\n\t\t\tif (item !== undefined && !result.includes(item)) {\n\t\t\t\tresult.push(item);\n\t\t\t}\n\t\t}\n\t\t// If nothing was added from b (all items already in a), return a\n\t\treturn result.length === aLen ? a : result;\n\t}\n\n\t// General case: use Set for larger arrays\n\tconst set = new Set(a);\n\tconst initialSize = set.size;\n\tfor (let i = 0; i < bLen; i++) {\n\t\tconst item = b[i];\n\t\tif (item !== undefined) set.add(item);\n\t}\n\n\t// If nothing new was added, return a directly\n\tif (set.size === initialSize && initialSize === aLen) return a;\n\n\treturn Array.from(set);\n}\n\n/**\n * Vérifie l'égalité structurelle entre deux JSONSchema7Definition.\n * Wrapper typé autour de deepEqual pour les schemas.\n */\nexport function schemaDeepEqual(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\treturn deepEqual(a, b);\n}\n"],"names":["deepEqual","hasOwn","isPlainObj","omitKeys","schemaDeepEqual","unionStrings","value","Array","isArray","obj","key","Object","a","b","len","length","i","aObj","bObj","aKeys","keys","bKeys","keysToOmit","k0","k1","has0","undefined","has1","result","omitSet","Set","hasAny","has","aLen","bLen","slice","item","includes","push","set","initialSize","size","add","from"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { JSONSchema7 } from "json-schema";
2
+ import type { MergeEngine } from "./merge-engine.js";
3
+ import type { ResolvedConditionResult } from "./types.js";
4
+ /**
5
+ * Résout les `if/then/else` d'un schema en évaluant le `if` contre
6
+ * des données partielles (discriminants).
7
+ *
8
+ * @param schema Le schema contenant potentiellement des if/then/else
9
+ * @param data Données partielles utilisées pour évaluer les conditions
10
+ * @param engine Le MergeEngine pour merger les branches
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const form = {
15
+ * type: "object",
16
+ * properties: { accountType: { type: "string" }, ... },
17
+ * if: { properties: { accountType: { const: "business" } } },
18
+ * then: { required: ["companyName"] },
19
+ * else: { required: ["firstName"] },
20
+ * };
21
+ *
22
+ * const { resolved } = resolveConditions(form, { accountType: "business" }, engine);
23
+ * // → resolved n'a plus de if/then/else, mais a required: ["companyName"]
24
+ * ```
25
+ */
26
+ export declare function resolveConditions(schema: JSONSchema7, data: Record<string, unknown>, engine: MergeEngine): ResolvedConditionResult;
@@ -0,0 +1,2 @@
1
+ import{validateFormat}from"./format-validator.js";import{inferType}from"./normalizer.js";import{deepEqual,hasOwn,isPlainObj,omitKeys,unionStrings}from"./utils.js";const SPECIAL_MERGE_KEYS=new Set(["required","properties","dependencies"]);const SUB_SCHEMA_KEYS=new Set(["additionalProperties","items","contains","propertyNames","not"]);const MIN_KEYS=new Set(["minimum","exclusiveMinimum","minLength","minItems","minProperties"]);const MAX_KEYS=new Set(["maximum","exclusiveMaximum","maxLength","maxItems","maxProperties"]);function matchesType(value,type){if(type===undefined)return true;const types=Array.isArray(type)?type:[type];const actualType=inferType(value);return types.some(t=>t===actualType||t==="number"&&actualType==="integer")}function evaluateNumericConstraints(value,prop){if(prop.minimum!==undefined&&!(value>=prop.minimum))return false;if(prop.maximum!==undefined&&!(value<=prop.maximum))return false;if(prop.exclusiveMinimum!==undefined&&!(value>prop.exclusiveMinimum))return false;if(prop.exclusiveMaximum!==undefined&&!(value<prop.exclusiveMaximum))return false;if(prop.multipleOf!==undefined&&value%prop.multipleOf!==0)return false;return true}const patternRegexCache=new Map;function getOrCompileRegex(pattern){let regex=patternRegexCache.get(pattern);if(regex===undefined){regex=new RegExp(pattern);patternRegexCache.set(pattern,regex)}return regex}function evaluateStringConstraints(value,prop){if(prop.minLength!==undefined&&!(value.length>=prop.minLength))return false;if(prop.maxLength!==undefined&&!(value.length<=prop.maxLength))return false;if(prop.pattern!==undefined&&!getOrCompileRegex(prop.pattern).test(value))return false;return true}function evaluateArrayConstraints(value,prop){if(prop.minItems!==undefined&&!(value.length>=prop.minItems))return false;if(prop.maxItems!==undefined&&!(value.length<=prop.maxItems))return false;if(prop.uniqueItems===true){const len=value.length;for(let i=0;i<len;i++){for(let j=i+1;j<len;j++){if(deepEqual(value[i],value[j]))return false}}}return true}function evaluateCondition(ifSchema,data){if(isPlainObj(ifSchema.properties)){const propsOk=Object.keys(ifSchema.properties).every(key=>{const propDef=ifSchema.properties?.[key];if(typeof propDef==="boolean")return true;const prop=propDef;const value=data[key];if(value===undefined)return true;if(hasOwn(prop,"const")){if(!deepEqual(value,prop.const))return false}if(hasOwn(prop,"enum")){if(!prop.enum?.some(v=>deepEqual(v,value)))return false}if(hasOwn(prop,"type")&&value!==undefined){if(!matchesType(value,prop.type))return false}if(typeof value==="number"){if(!evaluateNumericConstraints(value,prop))return false}if(typeof value==="string"){if(!evaluateStringConstraints(value,prop))return false}if(Array.isArray(value)){if(!evaluateArrayConstraints(value,prop))return false}if(prop.format!==undefined&&typeof value==="string"){const formatResult=validateFormat(value,prop.format);if(formatResult===false)return false}if(isPlainObj(prop.properties)||Array.isArray(prop.required)){if(isPlainObj(value)){if(!evaluateCondition(prop,value)){return false}}}return true});if(!propsOk)return false}if(Array.isArray(ifSchema.required)){const allRequired=ifSchema.required.every(key=>hasOwn(data,key));if(!allRequired)return false}if(Array.isArray(ifSchema.allOf)){const allMatch=ifSchema.allOf.every(entry=>{if(typeof entry==="boolean")return entry;return evaluateCondition(entry,data)});if(!allMatch)return false}if(Array.isArray(ifSchema.anyOf)){const anyMatch=ifSchema.anyOf.some(entry=>{if(typeof entry==="boolean")return entry;return evaluateCondition(entry,data)});if(!anyMatch)return false}if(Array.isArray(ifSchema.oneOf)){let matchCount=0;for(const entry of ifSchema.oneOf){const matches=typeof entry==="boolean"?entry:evaluateCondition(entry,data);if(matches)matchCount++;if(matchCount>1)break}if(matchCount!==1)return false}if(hasOwn(ifSchema,"not")&&isPlainObj(ifSchema.not)&&typeof ifSchema.not!=="boolean"){const notResult=evaluateCondition(ifSchema.not,data);if(notResult)return false}return true}const DISCRIMINANT_INDICATORS=["const","enum","minimum","maximum","exclusiveMinimum","exclusiveMaximum","pattern","minLength","maxLength","multipleOf","minItems","maxItems","format"];function extractDiscriminants(ifSchema,data,out){if(!isPlainObj(ifSchema.properties))return;const props=ifSchema.properties;for(const key of Object.keys(props)){const propDef=props[key];if(typeof propDef==="boolean")continue;const prop=propDef;const hasIndicator=DISCRIMINANT_INDICATORS.some(indicator=>hasOwn(prop,indicator));if(hasIndicator&&hasOwn(data,key)){out[key]=data[key]}}}function mergeBranchInto(resolved,branchDef,engine){if(typeof branchDef==="boolean")return;const branchSchema=branchDef;if(Array.isArray(branchSchema.required)){resolved.required=unionStrings(resolved.required??[],branchSchema.required)}if(isPlainObj(branchSchema.properties)){const branchProps=branchSchema.properties;const mergedProps={...resolved.properties??{}};for(const key of Object.keys(branchProps)){const branchProp=branchProps[key];if(branchProp===undefined)continue;const existing=resolved.properties?.[key];if(existing!==undefined&&typeof existing!=="boolean"&&typeof branchProp!=="boolean"){const merged=engine.merge(existing,branchProp);mergedProps[key]=merged??branchProp}else{mergedProps[key]=branchProp}}resolved.properties=mergedProps}if(isPlainObj(branchSchema.dependencies)){const resolvedDeps=resolved.dependencies??{};const branchDeps=branchSchema.dependencies;const acc={...resolvedDeps};for(const depKey of Object.keys(branchDeps)){const branchVal=branchDeps[depKey];if(branchVal===undefined)continue;const existingVal=acc[depKey];if(existingVal===undefined){acc[depKey]=branchVal}else if(Array.isArray(existingVal)&&Array.isArray(branchVal)){acc[depKey]=unionStrings(existingVal,branchVal)}else if(isPlainObj(existingVal)&&isPlainObj(branchVal)){const merged=engine.merge(existingVal,branchVal);acc[depKey]=merged??branchVal}else{acc[depKey]=branchVal}}resolved.dependencies=acc}for(const key of Object.keys(branchSchema)){if(SPECIAL_MERGE_KEYS.has(key))return;const branchVal=branchSchema[key];const resolvedVal=resolved[key];if(resolvedVal===undefined){resolved[key]=branchVal;return}if(deepEqual(resolvedVal,branchVal))return;if(SUB_SCHEMA_KEYS.has(key)){const merged=engine.merge(resolvedVal,branchVal);if(merged!==null){resolved[key]=merged}else{resolved[key]=branchVal}return}if(MIN_KEYS.has(key)){if(typeof resolvedVal==="number"&&typeof branchVal==="number"){resolved[key]=Math.max(resolvedVal,branchVal)}else{resolved[key]=branchVal}return}if(MAX_KEYS.has(key)){if(typeof resolvedVal==="number"&&typeof branchVal==="number"){resolved[key]=Math.min(resolvedVal,branchVal)}else{resolved[key]=branchVal}return}if(key==="uniqueItems"){resolved[key]=resolvedVal===true||branchVal===true;return}if(key==="pattern"||key==="format"){resolved[key]=branchVal;return}const base={[key]:resolvedVal};const branch={[key]:branchVal};const merged=engine.merge(base,branch);if(merged&&typeof merged!=="boolean"&&hasOwn(merged,key)){resolved[key]=merged[key]}else{resolved[key]=branchVal}}}export function resolveConditions(schema,data,engine){let branch=null;const discriminant={};const hasTopLevelIf=schema.if!==undefined;const hasAllOfConditions=Array.isArray(schema.allOf)&&schema.allOf.some(e=>typeof e!=="boolean"&&hasOwn(e,"if"));if(!hasTopLevelIf&&!hasAllOfConditions){const resolved=resolveNestedProperties(schema,data,engine,discriminant);return{resolved,branch,discriminant}}let resolved={...schema};if(hasAllOfConditions){resolved=resolveAllOfConditions(resolved,data,engine,discriminant)}if(resolved.if!==undefined){const ifSchema=resolved.if;const matches=evaluateCondition(ifSchema,data);extractDiscriminants(ifSchema,data,discriminant);const applicableBranch=matches?resolved.then:resolved.else;branch=matches?"then":"else";if(applicableBranch){mergeBranchInto(resolved,applicableBranch,engine)}delete resolved.if;delete resolved.then;delete resolved.else}resolved=resolveNestedProperties(resolved,data,engine,discriminant);return{resolved,branch,discriminant}}function resolveAllOfConditions(resolved,data,engine,discriminant){if(!Array.isArray(resolved.allOf))return resolved;const remainingAllOf=[];for(const entry of resolved.allOf){if(typeof entry==="boolean"){remainingAllOf.push(entry);continue}const subSchema=entry;if(subSchema.if===undefined){remainingAllOf.push(entry);continue}const ifSchema=subSchema.if;const matches=evaluateCondition(ifSchema,data);extractDiscriminants(ifSchema,data,discriminant);const applicableBranch=matches?subSchema.then:subSchema.else;if(applicableBranch){mergeBranchInto(resolved,applicableBranch,engine)}const remaining=omitKeys(subSchema,["if","then","else"]);if(Object.keys(remaining).length>0){remainingAllOf.push(remaining)}}resolved={...resolved};if(remainingAllOf.length===0){delete resolved.allOf}else{resolved.allOf=remainingAllOf}return resolved}function resolveNestedProperties(resolved,data,engine,discriminant){if(!isPlainObj(resolved.properties))return resolved;const props=resolved.properties;const propKeys=Object.keys(props);let changed=false;const resolvedProps={};for(const key of propKeys){const propDef=props[key];if(propDef===undefined)continue;if(typeof propDef==="boolean"){resolvedProps[key]=propDef;continue}const propSchema=propDef;const hasConditions=propSchema.if!==undefined||Array.isArray(propSchema.allOf)&&propSchema.allOf.some(e=>typeof e!=="boolean"&&hasOwn(e,"if"));if(!hasConditions){resolvedProps[key]=propDef;continue}const nestedData=isPlainObj(data[key])?data[key]:{};const nested=resolveConditions(propSchema,nestedData,engine);for(const dk of Object.keys(nested.discriminant)){discriminant[`${key}.${dk}`]=nested.discriminant[dk]}resolvedProps[key]=nested.resolved;changed=true}return changed?{...resolved,properties:resolvedProps}:resolved}
2
+ //# sourceMappingURL=condition-resolver.js.map