json-schema-compatibility-checker 1.0.0 → 1.0.2

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 (66) hide show
  1. package/dist/chunk-07z7fc5q.js +5 -0
  2. package/dist/chunk-07z7fc5q.js.map +10 -0
  3. package/dist/chunk-2ddbnbyq.js +5 -0
  4. package/dist/chunk-2ddbnbyq.js.map +10 -0
  5. package/dist/chunk-b55zsn5n.js +5 -0
  6. package/dist/chunk-b55zsn5n.js.map +10 -0
  7. package/dist/chunk-jkdzdb3r.js +5 -0
  8. package/dist/chunk-jkdzdb3r.js.map +10 -0
  9. package/dist/chunk-jybaxgmh.js +5 -0
  10. package/dist/chunk-jybaxgmh.js.map +10 -0
  11. package/dist/chunk-pyrx217p.js +5 -0
  12. package/dist/chunk-pyrx217p.js.map +10 -0
  13. package/dist/chunk-q7kq4fgq.js +5 -0
  14. package/dist/chunk-q7kq4fgq.js.map +10 -0
  15. package/dist/chunk-y8c2z1m3.js +6 -0
  16. package/dist/chunk-y8c2z1m3.js.map +10 -0
  17. package/dist/chunk-yg81ax5m.js +5 -0
  18. package/dist/chunk-yg81ax5m.js.map +10 -0
  19. package/dist/chunk-yqhv3py7.js +5 -0
  20. package/dist/chunk-yqhv3py7.js.map +10 -0
  21. package/dist/condition-resolver.js +2 -2
  22. package/dist/condition-resolver.js.map +1 -1
  23. package/dist/differ.d.ts +4 -5
  24. package/dist/differ.js +2 -2
  25. package/dist/differ.js.map +1 -1
  26. package/dist/format-validator.js +2 -2
  27. package/dist/format-validator.js.map +1 -1
  28. package/dist/formatter.js +2 -2
  29. package/dist/formatter.js.map +1 -1
  30. package/dist/index.js +2 -2
  31. package/dist/index.js.map +1 -1
  32. package/dist/json-schema-compatibility-checker.js +2 -2
  33. package/dist/json-schema-compatibility-checker.js.map +1 -1
  34. package/dist/merge-engine.js +2 -2
  35. package/dist/merge-engine.js.map +1 -1
  36. package/dist/normalizer.d.ts +7 -1
  37. package/dist/normalizer.js +2 -2
  38. package/dist/normalizer.js.map +1 -1
  39. package/dist/pattern-subset.d.ts +4 -0
  40. package/dist/pattern-subset.js +2 -2
  41. package/dist/pattern-subset.js.map +1 -1
  42. package/dist/subset-checker.d.ts +6 -1
  43. package/dist/subset-checker.js +2 -2
  44. package/dist/subset-checker.js.map +1 -1
  45. package/dist/utils.d.ts +43 -0
  46. package/dist/utils.js +4 -0
  47. package/dist/utils.js.map +9 -0
  48. package/package.json +6 -6
  49. package/dist/chunk-2vpph7cy.js +0 -5
  50. package/dist/chunk-2vpph7cy.js.map +0 -10
  51. package/dist/chunk-cspd2zw4.js +0 -6
  52. package/dist/chunk-cspd2zw4.js.map +0 -10
  53. package/dist/chunk-e4501gq7.js +0 -5
  54. package/dist/chunk-e4501gq7.js.map +0 -10
  55. package/dist/chunk-g0pfcnm5.js +0 -5
  56. package/dist/chunk-g0pfcnm5.js.map +0 -10
  57. package/dist/chunk-h080ggvf.js +0 -5
  58. package/dist/chunk-h080ggvf.js.map +0 -10
  59. package/dist/chunk-pw49kj6f.js +0 -5
  60. package/dist/chunk-pw49kj6f.js.map +0 -10
  61. package/dist/chunk-v5tqyc67.js +0 -5
  62. package/dist/chunk-v5tqyc67.js.map +0 -10
  63. package/dist/chunk-vcwsxmk4.js +0 -5
  64. package/dist/chunk-vcwsxmk4.js.map +0 -10
  65. package/dist/chunk-w7qcey06.js +0 -5
  66. package/dist/chunk-w7qcey06.js.map +0 -10
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/merge-engine.ts"],
4
+ "sourcesContent": [
5
+ "import {\n\tcreateComparator,\n\tcreateMerger,\n\tcreateShallowAllOfMerge,\n} from \"@x0k/json-schema-merge\";\nimport {\n\tcreateDeduplicator,\n\tcreateIntersector,\n} from \"@x0k/json-schema-merge/lib/array\";\n\nimport type {\n\tJSONSchema7,\n\tJSONSchema7Definition,\n\tJSONSchema7Type,\n} from \"json-schema\";\n\nimport { isFormatSubset } from \"./format-validator\";\nimport { deepEqual, hasOwn, isPlainObj } from \"./utils\";\n\n// ─── Merge Engine ────────────────────────────────────────────────────────────\n//\n// Encapsule la librairie `@x0k/json-schema-merge` et expose une API simple\n// pour merger et comparer des JSON Schemas.\n//\n// Principe mathématique :\n// A ∩ B = allOf([A, B]) résolu via shallow merge\n// A ≡ B ⟺ compare(A, B) === 0\n//\n// Pré-checks avant merge :\n// - `hasDeepConstConflict` : détecte les conflits de `const`/`enum`\n// - `hasAdditionalPropertiesConflict` : détecte les conflits `additionalProperties`\n// - `hasFormatConflict` : détecte les conflits de `format` entre deux schemas\n\n// ─── Const conflict detection ────────────────────────────────────────────────\n\n/**\n * Détecte un conflit de `const` entre deux schemas.\n *\n * Cas 1 — const vs const : les deux schemas ont un `const` avec des valeurs\n * différentes → intersection vide.\n *\n * Cas 2 — const vs enum : un schema a `const`, l'autre a `enum`.\n * Si la valeur de `const` n'est pas dans l'`enum` → intersection vide.\n *\n * Utilise `lodash/isEqual` pour la comparaison profonde (objets, tableaux).\n */\nfunction hasConstConflict(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\tif (typeof a === \"boolean\" || typeof b === \"boolean\") return false;\n\n\tconst aHasConst = hasOwn(a, \"const\");\n\tconst bHasConst = hasOwn(b, \"const\");\n\tconst aConst = (a as Record<string, unknown>).const;\n\tconst bConst = (b as Record<string, unknown>).const;\n\tconst aEnum = a.enum as unknown[] | undefined;\n\tconst bEnum = b.enum as unknown[] | undefined;\n\n\t// Cas 1 — const vs const\n\tif (aHasConst && bHasConst) {\n\t\treturn !deepEqual(aConst, bConst);\n\t}\n\n\t// Cas 2 — const vs enum\n\tif (aHasConst && Array.isArray(bEnum)) {\n\t\treturn !bEnum.some((v) => deepEqual(v, aConst));\n\t}\n\tif (bHasConst && Array.isArray(aEnum)) {\n\t\treturn !aEnum.some((v) => deepEqual(v, bConst));\n\t}\n\n\treturn false;\n}\n\n/** Mots-clés contenant un unique sous-schema à vérifier récursivement */\nconst SINGLE_SCHEMA_CONFLICT_KEYS = [\n\t\"items\",\n\t\"additionalProperties\",\n\t\"contains\",\n\t\"propertyNames\",\n\t\"not\",\n] as const;\n\n/** Mots-clés contenant un Record<string, JSONSchema7Definition> */\nconst PROPERTIES_MAP_CONFLICT_KEYS = [\n\t\"properties\",\n\t\"patternProperties\",\n] as const;\n\n/**\n * Détecte récursivement les conflits de `const` dans les sous-schemas.\n *\n * Quand la librairie de merge fait un shallow merge, les sous-schemas\n * imbriqués peuvent aussi avoir des conflits de `const` masqués\n * (elle utilise `identity` pour `const`).\n *\n * Récurse dans :\n * - `properties`, `patternProperties` (clés communes)\n * - `items` (single schema), tuple `items` (par index)\n * - `additionalProperties`, `contains`, `propertyNames`, `not`\n */\nfunction hasDeepConstConflict(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\tif (hasConstConflict(a, b)) return true;\n\n\tif (typeof a === \"boolean\" || typeof b === \"boolean\") return false;\n\n\t// ── Single sub-schema keywords ──\n\tfor (const key of SINGLE_SCHEMA_CONFLICT_KEYS) {\n\t\tconst aVal = (a as Record<string, unknown>)[key] as\n\t\t\t| JSONSchema7Definition\n\t\t\t| undefined;\n\t\tconst bVal = (b as Record<string, unknown>)[key] as\n\t\t\t| JSONSchema7Definition\n\t\t\t| undefined;\n\t\tif (\n\t\t\tisPlainObj(aVal) &&\n\t\t\tisPlainObj(bVal) &&\n\t\t\thasDeepConstConflict(\n\t\t\t\taVal as JSONSchema7Definition,\n\t\t\t\tbVal as JSONSchema7Definition,\n\t\t\t)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// ── Properties-like maps (properties, patternProperties) ──\n\tfor (const key of PROPERTIES_MAP_CONFLICT_KEYS) {\n\t\tconst aMap = (a as Record<string, unknown>)[key] as\n\t\t\t| Record<string, JSONSchema7Definition>\n\t\t\t| undefined;\n\t\tconst bMap = (b as Record<string, unknown>)[key] as\n\t\t\t| Record<string, JSONSchema7Definition>\n\t\t\t| undefined;\n\t\tif (!isPlainObj(aMap) || !isPlainObj(bMap)) continue;\n\t\tconst aMapSafe = aMap as Record<string, JSONSchema7Definition>;\n\t\tconst bMapSafe = bMap as Record<string, JSONSchema7Definition>;\n\t\tfor (const propKey of Object.keys(aMapSafe)) {\n\t\t\tconst aVal = aMapSafe[propKey];\n\t\t\tconst bVal = bMapSafe[propKey];\n\t\t\tif (\n\t\t\t\taVal !== undefined &&\n\t\t\t\tbVal !== undefined &&\n\t\t\t\thasOwn(bMapSafe, propKey) &&\n\t\t\t\thasDeepConstConflict(aVal, bVal)\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Tuple items (array of schemas, compared by index) ──\n\tif (Array.isArray(a.items) && Array.isArray(b.items)) {\n\t\tconst aItems = a.items as JSONSchema7Definition[];\n\t\tconst bItems = b.items as JSONSchema7Definition[];\n\t\tconst len = Math.min(aItems.length, bItems.length);\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tconst aItem = aItems[i];\n\t\t\tconst bItem = bItems[i];\n\t\t\tif (aItem === undefined || bItem === undefined) continue;\n\t\t\tif (hasDeepConstConflict(aItem, bItem)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n// ─── additionalProperties conflict detection ─────────────────────────────────\n\n/**\n * Détecte un conflit entre `additionalProperties` et les propriétés extra\n * **requises** de l'autre schema.\n *\n * ⚠️ Cette fonction est **ultra-conservatrice** : elle ne détecte que les\n * conflits où une propriété est à la fois :\n * - INTERDITE par `additionalProperties: false` d'un côté\n * - REQUISE (`required`) par l'autre côté\n * - ABSENTE des `properties` du côté restrictif\n * - ET le côté restrictif AUSSI a un `required` qui rend l'objet non-vide\n * (sinon la librairie gère déjà le cas en excluant les propriétés extra)\n *\n * La librairie de merge (`@x0k/json-schema-merge`) gère DÉJÀ correctement\n * le cas `additionalProperties: false` avec des propriétés simplement DÉFINIES\n * (non requises) dans l'autre schema — elle les exclut du résultat.\n * On ne détecte donc QUE les contradictions `required` impossibles à résoudre.\n *\n * Cas gérés :\n * 1. `a` a `additionalProperties: false` et `b` REQUIERT des propriétés\n * absentes de `a.properties`, ET ces propriétés sont dans `b.properties`\n * → conflit certain (intersection vide car b exige, a interdit)\n * 2. Symétrique pour `b.additionalProperties: false`\n * 3. `additionalProperties` comme schema → vérifier la compatibilité de type\n * des propriétés extra REQUISES uniquement\n * 4. Récursion dans les propriétés communes (sous-objets)\n *\n * ⚠️ Ne vérifie que les clés de `properties`, pas les `patternProperties`\n * (trop complexe à résoudre statiquement).\n *\n * Retourne `true` si un conflit évident est détecté, `false` sinon.\n * En cas de doute → `false` (conservateur, laisser le merge décider).\n *\n * Utilise `_.keys`, `_.some`, `_.every`, `_.has`, `_.get`, `_.isPlainObject`,\n * `_.includes` pour des vérifications concises.\n */\nfunction hasAdditionalPropertiesConflict(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\tif (typeof a === \"boolean\" || typeof b === \"boolean\") return false;\n\n\tconst aProps = isPlainObj(a.properties)\n\t\t? (a.properties as Record<string, JSONSchema7Definition>)\n\t\t: undefined;\n\tconst bProps = isPlainObj(b.properties)\n\t\t? (b.properties as Record<string, JSONSchema7Definition>)\n\t\t: undefined;\n\n\t// Si aucun des deux n'a de properties, on ne peut rien déterminer\n\tif (!aProps && !bProps) return false;\n\n\tconst aKeys = aProps ? Object.keys(aProps) : [];\n\tconst bKeys = bProps ? Object.keys(bProps) : [];\n\tconst aRequired = Array.isArray(a.required) ? (a.required as string[]) : [];\n\tconst bRequired = Array.isArray(b.required) ? (b.required as string[]) : [];\n\n\t// ── Vérifier additionalProperties: false de a vs propriétés REQUISES extra de b ──\n\t// Condition stricte : b doit DÉFINIR la propriété dans b.properties ET la\n\t// REQUÉRIR dans b.required, ET cette propriété doit être ABSENTE de a.properties.\n\t// De plus, a doit lui-même avoir des propriétés (sinon on ne peut rien dire).\n\tif (a.additionalProperties === false && aProps && bProps) {\n\t\tconst hasRequiredExtra = bRequired.some(\n\t\t\t(k) => !hasOwn(aProps, k) && hasOwn(bProps, k),\n\t\t);\n\t\t// Ne détecter le conflit que si a a aussi un required qui rend l'objet\n\t\t// structurellement contraint (pas un schema vague)\n\t\tif (hasRequiredExtra && aKeys.length > 0) return true;\n\t}\n\n\t// ── Vérification du cas additionalProperties comme schema ──\n\t// Si a.additionalProperties est un schema avec un type, et que b REQUIERT\n\t// une propriété extra dont le type est incompatible → conflit\n\tif (\n\t\tisPlainObj(a.additionalProperties) &&\n\t\ttypeof a.additionalProperties !== \"boolean\" &&\n\t\taProps &&\n\t\tbProps\n\t) {\n\t\tconst addPropsSchema = a.additionalProperties as JSONSchema7;\n\t\tif (hasOwn(addPropsSchema, \"type\")) {\n\t\t\tconst addPropsType = addPropsSchema.type;\n\t\t\tconst hasTypeConflict = bRequired.some((k) => {\n\t\t\t\tif (hasOwn(aProps, k)) return false;\n\t\t\t\tif (!hasOwn(bProps, k)) return false;\n\t\t\t\tconst bPropDef = bProps[k];\n\t\t\t\tif (typeof bPropDef === \"boolean\") return false;\n\t\t\t\tconst bProp = bPropDef as JSONSchema7;\n\t\t\t\tif (!hasOwn(bProp, \"type\")) return false;\n\t\t\t\tif (\n\t\t\t\t\ttypeof addPropsType === \"string\" &&\n\t\t\t\t\ttypeof bProp.type === \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\taddPropsType !== bProp.type &&\n\t\t\t\t\t\t!(addPropsType === \"number\" && bProp.type === \"integer\") &&\n\t\t\t\t\t\t!(addPropsType === \"integer\" && bProp.type === \"number\")\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t});\n\t\t\tif (hasTypeConflict) return true;\n\t\t}\n\t}\n\n\t// ── Vérification symétrique : additionalProperties de b vs propriétés REQUISES extra de a ──\n\tif (b.additionalProperties === false && bProps && aProps) {\n\t\tconst hasRequiredExtra = aRequired.some(\n\t\t\t(k) => !hasOwn(bProps, k) && hasOwn(aProps, k),\n\t\t);\n\t\tif (hasRequiredExtra && bKeys.length > 0) return true;\n\t}\n\n\t// Symétrique pour additionalProperties comme schema\n\tif (\n\t\tisPlainObj(b.additionalProperties) &&\n\t\ttypeof b.additionalProperties !== \"boolean\" &&\n\t\tbProps &&\n\t\taProps\n\t) {\n\t\tconst addPropsSchema = b.additionalProperties as JSONSchema7;\n\t\tif (hasOwn(addPropsSchema, \"type\")) {\n\t\t\tconst addPropsType = addPropsSchema.type;\n\t\t\tconst hasTypeConflict = aRequired.some((k) => {\n\t\t\t\tif (hasOwn(bProps, k)) return false;\n\t\t\t\tif (!hasOwn(aProps, k)) return false;\n\t\t\t\tconst aPropDef = aProps[k];\n\t\t\t\tif (typeof aPropDef === \"boolean\") return false;\n\t\t\t\tconst aProp = aPropDef as JSONSchema7;\n\t\t\t\tif (!hasOwn(aProp, \"type\")) return false;\n\t\t\t\tif (\n\t\t\t\t\ttypeof addPropsType === \"string\" &&\n\t\t\t\t\ttypeof aProp.type === \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\taddPropsType !== aProp.type &&\n\t\t\t\t\t\t!(addPropsType === \"number\" && aProp.type === \"integer\") &&\n\t\t\t\t\t\t!(addPropsType === \"integer\" && aProp.type === \"number\")\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t});\n\t\t\tif (hasTypeConflict) return true;\n\t\t}\n\t}\n\n\t// ── Récursion dans les propriétés communes ──\n\t// Si les deux schemas ont des propriétés communes qui sont des objets,\n\t// vérifier récursivement les conflits additionalProperties\n\tif (aProps && bProps) {\n\t\tfor (const k of aKeys) {\n\t\t\tif (!hasOwn(bProps, k)) continue;\n\t\t\tconst aPropDef = aProps[k];\n\t\t\tconst bPropDef = bProps[k];\n\t\t\tif (typeof aPropDef === \"boolean\" || typeof bPropDef === \"boolean\")\n\t\t\t\tcontinue;\n\t\t\tif (\n\t\t\t\thasAdditionalPropertiesConflict(\n\t\t\t\t\taPropDef as JSONSchema7Definition,\n\t\t\t\t\tbPropDef as JSONSchema7Definition,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n// ─── Format conflict detection ───────────────────────────────────────────────\n\n/**\n * Détecte un conflit de format entre deux schemas.\n *\n * ⚠️ Ne se déclenche QUE quand les DEUX schemas ont un `format`.\n * Si un seul schema a un `format`, il n'y a PAS de conflit — le merge\n * engine gère nativement ce cas (le format est conservé dans l'intersection,\n * et la comparaison `merged ≡ sub` détermine correctement la relation ⊆).\n *\n * Deux schemas avec des formats différents et sans relation d'inclusion\n * connue ont une intersection vide (ex: \"email\" ∩ \"ipv4\" = ∅).\n *\n * Utilise `isFormatSubset` de `format-validator.ts` pour vérifier la hiérarchie.\n *\n * Récurse dans les sous-schemas (`properties`, `items`, etc.) pour détecter\n * les conflits de format imbriqués.\n *\n * @returns `true` si un conflit de format est détecté, `false` sinon\n */\nfunction hasFormatConflict(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\tif (typeof a === \"boolean\" || typeof b === \"boolean\") return false;\n\n\t// ── Seulement quand LES DEUX ont un format ──\n\t// Si un seul a un format → pas de conflit, le merge gère nativement\n\tif (hasOwn(a, \"format\") && hasOwn(b, \"format\")) {\n\t\tconst aFormat = a.format as string;\n\t\tconst bFormat = b.format as string;\n\n\t\t// Même format → pas de conflit\n\t\tif (aFormat !== bFormat) {\n\t\t\t// Vérifier si l'un est un sous-ensemble de l'autre via la hiérarchie\n\t\t\tconst subsetCheck = isFormatSubset(aFormat, bFormat);\n\t\t\tif (subsetCheck !== true) {\n\t\t\t\tconst reverseCheck = isFormatSubset(bFormat, aFormat);\n\t\t\t\tif (reverseCheck !== true) {\n\t\t\t\t\t// Formats différents sans relation connue → conflit\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Récursion dans les sous-schemas ──\n\t// Vérifier les conflits de format dans les propriétés communes\n\tif (isPlainObj(a.properties) && isPlainObj(b.properties)) {\n\t\tconst aMap = a.properties as Record<string, JSONSchema7Definition>;\n\t\tconst bMap = b.properties as Record<string, JSONSchema7Definition>;\n\t\tfor (const k of Object.keys(aMap)) {\n\t\t\tconst aVal = aMap[k];\n\t\t\tconst bVal = bMap[k];\n\t\t\tif (\n\t\t\t\taVal !== undefined &&\n\t\t\t\tbVal !== undefined &&\n\t\t\t\thasOwn(bMap, k) &&\n\t\t\t\thasFormatConflict(aVal, bVal)\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Vérifier items (single schema)\n\tif (isPlainObj(a.items) && isPlainObj(b.items)) {\n\t\tif (\n\t\t\thasFormatConflict(\n\t\t\t\ta.items as JSONSchema7Definition,\n\t\t\t\tb.items as JSONSchema7Definition,\n\t\t\t)\n\t\t)\n\t\t\treturn true;\n\t}\n\n\t// Vérifier additionalProperties\n\tif (\n\t\tisPlainObj(a.additionalProperties) &&\n\t\tisPlainObj(b.additionalProperties)\n\t) {\n\t\tif (\n\t\t\thasFormatConflict(\n\t\t\t\ta.additionalProperties as JSONSchema7Definition,\n\t\t\t\tb.additionalProperties as JSONSchema7Definition,\n\t\t\t)\n\t\t)\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n// ─── MergeEngine class ───────────────────────────────────────────────────────\n\nexport class MergeEngine {\n\tprivate readonly compareFn: (\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t) => number;\n\n\tprivate readonly shallowAllOfMergeFn: (\n\t\tschema: JSONSchema7 & { allOf: JSONSchema7Definition[] },\n\t) => JSONSchema7Definition;\n\n\tconstructor() {\n\t\tconst { compareSchemaDefinitions, compareSchemaValues } =\n\t\t\tcreateComparator();\n\n\t\t// ── Null-safe wrapper for compareSchemaValues ──\n\t\t// The library's compareSchemaValues has a bug: when both a and b are null,\n\t\t// it returns -1 instead of 0 (the null check for `a` fires before checking\n\t\t// if `b` is also null). This causes createIntersector to lose null values\n\t\t// during enum intersection (the sort-merge join relies on compare(x,x)===0).\n\t\tconst safeCompareSchemaValues = (\n\t\t\ta: JSONSchema7Type,\n\t\t\tb: JSONSchema7Type,\n\t\t): number => {\n\t\t\tif (a === null && b === null) return 0;\n\t\t\treturn compareSchemaValues(a, b);\n\t\t};\n\n\t\tconst { mergeArrayOfSchemaDefinitions } = createMerger({\n\t\t\tintersectJson: createIntersector(safeCompareSchemaValues),\n\t\t\tdeduplicateJsonSchemaDef: createDeduplicator(compareSchemaDefinitions),\n\t\t});\n\n\t\tthis.compareFn = compareSchemaDefinitions;\n\t\tthis.shallowAllOfMergeFn = createShallowAllOfMerge(\n\t\t\tmergeArrayOfSchemaDefinitions,\n\t\t);\n\t}\n\n\t/**\n\t * Merge deux schemas via `allOf([a, b])`.\n\t * Retourne `null` si les schemas sont incompatibles.\n\t *\n\t * Post-merge : détecte les conflits de `const` que la librairie\n\t * ne capture pas (elle utilise `identity` pour `const`).\n\t */\n\tmerge(\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t): JSONSchema7Definition | null {\n\t\t// Pré-check : conflit de const détectable avant le merge\n\t\tif (hasDeepConstConflict(a, b)) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Pré-check : conflit de format (les DEUX ont un format incompatible)\n\t\tif (hasFormatConflict(a, b)) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Pré-check : conflit additionalProperties vs propriétés REQUISES extra\n\t\t// Ne détecte que les cas où une propriété est à la fois interdite\n\t\t// (additionalProperties: false) et requise (required) → intersection vide.\n\t\t// Les cas où les propriétés sont simplement définies sans être requises\n\t\t// sont gérés correctement par la librairie de merge elle-même.\n\t\tif (hasAdditionalPropertiesConflict(a, b)) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\treturn this.shallowAllOfMergeFn({ allOf: [a, b] });\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Merge via `shallowAllOfMerge` — lève une exception si incompatible.\n\t * Utile quand on veut capturer l'erreur pour le diagnostic.\n\t *\n\t * Post-merge : détecte les conflits de `const` et lève une exception.\n\t */\n\tmergeOrThrow(\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t): JSONSchema7Definition {\n\t\t// Pré-check : conflit de const\n\t\tif (hasDeepConstConflict(a, b)) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Incompatible const values: schemas have conflicting const constraints\",\n\t\t\t);\n\t\t}\n\n\t\t// Pré-check : conflit de format\n\t\tif (hasFormatConflict(a, b)) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Incompatible format values: schemas have conflicting format constraints\",\n\t\t\t);\n\t\t}\n\n\t\t// Pré-check : conflit additionalProperties vs propriétés REQUISES extra\n\t\tif (hasAdditionalPropertiesConflict(a, b)) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Incompatible additionalProperties: required properties conflict with additionalProperties constraint\",\n\t\t\t);\n\t\t}\n\n\t\treturn this.shallowAllOfMergeFn({ allOf: [a, b] });\n\t}\n\n\t/**\n\t * Compare structurellement deux schema definitions.\n\t * Retourne 0 si elles sont identiques, sinon un entier non nul.\n\t */\n\tcompare(a: JSONSchema7Definition, b: JSONSchema7Definition): number {\n\t\treturn this.compareFn(a, b);\n\t}\n\n\t/**\n\t * Vérifie l'égalité structurelle entre deux schema definitions.\n\t */\n\tisEqual(a: JSONSchema7Definition, b: JSONSchema7Definition): boolean {\n\t\treturn this.compareFn(a, b) === 0;\n\t}\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "4666F85E3B6FD5BA64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,5 @@
1
+ import{v as N,w as W,x as F}from"./chunk-jkdzdb3r.js";var j=new WeakMap;function T(J){if(J===null)return"null";switch(typeof J){case"string":return"string";case"number":return Number.isInteger(J)?"integer":"number";case"boolean":return"boolean";case"object":return Array.isArray(J)?"array":"object";default:return}}var _=["additionalProperties","additionalItems","contains","propertyNames","not","if","then","else"],R=new Set(["$id","$schema","$comment","title","description","default","examples","definitions","$defs"]);function A(J){return Object.keys(J).every((x)=>x==="not"||R.has(x))}var D=["anyOf","oneOf","allOf"],K=["properties","patternProperties"];function P(J){let Z=Object.keys(J),x=!1;for(let Q=0;Q<Z.length;Q++){let G=Z[Q];if(G===void 0)continue;let I=J[G];if(M(I)!==I){x=!0;break}}if(!x)return J;let L={};for(let Q=0;Q<Z.length;Q++){let G=Z[Q];if(G===void 0)continue;L[G]=M(J[G])}return L}function w(J){if(!W(J,"const")||J.type!==void 0)return;let Z=T(J.const);return Z?Z:void 0}function E(J){if(!Array.isArray(J.enum)||J.type!==void 0)return;let Z=new Set;for(let Q of J.enum){let G=T(Q);if(G)Z.add(G)}let x=Z.size;if(x===0)return;let L=Array.from(Z);if(x===1)return L[0];return L}function M(J){if(typeof J==="boolean")return J;let Z=j.get(J);if(Z!==void 0)return Z;let x=J,L=!1;function Q(){if(!L)x={...J},L=!0;return x}let G=w(x);if(G)Q().type=G;let I=E(x);if(I)Q().type=I;if(Array.isArray(x.enum)&&x.enum.length===1&&!W(x,"const")){let B=Q();B.const=x.enum[0],delete B.enum}if(W(x,"const")&&Array.isArray(x.enum)){if(x.enum.some((B)=>F(B,x.const)))delete Q().enum}for(let B of K){let U=x[B];if(N(U)){let V=P(U);if(V!==U)Q()[B]=V}}if(N(x.dependencies)){let B=x.dependencies,U=Object.keys(B),V=!1,$={};for(let q=0;q<U.length;q++){let X=U[q];if(X===void 0)continue;let H=B[X];if(H===void 0)continue;if(Array.isArray(H))$[X]=H;else if(N(H)){let Y=M(H);if($[X]=Y,Y!==H)V=!0}else $[X]=H}if(V)Q().dependencies=$}if(x.items){if(Array.isArray(x.items)){let B=x.items,U=!1,V=Array(B.length);for(let $=0;$<B.length;$++){let q=B[$];if(q===void 0)continue;let X=M(q);if(V[$]=X,X!==q)U=!0}if(U)Q().items=V}else if(N(x.items)){let B=M(x.items);if(B!==x.items)Q().items=B}}for(let B of _){let U=x[B];if(U!==void 0&&typeof U!=="boolean"){let V=M(U);if(V!==U)Q()[B]=V}}if(W(x,"not")&&N(x.not)&&typeof x.not!=="boolean"){let B=x.not;if(W(B,"not")&&A(B)&&N(B.not)&&typeof B.not!=="boolean"){let U=B.not,V=Q();delete V.not;let $=Object.keys(U);for(let q=0;q<$.length;q++){let X=$[q];if(X===void 0)continue;V[X]=U[X]}}}for(let B of D){let U=x[B];if(Array.isArray(U)){let V=U,$=!1,q=Array(V.length);for(let X=0;X<V.length;X++){let H=V[X];if(H===void 0)continue;let Y=M(H);if(q[X]=Y,Y!==H)$=!0}if($)Q()[B]=q}}let b=L?x:J;return j.set(J,b),b}
2
+ export{T as t,M as u};
3
+
4
+ //# debugId=B3ACDF5B982F389D64756E2164756E21
5
+ //# sourceMappingURL=chunk-yqhv3py7.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/normalizer.ts"],
4
+ "sourcesContent": [
5
+ "import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { deepEqual, hasOwn, isPlainObj } from \"./utils\";\n\n// ─── Schema Normalizer ───────────────────────────────────────────────────────\n//\n// Fonctions pures pour normaliser un JSON Schema :\n// - Inférer `type` depuis `const` ou `enum`\n// - Récurser dans toutes les sous-structures (properties, items, anyOf, etc.)\n// - Résoudre la double négation `not.not` → aplatir en contenu direct\n// - Récurser dans `patternProperties` (Point 2)\n// - Récurser dans `dependencies` forme schema (Point 3)\n//\n// Optimisations :\n// - WeakMap cache pour éviter de re-normaliser le même objet\n// - Lazy copy-on-write : ne crée une copie que si des mutations sont nécessaires\n// - Retourne l'original si rien n'a changé (évite les allocations)\n\n// ─── Normalization Cache ─────────────────────────────────────────────────────\n\n/**\n * Cache WeakMap pour les résultats de normalisation.\n * Évite de re-normaliser le même objet schema plusieurs fois.\n * WeakMap permet au GC de collecter les schemas qui ne sont plus référencés.\n */\nconst normalizeCache = new WeakMap<object, JSONSchema7Definition>();\n\n// ─── Type inference ──────────────────────────────────────────────────────────\n\n/**\n * Infère le type JSON Schema d'une valeur JavaScript.\n */\nexport function inferType(value: unknown): string | undefined {\n\tif (value === null) return \"null\";\n\tswitch (typeof value) {\n\t\tcase \"string\":\n\t\t\treturn \"string\";\n\t\tcase \"number\":\n\t\t\treturn Number.isInteger(value) ? \"integer\" : \"number\";\n\t\tcase \"boolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"object\":\n\t\t\treturn Array.isArray(value) ? \"array\" : \"object\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\n// ─── Sub-schema keywords ─────────────────────────────────────────────────────\n\n/** Mots-clés contenant un unique sous-schema */\nconst SINGLE_SCHEMA_KEYWORDS = [\n\t\"additionalProperties\",\n\t\"additionalItems\",\n\t\"contains\",\n\t\"propertyNames\",\n\t\"not\",\n\t\"if\",\n\t\"then\",\n\t\"else\",\n] as const;\n\n/**\n * Vérifie si un schema ne contient qu'un seul mot-clé `not` (et aucun\n * autre mot-clé significatif). Utilisé pour la résolution de double négation.\n *\n * Un schema « pur not » est de la forme `{ not: X }` sans aucune autre\n * contrainte. Dans ce cas, `{ not: { not: Y } }` ≡ `Y`.\n *\n * Les mots-clés de métadonnée (`$id`, `$schema`, `$comment`, `title`,\n * `description`, `default`, `examples`, `definitions`, `$defs`) ne sont\n * PAS considérés comme significatifs pour cette détection.\n */\nconst METADATA_KEYWORDS = new Set([\n\t\"$id\",\n\t\"$schema\",\n\t\"$comment\",\n\t\"title\",\n\t\"description\",\n\t\"default\",\n\t\"examples\",\n\t\"definitions\",\n\t\"$defs\",\n]);\n\n/**\n * Vérifie si un objet schema ne contient que le mot-clé `not`\n * (plus éventuellement des métadonnées non significatives).\n */\nfunction isPureNotSchema(schema: JSONSchema7): boolean {\n\tconst schemaKeys = Object.keys(schema);\n\treturn schemaKeys.every((k) => k === \"not\" || METADATA_KEYWORDS.has(k));\n}\n\n/** Mots-clés contenant un tableau de sous-schemas */\nconst ARRAY_SCHEMA_KEYWORDS = [\"anyOf\", \"oneOf\", \"allOf\"] as const;\n\n/**\n * Mots-clés contenant un Record<string, JSONSchema7Definition>\n * (chaque valeur est un sous-schema à normaliser récursivement).\n */\nconst PROPERTIES_LIKE_KEYWORDS = [\"properties\", \"patternProperties\"] as const;\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\n/**\n * Normalise un `Record<string, JSONSchema7Definition>` en appliquant\n * `normalize` à chaque valeur.\n * Retourne l'objet original si rien n'a changé (évite les allocations).\n */\nfunction normalizePropertiesMap(\n\tprops: Record<string, JSONSchema7Definition>,\n): Record<string, JSONSchema7Definition> {\n\tconst keys = Object.keys(props);\n\tlet changed = false;\n\n\t// First pass: detect if anything changes (sub-schemas get cached)\n\tfor (let i = 0; i < keys.length; i++) {\n\t\tconst key = keys[i];\n\t\tif (key === undefined) continue;\n\t\tconst original = props[key];\n\t\tconst normalized = normalize(original as JSONSchema7Definition);\n\t\tif (normalized !== original) {\n\t\t\tchanged = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!changed) return props;\n\n\t// Build result only when something changed (sub normalize calls hit cache)\n\tconst result: Record<string, JSONSchema7Definition> = {};\n\tfor (let i = 0; i < keys.length; i++) {\n\t\tconst key = keys[i];\n\t\tif (key === undefined) continue;\n\t\tresult[key] = normalize(props[key] as JSONSchema7Definition);\n\t}\n\n\treturn result;\n}\n\n/**\n * Infère le `type` depuis `const` si absent.\n * Retourne le type inféré ou undefined si non applicable.\n */\nfunction inferTypeFromConst(\n\tschema: JSONSchema7,\n): JSONSchema7[\"type\"] | undefined {\n\tif (!hasOwn(schema, \"const\") || schema.type !== undefined) return undefined;\n\tconst t = inferType(schema.const);\n\treturn t ? (t as JSONSchema7[\"type\"]) : undefined;\n}\n\n/**\n * Infère le `type` depuis `enum` si absent.\n * Retourne le type inféré (single ou array) ou undefined si non applicable.\n */\nfunction inferTypeFromEnum(\n\tschema: JSONSchema7,\n): JSONSchema7[\"type\"] | undefined {\n\tif (!Array.isArray(schema.enum) || schema.type !== undefined)\n\t\treturn undefined;\n\n\tconst typesSet = new Set<string>();\n\tfor (const v of schema.enum) {\n\t\tconst t = inferType(v);\n\t\tif (t) typesSet.add(t);\n\t}\n\n\tconst count = typesSet.size;\n\tif (count === 0) return undefined;\n\n\tconst types = Array.from(typesSet);\n\tif (count === 1) return types[0] as JSONSchema7[\"type\"];\n\treturn types as JSONSchema7[\"type\"];\n}\n\n// ─── Normalization ───────────────────────────────────────────────────────────\n\n/**\n * Normalise un schema : infère `type` depuis `const`/`enum`,\n * et normalise récursivement tous les sous-schemas.\n *\n * Récurse dans :\n * - `properties` et `patternProperties` (Point 2)\n * - `dependencies` forme schema (Point 3) — les valeurs tableau (forme 1)\n * sont laissées intactes\n * - `items` (single ou tuple)\n * - Mots-clés single-schema (`additionalProperties`, `not`, `if`, etc.)\n * - Mots-clés array-of-schema (`anyOf`, `oneOf`, `allOf`)\n *\n * Optimisations :\n * - WeakMap cache : retourne le résultat mis en cache en O(1)\n * - Lazy copy-on-write : ne crée une copie shallow que quand la première\n * mutation est nécessaire, via `ensureCopy()`\n * - Les sous-structures ne sont remplacées que si effectivement changées\n */\nexport function normalize(def: JSONSchema7Definition): JSONSchema7Definition {\n\tif (typeof def === \"boolean\") return def;\n\n\t// ── Cache lookup (O(1) fast path) ──\n\tconst cached = normalizeCache.get(def);\n\tif (cached !== undefined) return cached;\n\n\t// ── Lazy copy-on-write ──\n\t// We delay creating a shallow copy until the first actual mutation.\n\t// `schema` starts as `def` and only becomes a copy when `ensureCopy()` is called.\n\tlet schema = def as JSONSchema7 & Record<string, unknown>;\n\tlet copied = false;\n\n\tfunction ensureCopy(): JSONSchema7 & Record<string, unknown> {\n\t\tif (!copied) {\n\t\t\tschema = { ...(def as JSONSchema7) } as JSONSchema7 &\n\t\t\t\tRecord<string, unknown>;\n\t\t\tcopied = true;\n\t\t}\n\t\treturn schema;\n\t}\n\n\t// ── Inférer type depuis const ──\n\tconst typeFromConst = inferTypeFromConst(schema);\n\tif (typeFromConst) {\n\t\tensureCopy().type = typeFromConst;\n\t}\n\n\t// ── Inférer type depuis enum ──\n\tconst typeFromEnum = inferTypeFromEnum(schema);\n\tif (typeFromEnum) {\n\t\tensureCopy().type = typeFromEnum;\n\t}\n\n\t// ── Convertir enum à un seul élément en const ──\n\t// Sémantiquement, { enum: [X] } ≡ { const: X }.\n\t// Cette normalisation garantit que la comparaison structurelle\n\t// (isEqual) ne produit pas de faux négatifs quand un schema utilise\n\t// enum et l'autre utilise const pour la même valeur.\n\tif (\n\t\tArray.isArray(schema.enum) &&\n\t\tschema.enum.length === 1 &&\n\t\t!hasOwn(schema, \"const\")\n\t) {\n\t\tconst s = ensureCopy();\n\t\ts.const = schema.enum[0];\n\t\tdelete s.enum;\n\t}\n\n\t// ── Strip redundant enum when const is present ──\n\t// Si `const: X` et `enum: [... X ...]` coexistent, `const` est plus\n\t// restrictif → `enum` est redondant. Le merge engine peut produire\n\t// cette combinaison lors de l'intersection const ∩ enum.\n\tif (hasOwn(schema, \"const\") && Array.isArray(schema.enum)) {\n\t\tif (schema.enum.some((v) => deepEqual(v, schema.const))) {\n\t\t\tdelete ensureCopy().enum;\n\t\t}\n\t}\n\n\t// ── Récurser dans properties & patternProperties (Point 2) ──\n\tfor (const keyword of PROPERTIES_LIKE_KEYWORDS) {\n\t\tconst val = schema[keyword];\n\t\tif (isPlainObj(val)) {\n\t\t\tconst normalized = normalizePropertiesMap(\n\t\t\t\tval as Record<string, JSONSchema7Definition>,\n\t\t\t);\n\t\t\tif (normalized !== val) {\n\t\t\t\tensureCopy()[keyword] = normalized as JSONSchema7[\"properties\"];\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Récurser dans dependencies (Point 3) ──\n\t// `dependencies` peut contenir :\n\t// - Forme 1 (property deps) : { foo: [\"bar\", \"baz\"] } → tableau de strings, on skip\n\t// - Forme 2 (schema deps) : { foo: { required: [...] } } → objet schema, on normalise\n\tif (isPlainObj(schema.dependencies)) {\n\t\tconst deps = schema.dependencies as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition | string[]\n\t\t>;\n\t\tconst depsKeys = Object.keys(deps);\n\t\tlet depsChanged = false;\n\t\tconst newDeps: Record<string, JSONSchema7Definition | string[]> = {};\n\n\t\tfor (let i = 0; i < depsKeys.length; i++) {\n\t\t\tconst key = depsKeys[i];\n\t\t\tif (key === undefined) continue;\n\t\t\tconst val = deps[key];\n\t\t\tif (val === undefined) continue;\n\t\t\tif (Array.isArray(val)) {\n\t\t\t\t// Forme 1 : tableau de strings → laisser tel quel\n\t\t\t\tnewDeps[key] = val;\n\t\t\t} else if (isPlainObj(val)) {\n\t\t\t\t// Forme 2 : sous-schema → normaliser récursivement\n\t\t\t\tconst normalized = normalize(val as JSONSchema7Definition);\n\t\t\t\tnewDeps[key] = normalized;\n\t\t\t\tif (normalized !== val) depsChanged = true;\n\t\t\t} else {\n\t\t\t\tnewDeps[key] = val as JSONSchema7Definition;\n\t\t\t}\n\t\t}\n\n\t\tif (depsChanged) {\n\t\t\tensureCopy().dependencies = newDeps;\n\t\t}\n\t}\n\n\t// ── Récurser dans items (tuple ou single) ──\n\tif (schema.items) {\n\t\tif (Array.isArray(schema.items)) {\n\t\t\t// Tuple : normaliser chaque élément\n\t\t\tconst items = schema.items as JSONSchema7Definition[];\n\t\t\tlet itemsChanged = false;\n\t\t\tconst newItems: JSONSchema7Definition[] = new Array(items.length);\n\n\t\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\t\tconst original = items[i];\n\t\t\t\tif (original === undefined) continue;\n\t\t\t\tconst normalized = normalize(original);\n\t\t\t\tnewItems[i] = normalized;\n\t\t\t\tif (normalized !== original) itemsChanged = true;\n\t\t\t}\n\n\t\t\tif (itemsChanged) {\n\t\t\t\tensureCopy().items = newItems;\n\t\t\t}\n\t\t} else if (isPlainObj(schema.items)) {\n\t\t\t// Single items schema\n\t\t\tconst normalized = normalize(schema.items as JSONSchema7Definition);\n\t\t\tif (normalized !== schema.items) {\n\t\t\t\tensureCopy().items = normalized;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Récurser dans les mots-clés single-schema ──\n\tfor (const key of SINGLE_SCHEMA_KEYWORDS) {\n\t\tconst val = schema[key];\n\t\tif (val !== undefined && typeof val !== \"boolean\") {\n\t\t\tconst normalized = normalize(val as JSONSchema7Definition);\n\t\t\tif (normalized !== val) {\n\t\t\t\t(ensureCopy() as Record<string, JSONSchema7Definition>)[key] =\n\t\t\t\t\tnormalized;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Résoudre la double négation not(not(X)) → X ──\n\t// Après la récursion dans les sous-schemas, `schema.not` est normalisé.\n\t// Si `schema.not` est un objet qui ne contient QUE `not` (un « pur not »),\n\t// alors `{ ...rest, not: { not: X } }` ≡ `{ ...rest, ...X }`.\n\t//\n\t// Logique propositionnelle : ¬¬P ≡ P\n\t//\n\t// On ne résout que le cas « pur » (schema.not n'a que `not` comme clé\n\t// significative) pour éviter les faux-positifs dans les cas complexes.\n\tif (\n\t\thasOwn(schema, \"not\") &&\n\t\tisPlainObj(schema.not) &&\n\t\ttypeof schema.not !== \"boolean\"\n\t) {\n\t\tconst notSchema = schema.not as JSONSchema7;\n\t\tif (\n\t\t\thasOwn(notSchema, \"not\") &&\n\t\t\tisPureNotSchema(notSchema) &&\n\t\t\tisPlainObj(notSchema.not) &&\n\t\t\ttypeof notSchema.not !== \"boolean\"\n\t\t) {\n\t\t\t// Extraire le contenu de not.not et le fusionner avec le reste du schema\n\t\t\tconst innerSchema = notSchema.not as JSONSchema7;\n\t\t\tconst s = ensureCopy();\n\t\t\t// Retirer `not` du schema courant\n\t\t\tdelete s.not;\n\t\t\t// Fusionner le contenu interne dans le schema courant\n\t\t\tconst innerKeys = Object.keys(innerSchema);\n\t\t\tfor (let i = 0; i < innerKeys.length; i++) {\n\t\t\t\tconst ik = innerKeys[i];\n\t\t\t\tif (ik === undefined) continue;\n\t\t\t\t(s as Record<string, unknown>)[ik] = (\n\t\t\t\t\tinnerSchema as Record<string, unknown>\n\t\t\t\t)[ik];\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Récurser dans les mots-clés array-of-schema ──\n\tfor (const key of ARRAY_SCHEMA_KEYWORDS) {\n\t\tconst val = schema[key];\n\t\tif (Array.isArray(val)) {\n\t\t\tconst arr = val as JSONSchema7Definition[];\n\t\t\tlet arrChanged = false;\n\t\t\tconst newArr: JSONSchema7Definition[] = new Array(arr.length);\n\n\t\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\t\tconst original = arr[i];\n\t\t\t\tif (original === undefined) continue;\n\t\t\t\tconst normalized = normalize(original);\n\t\t\t\tnewArr[i] = normalized;\n\t\t\t\tif (normalized !== original) arrChanged = true;\n\t\t\t}\n\n\t\t\tif (arrChanged) {\n\t\t\t\tensureCopy()[key] = newArr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Determine result ──\n\t// If nothing changed (copied === false), return the original def.\n\t// Otherwise, return the mutated copy.\n\tconst result = (copied ? schema : def) as JSONSchema7Definition;\n\n\t// ── Cache the result ──\n\tnormalizeCache.set(def, result);\n\n\treturn result;\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "B3ACDF5B982F389D64756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,4 +1,4 @@
1
- import{j as a}from"./chunk-w7qcey06.js";import"./chunk-g0pfcnm5.js";import"./chunk-pw49kj6f.js";export{a as resolveConditions};
1
+ import{k as a}from"./chunk-pyrx217p.js";import"./chunk-07z7fc5q.js";import"./chunk-yqhv3py7.js";import"./chunk-jkdzdb3r.js";export{a as resolveConditions};
2
2
 
3
- //# debugId=2A62F997378840BC64756E2164756E21
3
+ //# debugId=635EC680B03DBCFB64756E2164756E21
4
4
  //# sourceMappingURL=condition-resolver.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "2A62F997378840BC64756E2164756E21",
7
+ "debugId": "635EC680B03DBCFB64756E2164756E21",
8
8
  "names": []
9
9
  }
package/dist/differ.d.ts CHANGED
@@ -1,15 +1,14 @@
1
1
  import type { JSONSchema7Definition } from "json-schema";
2
2
  import type { SchemaDiff } from "./types";
3
3
  /**
4
- * Calcule les différences structurelles entre le schema original et le schema
5
- * mergé (intersection). Récurse dans properties, patternProperties,
6
- * dependencies et les sous-schemas.
4
+ * Compare un schema original avec sa version mergée et retourne la liste
5
+ * des différences structurelles.
7
6
  *
8
- * @param original Le schema original (sub)
7
+ * @param original Le schema sub tel qu'il était avant le merge
9
8
  * @param merged Le schema résultant de l'intersection allOf(sub, sup)
10
9
  * @param path Chemin JSON-path courant (vide à la racine)
11
10
  *
12
- * Point 9 — Utilise `_.isEqual` au lieu de `JSON.stringify` pour comparer
11
+ * Point 9 — Utilise `deepEqual` au lieu de `JSON.stringify` pour comparer
13
12
  * les valeurs, ce qui élimine la dépendance à l'ordre des clés.
14
13
  */
15
14
  export declare function computeDiffs(original: JSONSchema7Definition, merged: JSONSchema7Definition, path: string): SchemaDiff[];
package/dist/differ.js CHANGED
@@ -1,4 +1,4 @@
1
- import{k as a}from"./chunk-v5tqyc67.js";export{a as computeDiffs};
1
+ import{l as a}from"./chunk-jybaxgmh.js";import"./chunk-jkdzdb3r.js";export{a as computeDiffs};
2
2
 
3
- //# debugId=FFC7C9BA2055405D64756E2164756E21
3
+ //# debugId=0BA02E52EAD844D264756E2164756E21
4
4
  //# sourceMappingURL=differ.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "FFC7C9BA2055405D64756E2164756E21",
7
+ "debugId": "0BA02E52EAD844D264756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -1,4 +1,4 @@
1
- import{n as a,o as b,p as c,q as d,r as e}from"./chunk-g0pfcnm5.js";export{d as validateFormat,c as isKnownFormat,e as isFormatSubset,a as KNOWN_FORMATS,b as FORMAT_SUPERSETS};
1
+ import{o as a,p as b,q as c,r as d,s as e}from"./chunk-07z7fc5q.js";export{d as validateFormat,c as isKnownFormat,e as isFormatSubset,a as KNOWN_FORMATS,b as FORMAT_SUPERSETS};
2
2
 
3
- //# debugId=B064BA7596626B4A64756E2164756E21
3
+ //# debugId=571D7363ED09D09E64756E2164756E21
4
4
  //# sourceMappingURL=format-validator.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "B064BA7596626B4A64756E2164756E21",
7
+ "debugId": "571D7363ED09D09E64756E2164756E21",
8
8
  "names": []
9
9
  }
