@speclynx/apidom-reference 4.7.0 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/apidom-reference.browser.js +167 -37
  3. package/dist/apidom-reference.browser.min.js +1 -1
  4. package/package.json +28 -28
  5. package/src/dereference/strategies/arazzo-1/index.cjs +5 -1
  6. package/src/dereference/strategies/arazzo-1/index.mjs +5 -1
  7. package/src/dereference/strategies/arazzo-1/visitor.cjs +15 -3
  8. package/src/dereference/strategies/arazzo-1/visitor.mjs +15 -3
  9. package/src/dereference/strategies/asyncapi-2/index.cjs +5 -1
  10. package/src/dereference/strategies/asyncapi-2/index.mjs +5 -1
  11. package/src/dereference/strategies/asyncapi-2/visitor.cjs +23 -5
  12. package/src/dereference/strategies/asyncapi-2/visitor.mjs +23 -5
  13. package/src/dereference/strategies/openapi-2/index.cjs +5 -1
  14. package/src/dereference/strategies/openapi-2/index.mjs +5 -1
  15. package/src/dereference/strategies/openapi-2/visitor.cjs +33 -7
  16. package/src/dereference/strategies/openapi-2/visitor.mjs +33 -7
  17. package/src/dereference/strategies/openapi-3-0/index.cjs +5 -1
  18. package/src/dereference/strategies/openapi-3-0/index.mjs +5 -1
  19. package/src/dereference/strategies/openapi-3-0/visitor.cjs +23 -5
  20. package/src/dereference/strategies/openapi-3-0/visitor.mjs +23 -5
  21. package/src/dereference/strategies/openapi-3-1/index.cjs +5 -1
  22. package/src/dereference/strategies/openapi-3-1/index.mjs +5 -1
  23. package/src/dereference/strategies/openapi-3-1/visitor.cjs +29 -7
  24. package/src/dereference/strategies/openapi-3-1/visitor.mjs +29 -7
  25. package/types/dereference/strategies/arazzo-1/visitor.d.ts +3 -1
  26. package/types/dereference/strategies/asyncapi-2/visitor.d.ts +3 -1
  27. package/types/dereference/strategies/openapi-2/visitor.d.ts +3 -1
  28. package/types/dereference/strategies/openapi-3-0/visitor.d.ts +3 -1
  29. package/types/dereference/strategies/openapi-3-1/visitor.d.ts +3 -1
@@ -36,6 +36,7 @@ class OpenAPI3_1DereferenceVisitor {
36
36
  reference;
37
37
  options;
38
38
  refractCache;
39
+ visited;
39
40
 
40
41
  /**
41
42
  * Tracks element ancestors across dive-deep traversal boundaries.
@@ -48,13 +49,15 @@ class OpenAPI3_1DereferenceVisitor {
48
49
  options,
49
50
  indirections = [],
50
51
  refractCache = new WeakMap(),
51
- ancestors = new _util2.AncestorLineage()
52
+ ancestors = new _util2.AncestorLineage(),
53
+ visited = new WeakSet()
52
54
  }) {
53
55
  this.indirections = indirections;
54
56
  this.reference = reference;
55
57
  this.options = options;
56
58
  this.refractCache = refractCache;
57
59
  this.ancestors = new _util2.AncestorLineage(...ancestors);
60
+ this.visited = visited;
58
61
  }
59
62
  toAncestorLineage(path) {
60
63
  const ancestorNodes = path.getAncestorNodes();
@@ -287,6 +290,7 @@ class OpenAPI3_1DereferenceVisitor {
287
290
  const replacer = this.options.dereference.strategyOpts['openapi-3-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
288
291
  const replacement = replacer(refElement);
289
292
  path.replaceWith(replacement);
293
+ path.skip();
290
294
  return;
291
295
  }
292
296
  }
@@ -302,17 +306,22 @@ class OpenAPI3_1DereferenceVisitor {
302
306
  */
303
307
  const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
304
308
  const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
305
- if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isReferenceElement)(referencedElement) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
309
+ if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isReferenceElement)(referencedElement) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
310
+ if (shouldDetectCircular) {
311
+ this.visited.add(referencedElement);
312
+ }
306
313
  directAncestors.add(referencingElement);
