json-schema-compatibility-checker 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/json-schema-compatibility-checker.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { resolveConditions } from \"./condition-resolver\";\nimport { formatResult } from \"./formatter\";\nimport { MergeEngine } from \"./merge-engine\";\nimport { normalize } from \"./normalizer\";\nimport {\n\tarePatternsEquivalent,\n\tisPatternSubset,\n\tisTrivialPattern,\n} from \"./pattern-subset\";\nimport type { BranchResult, BranchType } from \"./subset-checker\";\nimport {\n\tcheckAtomic,\n\tcheckBranchedSub,\n\tcheckBranchedSup,\n\tgetBranchesTyped,\n\tisAtomicSubsetOf,\n} from \"./subset-checker\";\nimport type {\n\tConnectionResult,\n\tResolvedConditionResult,\n\tSchemaError,\n\tSubsetResult,\n} from \"./types\";\nimport { deepEqual } from \"./utils\";\n\n// ─── Re-exports ──────────────────────────────────────────────────────────────\n\nexport type {\n\tSchemaError,\n\tSubsetResult,\n\tConnectionResult,\n\tResolvedConditionResult,\n\tBranchType,\n\tBranchResult,\n};\n\nexport {\n\tnormalize,\n\tresolveConditions,\n\tformatResult,\n\tMergeEngine,\n\tisPatternSubset,\n\tarePatternsEquivalent,\n\tisTrivialPattern,\n};\n\n// ─── Main Class ──────────────────────────────────────────────────────────────\n//\n// Façade légère qui orchestre les sous-modules pour vérifier la compatibilité\n// entre JSON Schemas (Draft-07).\n//\n// Principe mathématique :\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// En JSON Schema :\n// - A ∩ B = allOf([A, B]) résolu via merge\n// - ≡ = comparaison structurelle\n//\n// @example\n// ```ts\n// const checker = new JsonSchemaCompatibilityChecker();\n//\n// checker.isSubset(strict, loose); // true\n// checker.check(loose, strict); // { isSubset: false, diffs: [...] }\n// checker.canConnect(nodeA.output, nodeB.input); // ConnectionResult\n// ```\n\nexport class JsonSchemaCompatibilityChecker {\n\tprivate readonly engine: MergeEngine;\n\n\tconstructor() {\n\t\tthis.engine = new MergeEngine();\n\t}\n\n\t// ── Subset check (boolean) ─────────────────────────────────────────────\n\n\t/**\n\t * Vérifie si `sub ⊆ sup`.\n\t * Toute valeur valide pour sub est-elle aussi valide pour sup ?\n\t *\n\t * Point 6 — Utilise `getBranchesTyped` pour distinguer `anyOf` de `oneOf`\n\t * en interne, bien que le résultat boolean ne reflète pas la distinction.\n\t */\n\tisSubset(sub: JSONSchema7Definition, sup: JSONSchema7Definition): boolean {\n\t\t// ── Identity short-circuit ──\n\t\t// If sub and sup are the same reference, sub ⊆ sup is trivially true.\n\t\t// This avoids the entire normalize + merge + compare pipeline.\n\t\tif (sub === sup) return true;\n\n\t\t// ── Pre-normalize structural equality ──\n\t\t// If sub and sup are structurally identical before normalization,\n\t\t// they represent the same schema → sub ⊆ sup trivially.\n\t\t// This avoids the WeakMap overhead of normalize() for common cases\n\t\t// like {} ⊆ {} or identical schema objects with different references.\n\t\tif (deepEqual(sub, sup)) return true;\n\n\t\tconst nSub = normalize(sub);\n\t\tconst nSup = normalize(sup);\n\n\t\t// ── Post-normalize structural identity ──\n\t\t// After normalization, schemas that were syntactically different\n\t\t// but semantically equivalent become structurally equal\n\t\t// (e.g. {const:1} vs {const:1, type:\"integer\"}).\n\t\tif (nSub !== sub && nSup !== sup && deepEqual(nSub, nSup)) return true;\n\t\tif (nSub !== nSup && deepEqual(nSub, nSup)) return true;\n\n\t\tconst { branches: subBranches } = getBranchesTyped(nSub);\n\n\t\tif (subBranches.length > 1 || subBranches[0] !== nSub) {\n\t\t\treturn subBranches.every((branch) =>\n\t\t\t\tisAtomicSubsetOf(branch, nSup, this.engine),\n\t\t\t);\n\t\t}\n\n\t\treturn isAtomicSubsetOf(nSub, nSup, this.engine);\n\t}\n\n\t// ── Subset check (detailed) ────────────────────────────────────────────\n\n\t/**\n\t * Vérifie `sub ⊆ sup` et retourne un diagnostic complet\n\t * avec des erreurs sémantiques lisibles.\n\t *\n\t * Point 6 — Utilise `getBranchesTyped` pour distinguer `anyOf` de `oneOf`\n\t * dans les paths d'erreur.\n\t */\n\tcheck(sub: JSONSchema7Definition, sup: JSONSchema7Definition): SubsetResult {\n\t\t// ── Identity short-circuit ──\n\t\t// Same reference → no errors, no merge needed.\n\t\tif (sub === sup) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\t// ── Pre-normalize structural equality ──\n\t\t// Avoids WeakMap overhead for identical schemas ({} ⊆ {}, etc.).\n\t\tif (deepEqual(sub, sup)) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst nSub = normalize(sub);\n\t\tconst nSup = normalize(sup);\n\n\t\t// ── Post-normalize structural identity ──\n\t\t// Catches semantically equivalent schemas after normalization.\n\t\tif (deepEqual(nSub, nSup)) {\n\t\t\treturn { isSubset: true, merged: nSub, errors: [] };\n\t\t}\n\n\t\tconst { branches: subBranches, type: subBranchType } =\n\t\t\tgetBranchesTyped(nSub);\n\t\tconst { branches: supBranches, type: supBranchType } =\n\t\t\tgetBranchesTyped(nSup);\n\n\t\t// anyOf/oneOf dans sub\n\t\tif (subBranches.length > 1 || subBranches[0] !== nSub) {\n\t\t\treturn checkBranchedSub(subBranches, nSup, this.engine, subBranchType);\n\t\t}\n\n\t\t// anyOf/oneOf dans sup uniquement\n\t\tif (supBranches.length > 1 || supBranches[0] !== nSup) {\n\t\t\treturn checkBranchedSup(nSub, supBranches, this.engine, supBranchType);\n\t\t}\n\n\t\t// Cas standard\n\t\treturn checkAtomic(nSub, nSup, this.engine);\n\t}\n\n\t// ── Connection check ───────────────────────────────────────────────────\n\n\t/**\n\t * Vérifie si la sortie d'un nœud source peut alimenter l'entrée d'un nœud cible.\n\t *\n\t * Sémantique : `sourceOutput ⊆ targetInput`\n\t * → Toute donnée produite par source sera acceptée par target.\n\t */\n\tcanConnect(\n\t\tsourceOutput: JSONSchema7Definition,\n\t\ttargetInput: JSONSchema7Definition,\n\t): ConnectionResult {\n\t\tconst result = this.check(sourceOutput, targetInput);\n\t\treturn { ...result, direction: \"sourceOutput ⊆ targetInput\" };\n\t}\n\n\t// ── Equality ───────────────────────────────────────────────────────────\n\n\t/**\n\t * Vérifie l'égalité structurelle entre deux schemas.\n\t */\n\tisEqual(a: JSONSchema7Definition, b: JSONSchema7Definition): boolean {\n\t\treturn this.engine.isEqual(normalize(a), normalize(b));\n\t}\n\n\t// ── Intersection ───────────────────────────────────────────────────────\n\n\t/**\n\t * Calcule l'intersection de deux schemas (allOf merge).\n\t * Retourne null si les schemas sont incompatibles.\n\t *\n\t * Le résultat est normalisé pour éliminer les artefacts structurels\n\t * du merge (ex: `enum` redondant quand `const` est présent).\n\t */\n\tintersect(\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t): JSONSchema7Definition | null {\n\t\t// ── Identity short-circuit ──\n\t\t// If a and b are the same reference or structurally equal,\n\t\t// intersection is just normalize(a) — skip the merge entirely.\n\t\tif (a === b || deepEqual(a, b)) return normalize(a);\n\n\t\tconst nA = normalize(a);\n\t\tconst nB = normalize(b);\n\n\t\t// ── Post-normalize identity ──\n\t\tif (deepEqual(nA, nB)) return nA;\n\n\t\tconst merged = this.engine.merge(nA, nB);\n\t\tif (merged === null) return null;\n\t\t// Fast path: if merge result equals one of the normalized inputs,\n\t\t// it's already normalized — skip redundant normalize call.\n\t\tif (deepEqual(merged, nA) || deepEqual(merged, nB)) return merged;\n\t\treturn normalize(merged);\n\t}\n\n\t// ── Condition resolution ───────────────────────────────────────────────\n\n\t/**\n\t * Résout les `if/then/else` d'un schema en évaluant le `if` contre\n\t * des données partielles (discriminants).\n\t */\n\tresolveConditions(\n\t\tschema: JSONSchema7,\n\t\tdata: Record<string, unknown>,\n\t): ResolvedConditionResult {\n\t\treturn resolveConditions(schema, data, this.engine);\n\t}\n\n\t// ── Resolved check ────────────────────────────────────────────────────\n\n\t/**\n\t * Raccourci : résout les conditions des deux schemas puis vérifie sub ⊆ sup.\n\t *\n\t * Utile quand le superset contient des if/then/else et que tu connais\n\t * les valeurs discriminantes que le subset va produire.\n\t */\n\tcheckResolved(\n\t\tsub: JSONSchema7,\n\t\tsup: JSONSchema7,\n\t\tsubData: Record<string, unknown>,\n\t\tsupData?: Record<string, unknown>,\n\t): SubsetResult & {\n\t\tresolvedSub: ResolvedConditionResult;\n\t\tresolvedSup: ResolvedConditionResult;\n\t} {\n\t\tconst resolvedSub = resolveConditions(sub, subData, this.engine);\n\t\tconst resolvedSup = resolveConditions(sup, supData ?? subData, this.engine);\n\t\tconst result = this.check(resolvedSub.resolved, resolvedSup.resolved);\n\n\t\treturn { ...result, resolvedSub, resolvedSup };\n\t}\n\n\t// ── Normalization ──────────────────────────────────────────────────────\n\n\t/**\n\t * Normalise un schema : infère `type` depuis `const`/`enum`,\n\t * et normalise récursivement tous les sous-schemas.\n\t */\n\tnormalize(def: JSONSchema7Definition): JSONSchema7Definition {\n\t\treturn normalize(def);\n\t}\n\n\t// ── Formatting ─────────────────────────────────────────────────────────\n\n\t/**\n\t * Formate un SubsetResult en chaîne lisible (utile pour logs/debug).\n\t */\n\tformatResult(label: string, result: SubsetResult): string {\n\t\treturn formatResult(label, result);\n\t}\n}\n"],"names":["resolveConditions","formatResult","MergeEngine","normalize","arePatternsEquivalent","isPatternSubset","isTrivialPattern","checkAtomic","checkBranchedSub","checkBranchedSup","getBranchesTyped","isAtomicSubsetOf","deepEqual","JsonSchemaCompatibilityChecker","isSubset","sub","sup","nSub","nSup","branches","subBranches","length","every","branch","engine","check","merged","errors","type","subBranchType","supBranches","supBranchType","canConnect","sourceOutput","targetInput","result","direction","isEqual","a","b","intersect","nA","nB","merge","schema","data","checkResolved","subData","supData","resolvedSub","resolvedSup","resolved","def","label"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/json-schema-compatibility-checker.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { resolveConditions } from \"./condition-resolver.ts\";\nimport { narrowSchemaWithData } from \"./data-narrowing.ts\";\nimport { formatResult } from \"./formatter.ts\";\nimport { MergeEngine } from \"./merge-engine.ts\";\nimport { normalize } from \"./normalizer.ts\";\nimport {\n\tarePatternsEquivalent,\n\tisPatternSubset,\n\tisTrivialPattern,\n} from \"./pattern-subset.ts\";\nimport type { BranchResult, BranchType } from \"./subset-checker.ts\";\nimport {\n\tcheckAtomic,\n\tcheckBranchedSub,\n\tcheckBranchedSup,\n\tgetBranchesTyped,\n\tisAtomicSubsetOf,\n} from \"./subset-checker.ts\";\nimport type {\n\tCheckConditionsOptions,\n\tResolvedConditionResult,\n\tResolvedSubsetResult,\n\tSchemaError,\n\tSubsetResult,\n} from \"./types.ts\";\nimport { deepEqual, isPlainObj } from \"./utils.ts\";\n\n// ─── Re-exports ──────────────────────────────────────────────────────────────\n\nexport type {\n\tSchemaError,\n\tSubsetResult,\n\tResolvedConditionResult,\n\tResolvedSubsetResult,\n\tCheckConditionsOptions,\n\tBranchType,\n\tBranchResult,\n};\n\nexport {\n\tnormalize,\n\tresolveConditions,\n\tformatResult,\n\tMergeEngine,\n\tisPatternSubset,\n\tarePatternsEquivalent,\n\tisTrivialPattern,\n};\n\n// ─── Main Class ──────────────────────────────────────────────────────────────\n//\n// Façade légère qui orchestre les sous-modules pour vérifier la compatibilité\n// entre JSON Schemas (Draft-07).\n//\n// Principe mathématique :\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// En JSON Schema :\n// - A ∩ B = allOf([A, B]) résolu via merge\n// - ≡ = comparaison structurelle\n//\n// @example\n// ```ts\n// const checker = new JsonSchemaCompatibilityChecker();\n//\n// checker.isSubset(strict, loose); // true\n// checker.check(loose, strict); // { isSubset: false, diffs: [...] }\n// checker.check(sub, sup, { subData: {...} }); // resolves conditions then checks\n// ```\n\nexport class JsonSchemaCompatibilityChecker {\n\tprivate readonly engine: MergeEngine;\n\n\tconstructor() {\n\t\tthis.engine = new MergeEngine();\n\t}\n\n\t// ── Subset check (boolean) ─────────────────────────────────────────────\n\n\t/**\n\t * Vérifie si `sub ⊆ sup`.\n\t * Toute valeur valide pour sub est-elle aussi valide pour sup ?\n\t *\n\t * Point 6 — Utilise `getBranchesTyped` pour distinguer `anyOf` de `oneOf`\n\t * en interne, bien que le résultat boolean ne reflète pas la distinction.\n\t */\n\tisSubset(sub: JSONSchema7Definition, sup: JSONSchema7Definition): boolean {\n\t\t// ── Identity short-circuit ──\n\t\t// If sub and sup are the same reference, sub ⊆ sup is trivially true.\n\t\t// This avoids the entire normalize + merge + compare pipeline.\n\t\tif (sub === sup) return true;\n\n\t\t// ── Pre-normalize structural equality ──\n\t\t// If sub and sup are structurally identical before normalization,\n\t\t// they represent the same schema → sub ⊆ sup trivially.\n\t\t// This avoids the WeakMap overhead of normalize() for common cases\n\t\t// like {} ⊆ {} or identical schema objects with different references.\n\t\tif (deepEqual(sub, sup)) return true;\n\n\t\tconst nSub = normalize(sub);\n\t\tconst nSup = normalize(sup);\n\n\t\t// ── Post-normalize structural identity ──\n\t\t// After normalization, schemas that were syntactically different\n\t\t// but semantically equivalent become structurally equal\n\t\t// (e.g. {const:1} vs {const:1, type:\"integer\"}).\n\t\tif (nSub !== sub && nSup !== sup && deepEqual(nSub, nSup)) return true;\n\t\tif (nSub !== nSup && deepEqual(nSub, nSup)) return true;\n\n\t\tconst { branches: subBranches } = getBranchesTyped(nSub);\n\n\t\tif (subBranches.length > 1 || subBranches[0] !== nSub) {\n\t\t\treturn subBranches.every((branch) =>\n\t\t\t\tisAtomicSubsetOf(branch, nSup, this.engine),\n\t\t\t);\n\t\t}\n\n\t\treturn isAtomicSubsetOf(nSub, nSup, this.engine);\n\t}\n\n\t// ── Subset check (detailed) ────────────────────────────────────────────\n\n\t/**\n\t * Vérifie `sub ⊆ sup` et retourne un diagnostic complet\n\t * avec des erreurs sémantiques lisibles.\n\t *\n\t * Si `options` est fourni avec `subData`, les conditions `if/then/else`\n\t * des deux schemas sont résolues avant le check :\n\t * - `subData` est utilisé pour résoudre les conditions du sub\n\t * - `supData` (ou `subData` par défaut) est utilisé pour résoudre le sup\n\t *\n\t * @param sub - Le schema source (candidat subset)\n\t * @param sup - Le schema cible (superset attendu)\n\t * @param options - Options de résolution de conditions (optionnel)\n\t * @returns SubsetResult si pas d'options, ResolvedSubsetResult si options fournies\n\t *\n\t * @example\n\t * ```ts\n\t * // Sans résolution de conditions\n\t * checker.check(sub, sup);\n\t *\n\t * // Avec résolution de conditions (subData pour les deux)\n\t * checker.check(sub, sup, { subData: { kind: \"text\" } });\n\t *\n\t * // Avec résolution séparée pour sub et sup\n\t * checker.check(sub, sup, { subData: { kind: \"text\" }, supData: { kind: \"other\" } });\n\t * ```\n\t */\n\tcheck(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t\toptions: CheckConditionsOptions,\n\t): ResolvedSubsetResult;\n\tcheck(sub: JSONSchema7Definition, sup: JSONSchema7Definition): SubsetResult;\n\tcheck(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t\toptions?: CheckConditionsOptions,\n\t): SubsetResult | ResolvedSubsetResult {\n\t\t// ── Condition resolution path ──\n\t\tif (options) {\n\t\t\tconst subData = options.subData;\n\t\t\tconst supData = options.supData ?? options.subData;\n\n\t\t\t// resolveConditions expects Record<string, unknown> for property access;\n\t\t\t// coerce non-object data to empty object (no conditions to resolve for primitives)\n\t\t\tconst subDataForConditions = isPlainObj(subData)\n\t\t\t\t? subData\n\t\t\t\t: ({} as Record<string, unknown>);\n\t\t\tconst supDataForConditions = isPlainObj(supData)\n\t\t\t\t? supData\n\t\t\t\t: ({} as Record<string, unknown>);\n\n\t\t\tconst resolvedSub = resolveConditions(\n\t\t\t\tsub as JSONSchema7,\n\t\t\t\tsubDataForConditions,\n\t\t\t\tthis.engine,\n\t\t\t);\n\t\t\tconst resolvedSup = resolveConditions(\n\t\t\t\tsup as JSONSchema7,\n\t\t\t\tsupDataForConditions,\n\t\t\t\tthis.engine,\n\t\t\t);\n\n\t\t\t// ── Data narrowing ──\n\t\t\t// When runtime data is available, narrow the resolved schema by\n\t\t\t// constraining generic types to enum values when the data matches\n\t\t\t// the opposite schema's enum constraints.\n\t\t\tconst narrowedSubResolved =\n\t\t\t\tsubData !== undefined\n\t\t\t\t\t? narrowSchemaWithData(\n\t\t\t\t\t\t\tresolvedSub.resolved,\n\t\t\t\t\t\t\tsubData,\n\t\t\t\t\t\t\tresolvedSup.resolved,\n\t\t\t\t\t\t)\n\t\t\t\t\t: resolvedSub.resolved;\n\n\t\t\tconst narrowedSupResolved =\n\t\t\t\tsupData !== undefined\n\t\t\t\t\t? narrowSchemaWithData(\n\t\t\t\t\t\t\tresolvedSup.resolved,\n\t\t\t\t\t\t\tsupData,\n\t\t\t\t\t\t\tresolvedSub.resolved,\n\t\t\t\t\t\t)\n\t\t\t\t\t: resolvedSup.resolved;\n\n\t\t\tconst result = this.checkInternal(\n\t\t\t\tnarrowedSubResolved,\n\t\t\t\tnarrowedSupResolved,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tresolvedSub: { ...resolvedSub, resolved: narrowedSubResolved },\n\t\t\t\tresolvedSup: { ...resolvedSup, resolved: narrowedSupResolved },\n\t\t\t};\n\t\t}\n\n\t\t// ── Standard path (no condition resolution) ──\n\t\treturn this.checkInternal(sub, sup);\n\t}\n\n\t// ── Equality ───────────────────────────────────────────────────────────\n\n\t/**\n\t * Vérifie l'égalité structurelle entre deux schemas.\n\t */\n\tisEqual(a: JSONSchema7Definition, b: JSONSchema7Definition): boolean {\n\t\treturn this.engine.isEqual(normalize(a), normalize(b));\n\t}\n\n\t// ── Intersection ───────────────────────────────────────────────────────\n\n\t/**\n\t * Calcule l'intersection de deux schemas (allOf merge).\n\t * Retourne null si les schemas sont incompatibles.\n\t *\n\t * Le résultat est normalisé pour éliminer les artefacts structurels\n\t * du merge (ex: `enum` redondant quand `const` est présent).\n\t */\n\tintersect(\n\t\ta: JSONSchema7Definition,\n\t\tb: JSONSchema7Definition,\n\t): JSONSchema7Definition | null {\n\t\t// ── Identity short-circuit ──\n\t\t// If a and b are the same reference or structurally equal,\n\t\t// intersection is just normalize(a) — skip the merge entirely.\n\t\tif (a === b || deepEqual(a, b)) return normalize(a);\n\n\t\tconst nA = normalize(a);\n\t\tconst nB = normalize(b);\n\n\t\t// ── Post-normalize identity ──\n\t\tif (deepEqual(nA, nB)) return nA;\n\n\t\tconst merged = this.engine.merge(nA, nB);\n\t\tif (merged === null) return null;\n\t\t// Fast path: if merge result equals one of the normalized inputs,\n\t\t// it's already normalized — skip redundant normalize call.\n\t\tif (deepEqual(merged, nA) || deepEqual(merged, nB)) return merged;\n\t\treturn normalize(merged);\n\t}\n\n\t// ── Normalization ──────────────────────────────────────────────────────\n\n\t/**\n\t * Normalise un schema : infère `type` depuis `const`/`enum`,\n\t * et normalise récursivement tous les sous-schemas.\n\t */\n\tnormalize(def: JSONSchema7Definition): JSONSchema7Definition {\n\t\treturn normalize(def);\n\t}\n\n\t// ── Formatting ─────────────────────────────────────────────────────────\n\n\t/**\n\t * Formate un SubsetResult en chaîne lisible (utile pour logs/debug).\n\t */\n\tformatResult(label: string, result: SubsetResult): string {\n\t\treturn formatResult(label, result);\n\t}\n\n\t// ── Condition Resolution ────────────────────────────────────────────────\n\n\t/**\n\t * Resolves `if/then/else` conditions in a schema by evaluating the `if`\n\t * against partial data (discriminants).\n\t *\n\t * @param schema - The schema containing conditions to resolve\n\t * @param data - The runtime data used to evaluate conditions\n\t * @returns The resolved schema with branch info and discriminants\n\t */\n\tresolveConditions(\n\t\tschema: JSONSchema7,\n\t\tdata: Record<string, unknown>,\n\t): ResolvedConditionResult {\n\t\treturn resolveConditions(schema, data, this.engine);\n\t}\n\n\t// ── Private ────────────────────────────────────────────────────────────\n\n\t/**\n\t * Logique interne de check sans résolution de conditions.\n\t * Factorise le pipeline normalize → branch → atomic pour éviter\n\t * la duplication entre les deux chemins de `check()`.\n\t */\n\tprivate checkInternal(\n\t\tsub: JSONSchema7Definition,\n\t\tsup: JSONSchema7Definition,\n\t): SubsetResult {\n\t\t// ── Identity short-circuit ──\n\t\t// Same reference → no errors, no merge needed.\n\t\tif (sub === sup) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\t// ── Pre-normalize structural equality ──\n\t\t// Avoids WeakMap overhead for identical schemas ({} ⊆ {}, etc.).\n\t\tif (deepEqual(sub, sup)) {\n\t\t\treturn { isSubset: true, merged: sub, errors: [] };\n\t\t}\n\n\t\tconst nSub = normalize(sub);\n\t\tconst nSup = normalize(sup);\n\n\t\t// ── Post-normalize structural identity ──\n\t\t// Catches semantically equivalent schemas after normalization.\n\t\tif (deepEqual(nSub, nSup)) {\n\t\t\treturn { isSubset: true, merged: nSub, errors: [] };\n\t\t}\n\n\t\tconst { branches: subBranches, type: subBranchType } =\n\t\t\tgetBranchesTyped(nSub);\n\t\tconst { branches: supBranches, type: supBranchType } =\n\t\t\tgetBranchesTyped(nSup);\n\n\t\t// anyOf/oneOf dans sub\n\t\tif (subBranches.length > 1 || subBranches[0] !== nSub) {\n\t\t\treturn checkBranchedSub(subBranches, nSup, this.engine, subBranchType);\n\t\t}\n\n\t\t// anyOf/oneOf dans sup uniquement\n\t\tif (supBranches.length > 1 || supBranches[0] !== nSup) {\n\t\t\treturn checkBranchedSup(nSub, supBranches, this.engine, supBranchType);\n\t\t}\n\n\t\t// Cas standard\n\t\treturn checkAtomic(nSub, nSup, this.engine);\n\t}\n}\n"],"names":["resolveConditions","narrowSchemaWithData","formatResult","MergeEngine","normalize","arePatternsEquivalent","isPatternSubset","isTrivialPattern","checkAtomic","checkBranchedSub","checkBranchedSup","getBranchesTyped","isAtomicSubsetOf","deepEqual","isPlainObj","JsonSchemaCompatibilityChecker","isSubset","sub","sup","nSub","nSup","branches","subBranches","length","every","branch","engine","check","options","subData","supData","subDataForConditions","supDataForConditions","resolvedSub","resolvedSup","narrowedSubResolved","undefined","resolved","narrowedSupResolved","result","checkInternal","isEqual","a","b","intersect","nA","nB","merged","merge","def","label","schema","data","errors","type","subBranchType","supBranches","supBranchType"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/merge-engine.ts"],"sourcesContent":["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"],"names":["createComparator","createMerger","createShallowAllOfMerge","createDeduplicator","createIntersector","isFormatSubset","deepEqual","hasOwn","isPlainObj","hasConstConflict","a","b","aHasConst","bHasConst","aConst","const","bConst","aEnum","enum","bEnum","Array","isArray","some","v","SINGLE_SCHEMA_CONFLICT_KEYS","PROPERTIES_MAP_CONFLICT_KEYS","hasDeepConstConflict","key","aVal","bVal","aMap","bMap","aMapSafe","bMapSafe","propKey","Object","keys","undefined","items","aItems","bItems","len","Math","min","length","i","aItem","bItem","hasAdditionalPropertiesConflict","aProps","properties","bProps","aKeys","bKeys","aRequired","required","bRequired","additionalProperties","hasRequiredExtra","k","addPropsSchema","addPropsType","type","hasTypeConflict","bPropDef","bProp","aPropDef","aProp","hasFormatConflict","aFormat","format","bFormat","subsetCheck","reverseCheck","MergeEngine","merge","shallowAllOfMergeFn","allOf","mergeOrThrow","Error","compare","compareFn","isEqual","compareSchemaDefinitions","compareSchemaValues","safeCompareSchemaValues","mergeArrayOfSchemaDefinitions","intersectJson","deduplicateJsonSchemaDef"],"mappings":"oLAAA,OACCA,gBAAgB,CAChBC,YAAY,CACZC,uBAAuB,KACjB,wBAAyB,AAChC,QACCC,kBAAkB,CAClBC,iBAAiB,KACX,kCAAmC,AAQ1C,QAASC,cAAc,KAAQ,oBAAqB,AACpD,QAASC,SAAS,CAAEC,MAAM,CAAEC,UAAU,KAAQ,SAAU,CA6BxD,SAASC,iBACRC,CAAwB,CACxBC,CAAwB,EAExB,GAAI,OAAOD,IAAM,WAAa,OAAOC,IAAM,UAAW,OAAO,MAE7D,MAAMC,UAAYL,OAAOG,EAAG,SAC5B,MAAMG,UAAYN,OAAOI,EAAG,SAC5B,MAAMG,OAAS,AAACJ,EAA8BK,KAAK,CACnD,MAAMC,OAAS,AAACL,EAA8BI,KAAK,CACnD,MAAME,MAAQP,EAAEQ,IAAI,CACpB,MAAMC,MAAQR,EAAEO,IAAI,CAGpB,GAAIN,WAAaC,UAAW,CAC3B,MAAO,CAACP,UAAUQ,OAAQE,OAC3B,CAGA,GAAIJ,WAAaQ,MAAMC,OAAO,CAACF,OAAQ,CACtC,MAAO,CAACA,MAAMG,IAAI,CAAC,AAACC,GAAMjB,UAAUiB,EAAGT,QACxC,CACA,GAAID,WAAaO,MAAMC,OAAO,CAACJ,OAAQ,CACtC,MAAO,CAACA,MAAMK,IAAI,CAAC,AAACC,GAAMjB,UAAUiB,EAAGP,QACxC,CAEA,OAAO,KACR,CAGA,MAAMQ,4BAA8B,CACnC,QACA,uBACA,WACA,gBACA,MACA,CAGD,MAAMC,6BAA+B,CACpC,aACA,oBACA,CAcD,SAASC,qBACRhB,CAAwB,CACxBC,CAAwB,EAExB,GAAIF,iBAAiBC,EAAGC,GAAI,OAAO,KAEnC,GAAI,OAAOD,IAAM,WAAa,OAAOC,IAAM,UAAW,OAAO,MAG7D,IAAK,MAAMgB,OAAOH,4BAA6B,CAC9C,MAAMI,KAAO,AAAClB,CAA6B,CAACiB,IAAI,CAGhD,MAAME,KAAO,AAAClB,CAA6B,CAACgB,IAAI,CAGhD,GACCnB,WAAWoB,OACXpB,WAAWqB,OACXH,qBACCE,KACAC,MAEA,CACD,OAAO,IACR,CACD,CAGA,IAAK,MAAMF,OAAOF,6BAA8B,CAC/C,MAAMK,KAAO,AAACpB,CAA6B,CAACiB,IAAI,CAGhD,MAAMI,KAAO,AAACpB,CAA6B,CAACgB,IAAI,CAGhD,GAAI,CAACnB,WAAWsB,OAAS,CAACtB,WAAWuB,MAAO,SAC5C,MAAMC,SAAWF,KACjB,MAAMG,SAAWF,KACjB,IAAK,MAAMG,WAAWC,OAAOC,IAAI,CAACJ,UAAW,CAC5C,MAAMJ,KAAOI,QAAQ,CAACE,QAAQ,CAC9B,MAAML,KAAOI,QAAQ,CAACC,QAAQ,CAC9B,GACCN,OAASS,WACTR,OAASQ,WACT9B,OAAO0B,SAAUC,UACjBR,qBAAqBE,KAAMC,MAC1B,CACD,OAAO,IACR,CACD,CACD,CAGA,GAAIT,MAAMC,OAAO,CAACX,EAAE4B,KAAK,GAAKlB,MAAMC,OAAO,CAACV,EAAE2B,KAAK,EAAG,CACrD,MAAMC,OAAS7B,EAAE4B,KAAK,CACtB,MAAME,OAAS7B,EAAE2B,KAAK,CACtB,MAAMG,IAAMC,KAAKC,GAAG,CAACJ,OAAOK,MAAM,CAAEJ,OAAOI,MAAM,EACjD,IAAK,IAAIC,EAAI,EAAGA,EAAIJ,IAAKI,IAAK,CAC7B,MAAMC,MAAQP,MAAM,CAACM,EAAE,CACvB,MAAME,MAAQP,MAAM,CAACK,EAAE,CACvB,GAAIC,QAAUT,WAAaU,QAAUV,UAAW,SAChD,GAAIX,qBAAqBoB,MAAOC,OAAQ,CACvC,OAAO,IACR,CACD,CACD,CAEA,OAAO,KACR,CAuCA,SAASC,gCACRtC,CAAwB,CACxBC,CAAwB,EAExB,GAAI,OAAOD,IAAM,WAAa,OAAOC,IAAM,UAAW,OAAO,MAE7D,MAAMsC,OAASzC,WAAWE,EAAEwC,UAAU,EAClCxC,EAAEwC,UAAU,CACbb,UACH,MAAMc,OAAS3C,WAAWG,EAAEuC,UAAU,EAClCvC,EAAEuC,UAAU,CACbb,UAGH,GAAI,CAACY,QAAU,CAACE,OAAQ,OAAO,MAE/B,MAAMC,MAAQH,OAASd,OAAOC,IAAI,CAACa,QAAU,EAAE,CAC/C,MAAMI,MAAQF,OAAShB,OAAOC,IAAI,CAACe,QAAU,EAAE,CAC/C,MAAMG,UAAYlC,MAAMC,OAAO,CAACX,EAAE6C,QAAQ,EAAK7C,EAAE6C,QAAQ,CAAgB,EAAE,CAC3E,MAAMC,UAAYpC,MAAMC,OAAO,CAACV,EAAE4C,QAAQ,EAAK5C,EAAE4C,QAAQ,CAAgB,EAAE,CAM3E,GAAI7C,EAAE+C,oBAAoB,GAAK,OAASR,QAAUE,OAAQ,CACzD,MAAMO,iBAAmBF,UAAUlC,IAAI,CACtC,AAACqC,GAAM,CAACpD,OAAO0C,OAAQU,IAAMpD,OAAO4C,OAAQQ,IAI7C,GAAID,kBAAoBN,MAAMR,MAAM,CAAG,EAAG,OAAO,IAClD,CAKA,GACCpC,WAAWE,EAAE+C,oBAAoB,GACjC,OAAO/C,EAAE+C,oBAAoB,GAAK,WAClCR,QACAE,OACC,CACD,MAAMS,eAAiBlD,EAAE+C,oBAAoB,CAC7C,GAAIlD,OAAOqD,eAAgB,QAAS,CACnC,MAAMC,aAAeD,eAAeE,IAAI,CACxC,MAAMC,gBAAkBP,UAAUlC,IAAI,CAAC,AAACqC,IACvC,GAAIpD,OAAO0C,OAAQU,GAAI,OAAO,MAC9B,GAAI,CAACpD,OAAO4C,OAAQQ,GAAI,OAAO,MAC/B,MAAMK,SAAWb,MAAM,CAACQ,EAAE,CAC1B,GAAI,OAAOK,WAAa,UAAW,OAAO,MAC1C,MAAMC,MAAQD,SACd,GAAI,CAACzD,OAAO0D,MAAO,QAAS,OAAO,MACnC,GACC,OAAOJ,eAAiB,UACxB,OAAOI,MAAMH,IAAI,GAAK,SACrB,CACD,OACCD,eAAiBI,MAAMH,IAAI,EAC3B,CAAED,CAAAA,eAAiB,UAAYI,MAAMH,IAAI,GAAK,SAAQ,GACtD,CAAED,CAAAA,eAAiB,WAAaI,MAAMH,IAAI,GAAK,QAAO,CAExD,CACA,OAAO,KACR,GACA,GAAIC,gBAAiB,OAAO,IAC7B,CACD,CAGA,GAAIpD,EAAE8C,oBAAoB,GAAK,OAASN,QAAUF,OAAQ,CACzD,MAAMS,iBAAmBJ,UAAUhC,IAAI,CACtC,AAACqC,GAAM,CAACpD,OAAO4C,OAAQQ,IAAMpD,OAAO0C,OAAQU,IAE7C,GAAID,kBAAoBL,MAAMT,MAAM,CAAG,EAAG,OAAO,IAClD,CAGA,GACCpC,WAAWG,EAAE8C,oBAAoB,GACjC,OAAO9C,EAAE8C,oBAAoB,GAAK,WAClCN,QACAF,OACC,CACD,MAAMW,eAAiBjD,EAAE8C,oBAAoB,CAC7C,GAAIlD,OAAOqD,eAAgB,QAAS,CACnC,MAAMC,aAAeD,eAAeE,IAAI,CACxC,MAAMC,gBAAkBT,UAAUhC,IAAI,CAAC,AAACqC,IACvC,GAAIpD,OAAO4C,OAAQQ,GAAI,OAAO,MAC9B,GAAI,CAACpD,OAAO0C,OAAQU,GAAI,OAAO,MAC/B,MAAMO,SAAWjB,MAAM,CAACU,EAAE,CAC1B,GAAI,OAAOO,WAAa,UAAW,OAAO,MAC1C,MAAMC,MAAQD,SACd,GAAI,CAAC3D,OAAO4D,MAAO,QAAS,OAAO,MACnC,GACC,OAAON,eAAiB,UACxB,OAAOM,MAAML,IAAI,GAAK,SACrB,CACD,OACCD,eAAiBM,MAAML,IAAI,EAC3B,CAAED,CAAAA,eAAiB,UAAYM,MAAML,IAAI,GAAK,SAAQ,GACtD,CAAED,CAAAA,eAAiB,WAAaM,MAAML,IAAI,GAAK,QAAO,CAExD,CACA,OAAO,KACR,GACA,GAAIC,gBAAiB,OAAO,IAC7B,CACD,CAKA,GAAId,QAAUE,OAAQ,CACrB,IAAK,MAAMQ,KAAKP,MAAO,CACtB,GAAI,CAAC7C,OAAO4C,OAAQQ,GAAI,SACxB,MAAMO,SAAWjB,MAAM,CAACU,EAAE,CAC1B,MAAMK,SAAWb,MAAM,CAACQ,EAAE,CAC1B,GAAI,OAAOO,WAAa,WAAa,OAAOF,WAAa,UACxD,SACD,GACChB,gCACCkB,SACAF,UAEA,CACD,OAAO,IACR,CACD,CACD,CAEA,OAAO,KACR,CAsBA,SAASI,kBACR1D,CAAwB,CACxBC,CAAwB,EAExB,GAAI,OAAOD,IAAM,WAAa,OAAOC,IAAM,UAAW,OAAO,MAI7D,GAAIJ,OAAOG,EAAG,WAAaH,OAAOI,EAAG,UAAW,CAC/C,MAAM0D,QAAU3D,EAAE4D,MAAM,CACxB,MAAMC,QAAU5D,EAAE2D,MAAM,CAGxB,GAAID,UAAYE,QAAS,CAExB,MAAMC,YAAcnE,eAAegE,QAASE,SAC5C,GAAIC,cAAgB,KAAM,CACzB,MAAMC,aAAepE,eAAekE,QAASF,SAC7C,GAAII,eAAiB,KAAM,CAE1B,OAAO,IACR,CACD,CACD,CACD,CAIA,GAAIjE,WAAWE,EAAEwC,UAAU,GAAK1C,WAAWG,EAAEuC,UAAU,EAAG,CACzD,MAAMpB,KAAOpB,EAAEwC,UAAU,CACzB,MAAMnB,KAAOpB,EAAEuC,UAAU,CACzB,IAAK,MAAMS,KAAKxB,OAAOC,IAAI,CAACN,MAAO,CAClC,MAAMF,KAAOE,IAAI,CAAC6B,EAAE,CACpB,MAAM9B,KAAOE,IAAI,CAAC4B,EAAE,CACpB,GACC/B,OAASS,WACTR,OAASQ,WACT9B,OAAOwB,KAAM4B,IACbS,kBAAkBxC,KAAMC,MACvB,CACD,OAAO,IACR,CACD,CACD,CAGA,GAAIrB,WAAWE,EAAE4B,KAAK,GAAK9B,WAAWG,EAAE2B,KAAK,EAAG,CAC/C,GACC8B,kBACC1D,EAAE4B,KAAK,CACP3B,EAAE2B,KAAK,EAGR,OAAO,IACT,CAGA,GACC9B,WAAWE,EAAE+C,oBAAoB,GACjCjD,WAAWG,EAAE8C,oBAAoB,EAChC,CACD,GACCW,kBACC1D,EAAE+C,oBAAoB,CACtB9C,EAAE8C,oBAAoB,EAGvB,OAAO,IACT,CAEA,OAAO,KACR,CAIA,OAAO,MAAMiB,YA6CZC,MACCjE,CAAwB,CACxBC,CAAwB,CACO,CAE/B,GAAIe,qBAAqBhB,EAAGC,GAAI,CAC/B,OAAO,IACR,CAGA,GAAIyD,kBAAkB1D,EAAGC,GAAI,CAC5B,OAAO,IACR,CAOA,GAAIqC,gCAAgCtC,EAAGC,GAAI,CAC1C,OAAO,IACR,CAEA,GAAI,CACH,OAAO,IAAI,CAACiE,mBAAmB,CAAC,CAAEC,MAAO,CAACnE,EAAGC,EAAE,AAAC,EACjD,CAAE,KAAM,CACP,OAAO,IACR,CACD,CAQAmE,aACCpE,CAAwB,CACxBC,CAAwB,CACA,CAExB,GAAIe,qBAAqBhB,EAAGC,GAAI,CAC/B,MAAM,IAAIoE,MACT,wEAEF,CAGA,GAAIX,kBAAkB1D,EAAGC,GAAI,CAC5B,MAAM,IAAIoE,MACT,0EAEF,CAGA,GAAI/B,gCAAgCtC,EAAGC,GAAI,CAC1C,MAAM,IAAIoE,MACT,uGAEF,CAEA,OAAO,IAAI,CAACH,mBAAmB,CAAC,CAAEC,MAAO,CAACnE,EAAGC,EAAE,AAAC,EACjD,CAMAqE,QAAQtE,CAAwB,CAAEC,CAAwB,CAAU,CACnE,OAAO,IAAI,CAACsE,SAAS,CAACvE,EAAGC,EAC1B,CAKAuE,QAAQxE,CAAwB,CAAEC,CAAwB,CAAW,CACpE,OAAO,IAAI,CAACsE,SAAS,CAACvE,EAAGC,KAAO,CACjC,CAhHA,aAAc,CATd,sBAAiBsE,YAAjB,KAAA,GAKA,sBAAiBL,sBAAjB,KAAA,GAKC,KAAM,CAAEO,wBAAwB,CAAEC,mBAAmB,CAAE,CACtDpF,mBAOD,MAAMqF,wBAA0B,CAC/B3E,EACAC,KAEA,GAAID,IAAM,MAAQC,IAAM,KAAM,OAAO,EACrC,OAAOyE,oBAAoB1E,EAAGC,EAC/B,EAEA,KAAM,CAAE2E,6BAA6B,CAAE,CAAGrF,aAAa,CACtDsF,cAAenF,kBAAkBiF,yBACjCG,yBAA0BrF,mBAAmBgF,yBAC9C,EAEA,CAAA,IAAI,CAACF,SAAS,CAAGE,wBACjB,CAAA,IAAI,CAACP,mBAAmB,CAAG1E,wBAC1BoF,8BAEF,CAuFD"}
1
+ {"version":3,"sources":["../../src/merge-engine.ts"],"sourcesContent":["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 * Uses `deepEqual` from `utils.ts` for deep comparison (objects, arrays).\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"],"names":["createComparator","createMerger","createShallowAllOfMerge","createDeduplicator","createIntersector","isFormatSubset","deepEqual","hasOwn","isPlainObj","hasConstConflict","a","b","aHasConst","bHasConst","aConst","const","bConst","aEnum","enum","bEnum","Array","isArray","some","v","SINGLE_SCHEMA_CONFLICT_KEYS","PROPERTIES_MAP_CONFLICT_KEYS","hasDeepConstConflict","key","aVal","bVal","aMap","bMap","aMapSafe","bMapSafe","propKey","Object","keys","undefined","items","aItems","bItems","len","Math","min","length","i","aItem","bItem","hasAdditionalPropertiesConflict","aProps","properties","bProps","aKeys","bKeys","aRequired","required","bRequired","additionalProperties","hasRequiredExtra","k","addPropsSchema","addPropsType","type","hasTypeConflict","bPropDef","bProp","aPropDef","aProp","hasFormatConflict","aFormat","format","bFormat","subsetCheck","reverseCheck","MergeEngine","merge","shallowAllOfMergeFn","allOf","mergeOrThrow","Error","compare","compareFn","isEqual","compareSchemaDefinitions","compareSchemaValues","safeCompareSchemaValues","mergeArrayOfSchemaDefinitions","intersectJson","deduplicateJsonSchemaDef"],"mappings":"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"}
@@ -15,9 +15,25 @@ export interface SubsetResult {
15
15
  /** Erreurs sémantiques décrivant les incompatibilités entre les deux schemas */
16
16
  errors: SchemaError[];
17
17
  }
18
- export interface ConnectionResult extends SubsetResult {
19
- /** Direction lisible du check */
20
- direction: string;
18
+ /**
19
+ * Options pour résoudre les if/then/else avant un check de subset.
20
+ * Si `subData` est fourni, les conditions du sub sont résolues.
21
+ * Si `supData` est aussi fourni, il est utilisé pour résoudre le sup ;
22
+ * sinon `subData` est utilisé pour les deux.
23
+ */
24
+ export interface CheckConditionsOptions {
25
+ /** Runtime data for the sub schema — used for condition resolution and enum narrowing */
26
+ subData: unknown;
27
+ /** Runtime data for the sup schema (defaults to subData) — used for condition resolution and enum narrowing */
28
+ supData?: unknown;
29
+ }
30
+ /**
31
+ * Résultat étendu de `check()` quand des options de conditions sont fournies.
32
+ * Inclut les résultats de résolution pour sub et sup en plus du SubsetResult.
33
+ */
34
+ export interface ResolvedSubsetResult extends SubsetResult {
35
+ resolvedSub: ResolvedConditionResult;
36
+ resolvedSup: ResolvedConditionResult;
21
37
  }
22
38
  export interface ResolvedConditionResult {
23
39
  /** Le schema avec les if/then/else résolus (aplatis) */
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\n\n// ─── Public types ────────────────────────────────────────────────────────────\n\nexport interface SchemaError {\n\t/** Chemin normalisé vers la propriété concernée (ex: \"user.name\", \"users[].name\", \"accountId\") */\n\tkey: string;\n\t/** Type ou valeur attendu(e) par le schema cible (sup) */\n\texpected: string;\n\t/** Type ou valeur reçu(e) depuis le schema source (sub) */\n\treceived: string;\n}\n\nexport interface SubsetResult {\n\t/** true si sub ⊆ sup (toute valeur valide pour sub est valide pour sup) */\n\tisSubset: boolean;\n\t/** Le schema résultant de l'intersection allOf(sub, sup), ou null si incompatible */\n\tmerged: JSONSchema7Definition | null;\n\t/** Erreurs sémantiques décrivant les incompatibilités entre les deux schemas */\n\terrors: SchemaError[];\n}\n\nexport interface ConnectionResult extends SubsetResult {\n\t/** Direction lisible du check */\n\tdirection: string;\n}\n\nexport interface ResolvedConditionResult {\n\t/** Le schema avec les if/then/else résolus (aplatis) */\n\tresolved: JSONSchema7;\n\t/** La branche qui a été appliquée (\"then\" | \"else\" | null si pas de condition) */\n\tbranch: \"then\" | \"else\" | null;\n\t/** Le discriminant utilisé pour résoudre */\n\tdiscriminant: Record<string, unknown>;\n}\n"],"names":[],"mappings":"AA2BA,QAOC"}
1
+ {"version":3,"sources":["../../src/types.ts"],"sourcesContent":["import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\n\n// ─── Public types ────────────────────────────────────────────────────────────\n\nexport interface SchemaError {\n\t/** Chemin normalisé vers la propriété concernée (ex: \"user.name\", \"users[].name\", \"accountId\") */\n\tkey: string;\n\t/** Type ou valeur attendu(e) par le schema cible (sup) */\n\texpected: string;\n\t/** Type ou valeur reçu(e) depuis le schema source (sub) */\n\treceived: string;\n}\n\nexport interface SubsetResult {\n\t/** true si sub ⊆ sup (toute valeur valide pour sub est valide pour sup) */\n\tisSubset: boolean;\n\t/** Le schema résultant de l'intersection allOf(sub, sup), ou null si incompatible */\n\tmerged: JSONSchema7Definition | null;\n\t/** Erreurs sémantiques décrivant les incompatibilités entre les deux schemas */\n\terrors: SchemaError[];\n}\n\n/**\n * Options pour résoudre les if/then/else avant un check de subset.\n * Si `subData` est fourni, les conditions du sub sont résolues.\n * Si `supData` est aussi fourni, il est utilisé pour résoudre le sup ;\n * sinon `subData` est utilisé pour les deux.\n */\nexport interface CheckConditionsOptions {\n\t/** Runtime data for the sub schema — used for condition resolution and enum narrowing */\n\tsubData: unknown;\n\t/** Runtime data for the sup schema (defaults to subData) — used for condition resolution and enum narrowing */\n\tsupData?: unknown;\n}\n\n/**\n * Résultat étendu de `check()` quand des options de conditions sont fournies.\n * Inclut les résultats de résolution pour sub et sup en plus du SubsetResult.\n */\nexport interface ResolvedSubsetResult extends SubsetResult {\n\tresolvedSub: ResolvedConditionResult;\n\tresolvedSup: ResolvedConditionResult;\n}\n\nexport interface ResolvedConditionResult {\n\t/** Le schema avec les if/then/else résolus (aplatis) */\n\tresolved: JSONSchema7;\n\t/** La branche qui a été appliquée (\"then\" | \"else\" | null si pas de condition) */\n\tbranch: \"then\" | \"else\" | null;\n\t/** Le discriminant utilisé pour résoudre */\n\tdiscriminant: Record<string, unknown>;\n}\n"],"names":[],"mappings":"AA4CA,QAOC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-schema-compatibility-checker",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "license": "MIT",
5
5
  "description": "A tool to check compatibility between two JSON Schemas.",
6
6
  "author": {