package/dist/formatter.js CHANGED
@@ -1,4 +1,4 @@
1
- import{l as a}from"./chunk-cspd2zw4.js";export{a as formatResult};
1
+ import{m as a}from"./chunk-y8c2z1m3.js";export{a as formatResult};
2
2
 
3
- //# debugId=8794B15A440C518464756E2164756E21
3
+ //# debugId=B893FF70743DB57E64756E2164756E21
4
4
  //# sourceMappingURL=formatter.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "8794B15A440C518464756E2164756E21",
7
+ "debugId": "B893FF70743DB57E64756E2164756E21",
8
8
  "names": []
9
9
  }
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{a as w}from"./chunk-h080ggvf.js";import"./chunk-e4501gq7.js";import{g as f,h as q,i as v}from"./chunk-vcwsxmk4.js";import"./chunk-w7qcey06.js";import"./chunk-v5tqyc67.js";import"./chunk-cspd2zw4.js";import{m as d}from"./chunk-2vpph7cy.js";import"./chunk-g0pfcnm5.js";import"./chunk-pw49kj6f.js";export{v as isTrivialPattern,f as isPatternSubset,q as arePatternsEquivalent,d as MergeEngine,w as JsonSchemaCompatibilityChecker};
1
+ import{a as w}from"./chunk-2ddbnbyq.js";import"./chunk-b55zsn5n.js";import{h as f,i as q,j as v}from"./chunk-q7kq4fgq.js";import"./chunk-pyrx217p.js";import"./chunk-jybaxgmh.js";import"./chunk-y8c2z1m3.js";import{n as d}from"./chunk-yg81ax5m.js";import"./chunk-07z7fc5q.js";import"./chunk-yqhv3py7.js";import"./chunk-jkdzdb3r.js";export{v as isTrivialPattern,f as isPatternSubset,q as arePatternsEquivalent,d as MergeEngine,w as JsonSchemaCompatibilityChecker};
2
2
 