307
314
  const visitor = new OpenAPI3_1DereferenceVisitor({
308
315
  reference,
309
316
  indirections: [...this.indirections],
310
317
  options: this.options,
311
318
  refractCache: this.refractCache,
319
+ visited: this.visited,
312
320
  ancestors: ancestorsLineage
313
321
  });
314
322
  referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
315
- mutable: true
323
+ mutable: true,
324
+ skipVisited: true
316
325
  });
317
326
  directAncestors.delete(referencingElement);
318
327
  }
@@ -439,6 +448,7 @@ class OpenAPI3_1DereferenceVisitor {
439
448
  const replacer = this.options.dereference.strategyOpts['openapi-3-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
440
449
  const replacement = replacer(refElement);
441
450
  path.replaceWith(replacement);
451
+ path.skip();
442
452
  return;
443
453
  }
444
454
  }
@@ -454,17 +464,22 @@ class OpenAPI3_1DereferenceVisitor {
454
464
  */
455
465
  const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
456
466
  const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
457
- if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isPathItemElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
467
+ if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isPathItemElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
468
+ if (shouldDetectCircular) {
469
+ this.visited.add(referencedElement);
470
+ }
458
471
  directAncestors.add(referencingElement);
459
472
  const visitor = new OpenAPI3_1DereferenceVisitor({
460
473
  reference,
461
474
  indirections: [...this.indirections],
462
475
  options: this.options,
463
476
  refractCache: this.refractCache,
477
+ visited: this.visited,
464
478
  ancestors: ancestorsLineage
465
479
  });
466
480
  referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
467
- mutable: true
481
+ mutable: true,
482
+ skipVisited: true
468
483
  });
469
484
  directAncestors.delete(referencingElement);
470
485
  }
@@ -795,6 +810,7 @@ class OpenAPI3_1DereferenceVisitor {
795
810
  const replacer = this.options.dereference.strategyOpts['openapi-3-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
796
811
  const replacement = replacer(refElement);
797
812
  path.replaceWith(replacement);
813
+ path.skip();
798
814
  return;
799
815
  }
800
816
  }
@@ -810,17 +826,22 @@ class OpenAPI3_1DereferenceVisitor {
810
826
  */
811
827
  const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
812
828
  const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
813
- if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isSchemaElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
829
+ if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isSchemaElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
830
+ if (shouldDetectCircular) {
831
+ this.visited.add(referencedElement);
832
+ }
814
833
  directAncestors.add(referencingElement);
815
834
  const visitor = new OpenAPI3_1DereferenceVisitor({
816
835
  reference,
817
836
  indirections: [...this.indirections],
818
837
  options: this.options,
819
838
  refractCache: this.refractCache,
839
+ visited: this.visited,
820
840
  ancestors: ancestorsLineage
821
841
  });
822
842
  referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
823
- mutable: true
843
+ mutable: true,
844
+ skipVisited: true
824
845
  });
825
846
  directAncestors.delete(referencingElement);
826
847
  }
@@ -836,6 +857,7 @@ class OpenAPI3_1DereferenceVisitor {
836
857
  booleanJsonSchemaElement.meta.set('ref-origin', reference.uri);
837
858
  booleanJsonSchemaElement.meta.set('ref-type', referencingElement.element);
838
859
  path.replaceWith(booleanJsonSchemaElement);
860
+ path.skip();
839
861
  return;
840
862
  }
841
863
 
