json-schema-compatibility-checker 1.0.6 → 1.0.7
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/README.md +119 -151
- package/dist/cjs/condition-resolver.js.map +1 -1
- package/dist/cjs/data-narrowing.d.ts +31 -0
- package/dist/cjs/data-narrowing.js +2 -0
- package/dist/cjs/data-narrowing.js.map +1 -0
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/json-schema-compatibility-checker.d.ts +39 -26
- package/dist/cjs/json-schema-compatibility-checker.js +1 -1
- package/dist/cjs/json-schema-compatibility-checker.js.map +1 -1
- package/dist/cjs/merge-engine.js.map +1 -1
- package/dist/cjs/types.d.ts +19 -3
- package/dist/esm/condition-resolver.js.map +1 -1
- package/dist/esm/data-narrowing.d.ts +31 -0
- package/dist/esm/data-narrowing.js +2 -0
- package/dist/esm/data-narrowing.js.map +1 -0
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/json-schema-compatibility-checker.d.ts +39 -26
- package/dist/esm/json-schema-compatibility-checker.js +1 -1
- package/dist/esm/json-schema-compatibility-checker.js.map +1 -1
- package/dist/esm/merge-engine.js.map +1 -1
- package/dist/esm/types.d.ts +19 -3
- package/dist/esm/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
- [`check(sub, sup)`](#checksub-sup)
|
|
16
16
|
- [`isEqual(a, b)`](#isequala-b)
|
|
17
17
|
- [`intersect(a, b)`](#intersecta-b)
|
|
18
|
-
- [`canConnect(sourceOutput, targetInput)`](#canconnectsourceoutput-targetinput)
|
|
19
18
|
- [`resolveConditions(schema, data)`](#resolveconditionsschema-data)
|
|
20
|
-
- [`
|
|
19
|
+
- [`check(sub, sup, options)`](#checksub-sup-options)
|
|
21
20
|
- [`normalize(schema)`](#normalizeschema)
|
|
22
21
|
- [`formatResult(label, result)`](#formatresultlabel-result)
|
|
23
22
|
- [Guide des fonctionnalités](#guide-des-fonctionnalités)
|
|
@@ -203,22 +202,24 @@ checker.isSubset({ type: "string" }, true); // → true
|
|
|
203
202
|
|
|
204
203
|
```ts
|
|
205
204
|
check(sub: JSONSchema7Definition, sup: JSONSchema7Definition): SubsetResult
|
|
205
|
+
check(sub: JSONSchema7Definition, sup: JSONSchema7Definition, options: CheckConditionsOptions): ResolvedSubsetResult
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
-
Comme `isSubset`, mais retourne un **résultat détaillé** avec les
|
|
208
|
+
Comme `isSubset`, mais retourne un **résultat détaillé** avec les erreurs sémantiques.
|
|
209
|
+
|
|
210
|
+
Quand `options` est fourni, les conditions `if/then/else` sont résolues avant le check (voir [`check(sub, sup, options)`](#checksub-sup-options) plus bas).
|
|
209
211
|
|
|
210
212
|
```ts
|
|
213
|
+
interface SchemaError {
|
|
214
|
+
key: string; // Chemin normalisé (ex: "user.name", "users[].email")
|
|
215
|
+
expected: string; // Type/valeur attendu(e) par le schema cible (sup)
|
|
216
|
+
received: string; // Type/valeur reçu(e) depuis le schema source (sub)
|
|
217
|
+
}
|
|
218
|
+
|
|
211
219
|
interface SubsetResult {
|
|
212
220
|
isSubset: boolean;
|
|
213
221
|
merged: JSONSchema7Definition | null; // Résultat de l'intersection
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
interface SchemaDiff {
|
|
218
|
-
path: string; // Chemin JSON-path vers la divergence
|
|
219
|
-
type: "added" | "removed" | "changed";
|
|
220
|
-
expected: unknown; // Valeur dans le schema original (sub)
|
|
221
|
-
actual: unknown; // Valeur dans le schema mergé
|
|
222
|
+
errors: SchemaError[]; // Erreurs sémantiques
|
|
222
223
|
}
|
|
223
224
|
```
|
|
224
225
|
|
|
@@ -231,7 +232,7 @@ const result = checker.check(
|
|
|
231
232
|
);
|
|
232
233
|
|
|
233
234
|
console.log(result.isSubset); // true
|
|
234
|
-
console.log(result.
|
|
235
|
+
console.log(result.errors); // [] (aucune erreur)
|
|
235
236
|
console.log(result.merged); // { type: "string", minLength: 5 }
|
|
236
237
|
```
|
|
237
238
|
|
|
@@ -254,12 +255,13 @@ const sup = {
|
|
|
254
255
|
};
|
|
255
256
|
|
|
256
257
|
const result = checker.check(sub, sup);
|
|
258
|
+
console.log(result.errors);
|
|
259
|
+
// [{ key: "age", expected: "number", received: "undefined" }]
|
|
257
260
|
|
|
258
261
|
console.log(result.isSubset); // false
|
|
259
|
-
console.log(result.
|
|
262
|
+
console.log(result.errors);
|
|
260
263
|
// [
|
|
261
|
-
// {
|
|
262
|
-
// { path: "properties.age", type: "added", expected: undefined, actual: { type: "number" } }
|
|
264
|
+
// { key: "age", expected: "number", received: "undefined" }
|
|
263
265
|
// ]
|
|
264
266
|
```
|
|
265
267
|
|
|
@@ -270,7 +272,7 @@ const result = checker.check({ type: "string" }, { type: "number" });
|
|
|
270
272
|
|
|
271
273
|
console.log(result.isSubset); // false
|
|
272
274
|
console.log(result.merged); // null (intersection impossible)
|
|
273
|
-
console.log(result.
|
|
275
|
+
console.log(result.errors); // [{ key: "$root", expected: "number", received: "string" }]
|
|
274
276
|
```
|
|
275
277
|
|
|
276
278
|
---
|
|
@@ -363,64 +365,6 @@ checker.intersect({ type: "string" }, { type: "number" });
|
|
|
363
365
|
|
|
364
366
|
---
|
|
365
367
|
|
|
366
|
-
### `canConnect(sourceOutput, targetInput)`
|
|
367
|
-
|
|
368
|
-
```ts
|
|
369
|
-
canConnect(
|
|
370
|
-
sourceOutput: JSONSchema7Definition,
|
|
371
|
-
targetInput: JSONSchema7Definition
|
|
372
|
-
): ConnectionResult
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
Vérifie si la **sortie d'un nœud source** peut alimenter l'**entrée d'un nœud cible**. Sémantiquement : `sourceOutput ⊆ targetInput`.
|
|
376
|
-
|
|
377
|
-
```ts
|
|
378
|
-
interface ConnectionResult extends SubsetResult {
|
|
379
|
-
direction: string; // "sourceOutput ⊆ targetInput"
|
|
380
|
-
}
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
```ts
|
|
384
|
-
const nodeAOutput = {
|
|
385
|
-
type: "object",
|
|
386
|
-
properties: {
|
|
387
|
-
id: { type: "string" },
|
|
388
|
-
total: { type: "number", minimum: 0 },
|
|
389
|
-
customer: {
|
|
390
|
-
type: "object",
|
|
391
|
-
properties: {
|
|
392
|
-
email: { type: "string", format: "email" },
|
|
393
|
-
name: { type: "string" },
|
|
394
|
-
},
|
|
395
|
-
required: ["email", "name"],
|
|
396
|
-
},
|
|
397
|
-
},
|
|
398
|
-
required: ["id", "total", "customer"],
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
const nodeBInput = {
|
|
402
|
-
type: "object",
|
|
403
|
-
properties: {
|
|
404
|
-
id: { type: "string" },
|
|
405
|
-
total: { type: "number" },
|
|
406
|
-
customer: {
|
|
407
|
-
type: "object",
|
|
408
|
-
properties: { email: { type: "string" } },
|
|
409
|
-
required: ["email"],
|
|
410
|
-
},
|
|
411
|
-
},
|
|
412
|
-
required: ["id", "total", "customer"],
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
const result = checker.canConnect(nodeAOutput, nodeBInput);
|
|
416
|
-
|
|
417
|
-
console.log(result.isSubset); // true ✅
|
|
418
|
-
console.log(result.direction); // "sourceOutput ⊆ targetInput"
|
|
419
|
-
console.log(result.diffs); // []
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
---
|
|
423
|
-
|
|
424
368
|
### `resolveConditions(schema, data)`
|
|
425
369
|
|
|
426
370
|
```ts
|
|
@@ -481,22 +425,32 @@ console.log(personal.resolved.required);
|
|
|
481
425
|
|
|
482
426
|
---
|
|
483
427
|
|
|
484
|
-
### `
|
|
428
|
+
### `check(sub, sup, options)`
|
|
485
429
|
|
|
486
430
|
```ts
|
|
487
|
-
|
|
488
|
-
sub:
|
|
489
|
-
sup:
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
431
|
+
check(
|
|
432
|
+
sub: JSONSchema7Definition,
|
|
433
|
+
sup: JSONSchema7Definition,
|
|
434
|
+
options: CheckConditionsOptions
|
|
435
|
+
): ResolvedSubsetResult
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
Résout les conditions `if/then/else` des deux schemas **puis** vérifie `sub ⊆ sup`. Utile quand le superset contient des `if/then/else` et que vous connaissez les valeurs discriminantes. Effectue aussi un **narrowing** du sub par rapport aux contraintes `enum`/`const` du sup en utilisant les données runtime.
|
|
439
|
+
|
|
440
|
+
```ts
|
|
441
|
+
interface CheckConditionsOptions {
|
|
442
|
+
/** Runtime data for the sub schema — used for condition resolution and enum narrowing */
|
|
443
|
+
subData: unknown;
|
|
444
|
+
/** Runtime data for the sup schema (defaults to subData) — used for condition resolution and enum narrowing */
|
|
445
|
+
supData?: unknown;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
interface ResolvedSubsetResult extends SubsetResult {
|
|
493
449
|
resolvedSub: ResolvedConditionResult;
|
|
494
450
|
resolvedSup: ResolvedConditionResult;
|
|
495
451
|
}
|
|
496
452
|
```
|
|
497
453
|
|
|
498
|
-
Raccourci : résout les conditions des deux schemas **puis** vérifie `sub ⊆ sup`. Utile quand le superset contient des `if/then/else` et que vous connaissez les valeurs discriminantes.
|
|
499
|
-
|
|
500
454
|
```ts
|
|
501
455
|
const conditionalSup = {
|
|
502
456
|
type: "object",
|
|
@@ -529,10 +483,16 @@ const sub = {
|
|
|
529
483
|
// Sans résolution : false (le if/then/else brut ne matche pas)
|
|
530
484
|
console.log(checker.isSubset(sub, conditionalSup)); // false
|
|
531
485
|
|
|
532
|
-
// Avec résolution : true !
|
|
533
|
-
const result = checker.
|
|
486
|
+
// Avec résolution via options : true !
|
|
487
|
+
const result = checker.check(sub, conditionalSup, { subData: { kind: "text" } });
|
|
534
488
|
console.log(result.isSubset); // true ✅
|
|
535
489
|
console.log(result.resolvedSup.branch); // "then"
|
|
490
|
+
|
|
491
|
+
// Avec des données différentes pour sub et sup
|
|
492
|
+
const result2 = checker.check(sub, conditionalSup, {
|
|
493
|
+
subData: { kind: "text" },
|
|
494
|
+
supData: { kind: "text" },
|
|
495
|
+
});
|
|
536
496
|
```
|
|
537
497
|
|
|
538
498
|
---
|
|
@@ -581,9 +541,8 @@ const result = checker.check(
|
|
|
581
541
|
|
|
582
542
|
console.log(checker.formatResult("range check", result));
|
|
583
543
|
// ❌ range check: false
|
|
584
|
-
//
|
|
585
|
-
//
|
|
586
|
-
// ~ maximum: 100 → 10
|
|
544
|
+
// Errors:
|
|
545
|
+
// ✗ $root: expected minimum 5, received minimum 0
|
|
587
546
|
```
|
|
588
547
|
|
|
589
548
|
```ts
|
|
@@ -596,10 +555,10 @@ console.log(checker.formatResult("strict ⊆ loose", result2));
|
|
|
596
555
|
// ✅ strict ⊆ loose: true
|
|
597
556
|
```
|
|
598
557
|
|
|
599
|
-
|
|
600
|
-
-
|
|
601
|
-
-
|
|
602
|
-
-
|
|
558
|
+
Format de sortie :
|
|
559
|
+
- `✅` — le check a réussi (`isSubset: true`)
|
|
560
|
+
- `❌` — le check a échoué (`isSubset: false`), suivi de la liste des erreurs
|
|
561
|
+
- `✗ key: expected X, received Y` — détail de chaque erreur sémantique
|
|
603
562
|
|
|
604
563
|
---
|
|
605
564
|
|
|
@@ -664,11 +623,8 @@ checker.isSubset(loose, strict); // false
|
|
|
664
623
|
|
|
665
624
|
// Le diagnostic montre exactement ce qui manque
|
|
666
625
|
const result = checker.check(loose, strict);
|
|
667
|
-
console.log(result.
|
|
668
|
-
// [
|
|
669
|
-
// { path: "required", type: "changed", expected: ["name"], actual: ["name", "age"] },
|
|
670
|
-
// { path: "properties.age", type: "added", expected: undefined, actual: { type: "number" } }
|
|
671
|
-
// ]
|
|
626
|
+
console.log(result.errors);
|
|
627
|
+
// [{ key: "age", expected: "number", received: "undefined" }]
|
|
672
628
|
```
|
|
673
629
|
|
|
674
630
|
---
|
|
@@ -856,8 +812,8 @@ checker.isSubset(open, closed); // false
|
|
|
856
812
|
|
|
857
813
|
// Le diagnostic montre la contrainte
|
|
858
814
|
const result = checker.check(open, closed);
|
|
859
|
-
|
|
860
|
-
|
|
815
|
+
console.log(result.errors);
|
|
816
|
+
// [{ key: "age", expected: "not allowed (additionalProperties: false)", received: "number" }]
|
|
861
817
|
```
|
|
862
818
|
|
|
863
819
|
---
|
|
@@ -910,19 +866,17 @@ const shallow = {
|
|
|
910
866
|
checker.isSubset(deep, shallow); // true
|
|
911
867
|
checker.isSubset(shallow, deep); // false
|
|
912
868
|
|
|
913
|
-
// Les
|
|
869
|
+
// Les erreurs montrent les propriétés manquantes avec un chemin complet
|
|
914
870
|
const result = checker.check(shallow, deep);
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
);
|
|
918
|
-
console.log(bioDiff?.type); // "added"
|
|
871
|
+
console.log(result.errors);
|
|
872
|
+
// [{ key: "user.profile.bio", expected: "string", received: "undefined" }]
|
|
919
873
|
```
|
|
920
874
|
|
|
921
875
|
---
|
|
922
876
|
|
|
923
877
|
### 9. `anyOf` / `oneOf`
|
|
924
878
|
|
|
925
|
-
La librairie supporte `anyOf` et `oneOf`
|
|
879
|
+
La librairie supporte `anyOf` et `oneOf` pour la vérification de sous-ensemble.
|
|
926
880
|
|
|
927
881
|
#### anyOf
|
|
928
882
|
|
|
@@ -953,16 +907,16 @@ checker.isSubset(
|
|
|
953
907
|
|
|
954
908
|
#### oneOf
|
|
955
909
|
|
|
956
|
-
Le `oneOf` est traité comme `anyOf` pour la vérification de sous-ensemble (chaque branche doit être acceptée).
|
|
910
|
+
Le `oneOf` est traité comme `anyOf` pour la vérification de sous-ensemble (chaque branche doit être acceptée).
|
|
957
911
|
|
|
958
912
|
```ts
|
|
959
|
-
// Les chemins de diff utilisent le bon label
|
|
960
913
|
const result = checker.check(
|
|
961
914
|
{ oneOf: [{ type: "string" }, { type: "number" }, { type: "boolean" }] },
|
|
962
915
|
{ oneOf: [{ type: "string" }, { type: "number" }] }
|
|
963
916
|
);
|
|
964
917
|
|
|
965
|
-
result.
|
|
918
|
+
console.log(result.isSubset); // false
|
|
919
|
+
console.log(result.errors); // erreurs pour la branche non couverte
|
|
966
920
|
```
|
|
967
921
|
|
|
968
922
|
#### Unions discriminées
|
|
@@ -1636,13 +1590,12 @@ const nodeBInput = {
|
|
|
1636
1590
|
required: ["items"],
|
|
1637
1591
|
};
|
|
1638
1592
|
|
|
1639
|
-
const
|
|
1640
|
-
console.log(
|
|
1641
|
-
console.log(connection.direction); // "sourceOutput ⊆ targetInput"
|
|
1593
|
+
const result = checker.check(nodeAOutput, nodeBInput);
|
|
1594
|
+
console.log(result.isSubset); // true ✅
|
|
1642
1595
|
|
|
1643
1596
|
// Si incompatible, le diagnostic explique pourquoi
|
|
1644
|
-
if (!
|
|
1645
|
-
console.log(checker.formatResult("NodeA → NodeB",
|
|
1597
|
+
if (!result.isSubset) {
|
|
1598
|
+
console.log(checker.formatResult("NodeA → NodeB", result));
|
|
1646
1599
|
}
|
|
1647
1600
|
```
|
|
1648
1601
|
|
|
@@ -1706,7 +1659,7 @@ const consumerExpects = {
|
|
|
1706
1659
|
required: ["data"],
|
|
1707
1660
|
};
|
|
1708
1661
|
|
|
1709
|
-
const result = checker.
|
|
1662
|
+
const result = checker.check(apiResponse, consumerExpects);
|
|
1710
1663
|
console.log(result.isSubset); // true ✅
|
|
1711
1664
|
// L'API retourne plus de données que ce que le consommateur attend,
|
|
1712
1665
|
// mais TOUTES les données requises sont présentes et du bon type.
|
|
@@ -1796,8 +1749,8 @@ const businessOutput = {
|
|
|
1796
1749
|
checker.isSubset(businessOutput, formSchema); // false ❌
|
|
1797
1750
|
|
|
1798
1751
|
// Avec résolution, le schéma conditionnel est aplati
|
|
1799
|
-
const result = checker.
|
|
1800
|
-
accountType: "business",
|
|
1752
|
+
const result = checker.check(businessOutput, formSchema, {
|
|
1753
|
+
subData: { accountType: "business" },
|
|
1801
1754
|
});
|
|
1802
1755
|
console.log(result.isSubset); // true ✅
|
|
1803
1756
|
console.log(result.resolvedSup.branch); // "then"
|
|
@@ -1815,8 +1768,8 @@ const personalOutput = {
|
|
|
1815
1768
|
additionalProperties: false,
|
|
1816
1769
|
};
|
|
1817
1770
|
|
|
1818
|
-
const personalResult = checker.
|
|
1819
|
-
accountType: "personal",
|
|
1771
|
+
const personalResult = checker.check(personalOutput, formSchema, {
|
|
1772
|
+
subData: { accountType: "personal" },
|
|
1820
1773
|
});
|
|
1821
1774
|
console.log(personalResult.isSubset); // true ✅
|
|
1822
1775
|
console.log(personalResult.resolvedSup.branch); // "else"
|
|
@@ -1829,26 +1782,23 @@ console.log(personalResult.resolvedSup.branch); // "else"
|
|
|
1829
1782
|
```ts
|
|
1830
1783
|
import type {
|
|
1831
1784
|
SubsetResult,
|
|
1832
|
-
|
|
1785
|
+
SchemaError,
|
|
1833
1786
|
ResolvedConditionResult,
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
BranchResult,
|
|
1787
|
+
ResolvedSubsetResult,
|
|
1788
|
+
CheckConditionsOptions,
|
|
1837
1789
|
} from "json-schema-compatibility-checker";
|
|
1838
1790
|
```
|
|
1839
1791
|
|
|
1840
|
-
### `
|
|
1792
|
+
### `SchemaError`
|
|
1841
1793
|
|
|
1842
1794
|
```ts
|
|
1843
|
-
interface
|
|
1844
|
-
/** Chemin
|
|
1845
|
-
|
|
1846
|
-
/** Type
|
|
1847
|
-
|
|
1848
|
-
/**
|
|
1849
|
-
|
|
1850
|
-
/** Valeur dans le schema mergé (intersection) */
|
|
1851
|
-
actual: unknown;
|
|
1795
|
+
interface SchemaError {
|
|
1796
|
+
/** Chemin normalisé vers la propriété concernée (ex: "user.name", "users[].name", "accountId") */
|
|
1797
|
+
key: string;
|
|
1798
|
+
/** Type ou valeur attendu(e) par le schema cible (sup) */
|
|
1799
|
+
expected: string;
|
|
1800
|
+
/** Type ou valeur reçu(e) depuis le schema source (sub) */
|
|
1801
|
+
received: string;
|
|
1852
1802
|
}
|
|
1853
1803
|
```
|
|
1854
1804
|
|
|
@@ -1860,17 +1810,8 @@ interface SubsetResult {
|
|
|
1860
1810
|
isSubset: boolean;
|
|
1861
1811
|
/** Le schema résultant de l'intersection allOf(sub, sup), ou null si incompatible */
|
|
1862
1812
|
merged: JSONSchema7Definition | null;
|
|
1863
|
-
/**
|
|
1864
|
-
|
|
1865
|
-
}
|
|
1866
|
-
```
|
|
1867
|
-
|
|
1868
|
-
### `ConnectionResult`
|
|
1869
|
-
|
|
1870
|
-
```ts
|
|
1871
|
-
interface ConnectionResult extends SubsetResult {
|
|
1872
|
-
/** Direction lisible du check */
|
|
1873
|
-
direction: string;
|
|
1813
|
+
/** Erreurs sémantiques décrivant les incompatibilités entre les deux schemas */
|
|
1814
|
+
errors: SchemaError[];
|
|
1874
1815
|
}
|
|
1875
1816
|
```
|
|
1876
1817
|
|
|
@@ -1887,6 +1828,28 @@ interface ResolvedConditionResult {
|
|
|
1887
1828
|
}
|
|
1888
1829
|
```
|
|
1889
1830
|
|
|
1831
|
+
### `ResolvedSubsetResult`
|
|
1832
|
+
|
|
1833
|
+
```ts
|
|
1834
|
+
interface ResolvedSubsetResult extends SubsetResult {
|
|
1835
|
+
/** Résultat de résolution des conditions du sub */
|
|
1836
|
+
resolvedSub: ResolvedConditionResult;
|
|
1837
|
+
/** Résultat de résolution des conditions du sup */
|
|
1838
|
+
resolvedSup: ResolvedConditionResult;
|
|
1839
|
+
}
|
|
1840
|
+
```
|
|
1841
|
+
|
|
1842
|
+
### `CheckConditionsOptions`
|
|
1843
|
+
|
|
1844
|
+
```ts
|
|
1845
|
+
interface CheckConditionsOptions {
|
|
1846
|
+
/** Runtime data for the sub schema — used for condition resolution and enum narrowing */
|
|
1847
|
+
subData: unknown;
|
|
1848
|
+
/** Runtime data for the sup schema (defaults to subData) — used for condition resolution and enum narrowing */
|
|
1849
|
+
supData?: unknown;
|
|
1850
|
+
}
|
|
1851
|
+
```
|
|
1852
|
+
|
|
1890
1853
|
---
|
|
1891
1854
|
|
|
1892
1855
|
## Limitations connues
|
|
@@ -1929,7 +1892,7 @@ La comparaison de patterns regex utilise un **échantillonnage** (200 samples pa
|
|
|
1929
1892
|
|
|
1930
1893
|
### 4. `if/then/else` — nécessite des données discriminantes
|
|
1931
1894
|
|
|
1932
|
-
Les schemas avec `if/then/else` ne peuvent pas être comparés directement via `isSubset` car le merge brut ajoute les mots-clés conditionnels. Il faut utiliser `
|
|
1895
|
+
Les schemas avec `if/then/else` ne peuvent pas être comparés directement via `isSubset` car le merge brut ajoute les mots-clés conditionnels. Il faut utiliser `check(sub, sup, { subData })` avec les données discriminantes.
|
|
1933
1896
|
|
|
1934
1897
|
### 5. `$ref` — non supporté
|
|
1935
1898
|
|
|
@@ -1970,9 +1933,9 @@ La librairie est organisée en modules spécialisés, orchestrés par la façade
|
|
|
1970
1933
|
│ └──────────────┘ │ - stripNotFromSup │ │
|
|
1971
1934
|
│ │ - stripPatternFromSup │ │
|
|
1972
1935
|
│ ┌──────────────┐ └──────────────────────────┘ │
|
|
1973
|
-
│ │
|
|
1936
|
+
│ │Semantic Errors│ │
|
|
1974
1937
|
│ │ │ ┌──────────────────────────┐ │
|
|
1975
|
-
│ │
|
|
1938
|
+
│ │-computeErrors│ │ Pattern Subset │ │
|
|
1976
1939
|
│ │ - Recurse │ │ │ │
|
|
1977
1940
|
│ │ - Properties │ │ - isPatternSubset │ │
|
|
1978
1941
|
│ └──────────────┘ │ - arePatternsEquivalent │ │
|
|
@@ -1981,11 +1944,17 @@ La librairie est organisée en modules spécialisés, orchestrés par la façade
|
|
|
1981
1944
|
│ │ Formatter │ │
|
|
1982
1945
|
│ │ │ ┌──────────────────────────┐ │
|
|
1983
1946
|
│ │ - formatResult│ │ Format Validator │ │
|
|
1984
|
-
│ │ -
|
|
1947
|
+
│ │ - Error lines│ │ │ │
|
|
1985
1948
|
│ └──────────────┘ │ - validateFormat │ │
|
|
1986
1949
|
│ │ - isFormatSubset │ │
|
|
1987
|
-
│
|
|
1988
|
-
│
|
|
1950
|
+
│ ┌──────────────┐ │ - Format hierarchy │ │
|
|
1951
|
+
│ │Data Narrowing │ └──────────────────────────┘ │
|
|
1952
|
+
│ │ │ │
|
|
1953
|
+
│ │-narrowSchema │ │
|
|
1954
|
+
│ │ WithData │ │
|
|
1955
|
+
│ │ - enum match │ │
|
|
1956
|
+
│ │ - Recurse │ │
|
|
1957
|
+
│ └──────────────┘ │
|
|
1989
1958
|
└──────────────────────────────────────────────────┘
|
|
1990
1959
|
```
|
|
1991
1960
|
|
|
@@ -2010,7 +1979,6 @@ La librairie est organisée en modules spécialisés, orchestrés par la façade
|
|
|
2010
1979
|
| Package | Usage |
|
|
2011
1980
|
|---|---|
|
|
2012
1981
|
| `@x0k/json-schema-merge` | Merge engine pour `allOf` resolution |
|
|
2013
|
-
| `lodash` | Utilitaires (isEqual, mapValues, union, etc.) |
|
|
2014
1982
|
| `class-validator` | Validation des formats (email, URL, UUID, etc.) |
|
|
2015
1983
|
| `randexp` | Génération de strings pour le sampling de patterns |
|
|
2016
1984
|
|
|
@@ -2018,4 +1986,4 @@ La librairie est organisée en modules spécialisés, orchestrés par la façade
|
|
|
2018
1986
|
|
|
2019
1987
|
## Licence
|
|
2020
1988
|
|
|
2021
|
-
|
|
1989
|
+
MIT
|