3
- //# debugId=4C3097BD68CD2D6164756E2164756E21
3
+ //# debugId=CCC91644C5D64C3564756E2164756E21
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "4C3097BD68CD2D6164756E2164756E21",
7
+ "debugId": "CCC91644C5D64C3564756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -1,4 +1,4 @@
1
- import{a as h}from"./chunk-h080ggvf.js";import"./chunk-e4501gq7.js";import{g as e,h as f,i as g}from"./chunk-vcwsxmk4.js";import{j as b}from"./chunk-w7qcey06.js";import"./chunk-v5tqyc67.js";import{l as c}from"./chunk-cspd2zw4.js";import{m as d}from"./chunk-2vpph7cy.js";import"./chunk-g0pfcnm5.js";import{t as a}from"./chunk-pw49kj6f.js";export{b as resolveConditions,a as normalize,g as isTrivialPattern,e as isPatternSubset,c as formatResult,f as arePatternsEquivalent,d as MergeEngine,h as JsonSchemaCompatibilityChecker};
1
+ import{a as h}from"./chunk-2ddbnbyq.js";import"./chunk-b55zsn5n.js";import{h as e,i as f,j as g}from"./chunk-q7kq4fgq.js";import{k as b}from"./chunk-pyrx217p.js";import"./chunk-jybaxgmh.js";import{m as c}from"./chunk-y8c2z1m3.js";import{n as d}from"./chunk-yg81ax5m.js";import"./chunk-07z7fc5q.js";import{u as a}from"./chunk-yqhv3py7.js";import"./chunk-jkdzdb3r.js";export{b as resolveConditions,a as normalize,g as isTrivialPattern,e as isPatternSubset,c as formatResult,f as arePatternsEquivalent,d as MergeEngine,h as JsonSchemaCompatibilityChecker};
2
2
 