@@ -29,6 +29,7 @@ class OpenAPI3_1DereferenceVisitor {
29
29
  reference;
30
30
  options;
31
31
  refractCache;
32
+ visited;
32
33
 
33
34
  /**
34
35
  * Tracks element ancestors across dive-deep traversal boundaries.
@@ -41,13 +42,15 @@ class OpenAPI3_1DereferenceVisitor {
41
42
  options,
42
43
  indirections = [],
43
44
  refractCache = new WeakMap(),
44
- ancestors = new AncestorLineage()
45
+ ancestors = new AncestorLineage(),
46
+ visited = new WeakSet()
45
47
  }) {
46
48
  this.indirections = indirections;
47
49
  this.reference = reference;
48
50
  this.options = options;
49
51
  this.refractCache = refractCache;
50
52
  this.ancestors = new AncestorLineage(...ancestors);
53
+ this.visited = visited;
51
54
  }
52
55
  toAncestorLineage(path) {
53
56
  const ancestorNodes = path.getAncestorNodes();
@@ -280,6 +283,7 @@ class OpenAPI3_1DereferenceVisitor {
280
283
  const replacer = this.options.dereference.strategyOpts['openapi-3-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
281
284
  const replacement = replacer(refElement);
282
285
  path.replaceWith(replacement);
286
+ path.skip();
283
287
  return;
284
288
  }
285
289
  }
@@ -295,17 +299,22 @@ class OpenAPI3_1DereferenceVisitor {
295
299
  */
296
300
  const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
297
301
  const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
298
- if ((isExternalReference || isNonEntryDocument || isReferenceElement(referencedElement) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
302
+ if ((isExternalReference || isNonEntryDocument || isReferenceElement(referencedElement) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
303
+ if (shouldDetectCircular) {
304
+ this.visited.add(referencedElement);
305
+ }
299
306
  directAncestors.add(referencingElement);
300
307
  const visitor = new OpenAPI3_1DereferenceVisitor({
301
308
  reference,
302
309
  indirections: [...this.indirections],
303
310
  options: this.options,
304
311
  refractCache: this.refractCache,
312
+ visited: this.visited,
305
313
  ancestors: ancestorsLineage
306
314
  });
307
315
  referencedElement = await traverseAsync(referencedElement, visitor, {
308
- mutable: true
316
+ mutable: true,
317
+ skipVisited: true
309
318
  });
310
319
  directAncestors.delete(referencingElement);
311
320
  }
@@ -432,6 +441,7 @@ class OpenAPI3_1DereferenceVisitor {
432
441
  const replacer = this.options.dereference.strategyOpts['openapi-3-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
433
442
  const replacement = replacer(refElement);
434
443
  path.replaceWith(replacement);
444
+ path.skip();
435
445
  return;
436
446
  }
437
447
  }
@@ -447,17 +457,22 @@ class OpenAPI3_1DereferenceVisitor {
447
457
  */
448
458
  const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
449
459
  const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
450
- if ((isExternalReference || isNonEntryDocument || isPathItemElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
460
+ if ((isExternalReference || isNonEntryDocument || isPathItemElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
461
+ if (shouldDetectCircular) {
462
+ this.visited.add(referencedElement);
463
+ }
451
464
  directAncestors.add(referencingElement);
452
465
  const visitor = new OpenAPI3_1DereferenceVisitor({
453
466
  reference,
454
467
  indirections: [...this.indirections],
455
468
  options: this.options,
456
469
  refractCache: this.refractCache,
470
+ visited: this.visited,
457
471
  ancestors: ancestorsLineage
458
472
  });
459
473
  referencedElement = await traverseAsync(referencedElement, visitor, {
460
- mutable: true
474
+ mutable: true,
475
+ skipVisited: true
461
476
  });
462
477
  directAncestors.delete(referencingElement);
463
478
  }
@@ -788,6 +803,7 @@ class OpenAPI3_1DereferenceVisitor {
788
803
  const replacer = this.options.dereference.strategyOpts['openapi-3-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
789
804
  const replacement = replacer(refElement);
790
805
  path.replaceWith(replacement);
806
+ path.skip();
791
807
  return;
792
808
  }
793
809
  }
@@ -803,17 +819,22 @@ class OpenAPI3_1DereferenceVisitor {
803
819
  */
804
820
  const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
805
821
  const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
806
- if ((isExternalReference || isNonEntryDocument || isSchemaElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
822
+ if ((isExternalReference || isNonEntryDocument || isSchemaElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
823
+ if (shouldDetectCircular) {
824
+ this.visited.add(referencedElement);
825
+ }
807
826
  directAncestors.add(referencingElement);
808
827
  const visitor = new OpenAPI3_1DereferenceVisitor({
809
828
  reference,
810
829
  indirections: [...this.indirections],
811
830
  options: this.options,
812
831
  refractCache: this.refractCache,
832
+ visited: this.visited,
813
833
  ancestors: ancestorsLineage
814
834
  });
815
835
  referencedElement = await traverseAsync(referencedElement, visitor, {
816
- mutable: true
836
+ mutable: true,
837
+ skipVisited: true
817
838
  });
818
839
  directAncestors.delete(referencingElement);
819
840
  }
@@ -829,6 +850,7 @@ class OpenAPI3_1DereferenceVisitor {
829
850
  booleanJsonSchemaElement.meta.set('ref-origin', reference.uri);
830
851
  booleanJsonSchemaElement.meta.set('ref-type', referencingElement.element);
831
852
  path.replaceWith(booleanJsonSchemaElement);
853
+ path.skip();
832
854
  return;
833
855
  }
834
856
 
@@ -11,6 +11,7 @@ export interface Arazzo1DereferenceVisitorOptions {
11
11
  readonly options: ReferenceOptions;
12
12
  readonly indirections?: Element[];
13
13
  readonly ancestors?: AncestorLineage<Element>;
14
+ readonly visited?: WeakSet<Element>;
14
15
  }
15
16
  /**
16
17
  * @public
@@ -19,13 +20,14 @@ declare class Arazzo1DereferenceVisitor {
19
20
  protected readonly indirections: Element[];
20
21
  protected readonly reference: Reference;
21
22
  protected readonly options: ReferenceOptions;
23
+ protected readonly visited: WeakSet<Element>;
22
24
  /**
23
25
  * Tracks element ancestors across dive-deep traversal boundaries.
24
26
  * Used for cycle detection: if a referenced element is found in
25
27
  * the ancestor lineage, a circular reference is detected.
26
28
  */
27
29
  protected readonly ancestors: AncestorLineage<Element>;
28
- constructor({ reference, options, indirections, ancestors, }: Arazzo1DereferenceVisitorOptions);
30
+ constructor({ reference, options, indirections, ancestors, visited, }: Arazzo1DereferenceVisitorOptions);
29
31
  protected toAncestorLineage(path: Path<Element>): [AncestorLineage<Element>, Set<Element>];
30
32
  protected toBaseURI(uri: string): string;
31
33
  protected toReference(uri: string): Promise<Reference>;
@@ -12,6 +12,7 @@ export interface AsyncAPI2DereferenceVisitorOptions {
12
12
  readonly indirections?: Element[];
13
13
  readonly refractCache?: WeakMap<Element, Element>;
14
14
  readonly ancestors?: AncestorLineage<Element>;
15
+ readonly visited?: WeakSet<Element>;
15
16
  }
16
17
  /**
17
18
  * @public
@@ -21,13 +22,14 @@ declare class AsyncAPI2DereferenceVisitor {
21
22
  protected readonly reference: Reference;
22
23
  protected readonly options: ReferenceOptions;
23
24
  protected readonly refractCache: WeakMap<Element, Element>;
25
+ protected readonly visited: WeakSet<Element>;
24
26
  /**
25
27
  * Tracks element ancestors across dive-deep traversal boundaries.
26
28
  * Used for cycle detection: if a referenced element is found in
27
29
  * the ancestor lineage, a circular reference is detected.
28
30
  */
29
31
  protected readonly ancestors: AncestorLineage<Element>;
30
- constructor({ reference, options, indirections, ancestors, refractCache, }: AsyncAPI2DereferenceVisitorOptions);
32
+ constructor({ reference, options, indirections, ancestors, refractCache, visited, }: AsyncAPI2DereferenceVisitorOptions);
31
33
  protected toAncestorLineage(path: Path<Element>): [AncestorLineage<Element>, Set<Element>];
32
34
  protected toBaseURI(uri: string): string;
33
35
  protected toReference(uri: string): Promise<Reference>;
@@ -12,6 +12,7 @@ export interface OpenAPI2DereferenceVisitorOptions {
12
12
  readonly indirections?: Element[];
13
13
  readonly refractCache?: WeakMap<Element, Element>;
14
14
  readonly ancestors?: AncestorLineage<Element>;
15
+ readonly visited?: WeakSet<Element>;
15
16
  }
16
17
  /**
17
18
  * @public
@@ -21,13 +22,14 @@ declare class OpenAPI2DereferenceVisitor {
21
22
  protected readonly reference: Reference;
22
23
  protected readonly options: ReferenceOptions;
23
24
  protected readonly refractCache: WeakMap<Element, Element>;
25
+ protected readonly visited: WeakSet<Element>;
24
26
  /**
25
27
  * Tracks element ancestors across dive-deep traversal boundaries.
26
28
  * Used for cycle detection: if a referenced element is found in
27
29
  * the ancestor lineage, a circular reference is detected.
28
30
  */
29
31
  protected readonly ancestors: AncestorLineage<Element>;
30
- constructor({ reference, options, indirections, ancestors, refractCache, }: OpenAPI2DereferenceVisitorOptions);
32
+ constructor({ reference, options, indirections, ancestors, refractCache, visited, }: OpenAPI2DereferenceVisitorOptions);
31
33
  protected toAncestorLineage(path: Path<Element>): [AncestorLineage<Element>, Set<Element>];
32
34
  protected toBaseURI(uri: string): string;
33
35
  protected toReference(uri: string): Promise<Reference>;
@@ -12,6 +12,7 @@ export interface OpenAPI3_0DereferenceVisitorOptions {
12
12
  readonly indirections?: Element[];
13
13
  readonly refractCache?: WeakMap<Element, Element>;
14
14
  readonly ancestors?: AncestorLineage<Element>;
15
+ readonly visited?: WeakSet<Element>;
15
16
  }
16
17
  /**
17
18
  * @public
@@ -21,13 +22,14 @@ declare class OpenAPI3_0DereferenceVisitor {
21
22
  protected readonly reference: Reference;
22
23
  protected readonly options: ReferenceOptions;
23
24
  protected readonly refractCache: WeakMap<Element, Element>;
25
+ protected readonly visited: WeakSet<Element>;
24
26
  /**
25
27
  * Tracks element ancestors across dive-deep traversal boundaries.
26
28
  * Used for cycle detection: if a referenced element is found in
27
29
  * the ancestor lineage, a circular reference is detected.
28
30
  */
29
31
  protected readonly ancestors: AncestorLineage<Element>;
30
- constructor({ reference, options, indirections, ancestors, refractCache, }: OpenAPI3_0DereferenceVisitorOptions);
32
+ constructor({ reference, options, indirections, ancestors, refractCache, visited, }: OpenAPI3_0DereferenceVisitorOptions);
31
33
  protected toAncestorLineage(path: Path<Element>): [AncestorLineage<Element>, Set<Element>];
32
34
  protected toBaseURI(uri: string): string;
33
35
  protected toReference(uri: string): Promise<Reference>;
@@ -12,6 +12,7 @@ export interface OpenAPI3_1DereferenceVisitorOptions {
12
12
  readonly indirections?: Element[];
13
13
  readonly refractCache?: WeakMap<Element, Element>;
14
14
  readonly ancestors?: AncestorLineage<Element>;
15
+ readonly visited?: WeakSet<Element>;
15
16
  }
16
17
  /**
17
18
  * @public
@@ -21,13 +22,14 @@ declare class OpenAPI3_1DereferenceVisitor {
21
22
  protected readonly reference: Reference;
22
23
  protected readonly options: ReferenceOptions;
23
24
  protected readonly refractCache: WeakMap<Element, Element>;
25
+ protected readonly visited: WeakSet<Element>;
24
26
  /**
25
27
  * Tracks element ancestors across dive-deep traversal boundaries.
26
28
  * Used for cycle detection: if a referenced element is found in
27
29
  * the ancestor lineage, a circular reference is detected.
28
30
  */
29
31
  protected readonly ancestors: AncestorLineage<Element>;
30
- constructor({ reference, options, indirections, refractCache, ancestors, }: OpenAPI3_1DereferenceVisitorOptions);
32
+ constructor({ reference, options, indirections, refractCache, ancestors, visited, }: OpenAPI3_1DereferenceVisitorOptions);
31
33
  protected toAncestorLineage(path: Path<Element>): [AncestorLineage<Element>, Set<Element>];
32
34
  protected toBaseURI(uri: string): string;
33
35
  protected toReference(uri: string): Promise<Reference>;