json-schema-compatibility-checker 1.0.3 → 1.0.4
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.
- package/dist/{chunk-gdf3h8q4.js → chunk-07z7fc5q.js} +3 -3
- package/dist/{chunk-gdf3h8q4.js.map → chunk-07z7fc5q.js.map} +1 -1
- package/dist/chunk-2ddbnbyq.js +5 -0
- package/dist/chunk-2ddbnbyq.js.map +10 -0
- package/dist/chunk-b55zsn5n.js +5 -0
- package/dist/chunk-b55zsn5n.js.map +10 -0
- package/dist/{chunk-w1ypc97a.js → chunk-jkdzdb3r.js} +3 -3
- package/dist/{chunk-w1ypc97a.js.map → chunk-jkdzdb3r.js.map} +1 -1
- package/dist/chunk-jybaxgmh.js +5 -0
- package/dist/chunk-jybaxgmh.js.map +10 -0
- package/dist/{chunk-ayae82am.js → chunk-pyrx217p.js} +4 -4
- package/dist/{chunk-ayae82am.js.map → chunk-pyrx217p.js.map} +1 -1
- package/dist/{chunk-mfe3cw5r.js → chunk-q7kq4fgq.js} +3 -3
- package/dist/{chunk-mfe3cw5r.js.map → chunk-q7kq4fgq.js.map} +1 -1
- package/dist/chunk-y8c2z1m3.js +6 -0
- package/dist/chunk-y8c2z1m3.js.map +10 -0
- package/dist/chunk-yg81ax5m.js +5 -0
- package/dist/{chunk-etwjsbj3.js.map → chunk-yg81ax5m.js.map} +2 -2
- package/dist/{chunk-ywa6h8q4.js → chunk-yqhv3py7.js} +4 -4
- package/dist/{chunk-ywa6h8q4.js.map → chunk-yqhv3py7.js.map} +1 -1
- package/dist/condition-resolver.js +2 -2
- package/dist/condition-resolver.js.map +1 -1
- package/dist/differ.js +2 -2
- package/dist/differ.js.map +1 -1
- package/dist/format-validator.js +2 -2
- package/dist/format-validator.js.map +1 -1
- package/dist/formatter.d.ts +2 -14
- package/dist/formatter.js +2 -2
- package/dist/formatter.js.map +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/json-schema-compatibility-checker.js +2 -2
- package/dist/json-schema-compatibility-checker.js.map +1 -1
- package/dist/merge-engine.js +2 -2
- package/dist/merge-engine.js.map +1 -1
- package/dist/normalizer.js +2 -2
- package/dist/normalizer.js.map +1 -1
- package/dist/pattern-subset.js +2 -2
- package/dist/pattern-subset.js.map +1 -1
- package/dist/subset-checker.js +2 -2
- package/dist/subset-checker.js.map +1 -1
- package/dist/types.d.ts +3 -6
- package/dist/utils.js +2 -2
- package/dist/utils.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-8me729r7.js +0 -5
- package/dist/chunk-8me729r7.js.map +0 -12
- package/dist/chunk-8qenxa2z.js +0 -7
- package/dist/chunk-8qenxa2z.js.map +0 -10
- package/dist/chunk-etwjsbj3.js +0 -5
- package/dist/chunk-jy9206ze.js +0 -5
- package/dist/chunk-jy9206ze.js.map +0 -10
- package/dist/chunk-k92ftyzf.js +0 -5
- package/dist/chunk-k92ftyzf.js.map +0 -10
- package/dist/semantic-diff/analyzer.d.ts +0 -25
- package/dist/semantic-diff/detectors.d.ts +0 -79
- package/dist/semantic-diff/index.d.ts +0 -3
- package/dist/semantic-diff/types.d.ts +0 -81
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import{isEmail as y,isFQDN as z,isIP as C,isISO8601 as H,isURL as w,isUUID as Y}from"class-validator";var Z=/^\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/,$=/^\d{4}-\d{2}-\d{2}$/,x=/^(\/([^~/]|~[01])*)*$/,K=/^\d+(#|(\/([^~/]|~[01])*)*)$/;var W=new Set(["date-time","date","time","email","idn-email","hostname","idn-hostname","ipv4","ipv6","uri","uri-reference","iri","iri-reference","uri-template","uuid","json-pointer","relative-json-pointer","regex"]),q={email:["idn-email"],hostname:["idn-hostname"],uri:["iri"],"uri-reference":["iri-reference"]},J={"date-time":(g)=>{return H(g,{strict:!0})},date:(g)=>{if(!$.test(g))return!1;let j=new Date(`${g}T00:00:00Z`);return!Number.isNaN(j.getTime())&&g===j.toISOString().slice(0,10)},time:(g)=>{return Z.test(g)},email:(g)=>{return y(g)},"idn-email":(g)=>{return y(g)},hostname:(g)=>{return z(g,{require_tld:!1})},"idn-hostname":(g)=>{return z(g,{require_tld:!1})},ipv4:(g)=>{return C(g,4)},ipv6:(g)=>{return C(g,6)},uri:(g)=>{return w(g,{require_protocol:!0})},"uri-reference":(g)=>{return w(g,{require_protocol:!1})},iri:(g)=>{return w(g,{require_protocol:!0})},"iri-reference":(g)=>{return w(g,{require_protocol:!1})},"uri-template":(g)=>{let j=!1;for(let k of g)if(k==="{"){if(j)return!1;j=!0}else if(k==="}"){if(!j)return!1;j=!1}return!j},uuid:(g)=>{return Y(g)},"json-pointer":(g)=>{if(g==="")return!0;return x.test(g)},"relative-json-pointer":(g)=>{return K.test(g)},regex:(g)=>{try{return new RegExp(g),!0}catch{return!1}}};function V(g){return W.has(g)}function h(g,j){if(typeof g!=="string")return!0;let k=J[j];if(!k)return null;return k(g)}function b(g,j){if(g===j)return!0;if(q[g]?.includes(j))return!0;return null}
|
|
2
|
-
export{W as
|
|
2
|
+
export{W as o,q as p,V as q,h as r,b as s};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
5
|
-
//# sourceMappingURL=chunk-
|
|
4
|
+
//# debugId=23E9231E413DFF0864756E2164756E21
|
|
5
|
+
//# sourceMappingURL=chunk-07z7fc5q.js.map
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"import {\n\tisEmail,\n\tisFQDN,\n\tisIP,\n\tisISO8601,\n\tisURL,\n\tisUUID,\n} from \"class-validator\";\n\n// ─── Format Validator ─────────────────────────────────────────────────────────\n//\n// Valide les valeurs contre les formats JSON Schema Draft-07 en utilisant\n// les fonctions utilitaires de `class-validator`.\n//\n// ⚠️ Ce module ne gère PAS la relation format ⊆ type.\n// Cette relation est déjà correctement gérée par l'approche merge :\n// - { format: \"email\" } ⊆ { type: \"string\" } → true (merge ne change rien)\n// - { type: \"string\" } ⊄ { format: \"email\" } → false (merge ajoute format)\n//\n// Ce module gère UNIQUEMENT :\n// 1. La validation d'une valeur runtime contre un format (evaluateCondition)\n// 2. La compatibilité entre deux formats différents (format-vs-format)\n//\n// Expose :\n// - `validateFormat(value, format)` → validation runtime d'une valeur\n// - `isFormatSubset(sub, sup)` → compatibilité statique format-vs-format\n// - `isKnownFormat(format)` → vérifie si le format est supporté\n// - `FORMAT_SUPERSETS` → hiérarchie d'inclusion entre formats\n\n// ─── Regex patterns ──────────────────────────────────────────────────────────\n\n/** Regex pour le format `time` (HH:MM:SS avec offset optionnel) */\nconst TIME_REGEX = /^\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})?$/;\n\n/** Regex pour le format `date` (YYYY-MM-DD strict) */\nconst DATE_REGEX = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** Regex pour le format `json-pointer` (RFC 6901) */\nconst JSON_POINTER_REGEX = /^(\\/([^~/]|~[01])*)*$/;\n\n/** Regex pour le format `relative-json-pointer` (extension Draft-07) */\nconst RELATIVE_JSON_POINTER_REGEX = /^\\d+(#|(\\/([^~/]|~[01])*)*)$/;\n\n/** Regex pour le format `uri-template` (RFC 6570 — vérification basique) */\nconst _URI_TEMPLATE_REGEX = /\\{[^}]+\\}/;\n\n// ─── Known formats ──────────────────────────────────────────────────────────\n\n/** Formats reconnus par le validateur */\nexport const KNOWN_FORMATS: ReadonlySet<string> = new Set([\n\t\"date-time\",\n\t\"date\",\n\t\"time\",\n\t\"email\",\n\t\"idn-email\",\n\t\"hostname\",\n\t\"idn-hostname\",\n\t\"ipv4\",\n\t\"ipv6\",\n\t\"uri\",\n\t\"uri-reference\",\n\t\"iri\",\n\t\"iri-reference\",\n\t\"uri-template\",\n\t\"uuid\",\n\t\"json-pointer\",\n\t\"relative-json-pointer\",\n\t\"regex\",\n]);\n\n// ─── Format hierarchy ────────────────────────────────────────────────────────\n\n/**\n * Hiérarchie d'inclusion ENTRE FORMATS (pas format-vs-type).\n *\n * `FORMAT_SUPERSETS[format]` = liste des formats qui sont des sur-ensembles\n * de `format` (i.e., toute valeur valide pour `format` est aussi valide\n * pour chacun des sur-ensembles).\n *\n * Cette hiérarchie ne concerne QUE les comparaisons format-vs-format.\n * La relation format ⊆ type (ex: email ⊆ string) est gérée nativement\n * par le merge engine et n'a pas besoin d'être modélisée ici.\n *\n * En pratique, la plupart des formats sont **incomparables** (pas de relation d'inclusion).\n * Seule l'identité (même format) et les quelques relations ci-dessous sont garanties.\n */\nexport const FORMAT_SUPERSETS: Record<string, string[]> = {\n\temail: [\"idn-email\"], // email ⊆ idn-email (toute email ASCII est une idn-email)\n\thostname: [\"idn-hostname\"], // hostname ⊆ idn-hostname\n\turi: [\"iri\"], // uri ⊆ iri (toute URI est une IRI)\n\t\"uri-reference\": [\"iri-reference\"], // uri-reference ⊆ iri-reference\n};\n\n// ─── Format validators (internal) ───────────────────────────────────────────\n\n/**\n * Map interne des fonctions de validation par format.\n *\n * Chaque entrée associe un format Draft-07 à une fonction qui prend\n * une valeur `string` et retourne `boolean`.\n *\n * Utilise les fonctions standalone de `class-validator` quand disponibles,\n * sinon des regex ou des heuristiques.\n */\nconst FORMAT_VALIDATORS: Record<string, (value: string) => boolean> = {\n\t/** ISO 8601 date-time (ex: \"2023-01-15T10:30:00Z\") */\n\t\"date-time\": (value: string): boolean => {\n\t\treturn isISO8601(value, { strict: true });\n\t},\n\n\t/** Date complète (ex: \"2023-01-15\") */\n\tdate: (value: string): boolean => {\n\t\tif (!DATE_REGEX.test(value)) return false;\n\t\t// Vérifier que la date est valide (pas de 2023-02-30)\n\t\tconst d = new Date(`${value}T00:00:00Z`);\n\t\treturn !Number.isNaN(d.getTime()) && value === d.toISOString().slice(0, 10);\n\t},\n\n\t/** Heure complète (ex: \"10:30:00\") */\n\ttime: (value: string): boolean => {\n\t\treturn TIME_REGEX.test(value);\n\t},\n\n\t/** Adresse email (RFC 5321) */\n\temail: (value: string): boolean => {\n\t\treturn isEmail(value);\n\t},\n\n\t/** Adresse email internationalisée (approximation via isEmail) */\n\t\"idn-email\": (value: string): boolean => {\n\t\treturn isEmail(value);\n\t},\n\n\t/** Nom d'hôte (RFC 1123) */\n\thostname: (value: string): boolean => {\n\t\treturn isFQDN(value, { require_tld: false });\n\t},\n\n\t/** Nom d'hôte internationalisé (approximation via isFQDN) */\n\t\"idn-hostname\": (value: string): boolean => {\n\t\treturn isFQDN(value, { require_tld: false });\n\t},\n\n\t/** Adresse IPv4 (ex: \"192.168.1.1\") */\n\tipv4: (value: string): boolean => {\n\t\treturn isIP(value, 4);\n\t},\n\n\t/** Adresse IPv6 (ex: \"::1\") */\n\tipv6: (value: string): boolean => {\n\t\treturn isIP(value, 6);\n\t},\n\n\t/** URI absolue (RFC 3986) */\n\turi: (value: string): boolean => {\n\t\treturn isURL(value, { require_protocol: true });\n\t},\n\n\t/** Référence URI (absolue ou relative — approximation via isURL) */\n\t\"uri-reference\": (value: string): boolean => {\n\t\t// Une uri-reference peut être relative, isURL est une approximation\n\t\treturn isURL(value, { require_protocol: false });\n\t},\n\n\t/** IRI (RFC 3987 — approximation via isURL) */\n\tiri: (value: string): boolean => {\n\t\treturn isURL(value, { require_protocol: true });\n\t},\n\n\t/** Référence IRI (approximation via isURL) */\n\t\"iri-reference\": (value: string): boolean => {\n\t\treturn isURL(value, { require_protocol: false });\n\t},\n\n\t/** Template URI (RFC 6570 — vérification basique) */\n\t\"uri-template\": (value: string): boolean => {\n\t\t// Un uri-template valide peut contenir des expressions entre accolades\n\t\t// ou être une URI simple sans template expressions.\n\t\t// On vérifie juste que les accolades sont bien formées.\n\t\tlet inBrace = false;\n\t\tfor (const ch of value) {\n\t\t\tif (ch === \"{\") {\n\t\t\t\tif (inBrace) return false; // Accolades imbriquées\n\t\t\t\tinBrace = true;\n\t\t\t} else if (ch === \"}\") {\n\t\t\t\tif (!inBrace) return false; // Accolade fermante sans ouvrante\n\t\t\t\tinBrace = false;\n\t\t\t}\n\t\t}\n\t\treturn !inBrace; // Pas d'accolade non fermée\n\t},\n\n\t/** UUID (RFC 4122) */\n\tuuid: (value: string): boolean => {\n\t\treturn isUUID(value);\n\t},\n\n\t/** JSON Pointer (RFC 6901) */\n\t\"json-pointer\": (value: string): boolean => {\n\t\t// Chaîne vide est un json-pointer valide (pointe vers la racine)\n\t\tif (value === \"\") return true;\n\t\treturn JSON_POINTER_REGEX.test(value);\n\t},\n\n\t/** Relative JSON Pointer (extension Draft-07) */\n\t\"relative-json-pointer\": (value: string): boolean => {\n\t\treturn RELATIVE_JSON_POINTER_REGEX.test(value);\n\t},\n\n\t/** Expression régulière ECMA-262 */\n\tregex: (value: string): boolean => {\n\t\ttry {\n\t\t\tnew RegExp(value);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n};\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Vérifie si le format est connu/supporté.\n *\n * @param format Le nom du format à vérifier\n * @returns `true` si le format est dans la liste des formats reconnus\n */\nexport function isKnownFormat(format: string): boolean {\n\treturn KNOWN_FORMATS.has(format);\n}\n\n/**\n * Valide une valeur contre un format JSON Schema Draft-07.\n *\n * Retourne `true` si la valeur est valide pour le format,\n * `false` si elle ne l'est pas, `null` si le format est inconnu.\n *\n * Ne valide que les strings — pour les non-strings, retourne `true`\n * (le format ne s'applique qu'aux strings en Draft-07).\n *\n * @param value La valeur à valider\n * @param format Le format JSON Schema Draft-07 à vérifier\n * @returns `true` si valide, `false` si invalide, `null` si format inconnu\n *\n * @example\n * ```ts\n * validateFormat(\"test@example.com\", \"email\"); // true\n * validateFormat(\"not-an-email\", \"email\"); // false\n * validateFormat(42, \"email\"); // true (non-string → skip)\n * validateFormat(\"foo\", \"unknown-format\"); // null (format inconnu)\n * ```\n */\nexport function validateFormat(value: unknown, format: string): boolean | null {\n\t// Le format ne s'applique qu'aux strings en Draft-07\n\tif (typeof value !== \"string\") return true;\n\n\tconst validator = FORMAT_VALIDATORS[format];\n\tif (!validator) return null; // Format inconnu → indéterminé\n\n\treturn validator(value);\n}\n\n/**\n * Vérifie si le format `sub` est un sous-ensemble du format `sup`.\n *\n * ⚠️ Cette fonction compare UNIQUEMENT deux formats entre eux.\n * Elle ne gère PAS la relation format ⊆ type (ex: email ⊆ string),\n * qui est déjà correctement gérée par le merge engine.\n *\n * `sub ⊆ sup` signifie : toute valeur valide pour `sub` est aussi valide pour `sup`.\n *\n * Retourne `true` si `sub ⊆ sup`, `false` si incompatible, `null` si indéterminé.\n *\n * Cas gérés :\n * - Identité : `sub === sup` → `true`\n * - Hiérarchie : `sup` est dans `FORMAT_SUPERSETS[sub]` → `true`\n * - Hiérarchie inverse : `sub` est dans `FORMAT_SUPERSETS[sup]` → `null`\n * (le subset est un sur-ensemble du superset → indéterminé, pas un conflit\n * car certaines valeurs valides pour sub pourraient aussi être valides pour sup)\n * - Formats différents sans relation connue → `null` (indéterminé)\n *\n * @param subFormat Le format du schema sub\n * @param supFormat Le format du schema sup\n * @returns `true` si sub ⊆ sup, `null` si indéterminé\n *\n * @example\n * ```ts\n * isFormatSubset(\"email\", \"email\"); // true (identité)\n * isFormatSubset(\"email\", \"idn-email\"); // true (email ⊆ idn-email)\n * isFormatSubset(\"email\", \"ipv4\"); // null (incomparable)\n * isFormatSubset(\"idn-email\", \"email\"); // null (sur-ensemble, pas sous-ensemble)\n * ```\n */\nexport function isFormatSubset(\n\tsubFormat: string,\n\tsupFormat: string,\n): boolean | null {\n\t// Identité : même format → toujours un sous-ensemble\n\tif (subFormat === supFormat) return true;\n\n\t// Hiérarchie : vérifier si sup est un sur-ensemble connu de sub\n\tconst supersets = FORMAT_SUPERSETS[subFormat];\n\tif (supersets?.includes(supFormat)) {\n\t\treturn true;\n\t}\n\n\t// Formats différents sans relation connue → indéterminé\n\t// On ne retourne PAS false ici car on ne peut pas affirmer l'incompatibilité\n\t// entre deux formats quelconques sans les connaître parfaitement.\n\t// Le merge engine (via hasFormatConflict) se charge de détecter les conflits\n\t// quand les deux schemas ont un format et qu'aucune relation n'est connue.\n\treturn null;\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": "AAAA,kBACC,YACA,UACA,eACA,WACA,YACA,wBA0BD,IAAM,EAAa,kDAGb,EAAa,sBAGb,EAAqB,wBAGrB,EAA8B,+BAQ7B,IAAM,EAAqC,IAAI,IAAI,CACzD,YACA,OACA,OACA,QACA,YACA,WACA,eACA,OACA,OACA,MACA,gBACA,MACA,gBACA,eACA,OACA,eACA,wBACA,OACD,CAAC,EAkBY,EAA6C,CACzD,MAAO,CAAC,WAAW,EACnB,SAAU,CAAC,cAAc,EACzB,IAAK,CAAC,KAAK,EACX,gBAAiB,CAAC,eAAe,CAClC,EAaM,EAAgE,CAErE,YAAa,CAAC,IAA2B,CACxC,OAAO,EAAU,EAAO,CAAE,OAAQ,EAAK,CAAC,GAIzC,KAAM,CAAC,IAA2B,CACjC,GAAI,CAAC,EAAW,KAAK,CAAK,EAAG,MAAO,GAEpC,IAAM,EAAI,IAAI,KAAK,GAAG,aAAiB,EACvC,MAAO,CAAC,OAAO,MAAM,EAAE,QAAQ,CAAC,GAAK,IAAU,EAAE,YAAY,EAAE,MAAM,EAAG,EAAE,GAI3E,KAAM,CAAC,IAA2B,CACjC,OAAO,EAAW,KAAK,CAAK,GAI7B,MAAO,CAAC,IAA2B,CAClC,OAAO,EAAQ,CAAK,GAIrB,YAAa,CAAC,IAA2B,CACxC,OAAO,EAAQ,CAAK,GAIrB,SAAU,CAAC,IAA2B,CACrC,OAAO,EAAO,EAAO,CAAE,YAAa,EAAM,CAAC,GAI5C,eAAgB,CAAC,IAA2B,CAC3C,OAAO,EAAO,EAAO,CAAE,YAAa,EAAM,CAAC,GAI5C,KAAM,CAAC,IAA2B,CACjC,OAAO,EAAK,EAAO,CAAC,GAIrB,KAAM,CAAC,IAA2B,CACjC,OAAO,EAAK,EAAO,CAAC,GAIrB,IAAK,CAAC,IAA2B,CAChC,OAAO,EAAM,EAAO,CAAE,iBAAkB,EAAK,CAAC,GAI/C,gBAAiB,CAAC,IAA2B,CAE5C,OAAO,EAAM,EAAO,CAAE,iBAAkB,EAAM,CAAC,GAIhD,IAAK,CAAC,IAA2B,CAChC,OAAO,EAAM,EAAO,CAAE,iBAAkB,EAAK,CAAC,GAI/C,gBAAiB,CAAC,IAA2B,CAC5C,OAAO,EAAM,EAAO,CAAE,iBAAkB,EAAM,CAAC,GAIhD,eAAgB,CAAC,IAA2B,CAI3C,IAAI,EAAU,GACd,QAAW,KAAM,EAChB,GAAI,IAAO,IAAK,CACf,GAAI,EAAS,MAAO,GACpB,EAAU,GACJ,QAAI,IAAO,IAAK,CACtB,GAAI,CAAC,EAAS,MAAO,GACrB,EAAU,GAGZ,MAAO,CAAC,GAIT,KAAM,CAAC,IAA2B,CACjC,OAAO,EAAO,CAAK,GAIpB,eAAgB,CAAC,IAA2B,CAE3C,GAAI,IAAU,GAAI,MAAO,GACzB,OAAO,EAAmB,KAAK,CAAK,GAIrC,wBAAyB,CAAC,IAA2B,CACpD,OAAO,EAA4B,KAAK,CAAK,GAI9C,MAAO,CAAC,IAA2B,CAClC,GAAI,CAEH,OADA,IAAI,OAAO,CAAK,EACT,GACN,KAAM,CACP,MAAO,IAGV,EAUO,SAAS,CAAa,CAAC,EAAyB,CACtD,OAAO,EAAc,IAAI,CAAM,EAwBzB,SAAS,CAAc,CAAC,EAAgB,EAAgC,CAE9E,GAAI,OAAO,IAAU,SAAU,MAAO,GAEtC,IAAM,EAAY,EAAkB,GACpC,GAAI,CAAC,EAAW,OAAO,KAEvB,OAAO,EAAU,CAAK,EAkChB,SAAS,CAAc,CAC7B,EACA,EACiB,CAEjB,GAAI,IAAc,EAAW,MAAO,GAIpC,GADkB,EAAiB,IACpB,SAAS,CAAS,EAChC,MAAO,GAQR,OAAO",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "23E9231E413DFF0864756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{b as U,c as V,d as Y,e as Z,f as _}from"./chunk-b55zsn5n.js";import{k as Q}from"./chunk-pyrx217p.js";import{m as W}from"./chunk-y8c2z1m3.js";import{n as X}from"./chunk-yg81ax5m.js";import{u as J}from"./chunk-yqhv3py7.js";import{x as K}from"./chunk-jkdzdb3r.js";class F{engine;constructor(){this.engine=new X}isSubset(j,x){if(j===x)return!0;if(K(j,x))return!0;let w=J(j),G=J(x);if(w!==j&&G!==x&&K(w,G))return!0;if(w!==G&&K(w,G))return!0;let{branches:H}=U(w);if(H.length>1||H[0]!==w)return H.every((L)=>V(L,G,this.engine));return V(w,G,this.engine)}check(j,x){if(j===x)return{isSubset:!0,merged:j,diffs:[]};if(K(j,x))return{isSubset:!0,merged:j,diffs:[]};let w=J(j),G=J(x);if(K(w,G))return{isSubset:!0,merged:w,diffs:[]};let{branches:H,type:L}=U(w),{branches:N,type:$}=U(G);if(H.length>1||H[0]!==w)return Y(H,G,this.engine,L);if(N.length>1||N[0]!==G)return Z(w,N,this.engine,$);return _(w,G,this.engine)}canConnect(j,x){return{...this.check(j,x),direction:"sourceOutput ⊆ targetInput"}}isEqual(j,x){return this.engine.isEqual(J(j),J(x))}intersect(j,x){if(j===x||K(j,x))return J(j);let w=J(j),G=J(x);if(K(w,G))return w;let H=this.engine.merge(w,G);if(H===null)return null;if(K(H,w)||K(H,G))return H;return J(H)}resolveConditions(j,x){return Q(j,x,this.engine)}checkResolved(j,x,w,G){let H=Q(j,w,this.engine),L=Q(x,G??w,this.engine);return{...this.check(H.resolved,L.resolved),resolvedSub:H,resolvedSup:L}}normalize(j){return J(j)}formatResult(j,x){return W(j,x)}}
|
|
2
|
+
export{F as a};
|
|
3
|
+
|
|
4
|
+
//# debugId=E1A6658650822D7D64756E2164756E21
|
|
5
|
+
//# sourceMappingURL=chunk-2ddbnbyq.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/json-schema-compatibility-checker.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"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\tSchemaDiff,\n\tSubsetResult,\n} from \"./types\";\nimport { deepEqual } from \"./utils\";\n\n// ─── Re-exports ──────────────────────────────────────────────────────────────\n\nexport type {\n\tSchemaDiff,\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 les diffs structurels.\n\t *\n\t * Point 6 — Utilise `getBranchesTyped` pour distinguer `anyOf` de `oneOf`\n\t * dans les paths de diff (ex: `anyOf[0]` vs `oneOf[0]`).\n\t */\n\tcheck(sub: JSONSchema7Definition, sup: JSONSchema7Definition): SubsetResult {\n\t\t// ── Identity short-circuit ──\n\t\t// Same reference → no diffs, no merge needed.\n\t\tif (sub === sup) {\n\t\t\treturn { isSubset: true, merged: sub, diffs: [] };\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, diffs: [] };\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, diffs: [] };\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"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "0SAoEO,AAAM,LAA+B,LAC1B,CAEjB,KAAW,EAAG,CACb,KAAK,OAAS,IAAI,EAYnB,QAAQ,CAAC,EAA4B,EAAqC,CAIzE,GAAI,IAAQ,EAAK,MAAO,GAOxB,GAAI,EAAU,EAAK,CAAG,EAAG,MAAO,GAEhC,IAAM,EAAO,EAAU,CAAG,EACpB,EAAO,EAAU,CAAG,EAM1B,GAAI,IAAS,GAAO,IAAS,GAAO,EAAU,EAAM,CAAI,EAAG,MAAO,GAClE,GAAI,IAAS,GAAQ,EAAU,EAAM,CAAI,EAAG,MAAO,GAEnD,IAAQ,SAAU,GAAgB,EAAiB,CAAI,EAEvD,GAAI,EAAY,OAAS,GAAK,EAAY,KAAO,EAChD,OAAO,EAAY,MAAM,CAAC,IACzB,EAAiB,EAAQ,EAAM,KAAK,MAAM,CAC3C,EAGD,OAAO,EAAiB,EAAM,EAAM,KAAK,MAAM,EAYhD,KAAK,CAAC,EAA4B,EAA0C,CAG3E,GAAI,IAAQ,EACX,MAAO,CAAE,SAAU,GAAM,OAAQ,EAAK,MAAO,CAAC,CAAE,EAKjD,GAAI,EAAU,EAAK,CAAG,EACrB,MAAO,CAAE,SAAU,GAAM,OAAQ,EAAK,MAAO,CAAC,CAAE,EAGjD,IAAM,EAAO,EAAU,CAAG,EACpB,EAAO,EAAU,CAAG,EAI1B,GAAI,EAAU,EAAM,CAAI,EACvB,MAAO,CAAE,SAAU,GAAM,OAAQ,EAAM,MAAO,CAAC,CAAE,EAGlD,IAAQ,SAAU,EAAa,KAAM,GACpC,EAAiB,CAAI,GACd,SAAU,EAAa,KAAM,GACpC,EAAiB,CAAI,EAGtB,GAAI,EAAY,OAAS,GAAK,EAAY,KAAO,EAChD,OAAO,EAAiB,EAAa,EAAM,KAAK,OAAQ,CAAa,EAItE,GAAI,EAAY,OAAS,GAAK,EAAY,KAAO,EAChD,OAAO,EAAiB,EAAM,EAAa,KAAK,OAAQ,CAAa,EAItE,OAAO,EAAY,EAAM,EAAM,KAAK,MAAM,EAW3C,UAAU,CACT,EACA,EACmB,CAEnB,MAAO,IADQ,KAAK,MAAM,EAAc,CAAW,EAC/B,UAAW,4BAA4B,EAQ5D,OAAO,CAAC,EAA0B,EAAmC,CACpE,OAAO,KAAK,OAAO,QAAQ,EAAU,CAAC,EAAG,EAAU,CAAC,CAAC,EAYtD,SAAS,CACR,EACA,EAC+B,CAI/B,GAAI,IAAM,GAAK,EAAU,EAAG,CAAC,EAAG,OAAO,EAAU,CAAC,EAElD,IAAM,EAAK,EAAU,CAAC,EAChB,EAAK,EAAU,CAAC,EAGtB,GAAI,EAAU,EAAI,CAAE,EAAG,OAAO,EAE9B,IAAM,EAAS,KAAK,OAAO,MAAM,EAAI,CAAE,EACvC,GAAI,IAAW,KAAM,OAAO,KAG5B,GAAI,EAAU,EAAQ,CAAE,GAAK,EAAU,EAAQ,CAAE,EAAG,OAAO,EAC3D,OAAO,EAAU,CAAM,EASxB,iBAAiB,CAChB,EACA,EAC0B,CAC1B,OAAO,EAAkB,EAAQ,EAAM,KAAK,MAAM,EAWnD,aAAa,CACZ,EACA,EACA,EACA,EAIC,CACD,IAAM,EAAc,EAAkB,EAAK,EAAS,KAAK,MAAM,EACzD,EAAc,EAAkB,EAAK,GAAW,EAAS,KAAK,MAAM,EAG1E,MAAO,IAFQ,KAAK,MAAM,EAAY,SAAU,EAAY,QAAQ,EAEhD,cAAa,aAAY,EAS9C,SAAS,CAAC,EAAmD,CAC5D,OAAO,EAAU,CAAG,EAQrB,YAAY,CAAC,EAAe,EAA8B,CACzD,OAAO,EAAa,EAAO,CAAM,EAEnC",
|
|
8
|
+
"debugId": "E1A6658650822D7D64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{h as j}from"./chunk-q7kq4fgq.js";import{l as B}from"./chunk-jybaxgmh.js";import{s as k}from"./chunk-07z7fc5q.js";import{u as z}from"./chunk-yqhv3py7.js";import{v as K,w as W,x as V,y as R}from"./chunk-jkdzdb3r.js";var v={branches:[!0],type:"none"},g={branches:[!1],type:"none"},T=new WeakMap;function S(x){if(typeof x==="boolean")return x?v:g;if(W(x,"anyOf")&&Array.isArray(x.anyOf))return{branches:x.anyOf,type:"anyOf"};if(W(x,"oneOf")&&Array.isArray(x.oneOf))return{branches:x.oneOf,type:"oneOf"};let X=T.get(x);if(X===void 0)X={branches:[x],type:"none"},T.set(x,X);return X}function C(x,X){if(typeof x==="boolean"||typeof X==="boolean")return null;if(W(X,"not")&&K(X.not)){let Z=X.not;if(K(Z.properties)&&Array.isArray(Z.required)){let{properties:G,required:Q}=Z;if(K(x.properties)){let Y=x.properties,J=Array.isArray(x.required)?x.required:[],$=Object.keys(G);if($.some((_)=>{let L=G[_];if(typeof L==="boolean")return!1;let H=L;if(Q.includes(_)&&!J.includes(_)&&!W(Y,_))return!0;if(!W(Y,_))return!1;let M=Y[_];if(typeof M==="boolean")return!1;let A=M;if(W(H,"const")&&W(A,"const")){if(!V(H.const,A.const))return!0}if(W(H,"enum")&&Array.isArray(H.enum)){if(W(A,"const")){if(!H.enum.some((N)=>V(N,A.const)))return!0}if(W(A,"enum")&&Array.isArray(A.enum)){if(A.enum.every((N)=>!H.enum?.some((D)=>V(N,D))))return!0}}return!1}))return!0;if($.every((_)=>{let L=G[_];if(typeof L==="boolean")return!0;let H=L;if(Q.includes(_)&&!J.includes(_))return!1;if(!W(Y,_))return!1;let M=Y[_];if(typeof M==="boolean")return!0;let A=M;if(W(H,"const")&&W(A,"const"))return V(H.const,A.const);if(W(H,"enum")&&Array.isArray(H.enum)){if(W(A,"const"))return H.enum.some((F)=>V(F,A.const));if(W(A,"enum")&&Array.isArray(A.enum))return A.enum.every((F)=>H.enum?.some((N)=>V(F,N)))}return!1}))return!1}}if(W(Z,"const")&&W(x,"const")){let G=Z.const,Q=x.const;if(V(Q,G))return!1;return!0}if(W(Z,"enum")&&Array.isArray(Z.enum)&&W(x,"enum")&&Array.isArray(x.enum)){if(x.enum.every((Q)=>!Z.enum?.some((Y)=>V(Q,Y))))return!0}if(W(Z,"type")&&W(x,"type")){let G=Z.type,Q=x.type;if(typeof G==="string"&&typeof Q==="string"){if(!W(Z,"const")&&!W(Z,"enum")&&!K(Z.properties)){if(Q===G)return!1;return!0}}if(Array.isArray(G)&&typeof Q==="string"){if(G.includes(Q))return!1;return!0}}if(W(Z,"anyOf")&&Array.isArray(Z.anyOf)){let G=Z.anyOf;if(G.every((J)=>{if(typeof J==="boolean")return!J;return C(x,{not:J})===!0}))return!0;if(G.some((J)=>{if(typeof J==="boolean")return J;return C(x,{not:J})===!1}))return!1}if(W(Z,"oneOf")&&Array.isArray(Z.oneOf)){let G=Z.oneOf;if(G.every((J)=>{if(typeof J==="boolean")return!J;return C(x,{not:J})===!0}))return!0;if(G.some((J)=>{if(typeof J==="boolean")return J;return C(x,{not:J})===!1}))return!1}if(W(Z,"format")&&W(x,"format")){let G=x.format,Q=Z.format;if(G===Q)return!1;return!0}}if(W(x,"not")&&W(X,"not")){if(V(x.not,X.not))return!0}return null}function E(x,X,Z=!0){if(typeof X==="boolean"||typeof x==="boolean")return X;let G=X;if(Z&&W(G,"not"))G=R(G,["not"]);if(K(G.properties)&&K(x.properties)){let Q=x.properties,Y=G.properties,J;for(let $ of Object.keys(Y)){let U=Y[$],I=Q[$];if(U!==void 0&&I!==void 0&&typeof U!=="boolean"&&typeof I!=="boolean"&&W(U,"not")){if(C(I,U)===!0){if(!J)J={...Y};J[$]=R(U,["not"])}}}if(J)G={...G,properties:J}}return G}function q(x,X){if(typeof x==="boolean"||typeof X==="boolean")return X;let Z=X,G=Z,Q=!1;function Y(){if(!Q)G={...Z},Q=!0;return G}if(W(G,"pattern")&&W(x,"pattern")&&G.pattern!==x.pattern){if(j(x.pattern,G.pattern)===!0)G=R(Y(),["pattern"]),Q=!0}if(K(G.properties)&&K(x.properties)){let J=x.properties,$=G.properties,U=!1,I;for(let _ of Object.keys($)){let L=$[_],H=J[_];if(L!==void 0&&H!==void 0&&typeof L!=="boolean"&&typeof H!=="boolean"&&W(L,"pattern")&&W(H,"pattern")&&L.pattern!==H.pattern){if(j(H.pattern,L.pattern)===!0){if(!I)I={...$};I[_]=R(L,["pattern"]),U=!0}}}if(U&&I)Y().properties=I}if(K(G.items)&&typeof G.items!=="boolean"&&K(x.items)&&typeof x.items!=="boolean"){let J=x.items,$=G.items;if(W($,"pattern")&&W(J,"pattern")&&$.pattern!==J.pattern){if(j(J.pattern,$.pattern)===!0)Y().items=R($,["pattern"])}}return G}function w(x,X,Z){let{branches:G}=S(X);if(G.length===1&&G[0]===X){let Q=C(x,X);if(Q===!1)return!1;if(typeof x!=="boolean"&&typeof X!=="boolean"&&W(x,"format")&&W(X,"format")&&x.format!==X.format){if(k(x.format,X.format)!==!0)return!1}if(typeof x!=="boolean"&&typeof X!=="boolean"&&W(x,"pattern")&&W(X,"pattern")&&x.pattern!==X.pattern){if(j(x.pattern,X.pattern)===!1)return!1}let Y=X;if(typeof X!=="boolean"){if(Q===!0){if(Y=E(x,X,!0),typeof Y!=="boolean"&&Object.keys(Y).length===0)return!0}else Y=E(x,X,!1);Y=q(x,Y)}let J=Z.merge(x,Y);if(J===null)return!1;if(V(J,x))return!0;let $=z(J);return V($,x)||Z.isEqual($,x)}return G.some((Q)=>{let Y=C(x,Q);if(Y===!1)return!1;if(typeof x!=="boolean"&&typeof Q!=="boolean"&&W(x,"pattern")&&W(Q,"pattern")&&x.pattern!==Q.pattern){if(j(x.pattern,Q.pattern)===!1)return!1}let J=Q;if(typeof Q!=="boolean"){if(Y===!0){if(J=E(x,Q,!0),typeof J!=="boolean"&&Object.keys(J).length===0)return!0}else J=E(x,Q,!1);J=q(x,J)}let $=Z.merge(x,J);if($===null)return!1;if(V($,x))return!0;let U=z($);return V(U,x)||Z.isEqual(U,x)})}function f(x,X,Z,G="anyOf"){let Q=[],Y=!0,J=G==="none"?"anyOf":G;for(let $=0;$<x.length;$++){let U=x[$];if(U===void 0)continue;if(!w(U,X,Z))Y=!1,Q.push({path:`${J}[${$}]`,type:"changed",expected:U,actual:"Branch not accepted by superset"})}return{isSubset:Y,merged:Y?G==="oneOf"?{oneOf:x}:{anyOf:x}:null,diffs:Q}}function P(x,X,Z,G="anyOf"){for(let Y of X){let J=Y;if(typeof x!=="boolean"&&typeof Y!=="boolean")J=q(x,Y);let $=Z.merge(x,J);if($!==null){if(V($,x))return{isSubset:!0,merged:$,diffs:[]};let U=z($);if(V(U,x)||Z.isEqual(U,x))return{isSubset:!0,merged:$,diffs:[]}}}return{isSubset:!1,merged:null,diffs:[{path:"$",type:"changed",expected:x,actual:`No branch in superset's ${G==="none"?"anyOf":G} accepts this schema`}]}}function i(x,X,Z){let G=X;if(typeof x!=="boolean"&&typeof X!=="boolean")G=q(x,X);try{let Q=Z.mergeOrThrow(x,G);if(V(Q,x))return{isSubset:!0,merged:Q,diffs:[]};let Y=z(Q);if(V(Y,x)||Z.isEqual(Y,x))return{isSubset:!0,merged:Y,diffs:[]};let J=B(x,Y,"");return{isSubset:!1,merged:Y,diffs:J}}catch(Q){return{isSubset:!1,merged:null,diffs:[{path:"$",type:"changed",expected:x,actual:`Incompatible: ${Q instanceof Error?Q.message:String(Q)}`}]}}}
|
|
2
|
+
export{S as b,w as c,f as d,P as e,i as f};
|
|
3
|
+
|
|
4
|
+
//# debugId=B8207E42E9F16E9764756E2164756E21
|
|
5
|
+
//# sourceMappingURL=chunk-b55zsn5n.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/subset-checker.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { computeDiffs } from \"./differ\";\nimport { isFormatSubset } from \"./format-validator\";\nimport type { MergeEngine } from \"./merge-engine\";\nimport { normalize } from \"./normalizer\";\nimport { isPatternSubset } from \"./pattern-subset\";\nimport type { SchemaDiff, SubsetResult } from \"./types\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys } from \"./utils\";\n\n// ─── Subset Checker ──────────────────────────────────────────────────────────\n//\n// Logique de vérification sub ⊆ sup via l'approche :\n// A ⊆ B ⟺ A ∩ B ≡ A\n//\n// Gère les cas :\n// - Schemas atomiques (pas de anyOf/oneOf)\n// - anyOf/oneOf dans sub → chaque branche doit être acceptée par sup\n// - anyOf/oneOf dans sup → au moins une branche doit accepter sub\n// - Point 6 : Distinction anyOf / oneOf dans les messages de diff\n// - Point 7 : Raisonnement étendu sur `not` (evaluateNot)\n// - not.type, not.const, not.enum (existants)\n// - not avec properties+required (1.1)\n// - not avec anyOf/oneOf (1.2)\n// - not dans sub (1.3)\n// - not.format (format-vs-format)\n//\n// Utilise des helpers natifs partagés depuis `./utils` pour des performances\n// optimales (deepEqual, hasOwn, isPlainObj, omitKeys).\n\n// ─── Branch type ─────────────────────────────────────────────────────────────\n\n/**\n * Type de branchement détecté dans un schema.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` pour produire des messages\n * de diff plus précis. `\"none\"` indique un schema atomique (pas de branches).\n *\n * Note : la sémantique d'exclusivité de `oneOf` n'est pas vérifiée\n * (ce serait un problème NP-hard en général). Le checker traite `oneOf`\n * comme `anyOf` pour le subset checking, ce qui est correct pour le cas\n * `sub ⊆ sup` mais peut produire des faux-positifs si les branches\n * du sub se chevauchent.\n */\nexport type BranchType = \"anyOf\" | \"oneOf\" | \"none\";\n\nexport interface BranchResult {\n\t/** Les branches extraites du schema */\n\tbranches: JSONSchema7Definition[];\n\t/** Le type de branchement détecté */\n\ttype: BranchType;\n}\n\n// ─── Branch extraction ───────────────────────────────────────────────────────\n\n// Pre-allocated singleton results for boolean schemas to avoid per-call allocations.\n// These are safe because the branches arrays are never mutated after creation.\nconst BRANCH_TRUE: BranchResult = { branches: [true], type: \"none\" };\nconst BRANCH_FALSE: BranchResult = { branches: [false], type: \"none\" };\n\n/**\n * WeakMap cache for atomic (no anyOf/oneOf) schema branch results.\n * Avoids allocating `{ branches: [def], type: \"none\" }` on every call\n * for the same schema object. Since normalized schemas are cached and\n * return the same reference, this cache hits frequently.\n */\nconst atomicBranchCache = new WeakMap<object, BranchResult>();\n\n/**\n * Extrait les branches d'un schema et le type de branchement.\n *\n * Retourne les éléments de `anyOf`/`oneOf` s'ils existent, sinon retourne\n * le schema lui-même dans un tableau avec type `\"none\"`.\n *\n * Point 6 — Distingue `anyOf` de `oneOf` dans les paths de diff.\n *\n * Optimisation : réutilise des objets pré-alloués pour les cas boolean\n * (true/false) et un WeakMap cache pour les schemas atomiques afin\n * d'éviter les allocations sur ces chemins fréquents.\n */\nexport function getBranchesTyped(def: JSONSchema7Definition): BranchResult {\n\tif (typeof def === \"boolean\") {\n\t\treturn def ? BRANCH_TRUE : BRANCH_FALSE;\n\t}\n\tif (hasOwn(def, \"anyOf\") && Array.isArray(def.anyOf)) {\n\t\treturn { branches: def.anyOf, type: \"anyOf\" };\n\t}\n\tif (hasOwn(def, \"oneOf\") && Array.isArray(def.oneOf)) {\n\t\treturn { branches: def.oneOf, type: \"oneOf\" };\n\t}\n\t// Cache atomic results per schema object to avoid repeated allocations.\n\tlet cached = atomicBranchCache.get(def);\n\tif (cached === undefined) {\n\t\tcached = { branches: [def], type: \"none\" };\n\t\tatomicBranchCache.set(def, cached);\n\t}\n\treturn cached;\n}\n\n// ─── `not` reasoning (Point 7 — étendu) ─────────────────────────────────────\n\n/**\n * Raisonnement étendu sur `not` pour les cas courants.\n *\n * Point 7 — Vérifie la compatibilité quand `sup` et/ou `sub` contiennent `not` :\n *\n * **Cas existants (not dans sup) :**\n * - `not.type` : type exclu vs type de sub\n * - `not.const` : const exclu vs const de sub\n * - `not.enum` : valeurs exclues vs enum de sub\n *\n * **Cas ajoutés :**\n * - 1.1 — `not` avec `properties` + `required` : vérifier que les propriétés\n * de sub sont incompatibles avec celles du `not` (const/enum différents)\n * - 1.2 — `not` avec `anyOf`/`oneOf` : `not(anyOf([A,B]))` ≡ `allOf([not(A), not(B)])`,\n * donc sub doit être incompatible avec CHAQUE branche\n * - 1.3 — `not` dans `sub` (pas seulement dans `sup`) : un sub avec `not`\n * accepte un ensemble trop large pour être un sous-ensemble d'un sup concret\n * - `not.format` : format-vs-format via `isFormatSubset`\n *\n * Contrat ternaire conservateur :\n * - `true` → compatible (certain)\n * - `false` → incompatible (certain)\n * - `null` → indéterminé (laisser le merge engine décider)\n *\n * En cas de doute → `null`. Ne JAMAIS retourner `true` sans certitude.\n *\n * Utilise `_.has`, `_.get`, `_.isEqual`, `_.includes`, `_.every`, `_.some`,\n * `_.keys`, `_.isPlainObject`, `_.isArray` pour des vérifications concises.\n */\nfunction evaluateNot(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): boolean | null {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return null;\n\n\t// ── 1.3 — `not` dans sub (pas dans sup) ──\n\t// Un `not` dans sub est une restriction supplémentaire : il exclut des\n\t// valeurs de l'ensemble accepté par sub, ce qui le rend potentiellement\n\t// plus petit — donc plus susceptible d'être ⊆ sup, pas moins.\n\t// On laisse le merge engine décider : allOf(sub, sup) préservera le `not`\n\t// de sub, et la comparaison merged ≡ sub donnera le bon résultat.\n\t// Exception : si les deux ont `not`, on traite l'identité plus bas.\n\n\t// Vérifier `not` dans sup\n\tif (hasOwn(sup, \"not\") && isPlainObj(sup.not)) {\n\t\tconst notSchema = sup.not as JSONSchema7;\n\n\t\t// ── 1.1 — Cas not avec properties + required ──\n\t\t// IMPORTANT : ce check est placé AVANT le check not.type car quand\n\t\t// le not a à la fois `type` et `properties`, le check not.type seul\n\t\t// produirait un faux négatif (ex: sub type=object et not type=object\n\t\t// retournerait false, mais les properties pourraient être incompatibles\n\t\t// ce qui rendrait sub compatible avec le not).\n\t\t// Si not contient des properties avec const/enum et required,\n\t\t// vérifier que les propriétés de sub sont incompatibles avec celles du not.\n\t\tif (isPlainObj(notSchema.properties) && Array.isArray(notSchema.required)) {\n\t\t\tconst notProps = notSchema.properties as Record<\n\t\t\t\tstring,\n\t\t\t\tJSONSchema7Definition\n\t\t\t>;\n\t\t\tconst notRequired = notSchema.required as string[];\n\n\t\t\t// sub doit avoir des properties pour qu'on puisse comparer\n\t\t\tif (isPlainObj(sub.properties)) {\n\t\t\t\tconst subProps = sub.properties as Record<\n\t\t\t\t\tstring,\n\t\t\t\t\tJSONSchema7Definition\n\t\t\t\t>;\n\t\t\t\tconst subRequired = Array.isArray(sub.required)\n\t\t\t\t\t? (sub.required as string[])\n\t\t\t\t\t: [];\n\t\t\t\tconst notPropKeys = Object.keys(notProps);\n\n\t\t\t\t// Pour que sub soit compatible avec not(schema),\n\t\t\t\t// il suffit qu'au moins UNE propriété du not soit incompatible avec sub.\n\t\t\t\t// Cela signifie que sub ne peut jamais valider le schema inside not.\n\t\t\t\tconst hasIncompatibleProp = notPropKeys.some((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return false;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// Si la propriété est required dans not mais PAS dans sub.required\n\t\t\t\t\t// et qu'elle n'existe pas dans sub.properties → sub peut ne pas\n\t\t\t\t\t// avoir cette propriété → le not schema ne matcherait pas → compatible\n\t\t\t\t\tif (\n\t\t\t\t\t\tnotRequired.includes(key) &&\n\t\t\t\t\t\t!subRequired.includes(key) &&\n\t\t\t\t\t\t!hasOwn(subProps, key)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn true; // Propriété absente de sub → not ne matche pas\n\t\t\t\t\t}\n\n\t\t\t\t\t// Comparer les const/enum de la propriété\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return false;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// not.prop a un const, sub.prop a un const différent → incompatible pour cette prop\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\tif (!deepEqual(notProp.const, subProp.const)) {\n\t\t\t\t\t\t\treturn true; // Consts différents → sub ne matche pas le not\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// not.prop a un enum, sub.prop a un const ou enum dont aucune valeur\n\t\t\t\t\t// n'est dans not.enum → incompatible pour cette prop\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\tconst inNotEnum = notProp.enum.some((v) =>\n\t\t\t\t\t\t\t\tdeepEqual(v, subProp.const),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!inNotEnum) return true; // sub.const absent du not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\tconst noneInNotEnum = subProp.enum.every(\n\t\t\t\t\t\t\t\t(v) => !notProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (noneInNotEnum) return true; // Aucune valeur de sub.enum dans not.enum\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\n\t\t\t\tif (hasIncompatibleProp) return true;\n\n\t\t\t\t// Vérification inverse : si TOUTES les propriétés du not matchent sub\n\t\t\t\t// exactement (même const, sub a les required du not), alors sub VIOLE le not\n\t\t\t\tconst allPropsMatch = notPropKeys.every((key) => {\n\t\t\t\t\tconst notPropDef = notProps[key];\n\t\t\t\t\tif (typeof notPropDef === \"boolean\") return true;\n\t\t\t\t\tconst notProp = notPropDef as JSONSchema7;\n\n\t\t\t\t\t// La propriété doit être dans sub.required si elle est dans not.required\n\t\t\t\t\tif (notRequired.includes(key) && !subRequired.includes(key))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (!hasOwn(subProps, key)) return false;\n\t\t\t\t\tconst subPropDef = subProps[key];\n\t\t\t\t\tif (typeof subPropDef === \"boolean\") return true;\n\t\t\t\t\tconst subProp = subPropDef as JSONSchema7;\n\n\t\t\t\t\t// Vérifier const match\n\t\t\t\t\tif (hasOwn(notProp, \"const\") && hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\treturn deepEqual(notProp.const, subProp.const);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Vérifier enum inclusion\n\t\t\t\t\tif (hasOwn(notProp, \"enum\") && Array.isArray(notProp.enum)) {\n\t\t\t\t\t\tif (hasOwn(subProp, \"const\")) {\n\t\t\t\t\t\t\treturn notProp.enum.some((v) => deepEqual(v, subProp.const));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasOwn(subProp, \"enum\") && Array.isArray(subProp.enum)) {\n\t\t\t\t\t\t\t// Toutes les valeurs de sub.enum sont dans not.enum\n\t\t\t\t\t\t\treturn subProp.enum.every((v) =>\n\t\t\t\t\t\t\t\tnotProp.enum?.some((nv) => deepEqual(v, nv)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false; // Indéterminé pour cette propriété\n\t\t\t\t});\n\n\t\t\t\tif (allPropsMatch) return false; // sub matche exactement le not → incompatible\n\t\t\t}\n\t\t}\n\n\t\t// ── Cas not.const ──\n\t\t// IMPORTANT : ce check est placé AVANT not.type car quand le not a\n\t\t// à la fois `type` et `const`, le check not.type seul produirait un\n\t\t// faux négatif (ex: sub type=string const=\"active\" et not type=string\n\t\t// const=\"deleted\" → le type check retournerait false car même type,\n\t\t// alors que les consts sont différents → compatible).\n\t\tif (hasOwn(notSchema, \"const\") && hasOwn(sub, \"const\")) {\n\t\t\tconst notConst = notSchema.const;\n\t\t\tconst subConst = sub.const;\n\t\t\tif (deepEqual(subConst, notConst)) return false;\n\t\t\treturn true;\n\t\t}\n\n\t\t// ── Cas not.enum ──\n\t\t// Aussi placé AVANT not.type pour la même raison.\n\t\tif (\n\t\t\thasOwn(notSchema, \"enum\") &&\n\t\t\tArray.isArray(notSchema.enum) &&\n\t\t\thasOwn(sub, \"enum\") &&\n\t\t\tArray.isArray(sub.enum)\n\t\t) {\n\t\t\t// Toutes les valeurs de sub.enum doivent être absentes de not.enum\n\t\t\tconst allExcluded = sub.enum.every(\n\t\t\t\t(val) => !notSchema.enum?.some((notVal) => deepEqual(val, notVal)),\n\t\t\t);\n\t\t\tif (allExcluded) return true;\n\t\t\t// Certaines valeurs de sub sont dans not.enum → pas automatiquement faux,\n\t\t\t// le merge engine peut encore gérer\n\t\t}\n\n\t\t// ── Cas not.type ──\n\t\t// Placé APRÈS not.const, not.enum et properties+required pour ne pas\n\t\t// court-circuiter les cas où le not a des contraintes plus spécifiques.\n\t\t// Le check type seul est un fallback pour les not schemas simples\n\t\t// (ex: { not: { type: \"string\" } }).\n\t\tif (hasOwn(notSchema, \"type\") && hasOwn(sub, \"type\")) {\n\t\t\tconst notType = notSchema.type;\n\t\t\tconst subType = sub.type;\n\n\t\t\t// Si les deux sont des strings simples\n\t\t\tif (typeof notType === \"string\" && typeof subType === \"string\") {\n\t\t\t\t// Ne retourner que si le not n'a PAS de contraintes plus spécifiques\n\t\t\t\t// (const, enum, properties) qui auraient dû être traitées plus haut\n\t\t\t\tif (\n\t\t\t\t\t!hasOwn(notSchema, \"const\") &&\n\t\t\t\t\t!hasOwn(notSchema, \"enum\") &&\n\t\t\t\t\t!isPlainObj(notSchema.properties)\n\t\t\t\t) {\n\t\t\t\t\tif (subType === notType) return false; // Incompatible : sub est exactement le type exclu\n\t\t\t\t\treturn true; // Compatible : sub est un type différent du type exclu\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Si notType est un tableau, sub.type doit ne pas être dedans\n\t\t\tif (Array.isArray(notType) && typeof subType === \"string\") {\n\t\t\t\tif (notType.includes(subType)) return false;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// ── 1.2 — Cas not avec anyOf / oneOf ──\n\t\t// not(anyOf([A, B])) ≡ allOf([not(A), not(B)])\n\t\t// Pour que sub ⊆ not(anyOf(...)), sub doit être incompatible avec CHAQUE branche.\n\t\tif (hasOwn(notSchema, \"anyOf\") && Array.isArray(notSchema.anyOf)) {\n\t\t\tconst branches = notSchema.anyOf as JSONSchema7Definition[];\n\t\t\t// Pour chaque branche du not.anyOf, vérifier que sub est incompatible\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch; // not(true) = rien, not(false) = tout\n\t\t\t\t// Créer un sup virtuel { not: branch } et vérifier récursivement\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\t// result = true → sub est compatible avec not(branch) → sub ⊄ branch → OK\n\t\t\t\t// result = false → sub est incompatible avec not(branch) → sub ⊆ branch → pas OK\n\t\t\t\t// result = null → indéterminé\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\t// Vérifier si au moins une branche accepte sub → incompatible avec not(anyOf)\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false; // sub est incompatible avec not(branch) → sub ⊆ branch\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// Même logique pour oneOf (dans le contexte du not, traité comme anyOf)\n\t\tif (hasOwn(notSchema, \"oneOf\") && Array.isArray(notSchema.oneOf)) {\n\t\t\tconst branches = notSchema.oneOf as JSONSchema7Definition[];\n\t\t\tconst allIncompatible = branches.every((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return !branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === true;\n\t\t\t});\n\t\t\tif (allIncompatible) return true;\n\n\t\t\tconst anyBranchMatches = branches.some((branch) => {\n\t\t\t\tif (typeof branch === \"boolean\") return branch;\n\t\t\t\tconst result = evaluateNot(sub, { not: branch });\n\t\t\t\treturn result === false;\n\t\t\t});\n\t\t\tif (anyBranchMatches) return false;\n\t\t}\n\n\t\t// ── Cas not.format (format-vs-format uniquement) ──\n\t\t// Si not a un format et sub aussi, vérifier la compatibilité\n\t\tif (hasOwn(notSchema, \"format\") && hasOwn(sub, \"format\")) {\n\t\t\tconst subFormat = sub.format as string;\n\t\t\tconst notFormat = notSchema.format as string;\n\t\t\tif (subFormat === notFormat) return false; // Incompatible : sub a exactement le format exclu\n\t\t\t// Formats différents → compatible (approximation conservatrice)\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Vérifier `not` dans sub ET dans sup (identité : { not: X } ⊆ { not: X })\n\tif (hasOwn(sub, \"not\") && hasOwn(sup, \"not\")) {\n\t\tif (deepEqual(sub.not, sup.not)) return true;\n\t}\n\n\treturn null; // Pas d'avis → laisser le merge engine décider\n}\n\n// ─── Not stripping helper ────────────────────────────────────────────────────\n\n/**\n * Retire le mot-clé `not` d'un schema pour permettre un merge propre\n * quand `evaluateNot` a déjà confirmé la compatibilité.\n *\n * Gère aussi le `not` imbriqué dans les `properties` : si une propriété\n * de `sup` a un `not` qui est compatible avec la propriété correspondante\n * de `sub`, on le retire également.\n *\n * Retourne le schema nettoyé, ou `null` si le schema est vide après retrait.\n *\n * Utilise `_.omit`, `_.has`, `_.keys`, `_.isEmpty`, `_.isPlainObject`.\n */\nfunction stripNotFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tstripTopLevel: boolean = true,\n): JSONSchema7Definition {\n\tif (typeof sup === \"boolean\" || typeof sub === \"boolean\") return sup;\n\n\tlet result = sup as JSONSchema7;\n\n\t// ── Retirer le `not` de niveau supérieur (seulement si confirmé) ──\n\tif (stripTopLevel && hasOwn(result, \"not\")) {\n\t\tresult = omitKeys(result as unknown as Record<string, unknown>, [\n\t\t\t\"not\",\n\t\t]) as JSONSchema7;\n\t}\n\n\t// ── Retirer les `not` dans les propriétés communes ──\n\t// Si sup.properties[key] a un `not` et que evaluateNot(sub.prop, sup.prop)\n\t// confirme la compatibilité, on retire le `not` de cette propriété aussi.\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"not\")\n\t\t\t) {\n\t\t\t\t// Vérifier la compatibilité du not au niveau de la propriété\n\t\t\t\tconst propNotResult = evaluateNot(subPropDef, supPropDef);\n\t\t\t\tif (propNotResult === true) {\n\t\t\t\t\t// Lazy allocate newProps only on first modification\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"not\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (newProps) {\n\t\t\tresult = { ...result, properties: newProps };\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Pattern stripping helper ────────────────────────────────────────────────\n\n/**\n * Retire le `pattern` de `sup` quand `isPatternSubset` a confirmé que\n * sub.pattern ⊆ sup.pattern par échantillonnage.\n *\n * Fonctionne comme `stripNotFromSup` : on retire la contrainte de sup\n * qui est déjà satisfaite par sub, pour éviter que le merge engine\n * produise un pattern combiné (lookahead conjunction) structurellement\n * différent du pattern de sub, ce qui causerait un faux négatif.\n *\n * Récurse dans les `properties` pour traiter les patterns imbriqués.\n *\n * @param sub Le schema sub (utilisé pour extraire les patterns à comparer)\n * @param sup Le schema sup dont on retire les patterns confirmés\n * @returns Le schema sup nettoyé\n */\nfunction stripPatternFromSup(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n): JSONSchema7Definition {\n\tif (typeof sub === \"boolean\" || typeof sup === \"boolean\") return sup;\n\n\tconst supObj: JSONSchema7 = sup;\n\n\t// Lazy copy-on-write: only create a copy when the first mutation is needed.\n\tlet result: JSONSchema7 = supObj;\n\tlet copied = false;\n\n\tfunction ensureCopy(): JSONSchema7 {\n\t\tif (!copied) {\n\t\t\tresult = { ...supObj };\n\t\t\tcopied = true;\n\t\t}\n\t\treturn result;\n\t}\n\n\t// ── Top-level pattern ──\n\tif (\n\t\thasOwn(result, \"pattern\") &&\n\t\thasOwn(sub, \"pattern\") &&\n\t\tresult.pattern !== (sub as JSONSchema7).pattern\n\t) {\n\t\tconst patResult = isPatternSubset(\n\t\t\t(sub as JSONSchema7).pattern as string,\n\t\t\tresult.pattern as string,\n\t\t);\n\t\tif (patResult === true) {\n\t\t\tresult = omitKeys(ensureCopy() as unknown as Record<string, unknown>, [\n\t\t\t\t\"pattern\",\n\t\t\t]) as JSONSchema7;\n\t\t\tcopied = true;\n\t\t}\n\t}\n\n\t// ── Patterns dans les propriétés communes ──\n\tif (\n\t\tisPlainObj(result.properties) &&\n\t\tisPlainObj((sub as JSONSchema7).properties)\n\t) {\n\t\tconst subProps = (sub as JSONSchema7).properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst supProps = result.properties as Record<string, JSONSchema7Definition>;\n\t\tlet propsModified = false;\n\t\tlet newProps: Record<string, JSONSchema7Definition> | undefined;\n\n\t\tfor (const key of Object.keys(supProps)) {\n\t\t\tconst supPropDef = supProps[key];\n\t\t\tconst subPropDef = subProps[key];\n\t\t\tif (\n\t\t\t\tsupPropDef !== undefined &&\n\t\t\t\tsubPropDef !== undefined &&\n\t\t\t\ttypeof supPropDef !== \"boolean\" &&\n\t\t\t\ttypeof subPropDef !== \"boolean\" &&\n\t\t\t\thasOwn(supPropDef, \"pattern\") &&\n\t\t\t\thasOwn(subPropDef, \"pattern\") &&\n\t\t\t\tsupPropDef.pattern !== subPropDef.pattern\n\t\t\t) {\n\t\t\t\tconst propPatResult = isPatternSubset(\n\t\t\t\t\t(subPropDef as JSONSchema7).pattern as string,\n\t\t\t\t\t(supPropDef as JSONSchema7).pattern as string,\n\t\t\t\t);\n\t\t\t\tif (propPatResult === true) {\n\t\t\t\t\tif (!newProps) newProps = { ...supProps };\n\t\t\t\t\tnewProps[key] = omitKeys(\n\t\t\t\t\t\tsupPropDef as unknown as Record<string, unknown>,\n\t\t\t\t\t\t[\"pattern\"],\n\t\t\t\t\t) as JSONSchema7Definition;\n\t\t\t\t\tpropsModified = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (propsModified && newProps) {\n\t\t\tensureCopy().properties = newProps;\n\t\t}\n\t}\n\n\t// ── Pattern dans items (single schema) ──\n\tif (\n\t\tisPlainObj(result.items) &&\n\t\ttypeof result.items !== \"boolean\" &&\n\t\tisPlainObj((sub as JSONSchema7).items) &&\n\t\ttypeof (sub as JSONSchema7).items !== \"boolean\"\n\t) {\n\t\tconst subItems = (sub as JSONSchema7).items as JSONSchema7;\n\t\tconst supItems = result.items as JSONSchema7;\n\t\tif (\n\t\t\thasOwn(supItems, \"pattern\") &&\n\t\t\thasOwn(subItems, \"pattern\") &&\n\t\t\tsupItems.pattern !== subItems.pattern\n\t\t) {\n\t\t\tconst itemsPatResult = isPatternSubset(\n\t\t\t\tsubItems.pattern as string,\n\t\t\t\tsupItems.pattern as string,\n\t\t\t);\n\t\t\tif (itemsPatResult === true) {\n\t\t\t\tensureCopy().items = omitKeys(\n\t\t\t\t\tsupItems as unknown as Record<string, unknown>,\n\t\t\t\t\t[\"pattern\"],\n\t\t\t\t) as JSONSchema7Definition;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Atomic subset check ─────────────────────────────────────────────────────\n\n/**\n * Vérifie si `sub ⊆ sup` pour deux schemas sans anyOf/oneOf (ou avec\n * anyOf/oneOf uniquement côté sup).\n *\n * Point 7 — Intègre un pré-check `not` étendu (`evaluateNot`) avant le merge.\n *\n * Quand `evaluateNot` confirme la compatibilité (`true`), on retire le `not`\n * de `sup` avant le merge pour éviter que le merge engine ajoute une contrainte\n * `not` que `sub` n'a pas (ce qui ferait échouer `isEqual(merged, sub)`).\n *\n * Pattern pre-check — Quand les deux schemas ont des patterns différents,\n * vérifie l'inclusion par échantillonnage via `isPatternSubset`. Si confirmé,\n * retire le pattern de sup avant le merge (même stratégie que pour `not`).\n *\n * Principe : merge(sub, sup) ≡ sub → sub est un sous-ensemble de sup.\n *\n * Utilise `_.some`, `_.has`, `_.omit`, `_.keys`, `_.isEmpty` pour la logique.\n */\nexport function isAtomicSubsetOf(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): boolean {\n\tconst { branches: supBranches } = getBranchesTyped(sup);\n\n\t// Schema simple → merge direct\n\tif (supBranches.length === 1 && supBranches[0] === sup) {\n\t\t// Point 7 : pré-check `not` étendu\n\t\tconst notResult = evaluateNot(sub, sup);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Format pre-check ──\n\t\t// Si les deux schemas ont un `format` différent, vérifier que\n\t\t// sub.format ⊆ sup.format. Sinon, sub ne peut pas être ⊆ sup.\n\t\t// Cela complète hasFormatConflict (qui gère le merge) en gérant\n\t\t// la direction du subset check que le merge ne peut pas résoudre.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"format\") &&\n\t\t\thasOwn(sup, \"format\") &&\n\t\t\tsub.format !== sup.format\n\t\t) {\n\t\t\tconst fmtResult = isFormatSubset(\n\t\t\t\tsub.format as string,\n\t\t\t\tsup.format as string,\n\t\t\t);\n\t\t\tif (fmtResult !== true) return false;\n\t\t}\n\n\t\t// ── Pattern pre-check ──\n\t\t// Si les deux schemas ont des patterns différents, vérifier l'inclusion\n\t\t// par échantillonnage. Si sub.pattern ⊄ sup.pattern (contre-exemple trouvé),\n\t\t// on retourne false immédiatement. Sinon, on pourra retirer le pattern\n\t\t// de sup pour éviter le faux négatif structurel du merge.\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof sup !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(sup, \"pattern\") &&\n\t\t\tsub.pattern !== sup.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tsup.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Retirer `not` de sup (top-level et/ou dans les properties)\n\t\t// quand evaluateNot confirme la compatibilité au niveau correspondant.\n\t\t// Cela évite que le merge engine ajoute une contrainte `not` que sub n'a pas\n\t\t// (ce qui ferait merged ≠ sub et produirait un faux négatif).\n\t\tlet effectiveSup = sup;\n\t\tif (typeof sup !== \"boolean\") {\n\t\t\t// Si top-level not est confirmé compatible → retirer le not top-level\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, true);\n\t\t\t\t// Si sup n'avait QUE `not` → sub est compatible (le not est résolu)\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveSup !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveSup).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Même si le top-level not n'est pas confirmé (null), on tente\n\t\t\t\t// de retirer les `not` dans les properties individuelles\n\t\t\t\t// sans toucher au `not` top-level\n\t\t\t\teffectiveSup = stripNotFromSup(sub, sup, false);\n\t\t\t}\n\n\t\t\t// Retirer les patterns de sup confirmés par échantillonnage.\n\t\t\t// Même stratégie que pour `not` : on retire la contrainte déjà\n\t\t\t// satisfaite par sub pour éviter que le merge produise un pattern\n\t\t\t// combiné (lookahead conjunction) structurellement ≠ sub.\n\t\t\teffectiveSup = stripPatternFromSup(sub, effectiveSup);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveSup);\n\t\tif (merged === null) return false;\n\t\t// Fast path: if merged is already structurally equal to sub,\n\t\t// skip normalize entirely. This is the common case when sub ⊆ sup\n\t\t// (A ∩ B = A), saving O(n) normalize traversal on wide schemas.\n\t\tif (deepEqual(merged, sub)) return true;\n\t\t// Slow path: normalize to eliminate merge artifacts (e.g. redundant\n\t\t// enum when const is present), then compare.\n\t\tconst normalizedMerged = normalize(merged);\n\t\treturn (\n\t\t\tdeepEqual(normalizedMerged, sub) || engine.isEqual(normalizedMerged, sub)\n\t\t);\n\t}\n\n\t// anyOf/oneOf dans sup → au moins une branche doit accepter sub\n\treturn supBranches.some((branch) => {\n\t\t// Point 7 : pré-check `not` étendu par branche\n\t\tconst notResult = evaluateNot(sub, branch);\n\t\tif (notResult === false) return false;\n\n\t\t// ── Pattern pre-check par branche ──\n\t\tif (\n\t\t\ttypeof sub !== \"boolean\" &&\n\t\t\ttypeof branch !== \"boolean\" &&\n\t\t\thasOwn(sub, \"pattern\") &&\n\t\t\thasOwn(branch, \"pattern\") &&\n\t\t\tsub.pattern !== branch.pattern\n\t\t) {\n\t\t\tconst patResult = isPatternSubset(\n\t\t\t\tsub.pattern as string,\n\t\t\t\tbranch.pattern as string,\n\t\t\t);\n\t\t\tif (patResult === false) return false;\n\t\t}\n\n\t\t// Même logique de strip pour les branches\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof branch !== \"boolean\") {\n\t\t\tif (notResult === true) {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, true);\n\t\t\t\tif (\n\t\t\t\t\ttypeof effectiveBranch !== \"boolean\" &&\n\t\t\t\t\tObject.keys(effectiveBranch).length === 0\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\teffectiveBranch = stripNotFromSup(sub, branch, false);\n\t\t\t}\n\n\t\t\t// Strip patterns confirmés par échantillonnage\n\t\t\teffectiveBranch = stripPatternFromSup(sub, effectiveBranch);\n\t\t}\n\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged === null) return false;\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) return true;\n\t\tconst normalizedBranch = normalize(merged);\n\t\treturn (\n\t\t\tdeepEqual(normalizedBranch, sub) || engine.isEqual(normalizedBranch, sub)\n\t\t);\n\t});\n}\n\n// ─── Full subset check (with diffs) ─────────────────────────────────────────\n\n/**\n * Vérifie `sub ⊆ sup` pour un sub qui a des branches (anyOf/oneOf).\n * Chaque branche de sub doit être acceptée par sup.\n *\n * Point 6 — Utilise `getBranchesTyped` pour distinguer `anyOf[i]` de\n * `oneOf[i]` dans les paths de diff.\n *\n * Utilise `_.every` / `_.flatMap` / `_.map` pour une itération idiomatique.\n */\nexport function checkBranchedSub(\n\tsubBranches: JSONSchema7Definition[],\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n\tbranchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tconst allDiffs: SchemaDiff[] = [];\n\tlet allSubset = true;\n\n\t// Point 6 : utilise le type de branche réel pour le path\n\tconst branchLabel = branchType === \"none\" ? \"anyOf\" : branchType;\n\n\tfor (let i = 0; i < subBranches.length; i++) {\n\t\tconst branch = subBranches[i];\n\t\tif (branch === undefined) continue;\n\t\tif (!isAtomicSubsetOf(branch, sup, engine)) {\n\t\t\tallSubset = false;\n\t\t\tallDiffs.push({\n\t\t\t\tpath: `${branchLabel}[${i}]`,\n\t\t\t\ttype: \"changed\",\n\t\t\t\texpected: branch,\n\t\t\t\tactual: \"Branch not accepted by superset\",\n\t\t\t});\n\t\t}\n\t}\n\n\treturn {\n\t\tisSubset: allSubset,\n\t\tmerged: allSubset\n\t\t\t? branchType === \"oneOf\"\n\t\t\t\t? { oneOf: subBranches }\n\t\t\t\t: { anyOf: subBranches }\n\t\t\t: null,\n\t\tdiffs: allDiffs,\n\t};\n}\n\n/**\n * Vérifie `sub ⊆ sup` pour un sup qui a des branches (anyOf/oneOf).\n * Au moins une branche de sup doit accepter sub.\n *\n * Point 6 — Utilise le type de branche de sup pour des messages plus précis.\n *\n * Utilise `_.some` pour trouver la première branche compatible.\n */\nexport function checkBranchedSup(\n\tsub: JSONSchema7Definition,\n\tsupBranches: JSONSchema7Definition[],\n\tengine: MergeEngine,\n\tbranchType: BranchType = \"anyOf\",\n): SubsetResult {\n\tfor (const branch of supBranches) {\n\t\t// Strip patterns confirmés par échantillonnage avant le merge\n\t\tlet effectiveBranch = branch;\n\t\tif (typeof sub !== \"boolean\" && typeof branch !== \"boolean\") {\n\t\t\teffectiveBranch = stripPatternFromSup(sub, branch);\n\t\t}\n\t\tconst merged = engine.merge(sub, effectiveBranch);\n\t\tif (merged !== null) {\n\t\t\t// Fast path: skip normalize if merged already equals sub\n\t\t\tif (deepEqual(merged, sub)) {\n\t\t\t\treturn { isSubset: true, merged, diffs: [] };\n\t\t\t}\n\t\t\tconst normalizedMerged = normalize(merged);\n\t\t\tif (\n\t\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t\t) {\n\t\t\t\treturn { isSubset: true, merged, diffs: [] };\n\t\t\t}\n\t\t}\n\t}\n\n\t// Point 6 : message précis selon le type de branche\n\tconst branchLabel = branchType === \"none\" ? \"anyOf\" : branchType;\n\n\treturn {\n\t\tisSubset: false,\n\t\tmerged: null,\n\t\tdiffs: [\n\t\t\t{\n\t\t\t\tpath: \"$\",\n\t\t\t\ttype: \"changed\",\n\t\t\t\texpected: sub,\n\t\t\t\tactual: `No branch in superset's ${branchLabel} accepts this schema`,\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Vérifie `sub ⊆ sup` pour deux schemas atomiques (sans anyOf/oneOf).\n * Utilise `mergeOrThrow` pour capturer les erreurs d'incompatibilité.\n *\n * Utilise `deepEqual` pour la comparaison structurelle (avec short-circuit\n * par référence et comptage de clés).\n */\nexport function checkAtomic(\n\tsub: JSONSchema7Definition,\n\tsup: JSONSchema7Definition,\n\tengine: MergeEngine,\n): SubsetResult {\n\t// Strip patterns confirmés par échantillonnage avant le merge,\n\t// même stratégie que dans isAtomicSubsetOf pour éviter les faux négatifs\n\t// structurels causés par la conjonction de patterns en lookahead.\n\tlet effectiveSup = sup;\n\tif (typeof sub !== \"boolean\" && typeof sup !== \"boolean\") {\n\t\teffectiveSup = stripPatternFromSup(sub, sup);\n\t}\n\n\ttry {\n\t\tconst merged = engine.mergeOrThrow(sub, effectiveSup);\n\n\t\t// Fast path: skip normalize if merged already equals sub\n\t\tif (deepEqual(merged, sub)) {\n\t\t\treturn { isSubset: true, merged, diffs: [] };\n\t\t}\n\n\t\tconst normalizedMerged = normalize(merged);\n\n\t\tif (\n\t\t\tdeepEqual(normalizedMerged, sub) ||\n\t\t\tengine.isEqual(normalizedMerged, sub)\n\t\t) {\n\t\t\treturn { isSubset: true, merged: normalizedMerged, diffs: [] };\n\t\t}\n\n\t\tconst diffs = computeDiffs(sub, normalizedMerged, \"\");\n\t\treturn { isSubset: false, merged: normalizedMerged, diffs };\n\t} catch (e) {\n\t\treturn {\n\t\t\tisSubset: false,\n\t\t\tmerged: null,\n\t\t\tdiffs: [\n\t\t\t\t{\n\t\t\t\t\tpath: \"$\",\n\t\t\t\t\ttype: \"changed\",\n\t\t\t\t\texpected: sub,\n\t\t\t\t\tactual: `Incompatible: ${e instanceof Error ? e.message : String(e)}`,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "B8207E42E9F16E9764756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
function X(w){return typeof w==="object"&&w!==null&&!Array.isArray(w)}function Y(w,B){return Object.hasOwn(w,B)}function R(w,B){if(w===B)return!0;if(w===null||B===null)return!1;if(typeof w!==typeof B)return!1;if(typeof w==="object"){if(Array.isArray(w)){if(!Array.isArray(B))return!1;let C=w.length;if(C!==B.length)return!1;for(let G=0;G<C;G++)if(!R(w[G],B[G]))return!1;return!0}if(Array.isArray(B))return!1;let M=w,H=B,I=Object.keys(M),F=Object.keys(H);if(I.length!==F.length)return!1;for(let C of I)if(!(C in H)||!R(M[C],H[C]))return!1;return!0}return!1}function Z(w,B){if(B.length<=2){let F=B[0],C=B[1],G=F!==void 0&&F in w,P=C!==void 0&&C in w;if(!G&&!P)return w;let U={};for(let Q of Object.keys(w))if(Q!==F&&Q!==C)U[Q]=w[Q];return U}let M=new Set(B),H=!1;for(let F of B)if(F in w){H=!0;break}if(!H)return w;let I={};for(let F of Object.keys(w))if(!M.has(F))I[F]=w[F];return I}function _(w,B){let M=w.length,H=B.length;if(H===0)return w;if(M===0)return B;if(M+H<=8){let C=w.slice();for(let G=0;G<H;G++){let P=B[G];if(P!==void 0&&!C.includes(P))C.push(P)}return C.length===M?w:C}let I=new Set(w),F=I.size;for(let C=0;C<H;C++){let G=B[C];if(G!==void 0)I.add(G)}if(I.size===F&&F===M)return w;return Array.from(I)}function $(w,B){return R(w,B)}
|
|
2
|
-
export{X as
|
|
2
|
+
export{X as v,Y as w,R as x,Z as y,_ as z,$ as A};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
5
|
-
//# sourceMappingURL=chunk-
|
|
4
|
+
//# debugId=A3DFFE9932CFDCC564756E2164756E21
|
|
5
|
+
//# sourceMappingURL=chunk-jkdzdb3r.js.map
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"import type { JSONSchema7Definition } from \"json-schema\";\n\n// ─── Shared Utilities ────────────────────────────────────────────────────────\n//\n// Fonctions utilitaires natives partagées entre tous les modules.\n// Centralisées ici pour éviter la duplication et permettre à V8\n// d'optimiser une seule instance de chaque fonction hot-path.\n\n/**\n * Vérifie si une valeur est un plain object (pas null, pas un array).\n */\nexport function isPlainObj(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Vérifie si un objet possède une propriété propre.\n */\nexport function hasOwn(obj: object, key: string): boolean {\n\treturn Object.hasOwn(obj, key);\n}\n\n/**\n * Compare deux valeurs en profondeur (deep equality).\n *\n * Optimisations :\n * - Reference equality short-circuit (a === b)\n * - Length checks avant l'itération (arrays et objects)\n * - Pas de support pour Date, RegExp, Map, Set (pas nécessaire pour JSON Schema)\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n\tif (a === b) return true;\n\tif (a === null || b === null) return false;\n\tif (typeof a !== typeof b) return false;\n\n\tif (typeof a === \"object\") {\n\t\tif (Array.isArray(a)) {\n\t\t\tif (!Array.isArray(b)) return false;\n\t\t\tconst len = a.length;\n\t\t\tif (len !== b.length) return false;\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (!deepEqual(a[i], b[i])) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (Array.isArray(b)) return false;\n\n\t\tconst aObj = a as Record<string, unknown>;\n\t\tconst bObj = b as Record<string, unknown>;\n\t\tconst aKeys = Object.keys(aObj);\n\t\tconst bKeys = Object.keys(bObj);\n\t\tif (aKeys.length !== bKeys.length) return false;\n\t\tfor (const key of aKeys) {\n\t\t\tif (!(key in bObj) || !deepEqual(aObj[key], bObj[key])) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Crée une copie d'un objet sans les clés spécifiées.\n *\n * Optimisé pour le cas courant (1-2 clés à omettre) :\n * - Utilise un Set uniquement si > 2 clés\n * - Itère une seule fois sur l'objet source\n * - Retourne l'original si aucune clé à omettre n'est présente dans l'objet\n */\nexport function omitKeys<T extends Record<string, unknown>>(\n\tobj: T,\n\tkeysToOmit: string[],\n): T {\n\t// Fast path: check if any key to omit actually exists in the object\n\tif (keysToOmit.length <= 2) {\n\t\tconst k0 = keysToOmit[0];\n\t\tconst k1 = keysToOmit[1];\n\t\tconst has0 = k0 !== undefined && k0 in obj;\n\t\tconst has1 = k1 !== undefined && k1 in obj;\n\t\tif (!has0 && !has1) return obj;\n\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const key of Object.keys(obj)) {\n\t\t\tif (key !== k0 && key !== k1) {\n\t\t\t\tresult[key] = obj[key];\n\t\t\t}\n\t\t}\n\t\treturn result as T;\n\t}\n\n\tconst omitSet = new Set(keysToOmit);\n\n\t// Check if any key to omit exists\n\tlet hasAny = false;\n\tfor (const key of keysToOmit) {\n\t\tif (key in obj) {\n\t\t\thasAny = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!hasAny) return obj;\n\n\tconst result: Record<string, unknown> = {};\n\tfor (const key of Object.keys(obj)) {\n\t\tif (!omitSet.has(key)) {\n\t\t\tresult[key] = obj[key];\n\t\t}\n\t}\n\treturn result as T;\n}\n\n/**\n * Fusionne deux tableaux de strings en éliminant les doublons.\n * Retourne un tableau avec les éléments uniques des deux sources.\n *\n * Optimisé avec fast paths pour les cas courants :\n * - Si b est vide → retourne a directement\n * - Si a est vide → retourne b directement\n * - Pour les petits tableaux (≤ 8 éléments total), utilise\n * une boucle avec includes au lieu de créer un Set\n */\nexport function unionStrings(a: string[], b: string[]): string[] {\n\tconst aLen = a.length;\n\tconst bLen = b.length;\n\n\t// Fast paths for empty arrays\n\tif (bLen === 0) return a;\n\tif (aLen === 0) return b;\n\n\t// Fast path for small arrays: avoid Set allocation overhead\n\tif (aLen + bLen <= 8) {\n\t\tconst result = a.slice();\n\t\tfor (let i = 0; i < bLen; i++) {\n\t\t\tconst item = b[i];\n\t\t\tif (item !== undefined && !result.includes(item)) {\n\t\t\t\tresult.push(item);\n\t\t\t}\n\t\t}\n\t\t// If nothing was added from b (all items already in a), return a\n\t\treturn result.length === aLen ? a : result;\n\t}\n\n\t// General case: use Set for larger arrays\n\tconst set = new Set(a);\n\tconst initialSize = set.size;\n\tfor (let i = 0; i < bLen; i++) {\n\t\tconst item = b[i];\n\t\tif (item !== undefined) set.add(item);\n\t}\n\n\t// If nothing new was added, return a directly\n\tif (set.size === initialSize && initialSize === aLen) return a;\n\n\treturn Array.from(set);\n}\n\n/**\n * Vérifie l'égalité structurelle entre deux JSONSchema7Definition.\n * Wrapper typé autour de deepEqual pour les schemas.\n */\nexport function schemaDeepEqual(\n\ta: JSONSchema7Definition,\n\tb: JSONSchema7Definition,\n): boolean {\n\treturn deepEqual(a, b);\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": "AAWO,SAAS,CAAU,CAAC,EAAkD,CAC5E,OAAO,OAAO,IAAU,UAAY,IAAU,MAAQ,CAAC,MAAM,QAAQ,CAAK,EAMpE,SAAS,CAAM,CAAC,EAAa,EAAsB,CACzD,OAAO,OAAO,OAAO,EAAK,CAAG,EAWvB,SAAS,CAAS,CAAC,EAAY,EAAqB,CAC1D,GAAI,IAAM,EAAG,MAAO,GACpB,GAAI,IAAM,MAAQ,IAAM,KAAM,MAAO,GACrC,GAAI,OAAO,IAAM,OAAO,EAAG,MAAO,GAElC,GAAI,OAAO,IAAM,SAAU,CAC1B,GAAI,MAAM,QAAQ,CAAC,EAAG,CACrB,GAAI,CAAC,MAAM,QAAQ,CAAC,EAAG,MAAO,GAC9B,IAAM,EAAM,EAAE,OACd,GAAI,IAAQ,EAAE,OAAQ,MAAO,GAC7B,QAAS,EAAI,EAAG,EAAI,EAAK,IACxB,GAAI,CAAC,EAAU,EAAE,GAAI,EAAE,EAAE,EAAG,MAAO,GAEpC,MAAO,GAER,GAAI,MAAM,QAAQ,CAAC,EAAG,MAAO,GAE7B,IAAM,EAAO,EACP,EAAO,EACP,EAAQ,OAAO,KAAK,CAAI,EACxB,EAAQ,OAAO,KAAK,CAAI,EAC9B,GAAI,EAAM,SAAW,EAAM,OAAQ,MAAO,GAC1C,QAAW,KAAO,EACjB,GAAI,EAAE,KAAO,IAAS,CAAC,EAAU,EAAK,GAAM,EAAK,EAAI,EAAG,MAAO,GAEhE,MAAO,GAGR,MAAO,GAWD,SAAS,CAA2C,CAC1D,EACA,EACI,CAEJ,GAAI,EAAW,QAAU,EAAG,CAC3B,IAAM,EAAK,EAAW,GAChB,EAAK,EAAW,GAChB,EAAO,IAAO,QAAa,KAAM,EACjC,EAAO,IAAO,QAAa,KAAM,EACvC,GAAI,CAAC,GAAQ,CAAC,EAAM,OAAO,EAE3B,IAAM,EAAkC,CAAC,EACzC,QAAW,KAAO,OAAO,KAAK,CAAG,EAChC,GAAI,IAAQ,GAAM,IAAQ,EACzB,EAAO,GAAO,EAAI,GAGpB,OAAO,EAGR,IAAM,EAAU,IAAI,IAAI,CAAU,EAG9B,EAAS,GACb,QAAW,KAAO,EACjB,GAAI,KAAO,EAAK,CACf,EAAS,GACT,MAGF,GAAI,CAAC,EAAQ,OAAO,EAEpB,IAAM,EAAkC,CAAC,EACzC,QAAW,KAAO,OAAO,KAAK,CAAG,EAChC,GAAI,CAAC,EAAQ,IAAI,CAAG,EACnB,EAAO,GAAO,EAAI,GAGpB,OAAO,EAaD,SAAS,CAAY,CAAC,EAAa,EAAuB,CAChE,IAAM,EAAO,EAAE,OACT,EAAO,EAAE,OAGf,GAAI,IAAS,EAAG,OAAO,EACvB,GAAI,IAAS,EAAG,OAAO,EAGvB,GAAI,EAAO,GAAQ,EAAG,CACrB,IAAM,EAAS,EAAE,MAAM,EACvB,QAAS,EAAI,EAAG,EAAI,EAAM,IAAK,CAC9B,IAAM,EAAO,EAAE,GACf,GAAI,IAAS,QAAa,CAAC,EAAO,SAAS,CAAI,EAC9C,EAAO,KAAK,CAAI,EAIlB,OAAO,EAAO,SAAW,EAAO,EAAI,EAIrC,IAAM,EAAM,IAAI,IAAI,CAAC,EACf,EAAc,EAAI,KACxB,QAAS,EAAI,EAAG,EAAI,EAAM,IAAK,CAC9B,IAAM,EAAO,EAAE,GACf,GAAI,IAAS,OAAW,EAAI,IAAI,CAAI,EAIrC,GAAI,EAAI,OAAS,GAAe,IAAgB,EAAM,OAAO,EAE7D,OAAO,MAAM,KAAK,CAAG,EAOf,SAAS,CAAe,CAC9B,EACA,EACU,CACV,OAAO,EAAU,EAAG,CAAC",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "A3DFFE9932CFDCC564756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{v as M,x as Q,z as W}from"./chunk-jkdzdb3r.js";var $=new Set(["items","additionalProperties","additionalItems","contains","propertyNames","not","if","then","else"]),C=new Set(["properties","patternProperties","dependencies"]);function T(z,A,F){return $.has(z)&&M(A)&&M(F)}function U(z,A,F){return C.has(z)&&M(A)&&M(F)}function X(z,A,F){if(typeof z==="boolean"||typeof A==="boolean"){if(z!==A)return[{path:F||"$",type:"changed",expected:z,actual:A}];return[]}let N=W(Object.keys(z),Object.keys(A)),H=[];for(let x of N){let G=F?`${F}.${x}`:x,w=z[x],v=A[x];if(w===void 0&&v!==void 0){H.push({path:G,type:"added",expected:void 0,actual:v});continue}if(w!==void 0&&v===void 0){H.push({path:G,type:"removed",expected:w,actual:void 0});continue}if(w!==void 0&&v!==void 0&&!Q(w,v)){if(T(x,w,v)){let B=X(w,v,G);for(let J of B)H.push(J);continue}if(U(x,w,v)){let B=q(w,v,G,x);for(let J of B)H.push(J);continue}H.push({path:G,type:"changed",expected:w,actual:v})}}return H}function q(z,A,F,N){let H=W(Object.keys(z),Object.keys(A)),x=[];for(let G of H){let w=`${F}.${G}`,v=z[G],B=A[G];if(v===void 0&&B!==void 0){x.push({path:w,type:"added",expected:void 0,actual:B});continue}if(v!==void 0&&B===void 0){x.push({path:w,type:"removed",expected:v,actual:void 0});continue}if(v!==void 0&&B!==void 0){if(N==="dependencies"&&(Array.isArray(v)||Array.isArray(B))){if(!Q(v,B))x.push({path:w,type:"changed",expected:v,actual:B});continue}let J=X(v,B,w);for(let Z of J)x.push(Z)}}return x}
|
|
2
|
+
export{X as l};
|
|
3
|
+
|
|
4
|
+
//# debugId=587A5E069FE6D21A64756E2164756E21
|
|
5
|
+
//# sourceMappingURL=chunk-jybaxgmh.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/differ.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport type { SchemaDiff } from \"./types\";\nimport { deepEqual, isPlainObj, unionStrings } from \"./utils\";\n\n// ─── Schema Differ ───────────────────────────────────────────────────────────\n//\n// Calcul des différences structurelles entre un schema original et son\n// intersection (merged). Utilisé pour produire des diagnostics lisibles\n// quand sub ⊄ sup.\n//\n// Utilise des méthodes natives JS pour des performances optimales.\n\n// ─── Recursive diff keys ─────────────────────────────────────────────────────\n\n/** Mots-clés dont la valeur est un sous-schema unique (récursion possible) */\nconst RECURSIVE_KEYS: ReadonlySet<string> = new Set([\n\t\"items\",\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]);\n\n/**\n * Mots-clés dont la valeur est un `Record<string, JSONSchema7Definition>`.\n * Chaque propriété est un sous-schema → récursion au niveau des clés.\n *\n * `dependencies` est inclus ici avec une gestion spéciale (forme tableau\n * vs forme schema) dans\n `computePropertyDiffs`.\n *\n * Point 3 — dependencies ajouté ici (avec gestion spéciale forme tableau).\n */\nconst PROPERTIES_LIKE_KEYS: ReadonlySet<string> = new Set([\n\t\"properties\",\n\t\"patternProperties\",\n\t\"dependencies\",\n]);\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\n/**\n * Vérifie si on peut récurser dans un mot-clé single-schema :\n * la clé doit être dans RECURSIVE_KEYS et les deux valeurs doivent être\n * des objets (pas des tableaux, pas null).\n */\nfunction canRecurseInto(\n\tkey: string,\n\torigVal: unknown,\n\tmergedVal: unknown,\n): boolean {\n\treturn (\n\t\tRECURSIVE_KEYS.has(key) && isPlainObj(origVal) && isPlainObj(mergedVal)\n\t);\n}\n\n/**\n * Vérifie si un mot-clé est un objet de propriétés récursable.\n *\n * Utilise `_.includes` sur le Set pour une vérification concise.\n */\nfunction isPropertiesLikeObject(\n\tkey: string,\n\torigVal: unknown,\n\tmergedVal: unknown,\n): boolean {\n\treturn (\n\t\tPROPERTIES_LIKE_KEYS.has(key) &&\n\t\tisPlainObj(origVal) &&\n\t\tisPlainObj(mergedVal)\n\t);\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Compare un schema original avec sa version mergée et retourne la liste\n * des différences structurelles.\n *\n * @param original Le schema sub tel qu'il était avant le merge\n * @param merged Le schema résultant de l'intersection allOf(sub, sup)\n * @param path Chemin JSON-path courant (vide à la racine)\n *\n * Point 9 — Utilise `deepEqual` au lieu de `JSON.stringify` pour comparer\n * les valeurs, ce qui élimine la dépendance à l'ordre des clés.\n */\nexport function computeDiffs(\n\toriginal: JSONSchema7Definition,\n\tmerged: JSONSchema7Definition,\n\tpath: string,\n): SchemaDiff[] {\n\t// Cas boolean schemas\n\tif (typeof original === \"boolean\" || typeof merged === \"boolean\") {\n\t\tif (original !== merged) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tpath: path || \"$\",\n\t\t\t\t\ttype: \"changed\",\n\t\t\t\t\texpected: original,\n\t\t\t\t\tactual: merged,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\treturn [];\n\t}\n\n\t// Collecter toutes les clés des deux schemas\n\tconst allKeys = unionStrings(\n\t\tObject.keys(original),\n\t\tObject.keys(merged),\n\t) as (keyof JSONSchema7)[];\n\n\tconst result: SchemaDiff[] = [];\n\tfor (const key of allKeys) {\n\t\tconst currentPath = path ? `${path}.${key}` : key;\n\t\tconst origVal = original[key];\n\t\tconst mergedVal = merged[key];\n\n\t\t// Clé ajoutée par le merge\n\t\tif (origVal === undefined && mergedVal !== undefined) {\n\t\t\tresult.push({\n\t\t\t\tpath: currentPath,\n\t\t\t\ttype: \"added\",\n\t\t\t\texpected: undefined,\n\t\t\t\tactual: mergedVal,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Clé supprimée par le merge\n\t\tif (origVal !== undefined && mergedVal === undefined) {\n\t\t\tresult.push({\n\t\t\t\tpath: currentPath,\n\t\t\t\ttype: \"removed\",\n\t\t\t\texpected: origVal,\n\t\t\t\tactual: undefined,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Les deux sont définies — vérifier si elles diffèrent\n\t\t// Point 9 : deepEqual pour une comparaison profonde indépendante de l'ordre des clés\n\t\tif (\n\t\t\torigVal !== undefined &&\n\t\t\tmergedVal !== undefined &&\n\t\t\t!deepEqual(origVal, mergedVal)\n\t\t) {\n\t\t\t// Récurser dans les sous-schemas uniques\n\t\t\tif (canRecurseInto(key, origVal, mergedVal)) {\n\t\t\t\tconst sub = computeDiffs(\n\t\t\t\t\torigVal as JSONSchema7Definition,\n\t\t\t\t\tmergedVal as JSONSchema7Definition,\n\t\t\t\t\tcurrentPath,\n\t\t\t\t);\n\t\t\t\tfor (const d of sub) result.push(d);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Récurser dans les objets de propriétés (properties, patternProperties, dependencies)\n\t\t\tif (isPropertiesLikeObject(key, origVal, mergedVal)) {\n\t\t\t\tconst sub = computePropertyDiffs(\n\t\t\t\t\torigVal as Record<string, JSONSchema7Definition>,\n\t\t\t\t\tmergedVal as Record<string, JSONSchema7Definition>,\n\t\t\t\t\tcurrentPath,\n\t\t\t\t\tkey,\n\t\t\t\t);\n\t\t\t\tfor (const d of sub) result.push(d);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Valeur scalaire ou structure non-récursable\n\t\t\tresult.push({\n\t\t\t\tpath: currentPath,\n\t\t\t\ttype: \"changed\",\n\t\t\t\texpected: origVal,\n\t\t\t\tactual: mergedVal,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ─── Property-level diffs ────────────────────────────────────────────────────\n\n/**\n * Calcule les diffs au niveau des propriétés d'un objet `properties`,\n * `patternProperties`, ou `dependencies`.\n *\n * Pour `dependencies` (Point 3), gère les deux formes :\n * - Forme 1 (tableau de strings) : comparaison directe via `deepEqual`\n * - Forme 2 (sous-schema) : récursion via `computeDiffs`\n *\n * Fusionne les clés des deux côtés et produit un tableau aplati de diffs.\n */\nfunction computePropertyDiffs(\n\toriginal: Record<string, JSONSchema7Definition | string[]>,\n\tmerged: Record<string, JSONSchema7Definition | string[]>,\n\tbasePath: string,\n\tparentKey: string,\n): SchemaDiff[] {\n\tconst allPropKeys = unionStrings(Object.keys(original), Object.keys(merged));\n\n\tconst result: SchemaDiff[] = [];\n\tfor (const key of allPropKeys) {\n\t\tconst currentPath = `${basePath}.${key}`;\n\t\tconst origVal = original[key];\n\t\tconst mergedVal = merged[key];\n\n\t\tif (origVal === undefined && mergedVal !== undefined) {\n\t\t\tresult.push({\n\t\t\t\tpath: currentPath,\n\t\t\t\ttype: \"added\",\n\t\t\t\texpected: undefined,\n\t\t\t\tactual: mergedVal,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (origVal !== undefined && mergedVal === undefined) {\n\t\t\tresult.push({\n\t\t\t\tpath: currentPath,\n\t\t\t\ttype: \"removed\",\n\t\t\t\texpected: origVal,\n\t\t\t\tactual: undefined,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (origVal !== undefined && mergedVal !== undefined) {\n\t\t\t// Pour `dependencies`, les valeurs peuvent être des tableaux de strings (forme 1)\n\t\t\t// On ne récurse que si les deux valeurs sont des objets (sous-schemas)\n\t\t\tif (\n\t\t\t\tparentKey === \"dependencies\" &&\n\t\t\t\t(Array.isArray(origVal) || Array.isArray(mergedVal))\n\t\t\t) {\n\t\t\t\t// Comparaison directe pour les tableaux de strings\n\t\t\t\tif (!deepEqual(origVal, mergedVal)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\tpath: currentPath,\n\t\t\t\t\t\ttype: \"changed\",\n\t\t\t\t\t\texpected: origVal,\n\t\t\t\t\t\tactual: mergedVal,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Récursion standard pour les sous-schemas\n\t\t\tconst sub = computeDiffs(\n\t\t\t\torigVal as JSONSchema7Definition,\n\t\t\t\tmergedVal as JSONSchema7Definition,\n\t\t\t\tcurrentPath,\n\t\t\t);\n\t\t\tfor (const d of sub) result.push(d);\n\t\t}\n\t}\n\n\treturn result;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "sDAeA,IAAM,EAAsC,IAAI,IAAI,CACnD,QACA,uBACA,kBACA,WACA,gBACA,MACA,KACA,OACA,MACD,CAAC,EAYK,EAA4C,IAAI,IAAI,CACzD,aACA,oBACA,cACD,CAAC,EASD,SAAS,CAAc,CACtB,EACA,EACA,EACU,CACV,OACC,EAAe,IAAI,CAAG,GAAK,EAAW,CAAO,GAAK,EAAW,CAAS,EASxE,SAAS,CAAsB,CAC9B,EACA,EACA,EACU,CACV,OACC,EAAqB,IAAI,CAAG,GAC5B,EAAW,CAAO,GAClB,EAAW,CAAS,EAiBf,SAAS,CAAY,CAC3B,EACA,EACA,EACe,CAEf,GAAI,OAAO,IAAa,WAAa,OAAO,IAAW,UAAW,CACjE,GAAI,IAAa,EAChB,MAAO,CACN,CACC,KAAM,GAAQ,IACd,KAAM,UACN,SAAU,EACV,OAAQ,CACT,CACD,EAED,MAAO,CAAC,EAIT,IAAM,EAAU,EACf,OAAO,KAAK,CAAQ,EACpB,OAAO,KAAK,CAAM,CACnB,EAEM,EAAuB,CAAC,EAC9B,QAAW,KAAO,EAAS,CAC1B,IAAM,EAAc,EAAO,GAAG,KAAQ,IAAQ,EACxC,EAAU,EAAS,GACnB,EAAY,EAAO,GAGzB,GAAI,IAAY,QAAa,IAAc,OAAW,CACrD,EAAO,KAAK,CACX,KAAM,EACN,KAAM,QACN,SAAU,OACV,OAAQ,CACT,CAAC,EACD,SAID,GAAI,IAAY,QAAa,IAAc,OAAW,CACrD,EAAO,KAAK,CACX,KAAM,EACN,KAAM,UACN,SAAU,EACV,OAAQ,MACT,CAAC,EACD,SAKD,GACC,IAAY,QACZ,IAAc,QACd,CAAC,EAAU,EAAS,CAAS,EAC5B,CAED,GAAI,EAAe,EAAK,EAAS,CAAS,EAAG,CAC5C,IAAM,EAAM,EACX,EACA,EACA,CACD,EACA,QAAW,KAAK,EAAK,EAAO,KAAK,CAAC,EAClC,SAID,GAAI,EAAuB,EAAK,EAAS,CAAS,EAAG,CACpD,IAAM,EAAM,EACX,EACA,EACA,EACA,CACD,EACA,QAAW,KAAK,EAAK,EAAO,KAAK,CAAC,EAClC,SAID,EAAO,KAAK,CACX,KAAM,EACN,KAAM,UACN,SAAU,EACV,OAAQ,CACT,CAAC,GAIH,OAAO,EAeR,SAAS,CAAoB,CAC5B,EACA,EACA,EACA,EACe,CACf,IAAM,EAAc,EAAa,OAAO,KAAK,CAAQ,EAAG,OAAO,KAAK,CAAM,CAAC,EAErE,EAAuB,CAAC,EAC9B,QAAW,KAAO,EAAa,CAC9B,IAAM,EAAc,GAAG,KAAY,IAC7B,EAAU,EAAS,GACnB,EAAY,EAAO,GAEzB,GAAI,IAAY,QAAa,IAAc,OAAW,CACrD,EAAO,KAAK,CACX,KAAM,EACN,KAAM,QACN,SAAU,OACV,OAAQ,CACT,CAAC,EACD,SAGD,GAAI,IAAY,QAAa,IAAc,OAAW,CACrD,EAAO,KAAK,CACX,KAAM,EACN,KAAM,UACN,SAAU,EACV,OAAQ,MACT,CAAC,EACD,SAGD,GAAI,IAAY,QAAa,IAAc,OAAW,CAGrD,GACC,IAAc,iBACb,MAAM,QAAQ,CAAO,GAAK,MAAM,QAAQ,CAAS,GACjD,CAED,GAAI,CAAC,EAAU,EAAS,CAAS,EAChC,EAAO,KAAK,CACX,KAAM,EACN,KAAM,UACN,SAAU,EACV,OAAQ,CACT,CAAC,EAEF,SAID,IAAM,EAAM,EACX,EACA,EACA,CACD,EACA,QAAW,KAAK,EAAK,EAAO,KAAK,CAAC,GAIpC,OAAO",
|
|
8
|
+
"debugId": "587A5E069FE6D21A64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
2
|
-
export{b as
|
|
1
|
+
import{r as w}from"./chunk-07z7fc5q.js";import{t as E}from"./chunk-yqhv3py7.js";import{v as L,w as Y,x as B,y as I,z as R}from"./chunk-jkdzdb3r.js";var x=new Set(["required","properties","dependencies"]),D=new Set(["additionalProperties","items","contains","propertyNames","not"]),C=new Set(["minimum","exclusiveMinimum","minLength","minItems","minProperties"]),P=new Set(["maximum","exclusiveMaximum","maxLength","maxItems","maxProperties"]);function O(J,W){if(W===void 0)return!0;let H=Array.isArray(W)?W:[W],z=E(J);return H.some((Q)=>Q===z||Q==="number"&&z==="integer")}function V(J,W){if(W.minimum!==void 0&&!(J>=W.minimum))return!1;if(W.maximum!==void 0&&!(J<=W.maximum))return!1;if(W.exclusiveMinimum!==void 0&&!(J>W.exclusiveMinimum))return!1;if(W.exclusiveMaximum!==void 0&&!(J<W.exclusiveMaximum))return!1;if(W.multipleOf!==void 0&&J%W.multipleOf!==0)return!1;return!0}var T=new Map;function k(J){let W=T.get(J);if(W===void 0)W=new RegExp(J),T.set(J,W);return W}function g(J,W){if(W.minLength!==void 0&&!(J.length>=W.minLength))return!1;if(W.maxLength!==void 0&&!(J.length<=W.maxLength))return!1;if(W.pattern!==void 0&&!k(W.pattern).test(J))return!1;return!0}function f(J,W){if(W.minItems!==void 0&&!(J.length>=W.minItems))return!1;if(W.maxItems!==void 0&&!(J.length<=W.maxItems))return!1;if(W.uniqueItems===!0){let H=J.length;for(let z=0;z<H;z++)for(let Q=z+1;Q<H;Q++)if(B(J[z],J[Q]))return!1}return!0}function q(J,W){if(L(J.properties)){if(!Object.keys(J.properties).every((z)=>{let Q=J.properties?.[z];if(typeof Q==="boolean")return!0;let $=Q,Z=W[z];if(Z===void 0)return!0;if(Y($,"const")){if(!B(Z,$.const))return!1}if(Y($,"enum")){if(!$.enum?.some((F)=>B(F,Z)))return!1}if(Y($,"type")&&Z!==void 0){if(!O(Z,$.type))return!1}if(typeof Z==="number"){if(!V(Z,$))return!1}if(typeof Z==="string"){if(!g(Z,$))return!1}if(Array.isArray(Z)){if(!f(Z,$))return!1}if($.format!==void 0&&typeof Z==="string"){if(w(Z,$.format)===!1)return!1}if(L($.properties)||Array.isArray($.required)){if(L(Z)){if(!q($,Z))return!1}}return!0}))return!1}if(Array.isArray(J.required)){if(!J.required.every((z)=>Y(W,z)))return!1}if(Array.isArray(J.allOf)){if(!J.allOf.every((z)=>{if(typeof z==="boolean")return z;return q(z,W)}))return!1}if(Array.isArray(J.anyOf)){if(!J.anyOf.some((z)=>{if(typeof z==="boolean")return z;return q(z,W)}))return!1}if(Array.isArray(J.oneOf)){let H=0;for(let z of J.oneOf){if(typeof z==="boolean"?z:q(z,W))H++;if(H>1)break}if(H!==1)return!1}if(Y(J,"not")&&L(J.not)&&typeof J.not!=="boolean"){if(q(J.not,W))return!1}return!0}var S=["const","enum","minimum","maximum","exclusiveMinimum","exclusiveMaximum","pattern","minLength","maxLength","multipleOf","minItems","maxItems","format"];function K(J,W,H){if(!L(J.properties))return;let z=J.properties;for(let Q of Object.keys(z)){let $=z[Q];if(typeof $==="boolean")continue;let Z=$;if(S.some((G)=>Y(Z,G))&&Y(W,Q))H[Q]=W[Q]}}function j(J,W,H){if(typeof W==="boolean")return;let z=W;if(Array.isArray(z.required))J.required=R(J.required??[],z.required);if(L(z.properties)){let Q=z.properties,$={...J.properties??{}};for(let Z of Object.keys(Q)){let F=Q[Z];if(F===void 0)continue;let G=J.properties?.[Z];if(G!==void 0&&typeof G!=="boolean"&&typeof F!=="boolean"){let U=H.merge(G,F);$[Z]=U??F}else $[Z]=F}J.properties=$}if(L(z.dependencies)){let Q=J.dependencies??{},$=z.dependencies,Z={...Q};for(let F of Object.keys($)){let G=$[F];if(G===void 0)continue;let U=Z[F];if(U===void 0)Z[F]=G;else if(Array.isArray(U)&&Array.isArray(G))Z[F]=R(U,G);else if(L(U)&&L(G)){let X=H.merge(U,G);Z[F]=X??G}else Z[F]=G}J.dependencies=Z}for(let Q of Object.keys(z)){if(x.has(Q))return;let $=z[Q],Z=J[Q];if(Z===void 0){J[Q]=$;return}if(B(Z,$))return;if(D.has(Q)){let X=H.merge(Z,$);if(X!==null)J[Q]=X;else J[Q]=$;return}if(C.has(Q)){if(typeof Z==="number"&&typeof $==="number")J[Q]=Math.max(Z,$);else J[Q]=$;return}if(P.has(Q)){if(typeof Z==="number"&&typeof $==="number")J[Q]=Math.min(Z,$);else J[Q]=$;return}if(Q==="uniqueItems"){J[Q]=Z===!0||$===!0;return}if(Q==="pattern"||Q==="format"){J[Q]=$;return}let F={[Q]:Z},G={[Q]:$},U=H.merge(F,G);if(U&&typeof U!=="boolean"&&Y(U,Q))J[Q]=U[Q];else J[Q]=$}}function b(J,W,H){let z=null,Q={},$=J.if!==void 0,Z=Array.isArray(J.allOf)&&J.allOf.some((G)=>typeof G!=="boolean"&&Y(G,"if"));if(!$&&!Z)return{resolved:_(J,W,H,Q),branch:z,discriminant:Q};let F={...J};if(Z)F=u(F,W,H,Q);if(F.if!==void 0){let G=F.if,U=q(G,W);K(G,W,Q);let X=U?F.then:F.else;if(z=U?"then":"else",X)j(F,X,H);delete F.if,delete F.then,delete F.else}return F=_(F,W,H,Q),{resolved:F,branch:z,discriminant:Q}}function u(J,W,H,z){if(!Array.isArray(J.allOf))return J;let Q=[];for(let $ of J.allOf){if(typeof $==="boolean"){Q.push($);continue}let Z=$;if(Z.if===void 0){Q.push($);continue}let F=Z.if,G=q(F,W);K(F,W,z);let U=G?Z.then:Z.else;if(U)j(J,U,H);let X=I(Z,["if","then","else"]);if(Object.keys(X).length>0)Q.push(X)}if(J={...J},Q.length===0)delete J.allOf;else J.allOf=Q;return J}function _(J,W,H,z){if(!L(J.properties))return J;let Q=J.properties,$=Object.keys(Q),Z=!1,F={};for(let G of $){let U=Q[G];if(U===void 0)continue;if(typeof U==="boolean"){F[G]=U;continue}let X=U;if(!(X.if!==void 0||Array.isArray(X.allOf)&&X.allOf.some((M)=>typeof M!=="boolean"&&Y(M,"if")))){F[G]=U;continue}let A=L(W[G])?W[G]:{},N=b(X,A,H);for(let M of Object.keys(N.discriminant))z[`${G}.${M}`]=N.discriminant[M];F[G]=N.resolved,Z=!0}return Z?{...J,properties:F}:J}
|
|
2
|
+
export{b as k};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
5
|
-
//# sourceMappingURL=chunk-
|
|
4
|
+
//# debugId=472160296CD0458364756E2164756E21
|
|
5
|
+
//# sourceMappingURL=chunk-pyrx217p.js.map
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"import type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport { validateFormat } from \"./format-validator\";\nimport type { MergeEngine } from \"./merge-engine\";\nimport { inferType } from \"./normalizer\";\nimport type { ResolvedConditionResult } from \"./types\";\nimport { deepEqual, hasOwn, isPlainObj, omitKeys, unionStrings } from \"./utils\";\n\n// ─── Condition Resolver ──────────────────────────────────────────────────────\n//\n// Résout les `if/then/else` d'un schema en évaluant le `if` contre\n// des données partielles (discriminants).\n//\n// Stratégie :\n// 1. Évaluer si les données partielles satisfont le `if`\n// 2. Merger la branche applicable (`then` ou `else`) dans le schema de base\n// 3. Supprimer les mots-clés `if/then/else` du résultat\n// 4. Récurser dans les `properties` pour résoudre les conditions imbriquées\n//\n// L'évaluation du `if` (via `evaluateCondition`) gère :\n// - `properties` avec `const`, `enum`, `type`, contraintes numériques/string/array\n// - `required` (vérification de présence des clés)\n// - `allOf` (toutes les entrées doivent matcher — récursion) [2.1]\n// - `anyOf` (au moins une entrée doit matcher — récursion) [2.2]\n// - `oneOf` (exactement une entrée doit matcher — récursion) [2.3]\n// - `not` (inversion du résultat — récursion) [2.4]\n// - Propriétés imbriquées (nested objects — récursion) [2.5]\n// - `format` via `validateFormat` de `format-validator.ts` [2.6]\n//\n// Utilise lodash massivement :\n// - `_.has` / `_.get` pour l'accès sûr aux propriétés\n// - `_.every` / `_.some` pour les prédicats sur les collections\n// - `_.union` / `_.uniq` pour la fusion de tableaux (required, deps)\n// - `_.isArray` / `_.isPlainObject` pour le typage des valeurs\n// - `_.mapValues` pour transformer les propriétés\n// - `_.omit` / `_.pick` pour sélectionner/exclure des clés\n// - `_.keys` / `_.forEach` pour l'itération\n// - `_.reduce` pour accumuler les résultats\n// - `_.isEqual` pour la comparaison profonde\n// - `_.size` / `_.filter` pour le comptage (oneOf)\n\n// ─── Keywords classification ─────────────────────────────────────────────────\n\n/** Mots-clés qui ne doivent pas être traités par la boucle générique de mergeBranchInto */\nconst SPECIAL_MERGE_KEYS = new Set([\"required\", \"properties\", \"dependencies\"]);\n\n/** Mots-clés contenant un sous-schema unique (mergeable via engine.merge) */\nconst SUB_SCHEMA_KEYS = new Set([\n\t\"additionalProperties\",\n\t\"items\",\n\t\"contains\",\n\t\"propertyNames\",\n\t\"not\",\n]);\n\n/** Mots-clés numériques de type \"minimum\" (prendre le max pour être plus restrictif) */\nconst MIN_KEYS = new Set([\n\t\"minimum\",\n\t\"exclusiveMinimum\",\n\t\"minLength\",\n\t\"minItems\",\n\t\"minProperties\",\n]);\n\n/** Mots-clés numériques de type \"maximum\" (prendre le min pour être plus restrictif) */\nconst MAX_KEYS = new Set([\n\t\"maximum\",\n\t\"exclusiveMaximum\",\n\t\"maxLength\",\n\t\"maxItems\",\n\t\"maxProperties\",\n]);\n\n// ─── Condition evaluation (internal) ─────────────────────────────────────────\n\n/**\n * Vérifie si `value` correspond à un type JSON Schema.\n */\nfunction matchesType(value: unknown, type: JSONSchema7[\"type\"]): boolean {\n\tif (type === undefined) return true;\n\n\tconst types = Array.isArray(type) ? type : [type];\n\tconst actualType = inferType(value);\n\n\treturn types.some(\n\t\t(t) => t === actualType || (t === \"number\" && actualType === \"integer\"),\n\t);\n}\n\n/**\n * Évalue une contrainte numérique sur une valeur.\n * Point 5 — Enrichissement de evaluateCondition.\n */\nfunction evaluateNumericConstraints(value: number, prop: JSONSchema7): boolean {\n\tif (prop.minimum !== undefined && !(value >= prop.minimum)) return false;\n\tif (prop.maximum !== undefined && !(value <= prop.maximum)) return false;\n\tif (\n\t\tprop.exclusiveMinimum !== undefined &&\n\t\t!(value > (prop.exclusiveMinimum as number))\n\t)\n\t\treturn false;\n\tif (\n\t\tprop.exclusiveMaximum !== undefined &&\n\t\t!(value < (prop.exclusiveMaximum as number))\n\t)\n\t\treturn false;\n\tif (prop.multipleOf !== undefined && value % prop.multipleOf !== 0)\n\t\treturn false;\n\treturn true;\n}\n\n/**\n * Évalue une contrainte string sur une valeur.\n * Point 5 — Enrichissement de evaluateCondition.\n */\n/** Cache for compiled RegExp patterns used in evaluateStringConstraints */\nconst patternRegexCache = new Map<string, RegExp>();\n\nfunction getOrCompileRegex(pattern: string): RegExp {\n\tlet regex = patternRegexCache.get(pattern);\n\tif (regex === undefined) {\n\t\tregex = new RegExp(pattern);\n\t\tpatternRegexCache.set(pattern, regex);\n\t}\n\treturn regex;\n}\n\nfunction evaluateStringConstraints(value: string, prop: JSONSchema7): boolean {\n\tif (prop.minLength !== undefined && !(value.length >= prop.minLength))\n\t\treturn false;\n\tif (prop.maxLength !== undefined && !(value.length <= prop.maxLength))\n\t\treturn false;\n\tif (\n\t\tprop.pattern !== undefined &&\n\t\t!getOrCompileRegex(prop.pattern).test(value)\n\t)\n\t\treturn false;\n\treturn true;\n}\n\n/**\n * Évalue une contrainte array sur une valeur.\n * Point 5 — Enrichissement de evaluateCondition.\n */\nfunction evaluateArrayConstraints(\n\tvalue: unknown[],\n\tprop: JSONSchema7,\n): boolean {\n\tif (prop.minItems !== undefined && !(value.length >= prop.minItems))\n\t\treturn false;\n\tif (prop.maxItems !== undefined && !(value.length <= prop.maxItems))\n\t\treturn false;\n\tif (prop.uniqueItems === true) {\n\t\t// Vérifier l'unicité via deepEqual pour les éléments non-primitifs\n\t\t// Optimisation : double boucle sans slice pour éviter les allocations\n\t\tconst len = value.length;\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tfor (let j = i + 1; j < len; j++) {\n\t\t\t\tif (deepEqual(value[i], value[j])) return false;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Évalue si des données partielles satisfont un `if` schema.\n *\n * Stratégie pragmatique (pas un validateur complet) :\n * - Vérifie les `properties` avec `const`, `enum`, `type`\n * - Point 5 : Vérifie aussi minimum/maximum, minLength/maxLength,\n * pattern, multipleOf, minItems/maxItems, uniqueItems\n * - Vérifie les `required`\n * - 2.1 : `allOf` → toutes les entrées doivent matcher (récursion)\n * - 2.2 : `anyOf` → au moins une entrée doit matcher (récursion)\n * - 2.3 : `oneOf` → exactement une entrée doit matcher (récursion)\n * - 2.4 : `not` → inversion du résultat (récursion)\n * - 2.5 : Propriétés imbriquées → récursion sur les sous-objets\n * - 2.6 : `format` → validation via `validateFormat`\n *\n * Utilise `_.forEach` / `_.every` / `_.has` pour une itération idiomatique.\n */\nfunction evaluateCondition(\n\tifSchema: JSONSchema7,\n\tdata: Record<string, unknown>,\n): boolean {\n\tif (isPlainObj(ifSchema.properties)) {\n\t\tconst propsOk = Object.keys(ifSchema.properties).every((key) => {\n\t\t\tconst propDef = ifSchema.properties?.[key];\n\t\t\tif (typeof propDef === \"boolean\") return true;\n\t\t\tconst prop = propDef as JSONSchema7;\n\t\t\tconst value = data[key];\n\n\t\t\t// ── Propriété absente → skip ──\n\t\t\t// Selon la spec JSON Schema Draft-07, le keyword `properties` ne valide\n\t\t\t// une propriété que si elle est **présente** dans l'instance.\n\t\t\t// C'est le keyword `required` qui gère la présence obligatoire.\n\t\t\tif (value === undefined) return true;\n\n\t\t\t// ── const ──\n\t\t\tif (hasOwn(prop, \"const\")) {\n\t\t\t\tif (!deepEqual(value, prop.const)) return false;\n\t\t\t}\n\n\t\t\t// ── enum ──\n\t\t\tif (hasOwn(prop, \"enum\")) {\n\t\t\t\tif (!prop.enum?.some((v) => deepEqual(v, value))) return false;\n\t\t\t}\n\n\t\t\t// ── type ──\n\t\t\tif (hasOwn(prop, \"type\") && value !== undefined) {\n\t\t\t\tif (!matchesType(value, prop.type)) return false;\n\t\t\t}\n\n\t\t\t// ── Point 5 : Contraintes numériques/string/array ──\n\t\t\t// Quand `value` est `undefined`, aucun de ces blocs ne s'exécute\n\t\t\t// (`typeof undefined` vaut `\"undefined\"`, pas `\"number\"` ni `\"string\"`,\n\t\t\t// et `isArray(undefined)` retourne `false`).\n\t\t\t// C'est le comportement voulu : on ne peut pas évaluer une contrainte\n\t\t\t// sur une donnée absente → on skip, cohérent avec la logique pragmatique.\n\t\t\tif (typeof value === \"number\") {\n\t\t\t\tif (!evaluateNumericConstraints(value, prop)) return false;\n\t\t\t}\n\n\t\t\tif (typeof value === \"string\") {\n\t\t\t\tif (!evaluateStringConstraints(value, prop)) return false;\n\t\t\t}\n\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\tif (!evaluateArrayConstraints(value as unknown[], prop)) return false;\n\t\t\t}\n\n\t\t\t// ── 2.6 — format ──\n\t\t\t// Valide la valeur contre le format via class-validator.\n\t\t\t// Le format ne s'applique qu'aux strings en Draft-07.\n\t\t\t// Si le format est inconnu → skip (retourne null → on continue).\n\t\t\tif (prop.format !== undefined && typeof value === \"string\") {\n\t\t\t\tconst formatResult = validateFormat(value, prop.format);\n\t\t\t\tif (formatResult === false) return false;\n\t\t\t\t// null (format inconnu) → skip, cohérent avec l'approche pragmatique\n\t\t\t}\n\n\t\t\t// ── 2.5 — Propriétés imbriquées (nested objects) ──\n\t\t\t// Si la propriété elle-même a des `properties` ou un `required`,\n\t\t\t// et que la valeur dans data est un objet, récurser dans evaluateCondition\n\t\t\t// en passant la sous-donnée comme nouveau `data`.\n\t\t\t// Si data[key] n'est pas un objet, on skip (retourne true pour cette prop,\n\t\t\t// cohérent avec \"absence = pas de contrainte\").\n\t\t\tif (isPlainObj(prop.properties) || Array.isArray(prop.required)) {\n\t\t\t\tif (isPlainObj(value)) {\n\t\t\t\t\tif (!evaluateCondition(prop, value as Record<string, unknown>)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// value n'est pas un objet → skip, on ne peut pas évaluer les sous-props\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\t\tif (!propsOk) return false;\n\t}\n\n\t// ── required ──\n\tif (Array.isArray(ifSchema.required)) {\n\t\tconst allRequired = ifSchema.required.every((key) =>\n\t\t\thasOwn(data, key as string),\n\t\t);\n\t\tif (!allRequired) return false;\n\t}\n\n\t// ── 2.1 — allOf ──\n\t// Toutes les entrées du allOf doivent matcher (évaluation récursive).\n\tif (Array.isArray(ifSchema.allOf)) {\n\t\tconst allMatch = ifSchema.allOf.every((entry) => {\n\t\t\tif (typeof entry === \"boolean\") return entry;\n\t\t\treturn evaluateCondition(entry as JSONSchema7, data);\n\t\t});\n\t\tif (!allMatch) return false;\n\t}\n\n\t// ── 2.2 — anyOf ──\n\t// Au moins une entrée du anyOf doit matcher (évaluation récursive).\n\tif (Array.isArray(ifSchema.anyOf)) {\n\t\tconst anyMatch = ifSchema.anyOf.some((entry) => {\n\t\t\tif (typeof entry === \"boolean\") return entry;\n\t\t\treturn evaluateCondition(entry as JSONSchema7, data);\n\t\t});\n\t\tif (!anyMatch) return false;\n\t}\n\n\t// ── 2.3 — oneOf ──\n\t// Exactement une entrée du oneOf doit matcher (évaluation récursive).\n\tif (Array.isArray(ifSchema.oneOf)) {\n\t\tlet matchCount = 0;\n\t\tfor (const entry of ifSchema.oneOf) {\n\t\t\tconst matches =\n\t\t\t\ttypeof entry === \"boolean\"\n\t\t\t\t\t? entry\n\t\t\t\t\t: evaluateCondition(entry as JSONSchema7, data);\n\t\t\tif (matches) matchCount++;\n\t\t\tif (matchCount > 1) break;\n\t\t}\n\t\tif (matchCount !== 1) return false;\n\t}\n\n\t// ── 2.4 — not ──\n\t// Inverser le résultat de l'évaluation du contenu du `not`.\n\tif (\n\t\thasOwn(ifSchema, \"not\") &&\n\t\tisPlainObj(ifSchema.not) &&\n\t\ttypeof ifSchema.not !== \"boolean\"\n\t) {\n\t\tconst notResult = evaluateCondition(ifSchema.not as JSONSchema7, data);\n\t\tif (notResult) return false; // Le not matche → la condition not ne matche pas\n\t}\n\n\treturn true;\n}\n\n// ─── Discriminant extraction ─────────────────────────────────────────────────\n\n/**\n * Mots-clés qui indiquent qu'une propriété est un discriminant\n * (sa valeur dans les données est utilisée pour la résolution).\n *\n * Point 5 — Étendu avec les contraintes numériques/string/pattern.\n */\nconst DISCRIMINANT_INDICATORS = [\n\t\"const\",\n\t\"enum\",\n\t\"minimum\",\n\t\"maximum\",\n\t\"exclusiveMinimum\",\n\t\"exclusiveMaximum\",\n\t\"pattern\",\n\t\"minLength\",\n\t\"maxLength\",\n\t\"multipleOf\",\n\t\"minItems\",\n\t\"maxItems\",\n\t\"format\",\n] as const;\n\n/**\n * Extrait les valeurs discriminantes utilisées dans un `if` schema\n * depuis les données partielles.\n *\n * Point 5 — Collecte aussi les discriminants pour les nouvelles contraintes\n * (minimum, maximum, pattern, etc.).\n *\n * Utilise `_.some` pour vérifier qu'au moins un indicateur est présent,\n * et `_.has` pour un accès sûr.\n */\nfunction extractDiscriminants(\n\tifSchema: JSONSchema7,\n\tdata: Record<string, unknown>,\n\tout: Record<string, unknown>,\n): void {\n\tif (!isPlainObj(ifSchema.properties)) return;\n\n\tconst props = ifSchema.properties as Record<string, JSONSchema7Definition>;\n\tfor (const key of Object.keys(props)) {\n\t\tconst propDef = props[key];\n\t\tif (typeof propDef === \"boolean\") continue;\n\t\tconst prop = propDef as JSONSchema7;\n\n\t\t// Collecter si au moins un indicateur de discriminant est présent\n\t\tconst hasIndicator = DISCRIMINANT_INDICATORS.some((indicator) =>\n\t\t\thasOwn(prop, indicator),\n\t\t);\n\n\t\tif (hasIndicator && hasOwn(data, key)) {\n\t\t\tout[key] = data[key];\n\t\t}\n\t}\n}\n\n// ─── Branch merging (deduplicated) ───────────────────────────────────────────\n\n/**\n * Merge une branche conditionnelle (`then` ou `else`) dans le schema résolu.\n *\n * Point 4 — Fix first-writer-wins :\n * Au lieu d'ignorer les keywords déjà présents dans `resolved`,\n * on tente un merge intelligent selon le type de keyword :\n *\n * - `required` → union dédupliquée via `_.union`\n * - `properties` → merge individuel via engine.merge\n * - `dependencies` → Point 3 : union des tableaux (forme 1),\n * merge des schemas (forme 2) via `_.mapValues`\n * - Sub-schema keys → merge via engine.merge\n * - Min keys → `Math.max` (plus restrictif)\n * - Max keys → `Math.min` (plus restrictif)\n * - `uniqueItems` → `true` gagne sur `false`\n * - `pattern` / `format` → la branche gagne (plus spécifique)\n * - Autres → tentative de merge via engine, sinon la branche gagne\n *\n * Utilise lodash massivement pour chaque opération de merge.\n */\nfunction mergeBranchInto(\n\tresolved: JSONSchema7,\n\tbranchDef: JSONSchema7Definition,\n\tengine: MergeEngine,\n): void {\n\tif (typeof branchDef === \"boolean\") return;\n\n\tconst branchSchema = branchDef as JSONSchema7;\n\n\t// ── Merger required via _.union (dédupliquée automatiquement) ──\n\tif (Array.isArray(branchSchema.required)) {\n\t\tresolved.required = unionStrings(\n\t\t\tresolved.required ?? [],\n\t\t\tbranchSchema.required,\n\t\t);\n\t}\n\n\t// ── Merger properties ──\n\tif (isPlainObj(branchSchema.properties)) {\n\t\tconst branchProps = branchSchema.properties as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition\n\t\t>;\n\t\tconst mergedProps: Record<string, JSONSchema7Definition> = {\n\t\t\t...(resolved.properties ?? {}),\n\t\t};\n\t\tfor (const key of Object.keys(branchProps)) {\n\t\t\tconst branchProp = branchProps[key];\n\t\t\tif (branchProp === undefined) continue;\n\t\t\tconst existing = resolved.properties?.[key];\n\t\t\tif (\n\t\t\t\texisting !== undefined &&\n\t\t\t\ttypeof existing !== \"boolean\" &&\n\t\t\t\ttypeof branchProp !== \"boolean\"\n\t\t\t) {\n\t\t\t\tconst merged = engine.merge(\n\t\t\t\t\texisting as JSONSchema7Definition,\n\t\t\t\t\tbranchProp as JSONSchema7Definition,\n\t\t\t\t);\n\t\t\t\tmergedProps[key] = (merged ?? branchProp) as JSONSchema7Definition;\n\t\t\t} else {\n\t\t\t\tmergedProps[key] = branchProp;\n\t\t\t}\n\t\t}\n\t\tresolved.properties = mergedProps;\n\t}\n\n\t// ── Merger dependencies (Point 3) ──\n\tif (isPlainObj(branchSchema.dependencies)) {\n\t\tconst resolvedDeps = (resolved.dependencies ?? {}) as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition | string[]\n\t\t>;\n\t\tconst branchDeps = branchSchema.dependencies as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition | string[]\n\t\t>;\n\n\t\tconst acc = { ...resolvedDeps };\n\t\tfor (const depKey of Object.keys(branchDeps)) {\n\t\t\tconst branchVal = branchDeps[depKey] as\n\t\t\t\t| JSONSchema7Definition\n\t\t\t\t| string[]\n\t\t\t\t| undefined;\n\t\t\tif (branchVal === undefined) continue;\n\t\t\tconst existingVal = acc[depKey] as\n\t\t\t\t| JSONSchema7Definition\n\t\t\t\t| string[]\n\t\t\t\t| undefined;\n\n\t\t\tif (existingVal === undefined) {\n\t\t\t\t// Pas de valeur existante → copier directement\n\t\t\t\tacc[depKey] = branchVal;\n\t\t\t} else if (Array.isArray(existingVal) && Array.isArray(branchVal)) {\n\t\t\t\t// Forme 1 : union dédupliquée des tableaux de strings\n\t\t\t\tacc[depKey] = unionStrings(\n\t\t\t\t\texistingVal as string[],\n\t\t\t\t\tbranchVal as string[],\n\t\t\t\t);\n\t\t\t} else if (isPlainObj(existingVal) && isPlainObj(branchVal)) {\n\t\t\t\t// Forme 2 : merge des sous-schemas\n\t\t\t\tconst merged = engine.merge(\n\t\t\t\t\texistingVal as JSONSchema7Definition,\n\t\t\t\t\tbranchVal as JSONSchema7Definition,\n\t\t\t\t);\n\t\t\t\tacc[depKey] = (merged ?? branchVal) as JSONSchema7Definition;\n\t\t\t} else {\n\t\t\t\t// Types incompatibles (tableau vs schema) → la branche gagne\n\t\t\t\tacc[depKey] = branchVal;\n\t\t\t}\n\t\t}\n\t\tresolved.dependencies = acc as Record<\n\t\t\tstring,\n\t\t\tJSONSchema7Definition | string[]\n\t\t>;\n\t}\n\n\t// ── Merger les autres mots-clés (Point 4 — fix first-writer-wins) ──\n\tfor (const key of Object.keys(branchSchema) as (keyof JSONSchema7)[]) {\n\t\t// Skip les clés déjà traitées ci-dessus\n\t\tif (SPECIAL_MERGE_KEYS.has(key)) return;\n\n\t\tconst branchVal = branchSchema[key];\n\t\tconst resolvedVal = resolved[key];\n\n\t\t// Si le resolved n'a pas cette clé → copier directement\n\t\tif (resolvedVal === undefined) {\n\t\t\t(resolved as Record<string, unknown>)[key] = branchVal;\n\t\t\treturn;\n\t\t}\n\n\t\t// Si les deux ont la même valeur → rien à faire\n\t\tif (deepEqual(resolvedVal, branchVal)) return;\n\n\t\t// ── Sub-schema keys → merge via engine ──\n\t\tif (SUB_SCHEMA_KEYS.has(key)) {\n\t\t\tconst merged = engine.merge(\n\t\t\t\tresolvedVal as JSONSchema7Definition,\n\t\t\t\tbranchVal as JSONSchema7Definition,\n\t\t\t);\n\t\t\tif (merged !== null) {\n\t\t\t\t(resolved as Record<string, unknown>)[key] = merged;\n\t\t\t} else {\n\t\t\t\t// Merge impossible → la branche gagne (contexte conditionnel)\n\t\t\t\t(resolved as Record<string, unknown>)[key] = branchVal;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// ── Min keys → Math.max (plus restrictif) ──\n\t\tif (MIN_KEYS.has(key)) {\n\t\t\tif (typeof resolvedVal === \"number\" && typeof branchVal === \"number\") {\n\t\t\t\t(resolved as Record<string, unknown>)[key] = Math.max(\n\t\t\t\t\tresolvedVal,\n\t\t\t\t\tbranchVal,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t(resolved as Record<string, unknown>)[key] = branchVal;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// ── Max keys → Math.min (plus restrictif) ──\n\t\tif (MAX_KEYS.has(key)) {\n\t\t\tif (typeof resolvedVal === \"number\" && typeof branchVal === \"number\") {\n\t\t\t\t(resolved as Record<string, unknown>)[key] = Math.min(\n\t\t\t\t\tresolvedVal,\n\t\t\t\t\tbranchVal,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t(resolved as Record<string, unknown>)[key] = branchVal;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// ── uniqueItems → true gagne sur false ──\n\t\tif (key === \"uniqueItems\") {\n\t\t\t(resolved as Record<string, unknown>)[key] =\n\t\t\t\tresolvedVal === true || branchVal === true;\n\t\t\treturn;\n\t\t}\n\n\t\t// ── pattern / format → la branche gagne (plus spécifique au contexte) ──\n\t\tif (key === \"pattern\" || key === \"format\") {\n\t\t\t(resolved as Record<string, unknown>)[key] = branchVal;\n\t\t\treturn;\n\t\t}\n\n\t\t// ── Fallback : tentative de merge via engine pour les cas restants ──\n\t\tconst base = { [key]: resolvedVal } as JSONSchema7Definition;\n\t\tconst branch = { [key]: branchVal } as JSONSchema7Definition;\n\t\tconst merged = engine.merge(base, branch);\n\t\tif (\n\t\t\tmerged &&\n\t\t\ttypeof merged !== \"boolean\" &&\n\t\t\thasOwn(merged as object, key)\n\t\t) {\n\t\t\t(resolved as Record<string, unknown>)[key] = (\n\t\t\t\tmerged as unknown as Record<string, unknown>\n\t\t\t)[key];\n\t\t} else {\n\t\t\t// Merge échoué → la branche gagne (contexte conditionnel applicable)\n\t\t\t(resolved as Record<string, unknown>)[key] = branchVal;\n\t\t}\n\t}\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Résout les `if/then/else` d'un schema en évaluant le `if` contre\n * des données partielles (discriminants).\n *\n * @param schema Le schema contenant potentiellement des if/then/else\n * @param data Données partielles utilisées pour évaluer les conditions\n * @param engine Le MergeEngine pour merger les branches\n *\n * @example\n * ```ts\n * const form = {\n * type: \"object\",\n * properties: { accountType: { type: \"string\" }, ... },\n * if: { properties: { accountType: { const: \"business\" } } },\n * then: { required: [\"companyName\"] },\n * else: { required: [\"firstName\"] },\n * };\n *\n * const { resolved } = resolveConditions(form, { accountType: \"business\" }, engine);\n * // → resolved n'a plus de if/then/else, mais a required: [\"companyName\"]\n * ```\n */\nexport function resolveConditions(\n\tschema: JSONSchema7,\n\tdata: Record<string, unknown>,\n\tengine: MergeEngine,\n): ResolvedConditionResult {\n\tlet branch: \"then\" | \"else\" | null = null;\n\tconst discriminant: Record<string, unknown> = {};\n\n\t// ── Fast path: no conditions at all ──\n\t// If there's no `if` and no `allOf` with conditions, skip the copy entirely.\n\tconst hasTopLevelIf = schema.if !== undefined;\n\tconst hasAllOfConditions =\n\t\tArray.isArray(schema.allOf) &&\n\t\tschema.allOf.some(\n\t\t\t(e) => typeof e !== \"boolean\" && hasOwn(e as object, \"if\"),\n\t\t);\n\n\tif (!hasTopLevelIf && !hasAllOfConditions) {\n\t\t// Phase 3 only: check nested properties (resolveNestedProperties\n\t\t// already returns the original if nothing changes)\n\t\tconst resolved = resolveNestedProperties(\n\t\t\tschema,\n\t\t\tdata,\n\t\t\tengine,\n\t\t\tdiscriminant,\n\t\t);\n\t\treturn { resolved, branch, discriminant };\n\t}\n\n\t// ── Copy-on-write: only copy when mutations are needed ──\n\tlet resolved = { ...schema };\n\n\t// ── Phase 1 : Résoudre les if/then/else dans allOf ──\n\tif (hasAllOfConditions) {\n\t\tresolved = resolveAllOfConditions(resolved, data, engine, discriminant);\n\t}\n\n\t// ── Phase 2 : Résoudre le if/then/else de ce niveau ──\n\tif (resolved.if !== undefined) {\n\t\tconst ifSchema = resolved.if as JSONSchema7;\n\t\tconst matches = evaluateCondition(ifSchema, data);\n\n\t\textractDiscriminants(ifSchema, data, discriminant);\n\n\t\tconst applicableBranch = matches ? resolved.then : resolved.else;\n\t\tbranch = matches ? \"then\" : \"else\";\n\n\t\tif (applicableBranch) {\n\t\t\tmergeBranchInto(\n\t\t\t\tresolved,\n\t\t\t\tapplicableBranch as JSONSchema7Definition,\n\t\t\t\tengine,\n\t\t\t);\n\t\t}\n\n\t\tdelete resolved.if;\n\t\tdelete resolved.then;\n\t\tdelete resolved.else;\n\t}\n\n\t// ── Phase 3 : Récurser dans les properties ──\n\tresolved = resolveNestedProperties(resolved, data, engine, discriminant);\n\n\treturn { resolved, branch, discriminant };\n}\n\n// ─── Internal phases ─────────────────────────────────────────────────────────\n\n/**\n * Phase 1 : Parcourt les entrées `allOf` et résout celles qui contiennent\n * un `if/then/else`. Les entrées non-conditionnelles sont préservées.\n *\n * Utilise `_.reduce` pour accumuler les entrées restantes et `_.filter`\n * pour séparer les clés conditionnelles des non-conditionnelles.\n */\nfunction resolveAllOfConditions(\n\tresolved: JSONSchema7,\n\tdata: Record<string, unknown>,\n\tengine: MergeEngine,\n\tdiscriminant: Record<string, unknown>,\n): JSONSchema7 {\n\tif (!Array.isArray(resolved.allOf)) return resolved;\n\n\tconst remainingAllOf: JSONSchema7Definition[] = [];\n\n\tfor (const entry of resolved.allOf) {\n\t\tif (typeof entry === \"boolean\") {\n\t\t\tremainingAllOf.push(entry);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst subSchema = entry as JSONSchema7;\n\n\t\tif (subSchema.if === undefined) {\n\t\t\tremainingAllOf.push(entry);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Résoudre la condition de cette entrée allOf\n\t\tconst ifSchema = subSchema.if as JSONSchema7;\n\t\tconst matches = evaluateCondition(ifSchema, data);\n\n\t\textractDiscriminants(ifSchema, data, discriminant);\n\n\t\tconst applicableBranch = matches ? subSchema.then : subSchema.else;\n\n\t\tif (applicableBranch) {\n\t\t\tmergeBranchInto(\n\t\t\t\tresolved,\n\t\t\t\tapplicableBranch as JSONSchema7Definition,\n\t\t\t\tengine,\n\t\t\t);\n\t\t}\n\n\t\t// Garder les parties non-conditionnelles de l'entrée allOf\n\t\tconst remaining = omitKeys(\n\t\t\tsubSchema as unknown as Record<string, unknown>,\n\t\t\t[\"if\", \"then\", \"else\"],\n\t\t);\n\t\tif (Object.keys(remaining).length > 0) {\n\t\t\tremainingAllOf.push(remaining as JSONSchema7);\n\t\t}\n\t}\n\n\tresolved = { ...resolved };\n\tif (remainingAllOf.length === 0) {\n\t\tdelete resolved.allOf;\n\t} else {\n\t\tresolved.allOf = remainingAllOf;\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Phase 3 : Récurse dans les `properties` du schema résolu pour résoudre\n * les conditions imbriquées (ex: un objet dont une propriété a un if/then/else).\n *\n * Utilise `_.mapValues` pour transformer chaque propriété en une seule passe,\n * et `_.forEach` pour remonter les discriminants imbriqués.\n */\nfunction resolveNestedProperties(\n\tresolved: JSONSchema7,\n\tdata: Record<string, unknown>,\n\tengine: MergeEngine,\n\tdiscriminant: Record<string, unknown>,\n): JSONSchema7 {\n\tif (!isPlainObj(resolved.properties)) return resolved;\n\n\tconst props = resolved.properties as Record<string, JSONSchema7Definition>;\n\tconst propKeys = Object.keys(props);\n\tlet changed = false;\n\tconst resolvedProps: Record<string, JSONSchema7Definition> = {};\n\n\tfor (const key of propKeys) {\n\t\tconst propDef = props[key];\n\t\tif (propDef === undefined) continue;\n\t\tif (typeof propDef === \"boolean\") {\n\t\t\tresolvedProps[key] = propDef;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst propSchema = propDef as JSONSchema7;\n\t\tconst hasConditions =\n\t\t\tpropSchema.if !== undefined ||\n\t\t\t(Array.isArray(propSchema.allOf) &&\n\t\t\t\tpropSchema.allOf.some(\n\t\t\t\t\t(e) => typeof e !== \"boolean\" && hasOwn(e as object, \"if\"),\n\t\t\t\t));\n\n\t\tif (!hasConditions) {\n\t\t\tresolvedProps[key] = propDef;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Données imbriquées disponibles → résoudre récursivement\n\t\tconst nestedData = isPlainObj(data[key])\n\t\t\t? (data[key] as Record<string, unknown>)\n\t\t\t: {};\n\n\t\tconst nested = resolveConditions(propSchema, nestedData, engine);\n\n\t\t// Remonter les discriminants imbriqués avec prefix\n\t\tfor (const dk of Object.keys(nested.discriminant)) {\n\t\t\tdiscriminant[`${key}.${dk}`] = nested.discriminant[dk];\n\t\t}\n\n\t\tresolvedProps[key] = nested.resolved;\n\t\tchanged = true;\n\t}\n\n\treturn changed ? { ...resolved, properties: resolvedProps } : resolved;\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "472160296CD0458364756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import k from"randexp";var V=200,q=100,K=20,Y=new Map,w=new Map,H=new Map;function _(){Y.clear(),w.clear(),H.clear()}var I=new Set([".*",".+","^.*$","^.+$","^.*",".*$","^.+",".+$","(?:.*)","(?:.+)"]);function y(J){let z=H.get(J);if(z!==void 0)return z;try{let Q=new k(J);return Q.max=K,H.set(J,Q),Q}catch{return H.set(J,null),null}}function B(J){let z=w.get(J);if(z!==void 0)return z;try{let Q=new RegExp(J);return w.set(J,Q),Q}catch{return w.set(J,null),null}}function L(J){let z=J.trim();if(z===""||I.has(z))return!0;if(z==="^(.*)$"||z==="^(.+)$")return!0;return!1}function U(J,z){if(L(z))return!0;return null}function O(J,z,Q=V){if(J===z)return!0;let W=`${J}\x00${z}\x00${Q}`,Z=Y.get(W);if(Z!==void 0)return Z;let F=U(J,z);if(F!==null)return Y.set(W,F),F;let $=B(z);if($===null)return Y.set(W,null),null;let f=y(J);if(f===null)return Y.set(W,null),null;let D=new Set,X=0,G=0,M=Q*3;while(X<Q&&G<M){G++;let j=f.gen();if(typeof j!=="string"||j.length>q)continue;if(D.has(j))continue;if(D.add(j),X++,!$.test(j))return Y.set(W,!1),!1}if(X===0)return Y.set(W,null),null;return Y.set(W,!0),!0}function R(J,z,Q=V){if(J===z)return!0;let W=O(J,z,Q);if(W===null)return null;if(W===!1)return!1;let Z=O(z,J,Q);if(Z===null)return null;return Z}function v(J){let z=J.trim();if(z==="")return!0;return I.has(z)}
|
|
2
|
-
export{_ as
|
|
2
|
+
export{_ as g,O as h,R as i,v as j};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
5
|
-
//# sourceMappingURL=chunk-
|
|
4
|
+
//# debugId=E5FA63FE2567424D64756E2164756E21
|
|
5
|
+
//# sourceMappingURL=chunk-q7kq4fgq.js.map
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"import RandExp from \"randexp\";\n\n// ─── Pattern Subset Checker ──────────────────────────────────────────────────\n//\n// Vérifie si un pattern regex est un sous-ensemble d'un autre pattern regex\n// via une approche par échantillonnage (sampling).\n//\n// Principe :\n// L(A) ⊆ L(B) ⟺ ∀s ∈ L(A), s ∈ L(B)\n//\n// On ne peut pas prouver ça formellement pour des regex ECMA-262 arbitraires\n// (le problème est PSPACE-complet pour les regex pures, et indécidable avec\n// les extensions comme les backreferences).\n//\n// Approche pragmatique :\n// 1. Générer N strings aléatoires matchant le pattern sub (via `randexp`)\n// 2. Vérifier que CHAQUE string matche aussi le pattern sup\n// 3. Si toutes matchent → retourner `true` (confiance haute)\n// 4. Si au moins une ne matche pas → retourner `false` (certain)\n// 5. Si la génération échoue → retourner `null` (indéterminé)\n//\n// Limites :\n// - Faux positifs possibles (mais très improbables avec N suffisant)\n// - Ne gère pas les regex avec backreferences complexes\n// - `randexp` peut générer des strings biaisées (pas uniformément distribuées)\n//\n// Pour mitiger les faux positifs, on utilise :\n// - Un nombre d'échantillons élevé (200 par défaut)\n// - Plusieurs seeds pour diversifier la génération\n// - Un fallback `null` en cas de doute\n\n// ─── Configuration ───────────────────────────────────────────────────────────\n\n/** Nombre d'échantillons générés par défaut */\nconst DEFAULT_SAMPLE_COUNT = 200;\n\n/** Longueur maximale des strings générées par randexp */\nconst MAX_GENERATED_LENGTH = 100;\n\n/** Nombre maximal de répétitions pour les quantificateurs unbounded (*, +, {n,}) */\nconst MAX_REPETITION = 20;\n\n// ─── Result Cache ────────────────────────────────────────────────────────────\n\n/**\n * Cache des résultats de isPatternSubset pour éviter de recalculer\n * les mêmes comparaisons. La clé est `${subPattern}\\0${supPattern}\\0${sampleCount}`.\n */\nconst subsetCache = new Map<string, boolean | null>();\n\n/**\n * Cache des résultats de compilation RegExp pour éviter les recompilations.\n */\nconst regexCache = new Map<string, RegExp | null>();\n\n/**\n * Cache des générateurs RandExp pour éviter les re-créations.\n */\nconst generatorCache = new Map<string, RandExp | null>();\n\n/**\n * Vide les caches internes. Utile pour les tests ou la gestion mémoire.\n */\nexport function clearPatternCaches(): void {\n\tsubsetCache.clear();\n\tregexCache.clear();\n\tgeneratorCache.clear();\n}\n\n// ─── Trivial pattern detection (module-level constants) ──────────────────────\n\n/**\n * Patterns universels connus — matchent toute string (ou presque).\n * Défini au niveau du module pour éviter de recréer le Set à chaque appel.\n */\nconst UNIVERSAL_PATTERNS: ReadonlySet<string> = new Set([\n\t\".*\",\n\t\".+\",\n\t\"^.*$\",\n\t\"^.+$\",\n\t\"^.*\",\n\t\".*$\",\n\t\"^.+\",\n\t\".+$\",\n\t\"(?:.*)\",\n\t\"(?:.+)\",\n]);\n\n/**\n * Patterns anchored universal — variantes fréquentes qui matchent tout.\n * Utilisé pour la détection rapide de superset universels.\n */\nconst _ANCHORED_UNIVERSAL_REGEX =\n\t/^\\^?\\(?:\\.\\*\\)?\\$?$|^\\^?\\.\\*\\$?$|^\\^?\\.\\+\\$?$/;\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\n/**\n * Crée un générateur RandExp configuré pour un pattern donné (avec cache).\n *\n * @param pattern Le pattern regex source\n * @returns L'instance RandExp configurée, ou null si le pattern est invalide\n */\nfunction createGenerator(pattern: string): RandExp | null {\n\tconst cached = generatorCache.get(pattern);\n\tif (cached !== undefined) return cached;\n\n\ttry {\n\t\tconst randexp = new RandExp(pattern);\n\t\trandexp.max = MAX_REPETITION;\n\t\tgeneratorCache.set(pattern, randexp);\n\t\treturn randexp;\n\t} catch {\n\t\tgeneratorCache.set(pattern, null);\n\t\treturn null;\n\t}\n}\n\n/**\n * Compile un pattern en RegExp avec gestion d'erreur et cache.\n *\n * @param pattern Le pattern regex à compiler\n * @returns L'objet RegExp compilé, ou null si invalide\n */\nfunction compileRegex(pattern: string): RegExp | null {\n\tconst cached = regexCache.get(pattern);\n\tif (cached !== undefined) return cached;\n\n\ttry {\n\t\tconst regex = new RegExp(pattern);\n\t\tregexCache.set(pattern, regex);\n\t\treturn regex;\n\t} catch {\n\t\tregexCache.set(pattern, null);\n\t\treturn null;\n\t}\n}\n\n/**\n * Vérifie si un pattern est un superset universel (matche tout).\n * Utilisé pour court-circuiter le sampling quand sup matche tout.\n */\nfunction isUniversalSuperset(pattern: string): boolean {\n\tconst trimmed = pattern.trim();\n\tif (trimmed === \"\" || UNIVERSAL_PATTERNS.has(trimmed)) return true;\n\n\t// Vérifier des variantes avec anchors optionnels\n\t// Ex: \"^(.*)$\", \"^(.+)$\" etc.\n\tif (trimmed === \"^(.*)$\" || trimmed === \"^(.+)$\") return true;\n\n\treturn false;\n}\n\n/**\n * Vérifie si subPattern est un sous-string littéral de supPattern\n * ou si le sup est clairement plus large (heuristiques rapides).\n * Retourne true si sub ⊆ sup est garanti, false sinon.\n */\nfunction quickSubsetCheck(\n\t_subPattern: string,\n\tsupPattern: string,\n): boolean | null {\n\t// Si sup est universel → tout est un sous-ensemble\n\tif (isUniversalSuperset(supPattern)) return true;\n\n\t// Si sub est un pattern littéral exact (anchored string sans métacaractères)\n\t// et que sup contient une classe de caractères ou quantificateur qui l'englobe,\n\t// on ne peut pas le déterminer facilement → null\n\treturn null;\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Vérifie si le langage du pattern `sub` est un sous-ensemble du langage\n * du pattern `sup` via échantillonnage.\n *\n * `sub ⊆ sup` signifie : toute string matchant `sub` matche aussi `sup`.\n *\n * Contrat ternaire :\n * - `true` → toutes les strings échantillonnées de sub matchent sup\n * (confiance haute, pas une preuve formelle)\n * - `false` → au moins une string de sub ne matche PAS sup\n * (certain — c'est un contre-exemple concret)\n * - `null` → impossible de déterminer (pattern invalide, génération échouée)\n *\n * @param subPattern Le pattern regex du schema sub\n * @param supPattern Le pattern regex du schema sup\n * @param sampleCount Nombre d'échantillons (défaut: 200)\n * @returns `true`, `false`, ou `null`\n *\n * @example\n * ```ts\n * isPatternSubset(\"^[a-z]{3}$\", \"^[a-z]+$\"); // true — 3 lettres ⊆ 1+ lettres\n * isPatternSubset(\"^[a-z]+$\", \"^[0-9]+$\"); // false — lettres ⊄ chiffres\n * isPatternSubset(\"^[a-z]+$\", \"^[a-z]{3}$\"); // false — \"ab\" matche sub mais pas sup\n * isPatternSubset(\"invalid[\", \"^[a-z]+$\"); // null — pattern invalide\n * ```\n */\nexport function isPatternSubset(\n\tsubPattern: string,\n\tsupPattern: string,\n\tsampleCount: number = DEFAULT_SAMPLE_COUNT,\n): boolean | null {\n\t// ── Identité : même pattern → toujours subset ──\n\tif (subPattern === supPattern) return true;\n\n\t// ── Cache lookup ──\n\tconst cacheKey = `${subPattern}\\0${supPattern}\\0${sampleCount}`;\n\tconst cached = subsetCache.get(cacheKey);\n\tif (cached !== undefined) return cached;\n\n\t// ── Quick checks avant le sampling ──\n\tconst quick = quickSubsetCheck(subPattern, supPattern);\n\tif (quick !== null) {\n\t\tsubsetCache.set(cacheKey, quick);\n\t\treturn quick;\n\t}\n\n\t// ── Compiler le pattern sup ──\n\tconst supRegex = compileRegex(supPattern);\n\tif (supRegex === null) {\n\t\tsubsetCache.set(cacheKey, null);\n\t\treturn null;\n\t}\n\n\t// ── Créer le générateur pour sub ──\n\tconst generator = createGenerator(subPattern);\n\tif (generator === null) {\n\t\tsubsetCache.set(cacheKey, null);\n\t\treturn null;\n\t}\n\n\t// ── Générer et vérifier les échantillons paresseusement ──\n\t// Au lieu de générer tous les échantillons d'abord puis les vérifier,\n\t// on génère et vérifie un par un pour permettre un arrêt précoce\n\t// dès qu'un contre-exemple est trouvé.\n\tconst seen = new Set<string>();\n\tlet validSamples = 0;\n\tlet attempts = 0;\n\tconst maxAttempts = sampleCount * 3; // Éviter les boucles infinies\n\n\twhile (validSamples < sampleCount && attempts < maxAttempts) {\n\t\tattempts++;\n\t\tconst sample = generator.gen();\n\n\t\t// Valider que l'échantillon est utilisable\n\t\tif (typeof sample !== \"string\" || sample.length > MAX_GENERATED_LENGTH) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Dédupliquer les échantillons\n\t\tif (seen.has(sample)) {\n\t\t\tcontinue;\n\t\t}\n\t\tseen.add(sample);\n\t\tvalidSamples++;\n\n\t\t// ── Vérification immédiate contre sup ──\n\t\t// Arrêt précoce dès qu'un contre-exemple est trouvé\n\t\tif (!supRegex.test(sample)) {\n\t\t\t// Contre-exemple trouvé → sub ⊄ sup (certain)\n\t\t\tsubsetCache.set(cacheKey, false);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Si aucun échantillon n'a pu être généré → indéterminé\n\tif (validSamples === 0) {\n\t\tsubsetCache.set(cacheKey, null);\n\t\treturn null;\n\t}\n\n\t// Tous les échantillons matchent → sub ⊆ sup (confiance haute)\n\tsubsetCache.set(cacheKey, true);\n\treturn true;\n}\n\n/**\n * Vérifie si deux patterns sont équivalents (acceptent le même langage)\n * via échantillonnage bidirectionnel.\n *\n * `A ≡ B` signifie : `A ⊆ B` ET `B ⊆ A`.\n *\n * @param patternA Premier pattern regex\n * @param patternB Second pattern regex\n * @param sampleCount Nombre d'échantillons par direction (défaut: 200)\n * @returns `true`, `false`, ou `null`\n */\nexport function arePatternsEquivalent(\n\tpatternA: string,\n\tpatternB: string,\n\tsampleCount: number = DEFAULT_SAMPLE_COUNT,\n): boolean | null {\n\tif (patternA === patternB) return true;\n\n\tconst aSubB = isPatternSubset(patternA, patternB, sampleCount);\n\tif (aSubB === null) return null;\n\tif (aSubB === false) return false;\n\n\tconst bSubA = isPatternSubset(patternB, patternA, sampleCount);\n\tif (bSubA === null) return null;\n\n\treturn bSubA;\n}\n\n/**\n * Vérifie si un pattern est \"trivially universal\" — i.e., il matche\n * toute string (ou presque). Utile pour détecter les patterns qui\n * n'ajoutent aucune contrainte réelle.\n *\n * Patterns détectés comme universels :\n * - `.*`\n * - `.+` (matche tout sauf la string vide)\n * - `^.*$`\n * - `^.+$`\n * - Patterns vides ou whitespace\n *\n * @param pattern Le pattern à vérifier\n * @returns `true` si le pattern est trivial/universel\n */\nexport function isTrivialPattern(pattern: string): boolean {\n\tconst trimmed = pattern.trim();\n\tif (trimmed === \"\") return true;\n\n\treturn UNIVERSAL_PATTERNS.has(trimmed);\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "E5FA63FE2567424D64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
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 G(j,w){let z=[`${w.isSubset?"✅":"❌"} ${j}: ${w.isSubset}`];if(!w.isSubset&&w.diffs.length>0){z.push(" Diffs:");for(let A of w.diffs)z.push(` ${B(A)}`)}return z.join(`
|
|
2
|
+
`)}
|
|
3
|
+
export{G as m};
|
|
4
|
+
|
|
5
|
+
//# debugId=A2490CE4A5AB928D64756E2164756E21
|
|
6
|
+
//# sourceMappingURL=chunk-y8c2z1m3.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/formatter.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { SubsetResult } from \"./types\";\n\n// ─── Result Formatter ────────────────────────────────────────────────────────\n//\n// Formate un `SubsetResult` en chaîne lisible pour logs / debug.\n\n/**\n * Formate un diff individuel en ligne lisible avec préfixe iconique.\n *\n * @param d Le diff à formater\n * @returns Ligne formatée avec +, - ou ~ selon le type\n */\nfunction formatDiffLine(d: {\n\ttype: string;\n\tpath: string;\n\texpected: unknown;\n\tactual: unknown;\n}): string {\n\tswitch (d.type) {\n\t\tcase \"added\":\n\t\t\treturn ` + ${d.path}: ${JSON.stringify(d.actual)}`;\n\t\tcase \"removed\":\n\t\t\treturn ` - ${d.path}: was ${JSON.stringify(d.expected)}`;\n\t\tdefault:\n\t\t\treturn ` ~ ${d.path}: ${JSON.stringify(d.expected)} → ${JSON.stringify(d.actual)}`;\n\t}\n}\n\n/**\n * Formate un SubsetResult en chaîne lisible (utile pour logs/debug).\n *\n * @param label Label descriptif du check (ex: \"strict ⊆ loose\")\n * @param result Le résultat du check à formater\n * @returns Chaîne multi-lignes formatée avec icônes et diffs\n *\n * @example\n * ```\n * ✅ strict ⊆ loose: true\n * ```\n *\n * @example\n * ```\n * ❌ loose ⊆ strict: false\n * Diffs:\n * ~ required: [\"name\"] → [\"name\",\"age\"]\n * + properties.age: {\"type\":\"number\"}\n * ```\n */\nexport function formatResult(label: string, result: SubsetResult): string {\n\tconst icon = result.isSubset ? \"✅\" : \"❌\";\n\tconst lines: string[] = [`${icon} ${label}: ${result.isSubset}`];\n\n\tif (!result.isSubset && result.diffs.length > 0) {\n\t\tlines.push(\" Diffs:\");\n\n\t\tfor (const d of result.diffs) {\n\t\t\tlines.push(` ${formatDiffLine(d)}`);\n\t\t}\n\t}\n\n\treturn lines.join(\"\\n\");\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "AAYA,SAAS,CAAc,CAAC,EAKb,CACV,OAAQ,EAAE,UACJ,QACJ,MAAO,OAAO,EAAE,SAAS,KAAK,UAAU,EAAE,MAAM,QAC5C,UACJ,MAAO,OAAO,EAAE,aAAa,KAAK,UAAU,EAAE,QAAQ,YAEtD,MAAO,OAAO,EAAE,SAAS,KAAK,UAAU,EAAE,QAAQ,OAAM,KAAK,UAAU,EAAE,MAAM,KAwB3E,SAAS,CAAY,CAAC,EAAe,EAA8B,CAEzE,IAAM,EAAkB,CAAC,GADZ,EAAO,SAAW,IAAK,OACA,MAAU,EAAO,UAAU,EAE/D,GAAI,CAAC,EAAO,UAAY,EAAO,MAAM,OAAS,EAAG,CAChD,EAAM,KAAK,WAAW,EAEtB,QAAW,KAAK,EAAO,MACtB,EAAM,KAAK,QAAQ,EAAe,CAAC,GAAG,EAIxC,OAAO,EAAM,KAAK;AAAA,CAAI",
|
|
8
|
+
"debugId": "A2490CE4A5AB928D64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{s as q}from"./chunk-07z7fc5q.js";import{v as x,w as X,x as _}from"./chunk-jkdzdb3r.js";import{createComparator as K,createMerger as T,createShallowAllOfMerge as E}from"@x0k/json-schema-merge";import{createDeduplicator as I,createIntersector as V}from"@x0k/json-schema-merge/lib/array";function j(z,B){if(typeof z==="boolean"||typeof B==="boolean")return!1;let Q=X(z,"const"),J=X(B,"const"),U=z.const,Z=B.const,G=z.enum,Y=B.enum;if(Q&&J)return!_(U,Z);if(Q&&Array.isArray(Y))return!Y.some(($)=>_($,U));if(J&&Array.isArray(G))return!G.some(($)=>_($,Z));return!1}var F=["items","additionalProperties","contains","propertyNames","not"],M=["properties","patternProperties"];function v(z,B){if(j(z,B))return!0;if(typeof z==="boolean"||typeof B==="boolean")return!1;for(let Q of F){let J=z[Q],U=B[Q];if(x(J)&&x(U)&&v(J,U))return!0}for(let Q of M){let J=z[Q],U=B[Q];if(!x(J)||!x(U))continue;let Z=J,G=U;for(let Y of Object.keys(Z)){let $=Z[Y],W=G[Y];if($!==void 0&&W!==void 0&&X(G,Y)&&v($,W))return!0}}if(Array.isArray(z.items)&&Array.isArray(B.items)){let Q=z.items,J=B.items,U=Math.min(Q.length,J.length);for(let Z=0;Z<U;Z++){let G=Q[Z],Y=J[Z];if(G===void 0||Y===void 0)continue;if(v(G,Y))return!0}}return!1}function A(z,B){if(typeof z==="boolean"||typeof B==="boolean")return!1;let Q=x(z.properties)?z.properties:void 0,J=x(B.properties)?B.properties:void 0;if(!Q&&!J)return!1;let U=Q?Object.keys(Q):[],Z=J?Object.keys(J):[],G=Array.isArray(z.required)?z.required:[],Y=Array.isArray(B.required)?B.required:[];if(z.additionalProperties===!1&&Q&&J){if(Y.some((W)=>!X(Q,W)&&X(J,W))&&U.length>0)return!0}if(x(z.additionalProperties)&&typeof z.additionalProperties!=="boolean"&&Q&&J){let $=z.additionalProperties;if(X($,"type")){let W=$.type;if(Y.some((N)=>{if(X(Q,N))return!1;if(!X(J,N))return!1;let g=J[N];if(typeof g==="boolean")return!1;let L=g;if(!X(L,"type"))return!1;if(typeof W==="string"&&typeof L.type==="string")return W!==L.type&&!(W==="number"&&L.type==="integer")&&!(W==="integer"&&L.type==="number");return!1}))return!0}}if(B.additionalProperties===!1&&J&&Q){if(G.some((W)=>!X(J,W)&&X(Q,W))&&Z.length>0)return!0}if(x(B.additionalProperties)&&typeof B.additionalProperties!=="boolean"&&J&&Q){let $=B.additionalProperties;if(X($,"type")){let W=$.type;if(G.some((N)=>{if(X(J,N))return!1;if(!X(Q,N))return!1;let g=Q[N];if(typeof g==="boolean")return!1;let L=g;if(!X(L,"type"))return!1;if(typeof W==="string"&&typeof L.type==="string")return W!==L.type&&!(W==="number"&&L.type==="integer")&&!(W==="integer"&&L.type==="number");return!1}))return!0}}if(Q&&J)for(let $ of U){if(!X(J,$))continue;let W=Q[$],R=J[$];if(typeof W==="boolean"||typeof R==="boolean")continue;if(A(W,R))return!0}return!1}function H(z,B){if(typeof z==="boolean"||typeof B==="boolean")return!1;if(X(z,"format")&&X(B,"format")){let Q=z.format,J=B.format;if(Q!==J){if(q(Q,J)!==!0){if(q(J,Q)!==!0)return!0}}}if(x(z.properties)&&x(B.properties)){let Q=z.properties,J=B.properties;for(let U of Object.keys(Q)){let Z=Q[U],G=J[U];if(Z!==void 0&&G!==void 0&&X(J,U)&&H(Z,G))return!0}}if(x(z.items)&&x(B.items)){if(H(z.items,B.items))return!0}if(x(z.additionalProperties)&&x(B.additionalProperties)){if(H(z.additionalProperties,B.additionalProperties))return!0}return!1}class u{compareFn;shallowAllOfMergeFn;constructor(){let{compareSchemaDefinitions:z,compareSchemaValues:B}=K(),Q=(U,Z)=>{if(U===null&&Z===null)return 0;return B(U,Z)},{mergeArrayOfSchemaDefinitions:J}=T({intersectJson:V(Q),deduplicateJsonSchemaDef:I(z)});this.compareFn=z,this.shallowAllOfMergeFn=E(J)}merge(z,B){if(v(z,B))return null;if(H(z,B))return null;if(A(z,B))return null;try{return this.shallowAllOfMergeFn({allOf:[z,B]})}catch{return null}}mergeOrThrow(z,B){if(v(z,B))throw Error("Incompatible const values: schemas have conflicting const constraints");if(H(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{u as n};
|
|
3
|
+
|
|
4
|
+
//# debugId=4666F85E3B6FD5BA64756E2164756E21
|
|
5
|
+
//# sourceMappingURL=chunk-yg81ax5m.js.map
|