3
- //# debugId=B10A10C37F6462BD64756E2164756E21
3
+ //# debugId=3BCDDF0F1AF47F1264756E2164756E21
4
4
  //# sourceMappingURL=json-schema-compatibility-checker.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "B10A10C37F6462BD64756E2164756E21",
7
+ "debugId": "3BCDDF0F1AF47F1264756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -1,4 +1,4 @@
1
- import{m as a}from"./chunk-2vpph7cy.js";import"./chunk-g0pfcnm5.js";export{a as MergeEngine};
1
+ import{n as a}from"./chunk-yg81ax5m.js";import"./chunk-07z7fc5q.js";import"./chunk-jkdzdb3r.js";export{a as MergeEngine};
2
2
 
3
- //# debugId=8B49A616A48C06F764756E2164756E21
3
+ //# debugId=095A067ED907FB9A64756E2164756E21
4
4
  //# sourceMappingURL=merge-engine.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "8B49A616A48C06F764756E2164756E21",
7
+ "debugId": "095A067ED907FB9A64756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -8,11 +8,17 @@ export declare function inferType(value: unknown): string | undefined;
8
8
  * et normalise récursivement tous les sous-schemas.
9
9
  *
10
10
  * Récurse dans :
11
- * - `properties` et `patternProperties` (Point 2) via `_.mapValues`
11
+ * - `properties` et `patternProperties` (Point 2)
12
12
  * - `dependencies` forme schema (Point 3) — les valeurs tableau (forme 1)
13
13
  * sont laissées intactes
14
14
  * - `items` (single ou tuple)
15
15
  * - Mots-clés single-schema (`additionalProperties`, `not`, `if`, etc.)
16
16
  * - Mots-clés array-of-schema (`anyOf`, `oneOf`, `allOf`)
17
+ *
18
+ * Optimisations :
19
+ * - WeakMap cache : retourne le résultat mis en cache en O(1)
20
+ * - Lazy copy-on-write : ne crée une copie shallow que quand la première
21
+ * mutation est nécessaire, via `ensureCopy()`
22
+ * - Les sous-structures ne sont remplacées que si effectivement changées
17
23
  */
18
24
  export declare function normalize(def: JSONSchema7Definition): JSONSchema7Definition;
@@ -1,4 +1,4 @@
1
- import{s as a,t as b}from"./chunk-pw49kj6f.js";export{b as normalize,a as inferType};
1
+ import{t as a,u as b}from"./chunk-yqhv3py7.js";import"./chunk-jkdzdb3r.js";export{b as normalize,a as inferType};
2
2
 
3
- //# debugId=6DCFB8042D312F0964756E2164756E21
3
+ //# debugId=59624DE2482E077C64756E2164756E21
4
4
  //# sourceMappingURL=normalizer.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "6DCFB8042D312F0964756E2164756E21",
7
+ "debugId": "59624DE2482E077C64756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Vide les caches internes. Utile pour les tests ou la gestion mémoire.
3
+ */
4
+ export declare function clearPatternCaches(): void;
1
5
  /**
2
6
  * Vérifie si le langage du pattern `sub` est un sous-ensemble du langage
3
7
  * du pattern `sup` via échantillonnage.
@@ -1,4 +1,4 @@
1
- import{g as a,h as b,i as c}from"./chunk-vcwsxmk4.js";export{c as isTrivialPattern,a as isPatternSubset,b as arePatternsEquivalent};
1
+ import{g as a,h as b,i as c,j as d}from"./chunk-q7kq4fgq.js";export{d as isTrivialPattern,b as isPatternSubset,a as clearPatternCaches,c as arePatternsEquivalent};
2
2
 
3
- //# debugId=4450229A81A6064B64756E2164756E21
3
+ //# debugId=0415553C48C25D8064756E2164756E21
4
4
  //# sourceMappingURL=pattern-subset.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "4450229A81A6064B64756E2164756E21",
7
+ "debugId": "0415553C48C25D8064756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -27,6 +27,10 @@ export interface BranchResult {
27
27
  * le schema lui-même dans un tableau avec type `"none"`.
28
28
  *
29
29
  * Point 6 — Distingue `anyOf` de `oneOf` dans les paths de diff.
30
+ *
31
+ * Optimisation : réutilise des objets pré-alloués pour les cas boolean
32
+ * (true/false) et un WeakMap cache pour les schemas atomiques afin
33
+ * d'éviter les allocations sur ces chemins fréquents.
30
34
  */
31
35
  export declare function getBranchesTyped(def: JSONSchema7Definition): BranchResult;
32
36
  /**
@@ -71,6 +75,7 @@ export declare function checkBranchedSup(sub: JSONSchema7Definition, supBranches
71
75
  * Vérifie `sub ⊆ sup` pour deux schemas atomiques (sans anyOf/oneOf).
72
76
  * Utilise `mergeOrThrow` pour capturer les erreurs d'incompatibilité.
73
77
  *
74
- * Utilise `_.isEqual` via engine.isEqual pour la comparaison structurelle.
78
+ * Utilise `deepEqual` pour la comparaison structurelle (avec short-circuit
79
+ * par référence et comptage de clés).
75
80
  */
76
81
  export declare function checkAtomic(sub: JSONSchema7Definition, sup: JSONSchema7Definition, engine: MergeEngine): SubsetResult;
@@ -1,4 +1,4 @@
1
- import{b as a,c as b,d as c,e as d,f as e}from"./chunk-e4501gq7.js";import"./chunk-vcwsxmk4.js";import"./chunk-v5tqyc67.js";import"./chunk-g0pfcnm5.js";import"./chunk-pw49kj6f.js";export{b as isAtomicSubsetOf,a as getBranchesTyped,d as checkBranchedSup,c as checkBranchedSub,e as checkAtomic};
1
+ import{b as a,c as b,d as c,e as d,f as e}from"./chunk-b55zsn5n.js";import"./chunk-q7kq4fgq.js";import"./chunk-jybaxgmh.js";import"./chunk-07z7fc5q.js";import"./chunk-yqhv3py7.js";import"./chunk-jkdzdb3r.js";export{b as isAtomicSubsetOf,a as getBranchesTyped,d as checkBranchedSup,c as checkBranchedSub,e as checkAtomic};
2
2
 
3
- //# debugId=E49CFA87DE09786B64756E2164756E21
3
+ //# debugId=F9684ED9F9ECB1E264756E2164756E21
4
4
  //# sourceMappingURL=subset-checker.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "E49CFA87DE09786B64756E2164756E21",
7
+ "debugId": "F9684ED9F9ECB1E264756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -0,0 +1,43 @@
1
+ import type { JSONSchema7Definition } from "json-schema";
2
+ /**
3
+ * Vérifie si une valeur est un plain object (pas null, pas un array).
4
+ */
5
+ export declare function isPlainObj(value: unknown): value is Record<string, unknown>;
6
+ /**
7
+ * Vérifie si un objet possède une propriété propre.
8
+ */
9
+ export declare function hasOwn(obj: object, key: string): boolean;
10
+ /**
11
+ * Compare deux valeurs en profondeur (deep equality).
12
+ *
13
+ * Optimisations :
14
+ * - Reference equality short-circuit (a === b)
15
+ * - Length checks avant l'itération (arrays et objects)
16
+ * - Pas de support pour Date, RegExp, Map, Set (pas nécessaire pour JSON Schema)
17
+ */
18
+ export declare function deepEqual(a: unknown, b: unknown): boolean;
19
+ /**
20
+ * Crée une copie d'un objet sans les clés spécifiées.
21
+ *
22
+ * Optimisé pour le cas courant (1-2 clés à omettre) :
23
+ * - Utilise un Set uniquement si > 2 clés
24
+ * - Itère une seule fois sur l'objet source
25
+ * - Retourne l'original si aucune clé à omettre n'est présente dans l'objet
26
+ */
27
+ export declare function omitKeys<T extends Record<string, unknown>>(obj: T, keysToOmit: string[]): T;
28
+ /**
29
+ * Fusionne deux tableaux de strings en éliminant les doublons.
30
+ * Retourne un tableau avec les éléments uniques des deux sources.
31
+ *
32
+ * Optimisé avec fast paths pour les cas courants :
33
+ * - Si b est vide → retourne a directement
34
+ * - Si a est vide → retourne b directement
35
+ * - Pour les petits tableaux (≤ 8 éléments total), utilise
36
+ * une boucle avec includes au lieu de créer un Set
37
+ */
38
+ export declare function unionStrings(a: string[], b: string[]): string[];
39
+ /**
40
+ * Vérifie l'égalité structurelle entre deux JSONSchema7Definition.
41
+ * Wrapper typé autour de deepEqual pour les schemas.
42
+ */
43
+ export declare function schemaDeepEqual(a: JSONSchema7Definition, b: JSONSchema7Definition): boolean;
package/dist/utils.js ADDED
@@ -0,0 +1,4 @@
1
+ import{A as f,v as a,w as b,x as c,y as d,z as e}from"./chunk-jkdzdb3r.js";export{e as unionStrings,f as schemaDeepEqual,d as omitKeys,a as isPlainObj,b as hasOwn,c as deepEqual};
2
+
3
+ //# debugId=A54C3DD64AB7F25664756E2164756E21
4
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "A54C3DD64AB7F25664756E2164756E21",
8
+ "names": []
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-schema-compatibility-checker",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "license": "MIT",
5
5
  "description": "A tool to check compatibility between two JSON Schemas.",
6
6
  "author": {
@@ -23,20 +23,21 @@
23
23
  "README.md"
24
24
  ],
25
25
  "scripts": {
26
- "postinstall": "lefthook install",
26
+ "prepare": "lefthook install",
27
27
  "build:bun": "bun build src/*.ts --outdir ./dist --production --minify --root src --sourcemap --splitting --target node --format esm --packages external --chunk-naming='chunk-[hash].js'",
28
28
  "build:tsc": "tsc --project tsconfig.build.json",
29
29
  "build": "bun --parallel build:bun build:tsc",
30
30
  "prepublishOnly": "bun run build",
31
31
  "check-types": "tsc --noEmit",
32
32
  "check": "biome check --write --unsafe",
33
- "test": "bun test"
33
+ "test": "bun test",
34
+ "bench": "bun run benchmarks/run.ts"
34
35
  },
35
36
  "devDependencies": {
36
37
  "@biomejs/biome": "2.4.3",
37
38
  "@types/bun": "latest",
38
- "@types/lodash": "4.17.23",
39
- "lefthook": "^2.1.1"
39
+ "lefthook": "^2.1.1",
40
+ "mitata": "^1.0.34"
40
41
  },
41
42
  "peerDependencies": {
42
43
  "typescript": "^5"
@@ -44,7 +45,6 @@
44
45
  "dependencies": {
45
46
  "@x0k/json-schema-merge": "1.0.2",
46
47
  "class-validator": "0.14.3",
47
- "lodash": "4.17.23",
48
48
  "randexp": "0.5.3"
49
49
  }
50
50
  }
@@ -1,5 +0,0 @@
1
- import{r as g}from"./chunk-g0pfcnm5.js";import{createComparator as E,createMerger as V,createShallowAllOfMerge as F}from"@x0k/json-schema-merge";import{createDeduplicator as j,createIntersector as M}from"@x0k/json-schema-merge/lib/array";import v from"lodash/get";import X from"lodash/has";import H from"lodash/isArray";import T from"lodash/isEqual";import w from"lodash/isPlainObject";import K from"lodash/keys";import L from"lodash/some";function u(z,B){if(typeof z==="boolean"||typeof B==="boolean")return!1;let J=X(z,"const"),Q=X(B,"const"),U=v(z,"const"),$=v(B,"const"),Y=v(z,"enum"),N=v(B,"enum");if(J&&Q)return!T(U,$);if(J&&H(N))return!N.some((Z)=>T(Z,U));if(Q&&H(Y))return!Y.some((Z)=>T(Z,$));return!1}var D=["items","additionalProperties","contains","propertyNames","not"],O=["properties","patternProperties"];function _(z,B){if(u(z,B))return!0;if(typeof z==="boolean"||typeof B==="boolean")return!1;if(L(D,(J)=>{let Q=v(z,J),U=v(B,J);return w(Q)&&w(U)&&_(Q,U)}))return!0;if(L(O,(J)=>{let Q=v(z,J),U=v(B,J);if(!w(Q)||!w(U))return!1;let $=Q,Y=U;return L(K($),(N)=>{let Z=$[N],W=Y[N];return Z!==void 0&&W!==void 0&&X(U,N)&&_(Z,W)})}))return!0;if(H(z.items)&&H(B.items)){let J=B.items;if(L(z.items,(Q,U)=>{let $=J[U];return $!==void 0&&U<J.length&&_(Q,$)}))return!0}return!1}function A(z,B){if(typeof z==="boolean"||typeof B==="boolean")return!1;let J=w(z.properties)?z.properties:void 0,Q=w(B.properties)?B.properties:void 0;if(!J&&!Q)return!1;let U=J?K(J):[],$=Q?K(Q):[],Y=H(z.required)?z.required:[],N=H(B.required)?B.required:[];if(z.additionalProperties===!1&&J&&Q){if(L(N,(W)=>!X(J,W)&&X(Q,W))&&U.length>0)return!0}if(w(z.additionalProperties)&&typeof z.additionalProperties!=="boolean"&&J&&Q){let Z=z.additionalProperties;if(X(Z,"type")){let W=Z.type;if(L(N,(x)=>{if(X(J,x))return!1;if(!X(Q,x))return!1;let R=Q[x];if(typeof R==="boolean")return!1;let G=R;if(!X(G,"type"))return!1;if(typeof W==="string"&&typeof G.type==="string")return W!==G.type&&!(W==="number"&&G.type==="integer")&&!(W==="integer"&&G.type==="number");return!1}))return!0}}if(B.additionalProperties===!1&&Q&&J){if(L(Y,(W)=>!X(Q,W)&&X(J,W))&&$.length>0)return!0}if(w(B.additionalProperties)&&typeof B.additionalProperties!=="boolean"&&Q&&J){let Z=B.additionalProperties;if(X(Z,"type")){let W=Z.type;if(L(Y,(x)=>{if(X(Q,x))return!1;if(!X(J,x))return!1;let R=J[x];if(typeof R==="boolean")return!1;let G=R;if(!X(G,"type"))return!1;if(typeof W==="string"&&typeof G.type==="string")return W!==G.type&&!(W==="number"&&G.type==="integer")&&!(W==="integer"&&G.type==="number");return!1}))return!0}}if(J&&Q){if(L(U,(Z)=>{if(!X(Q,Z))return!1;let W=J[Z],I=Q[Z];if(typeof W==="boolean"||typeof I==="boolean")return!1;return A(W,I)}))return!0}return!1}function q(z,B){if(typeof z==="boolean"||typeof B==="boolean")return!1;if(X(z,"format")&&X(B,"format")){let J=z.format,Q=B.format;if(J!==Q){if(g(J,Q)!==!0){if(g(Q,J)!==!0)return!0}}}if(w(z.properties)&&w(B.properties)){let J=z.properties,Q=B.properties;if(L(K(J),(U)=>{let $=J[U],Y=Q[U];return $!==void 0&&Y!==void 0&&X(Q,U)&&q($,Y)}))return!0}if(w(z.items)&&w(B.items)){if(q(z.items,B.items))return!0}if(w(z.additionalProperties)&&w(B.additionalProperties)){if(q(z.additionalProperties,B.additionalProperties))return!0}return!1}class S{compareFn;shallowAllOfMergeFn;constructor(){let{compareSchemaDefinitions:z,compareSchemaValues:B}=E(),J=(U,$)=>{if(U===null&&$===null)return 0;return B(U,$)},{mergeArrayOfSchemaDefinitions:Q}=V({intersectJson:M(J),deduplicateJsonSchemaDef:j(z)});this.compareFn=z,this.shallowAllOfMergeFn=F(Q)}merge(z,B){if(_(z,B))return null;if(q(z,B))return null;if(A(z,B))return null;try{return this.shallowAllOfMergeFn({allOf:[z,B]})}catch{return null}}mergeOrThrow(z,B){if(_(z,B))throw Error("Incompatible const values: schemas have conflicting const constraints");if(q(z,B))throw Error("Incompatible format values: schemas have conflicting format constraints");if(A(z,B))throw Error("Incompatible additionalProperties: required properties conflict with additionalProperties constraint");return this.shallowAllOfMergeFn({allOf:[z,B]})}compare(z,B){return this.compareFn(z,B)}isEqual(z,B){return this.compareFn(z,B)===0}}
2
- export{S as m};
3
-
4
- //# debugId=43562DCBF631899F64756E2164756E21
5
- //# sourceMappingURL=chunk-2vpph7cy.js.map
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/merge-engine.ts"],
4
- "sourcesContent": [
5
- "import {\n\tcreateComparator,\n\tcreateMerger,\n\tcreateShallowAllOfMerge,\n} from \"@x0k/json-schema-merge\";\nimport {\n\tcreateDeduplicator,\n\tcreateIntersector,\n} from \"@x0k/json-schema-merge/lib/array\";\n\nimport type {\n\tJSONSchema7,\n\tJSONSchema7Definition,\n\tJSONSchema7Type,\n} from \"json-schema\";\nimport get from \"lodash/get\";\nimport has from \"lodash/has\";\nimport isArray from \"lodash/isArray\";\nimport isEqual from \"lodash/isEqual\";\nimport isPlainObject from \"lodash/isPlainObject\";\nimport keys from \"lodash/keys\";\nimport some from \"lodash/some\";\n\nimport { isFormatSubset } from \"./format-validator\";\n\n// ─── Merge Engine ────────────────────────────────────────────────────────────\n//\n// Encapsule la librairie `@x0k/json-schema-merge` et expose une API simple\n// pour merger et comparer des JSON Schemas.\n//\n// Principe mathématique :\n// A ∩ B = allOf([A, B]) résolu via shallow merge\n// A ≡ B ⟺ compare(A, B) === 0\n//\n// Pré-checks avant merge :\n// - `hasDeepConstConflict` : détecte les conflits de `const`/`enum`\n// - `hasAdditionalPropertiesConflict` : détecte les conflits `additionalProperties`\n// - `hasFormatConflict` : détecte les conflits de `format` entre deux schemas\n\n// ─── Const conflict detection ────────────────────────────────────────────────\n\n/**\n * Détecte un conflit de `const` entre deux schemas.\n *\n * Cas 1 — const vs const : les deux schemas ont un `const` avec des valeurs\n * différentes → intersection vide.\n *\n * Cas 2 — const vs enum : un schema a `const`, l'autre a `enum`.\n * Si la valeur de `const` n'est pas dans l'`enum` → intersection vide.\n *\n * Utilise `lodash/isEqual` pour la comparaison profonde (objets, tableaux).\n */\nfunction hasConstConflict(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\tif (typeof a === \"boolean\" || typeof b === \"boolean\") return false;\n\n\tconst aHasConst = has(a, \"const\");\n\tconst bHasConst = has(b, \"const\");\n\tconst aConst = get(a, \"const\");\n\tconst bConst = get(b, \"const\");\n\tconst aEnum: unknown[] | undefined = get(a, \"enum\");\n\tconst bEnum: unknown[] | undefined = get(b, \"enum\");\n\n\t// Cas 1 — const vs const\n\tif (aHasConst && bHasConst) {\n\t\treturn !isEqual(aConst, bConst);\n\t}\n\n\t// Cas 2 — const vs enum\n\tif (aHasConst && isArray(bEnum)) {\n\t\treturn !bEnum.some((v) => isEqual(v, aConst));\n\t}\n\tif (bHasConst && isArray(aEnum)) {\n\t\treturn !aEnum.some((v) => isEqual(v, bConst));\n\t}\n\n\treturn false;\n}\n\n/** Mots-clés contenant un unique sous-schema à vérifier récursivement */\nconst SINGLE_SCHEMA_CONFLICT_KEYS = [\n\t\"items\",\n\t\"additionalProperties\",\n\t\"contains\",\n\t\"propertyNames\",\n\t\"not\",\n] as const;\n\n/** Mots-clés contenant un Record<string, JSONSchema7Definition> */\nconst PROPERTIES_MAP_CONFLICT_KEYS = [\n\t\"properties\",\n\t\"patternProperties\",\n] as const;\n\n/**\n * Détecte récursivement les conflits de `const` dans les sous-schemas.\n *\n * Quand la librairie de merge fait un shallow merge, les sous-schemas\n * imbriqués peuvent aussi avoir des conflits de `const` masqués\n * (elle utilise `identity` pour `const`).\n *\n * Récurse dans :\n * - `properties`, `patternProperties` (clés communes)\n * - `items` (single schema), tuple `items` (par index)\n * - `additionalProperties`, `contains`, `propertyNames`, `not`\n */\nfunction hasDeepConstConflict(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\tif (hasConstConflict(a, b)) return true;\n\n\tif (typeof a === \"boolean\" || typeof b === \"boolean\") return false;\n\n\t// ── Single sub-schema keywords ──\n\tif (\n\t\tsome(SINGLE_SCHEMA_CONFLICT_KEYS, (key) => {\n\t\t\tconst aVal = get(a, key) as JSONSchema7Definition | undefined;\n\t\t\tconst bVal = get(b, key) as JSONSchema7Definition | undefined;\n\t\t\treturn (\n\t\t\t\tisPlainObject(aVal) &&\n\t\t\t\tisPlainObject(bVal) &&\n\t\t\t\thasDeepConstConflict(\n\t\t\t\t\taVal as JSONSchema7Definition,\n\t\t\t\t\tbVal as JSONSchema7Definition,\n\t\t\t\t)\n\t\t\t);\n\t\t})\n\t)\n\t\treturn true;\n\n\t// ── Properties-like maps (properties, patternProperties) ──\n\tif (\n\t\tsome(PROPERTIES_MAP_CONFLICT_KEYS, (key) => {\n\t\t\tconst aMap = get(a, key) as\n\t\t\t\t| Record<string, JSONSchema7Definition>\n\t\t\t\t| undefined;\n\t\t\tconst bMap = get(b, key) as\n\t\t\t\t| Record<string, JSONSchema7Definition>\n\t\t\t\t| undefined;\n\t\t\tif (!isPlainObject(aMap) || !isPlainObject(bMap)) return false;\n\t\t\tconst aMapSafe = aMap as Record<string, JSONSchema7Definition>;\n\t\t\tconst bMapSafe = bMap as Record<string, JSONSchema7Definition>;\n\t\t\treturn some(keys(aMapSafe), (propKey) => {\n\t\t\t\tconst aVal = aMapSafe[propKey];\n\t\t\t\tconst bVal = bMapSafe[propKey];\n\t\t\t\treturn (\n\t\t\t\t\taVal !== undefined &&\n\t\t\t\t\tbVal !== undefined &&\n\t\t\t\t\thas(bMap, propKey) &&\n\t\t\t\t\thasDeepConstConflict(aVal, bVal)\n\t\t\t\t);\n\t\t\t});\n\t\t})\n\t)\n\t\treturn true;\n\n\t// ── Tuple items (array of schemas, compared by index) ──\n\tif (isArray(a.items) && isArray(b.items)) {\n\t\tconst bItems = b.items as JSONSchema7Definition[];\n\t\tif (\n\t\t\tsome(a.items as JSONSchema7Definition[], (aItem, idx) => {\n\t\t\t\tconst bItem = bItems[idx];\n\t\t\t\treturn (\n\t\t\t\t\tbItem !== undefined &&\n\t\t\t\t\tidx < bItems.length &&\n\t\t\t\t\thasDeepConstConflict(aItem, bItem)\n\t\t\t\t);\n\t\t\t})\n\t\t)\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n// ─── additionalProperties conflict detection ─────────────────────────────────\n\n/**\n * Détecte un conflit entre `additionalProperties` et les propriétés extra\n * **requises** de l'autre schema.\n *\n * ⚠️ Cette fonction est **ultra-conservatrice** : elle ne détecte que les\n * conflits où une propriété est à la fois :\n * - INTERDITE par `additionalProperties: false` d'un côté\n * - REQUISE (`required`) par l'autre côté\n * - ABSENTE des `properties` du côté restrictif\n * - ET le côté restrictif AUSSI a un `required` qui rend l'objet non-vide\n * (sinon la librairie gère déjà le cas en excluant les propriétés extra)\n *\n * La librairie de merge (`@x0k/json-schema-merge`) gère DÉJÀ correctement\n * le cas `additionalProperties: false` avec des propriétés simplement DÉFINIES\n * (non requises) dans l'autre schema — elle les exclut du résultat.\n * On ne détecte donc QUE les contradictions `required` impossibles à résoudre.\n *\n * Cas gérés :\n * 1. `a` a `additionalProperties: false` et `b` REQUIERT des propriétés\n * absentes de `a.properties`, ET ces propriétés sont dans `b.properties`\n * → conflit certain (intersection vide car b exige, a interdit)\n * 2. Symétrique pour `b.additionalProperties: false`\n * 3. `additionalProperties` comme schema → vérifier la compatibilité de type\n * des propriétés extra REQUISES uniquement\n * 4. Récursion dans les propriétés communes (sous-objets)\n *\n * ⚠️ Ne vérifie que les clés de `properties`, pas les `patternProperties`\n * (trop complexe à résoudre statiquement).\n *\n * Retourne `true` si un conflit évident est détecté, `false` sinon.\n * En cas de doute → `false` (conservateur, laisser le merge décider).\n *\n * Utilise `_.keys`, `_.some`, `_.every`, `_.has`, `_.get`, `_.isPlainObject`,\n * `_.includes` pour des vérifications concises.\n */\nfunction hasAdditionalPropertiesConflict(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\tif (typeof a === \"boolean\" || typeof b === \"boolean\") return false;\n\n\tconst aProps = isPlainObject(a.properties)\n\t\t? (a.properties as Record<string, JSONSchema7Definition>)\n\t\t: undefined;\n\tconst bProps = isPlainObject(b.properties)\n\t\t? (b.properties as Record<string, JSONSchema7Definition>)\n\t\t: undefined;\n\n\t// Si aucun des deux n'a de properties, on ne peut rien déterminer\n\tif (!aProps && !bProps) return false;\n\n\tconst aKeys = aProps ? keys(aProps) : [];\n\tconst bKeys = bProps ? keys(bProps) : [];\n\tconst aRequired = isArray(a.required) ? (a.required as string[]) : [];\n\tconst bRequired = isArray(b.required) ? (b.required as string[]) : [];\n\n\t// ── Vérifier additionalProperties: false de a vs propriétés REQUISES extra de b ──\n\t// Condition stricte : b doit DÉFINIR la propriété dans b.properties ET la\n\t// REQUÉRIR dans b.required, ET cette propriété doit être ABSENTE de a.properties.\n\t// De plus, a doit lui-même avoir des propriétés (sinon on ne peut rien dire).\n\tif (a.additionalProperties === false && aProps && bProps) {\n\t\tconst hasRequiredExtra = some(\n\t\t\tbRequired,\n\t\t\t(k) => !has(aProps, k) && has(bProps, k),\n\t\t);\n\t\t// Ne détecter le conflit que si a a aussi un required qui rend l'objet\n\t\t// structurellement contraint (pas un schema vague)\n\t\tif (hasRequiredExtra && aKeys.length > 0) return true;\n\t}\n\n\t// ── Vérification du cas additionalProperties comme schema ──\n\t// Si a.additionalProperties est un schema avec un type, et que b REQUIERT\n\t// une propriété extra dont le type est incompatible → conflit\n\tif (\n\t\tisPlainObject(a.additionalProperties) &&\n\t\ttypeof a.additionalProperties !== \"boolean\" &&\n\t\taProps &&\n\t\tbProps\n\t) {\n\t\tconst addPropsSchema = a.additionalProperties as JSONSchema7;\n\t\tif (has(addPropsSchema, \"type\")) {\n\t\t\tconst addPropsType = addPropsSchema.type;\n\t\t\tconst hasTypeConflict = some(bRequired, (k) => {\n\t\t\t\tif (has(aProps, k)) return false;\n\t\t\t\tif (!has(bProps, k)) return false;\n\t\t\t\tconst bPropDef = bProps[k];\n\t\t\t\tif (typeof bPropDef === \"boolean\") return false;\n\t\t\t\tconst bProp = bPropDef as JSONSchema7;\n\t\t\t\tif (!has(bProp, \"type\")) return false;\n\t\t\t\tif (\n\t\t\t\t\ttypeof addPropsType === \"string\" &&\n\t\t\t\t\ttypeof bProp.type === \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\taddPropsType !== bProp.type &&\n\t\t\t\t\t\t!(addPropsType === \"number\" && bProp.type === \"integer\") &&\n\t\t\t\t\t\t!(addPropsType === \"integer\" && bProp.type === \"number\")\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t});\n\t\t\tif (hasTypeConflict) return true;\n\t\t}\n\t}\n\n\t// ── Vérification symétrique : additionalProperties de b vs propriétés REQUISES extra de a ──\n\tif (b.additionalProperties === false && bProps && aProps) {\n\t\tconst hasRequiredExtra = some(\n\t\t\taRequired,\n\t\t\t(k) => !has(bProps, k) && has(aProps, k),\n\t\t);\n\t\tif (hasRequiredExtra && bKeys.length > 0) return true;\n\t}\n\n\t// Symétrique pour additionalProperties comme schema\n\tif (\n\t\tisPlainObject(b.additionalProperties) &&\n\t\ttypeof b.additionalProperties !== \"boolean\" &&\n\t\tbProps &&\n\t\taProps\n\t) {\n\t\tconst addPropsSchema = b.additionalProperties as JSONSchema7;\n\t\tif (has(addPropsSchema, \"type\")) {\n\t\t\tconst addPropsType = addPropsSchema.type;\n\t\t\tconst hasTypeConflict = some(aRequired, (k) => {\n\t\t\t\tif (has(bProps, k)) return false;\n\t\t\t\tif (!has(aProps, k)) return false;\n\t\t\t\tconst aPropDef = aProps[k];\n\t\t\t\tif (typeof aPropDef === \"boolean\") return false;\n\t\t\t\tconst aProp = aPropDef as JSONSchema7;\n\t\t\t\tif (!has(aProp, \"type\")) return false;\n\t\t\t\tif (\n\t\t\t\t\ttypeof addPropsType === \"string\" &&\n\t\t\t\t\ttypeof aProp.type === \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\taddPropsType !== aProp.type &&\n\t\t\t\t\t\t!(addPropsType === \"number\" && aProp.type === \"integer\") &&\n\t\t\t\t\t\t!(addPropsType === \"integer\" && aProp.type === \"number\")\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t});\n\t\t\tif (hasTypeConflict) return true;\n\t\t}\n\t}\n\n\t// ── Récursion dans les propriétés communes ──\n\t// Si les deux schemas ont des propriétés communes qui sont des objets,\n\t// vérifier récursivement les conflits additionalProperties\n\tif (aProps && bProps) {\n\t\tif (\n\t\t\tsome(aKeys, (k) => {\n\t\t\t\tif (!has(bProps, k)) return false;\n\t\t\t\tconst aPropDef = aProps[k];\n\t\t\t\tconst bPropDef = bProps[k];\n\t\t\t\tif (typeof aPropDef === \"boolean\" || typeof bPropDef === \"boolean\")\n\t\t\t\t\treturn false;\n\t\t\t\treturn hasAdditionalPropertiesConflict(\n\t\t\t\t\taPropDef as JSONSchema7Definition,\n\t\t\t\t\tbPropDef as JSONSchema7Definition,\n\t\t\t\t);\n\t\t\t})\n\t\t)\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n// ─── Format conflict detection ───────────────────────────────────────────────\n\n/**\n * Détecte un conflit de format entre deux schemas.\n *\n * ⚠️ Ne se déclenche QUE quand les DEUX schemas ont un `format`.\n * Si un seul schema a un `format`, il n'y a PAS de conflit — le merge\n * engine gère nativement ce cas (le format est conservé dans l'intersection,\n * et la comparaison `merged ≡ sub` détermine correctement la relation ⊆).\n *\n * Deux schemas avec des formats différents et sans relation d'inclusion\n * connue ont une intersection vide (ex: \"email\" ∩ \"ipv4\" = ∅).\n *\n * Utilise `isFormatSubset` de `format-validator.ts` pour vérifier la hiérarchie.\n *\n * Récurse dans les sous-schemas (`properties`, `items`, etc.) pour détecter\n * les conflits de format imbriqués.\n *\n * @returns `true` si un conflit de format est détecté, `false` sinon\n */\nfunction hasFormatConflict(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\tif (typeof a === \"boolean\" || typeof b === \"boolean\") return false;\n\n\t// ── Seulement quand LES DEUX ont un format ──\n\t// Si un seul a un format → pas de conflit, le merge gère nativement\n\tif (has(a, \"format\") && has(b, \"format\")) {\n\t\tconst aFormat = a.format as string;\n\t\tconst bFormat = b.format as string;\n\n\t\t// Même format → pas de conflit\n\t\tif (aFormat !== bFormat) {\n\t\t\t// Vérifier si l'un est un sous-ensemble de l'autre via la hiérarchie\n\t\t\tconst subsetCheck = isFormatSubset(aFormat, bFormat);\n\t\t\tif (subsetCheck !== true) {\n\t\t\t\tconst reverseCheck = isFormatSubset(bFormat, aFormat);\n\t\t\t\tif (reverseCheck !== true) {\n\t\t\t\t\t// Formats différents sans relation connue → conflit\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Récursion dans les sous-schemas ──\n\t// Vérifier les conflits de format dans les propriétés communes\n\tif (isPlainObject(a.properties) && isPlainObject(b.properties)) {\n\t\tconst aMap = a.properties as Record<string, JSONSchema7Definition>;\n\t\tconst bMap = b.properties as Record<string, JSONSchema7Definition>;\n\t\tif (\n\t\t\tsome(keys(aMap), (k) => {\n\t\t\t\tconst aVal = aMap[k];\n\t\t\t\tconst bVal = bMap[k];\n\t\t\t\treturn (\n\t\t\t\t\taVal !== undefined &&\n\t\t\t\t\tbVal !== undefined &&\n\t\t\t\t\thas(bMap, k) &&\n\t\t\t\t\thasFormatConflict(aVal, bVal)\n\t\t\t\t);\n\t\t\t})\n\t\t)\n\t\t\treturn true;\n\t}\n\n\t// Vérifier items (single schema)\n\tif (isPlainObject(a.items) && isPlainObject(b.items)) {\n\t\tif (\n\t\t\thasFormatConflict(\n\t\t\t\ta.items as JSONSchema7Definition,\n\t\t\t\tb.items as JSONSchema7Definition,\n\t\t\t)\n\t\t)\n\t\t\treturn true;\n\t}\n\n\t// Vérifier additionalProperties\n\tif (\n\t\tisPlainObject(a.additionalProperties) &&\n\t\tisPlainObject(b.additionalProperties)\n\t) {\n\t\tif (\n\t\t\thasFormatConflict(\n\t\t\t\ta.additionalProperties as JSONSchema7Definition,\n\t\t\t\tb.additionalProperties as JSONSchema7Definition,\n\t\t\t)\n\t\t)\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n// ─── MergeEngine class ───────────────────────────────────────────────────────\n\nexport class MergeEngine {\n\tprivate readonly compareFn: (\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t) => number;\n\n\tprivate readonly shallowAllOfMergeFn: (\n\t\tschema: JSONSchema7 & { allOf: JSONSchema7Definition[] },\n\t) => JSONSchema7Definition;\n\n\tconstructor() {\n\t\tconst { compareSchemaDefinitions, compareSchemaValues } =\n\t\t\tcreateComparator();\n\n\t\t// ── Null-safe wrapper for compareSchemaValues ──\n\t\t// The library's compareSchemaValues has a bug: when both a and b are null,\n\t\t// it returns -1 instead of 0 (the null check for `a` fires before checking\n\t\t// if `b` is also null). This causes createIntersector to lose null values\n\t\t// during enum intersection (the sort-merge join relies on compare(x,x)===0).\n\t\tconst safeCompareSchemaValues = (\n\t\t\ta: JSONSchema7Type,\n\t\t\tb: JSONSchema7Type,\n\t\t): number => {\n\t\t\tif (a === null && b === null) return 0;\n\t\t\treturn compareSchemaValues(a, b);\n\t\t};\n\n\t\tconst { mergeArrayOfSchemaDefinitions } = createMerger({\n\t\t\tintersectJson: createIntersector(safeCompareSchemaValues),\n\t\t\tdeduplicateJsonSchemaDef: createDeduplicator(compareSchemaDefinitions),\n\t\t});\n\n\t\tthis.compareFn = compareSchemaDefinitions;\n\t\tthis.shallowAllOfMergeFn = createShallowAllOfMerge(\n\t\t\tmergeArrayOfSchemaDefinitions,\n\t\t);\n\t}\n\n\t/**\n\t * Merge deux schemas via `allOf([a, b])`.\n\t * Retourne `null` si les schemas sont incompatibles.\n\t *\n\t * Post-merge : détecte les conflits de `const` que la librairie\n\t * ne capture pas (elle utilise `identity` pour `const`).\n\t */\n\tmerge(\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t): JSONSchema7Definition | null {\n\t\t// Pré-check : conflit de const détectable avant le merge\n\t\tif (hasDeepConstConflict(a, b)) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Pré-check : conflit de format (les DEUX ont un format incompatible)\n\t\tif (hasFormatConflict(a, b)) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Pré-check : conflit additionalProperties vs propriétés REQUISES extra\n\t\t// Ne détecte que les cas où une propriété est à la fois interdite\n\t\t// (additionalProperties: false) et requise (required) → intersection vide.\n\t\t// Les cas où les propriétés sont simplement définies sans être requises\n\t\t// sont gérés correctement par la librairie de merge elle-même.\n\t\tif (hasAdditionalPropertiesConflict(a, b)) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\treturn this.shallowAllOfMergeFn({ allOf: [a, b] });\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Merge via `shallowAllOfMerge` — lève une exception si incompatible.\n\t * Utile quand on veut capturer l'erreur pour le diagnostic.\n\t *\n\t * Post-merge : détecte les conflits de `const` et lève une exception.\n\t */\n\tmergeOrThrow(\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t): JSONSchema7Definition {\n\t\t// Pré-check : conflit de const\n\t\tif (hasDeepConstConflict(a, b)) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Incompatible const values: schemas have conflicting const constraints\",\n\t\t\t);\n\t\t}\n\n\t\t// Pré-check : conflit de format\n\t\tif (hasFormatConflict(a, b)) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Incompatible format values: schemas have conflicting format constraints\",\n\t\t\t);\n\t\t}\n\n\t\t// Pré-check : conflit additionalProperties vs propriétés REQUISES extra\n\t\tif (hasAdditionalPropertiesConflict(a, b)) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Incompatible additionalProperties: required properties conflict with additionalProperties constraint\",\n\t\t\t);\n\t\t}\n\n\t\treturn this.shallowAllOfMergeFn({ allOf: [a, b] });\n\t}\n\n\t/**\n\t * Compare structurellement deux schema definitions.\n\t * Retourne 0 si elles sont identiques, sinon un entier non nul.\n\t */\n\tcompare(a: JSONSchema7Definition, b: JSONSchema7Definition): number {\n\t\treturn this.compareFn(a, b);\n\t}\n\n\t/**\n\t * Vérifie l'égalité structurelle entre deux schema definitions.\n\t */\n\tisEqual(a: JSONSchema7Definition, b: JSONSchema7Definition): boolean {\n\t\treturn this.compareFn(a, b) === 0;\n\t}\n}\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "43562DCBF631899F64756E2164756E21",
9
- "names": []
10
- }
@@ -1,6 +0,0 @@
1
- import z from"lodash/isEmpty";import A from"lodash/map";function B(j){switch(j.type){case"added":return` + ${j.path}: ${JSON.stringify(j.actual)}`;case"removed":return` - ${j.path}: was ${JSON.stringify(j.expected)}`;default:return` ~ ${j.path}: ${JSON.stringify(j.expected)} → ${JSON.stringify(j.actual)}`}}function H(j,k){let v=[`${k.isSubset?"✅":"❌"} ${j}: ${k.isSubset}`];if(!k.isSubset&&!z(k.diffs)){v.push(" Diffs:");let w=A(k.diffs,(x)=>` ${B(x)}`);v.push(...w)}return v.join(`
2
- `)}
3
- export{H as l};
4
-
5
- //# debugId=C49CD60F9FB46AC664756E2164756E21
6
- //# sourceMappingURL=chunk-cspd2zw4.js.map