@speclynx/apidom-reference 4.7.1 → 4.9.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.
- package/CHANGELOG.md +10 -0
- package/dist/apidom-reference.browser.js +148 -36
- package/dist/apidom-reference.browser.min.js +1 -1
- package/package.json +28 -28
- package/src/dereference/strategies/arazzo-1/index.cjs +5 -1
- package/src/dereference/strategies/arazzo-1/index.mjs +5 -1
- package/src/dereference/strategies/arazzo-1/visitor.cjs +12 -3
- package/src/dereference/strategies/arazzo-1/visitor.mjs +12 -3
- package/src/dereference/strategies/asyncapi-2/index.cjs +5 -1
- package/src/dereference/strategies/asyncapi-2/index.mjs +5 -1
- package/src/dereference/strategies/asyncapi-2/visitor.cjs +20 -5
- package/src/dereference/strategies/asyncapi-2/visitor.mjs +20 -5
- package/src/dereference/strategies/openapi-2/index.cjs +5 -1
- package/src/dereference/strategies/openapi-2/index.mjs +5 -1
- package/src/dereference/strategies/openapi-2/visitor.cjs +28 -7
- package/src/dereference/strategies/openapi-2/visitor.mjs +28 -7
- package/src/dereference/strategies/openapi-3-0/index.cjs +5 -1
- package/src/dereference/strategies/openapi-3-0/index.mjs +5 -1
- package/src/dereference/strategies/openapi-3-0/visitor.cjs +20 -5
- package/src/dereference/strategies/openapi-3-0/visitor.mjs +20 -5
- package/src/dereference/strategies/openapi-3-1/index.cjs +5 -1
- package/src/dereference/strategies/openapi-3-1/index.mjs +5 -1
- package/src/dereference/strategies/openapi-3-1/visitor.cjs +25 -7
- package/src/dereference/strategies/openapi-3-1/visitor.mjs +25 -7
- package/types/dereference/strategies/arazzo-1/visitor.d.ts +3 -1
- package/types/dereference/strategies/asyncapi-2/visitor.d.ts +3 -1
- package/types/dereference/strategies/openapi-2/visitor.d.ts +3 -1
- package/types/dereference/strategies/openapi-3-0/visitor.d.ts +3 -1
- package/types/dereference/strategies/openapi-3-1/visitor.d.ts +3 -1
|
@@ -64,12 +64,16 @@ class OpenAPI3_0DereferenceStrategy extends _DereferenceStrategy.default {
|
|
|
64
64
|
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
65
65
|
refSet = mutableRefSet;
|
|
66
66
|
}
|
|
67
|
+
const shouldDetectCircular = ['error', 'replace'].includes(options.dereference.circular);
|
|
67
68
|
const visitor = new _visitor.default({
|
|
68
69
|
reference: reference,
|
|
69
70
|
options
|
|
70
71
|
});
|
|
71
72
|
const dereferencedElement = await (0, _apidomTraverse.traverseAsync)(refSet.rootRef.value, visitor, {
|
|
72
|
-
mutable: true
|
|
73
|
+
mutable: true,
|
|
74
|
+
...(shouldDetectCircular && {
|
|
75
|
+
skipVisited: true
|
|
76
|
+
})
|
|
73
77
|
});
|
|
74
78
|
|
|
75
79
|
/**
|
|
@@ -57,12 +57,16 @@ class OpenAPI3_0DereferenceStrategy extends DereferenceStrategy {
|
|
|
57
57
|
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
58
58
|
refSet = mutableRefSet;
|
|
59
59
|
}
|
|
60
|
+
const shouldDetectCircular = ['error', 'replace'].includes(options.dereference.circular);
|
|
60
61
|
const visitor = new OpenAPI3_0DereferenceVisitor({
|
|
61
62
|
reference: reference,
|
|
62
63
|
options
|
|
63
64
|
});
|
|
64
65
|
const dereferencedElement = await traverseAsync(refSet.rootRef.value, visitor, {
|
|
65
|
-
mutable: true
|
|
66
|
+
mutable: true,
|
|
67
|
+
...(shouldDetectCircular && {
|
|
68
|
+
skipVisited: true
|
|
69
|
+
})
|
|
66
70
|
});
|
|
67
71
|
|
|
68
72
|
/**
|
|
@@ -31,6 +31,7 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
31
31
|
reference;
|
|
32
32
|
options;
|
|
33
33
|
refractCache;
|
|
34
|
+
visited;
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Tracks element ancestors across dive-deep traversal boundaries.
|
|
@@ -43,13 +44,15 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
43
44
|
options,
|
|
44
45
|
indirections = [],
|
|
45
46
|
ancestors = new _util.AncestorLineage(),
|
|
46
|
-
refractCache = new WeakMap()
|
|
47
|
+
refractCache = new WeakMap(),
|
|
48
|
+
visited = new WeakSet()
|
|
47
49
|
}) {
|
|
48
50
|
this.indirections = indirections;
|
|
49
51
|
this.reference = reference;
|
|
50
52
|
this.options = options;
|
|
51
53
|
this.ancestors = new _util.AncestorLineage(...ancestors);
|
|
52
54
|
this.refractCache = refractCache;
|
|
55
|
+
this.visited = visited;
|
|
53
56
|
}
|
|
54
57
|
toAncestorLineage(path) {
|
|
55
58
|
const ancestorNodes = path.getAncestorNodes();
|
|
@@ -298,7 +301,11 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
298
301
|
*/
|
|
299
302
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
300
303
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
301
|
-
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isReferenceElement)(referencedElement) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
304
|
+
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isReferenceElement)(referencedElement) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
305
|
+
if (shouldDetectCircular) {
|
|
306
|
+
this.visited.add(referencedElement);
|
|
307
|
+
}
|
|
308
|
+
|
|
302
309
|
// append referencing reference to ancestors lineage
|
|
303
310
|
directAncestors.add(referencingElement);
|
|
304
311
|
const visitor = new OpenAPI3_0DereferenceVisitor({
|
|
@@ -306,10 +313,12 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
306
313
|
indirections: [...this.indirections],
|
|
307
314
|
options: this.options,
|
|
308
315
|
refractCache: this.refractCache,
|
|
316
|
+
visited: this.visited,
|
|
309
317
|
ancestors: ancestorsLineage
|
|
310
318
|
});
|
|
311
319
|
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
312
|
-
mutable: true
|
|
320
|
+
mutable: true,
|
|
321
|
+
skipVisited: true
|
|
313
322
|
});
|
|
314
323
|
|
|
315
324
|
// remove referencing reference from ancestors lineage
|
|
@@ -436,7 +445,11 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
436
445
|
*/
|
|
437
446
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
438
447
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
439
|
-
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isPathItemElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
448
|
+
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isPathItemElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
449
|
+
if (shouldDetectCircular) {
|
|
450
|
+
this.visited.add(referencedElement);
|
|
451
|
+
}
|
|
452
|
+
|
|
440
453
|
// append referencing reference to ancestors lineage
|
|
441
454
|
directAncestors.add(referencingElement);
|
|
442
455
|
const visitor = new OpenAPI3_0DereferenceVisitor({
|
|
@@ -444,10 +457,12 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
444
457
|
indirections: [...this.indirections],
|
|
445
458
|
options: this.options,
|
|
446
459
|
refractCache: this.refractCache,
|
|
460
|
+
visited: this.visited,
|
|
447
461
|
ancestors: ancestorsLineage
|
|
448
462
|
});
|
|
449
463
|
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
450
|
-
mutable: true
|
|
464
|
+
mutable: true,
|
|
465
|
+
skipVisited: true
|
|
451
466
|
});
|
|
452
467
|
|
|
453
468
|
// remove referencing reference from ancestors lineage
|
|
@@ -24,6 +24,7 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
24
24
|
reference;
|
|
25
25
|
options;
|
|
26
26
|
refractCache;
|
|
27
|
+
visited;
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Tracks element ancestors across dive-deep traversal boundaries.
|
|
@@ -36,13 +37,15 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
36
37
|
options,
|
|
37
38
|
indirections = [],
|
|
38
39
|
ancestors = new AncestorLineage(),
|
|
39
|
-
refractCache = new WeakMap()
|
|
40
|
+
refractCache = new WeakMap(),
|
|
41
|
+
visited = new WeakSet()
|
|
40
42
|
}) {
|
|
41
43
|
this.indirections = indirections;
|
|
42
44
|
this.reference = reference;
|
|
43
45
|
this.options = options;
|
|
44
46
|
this.ancestors = new AncestorLineage(...ancestors);
|
|
45
47
|
this.refractCache = refractCache;
|
|
48
|
+
this.visited = visited;
|
|
46
49
|
}
|
|
47
50
|
toAncestorLineage(path) {
|
|
48
51
|
const ancestorNodes = path.getAncestorNodes();
|
|
@@ -291,7 +294,11 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
291
294
|
*/
|
|
292
295
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
293
296
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
294
|
-
if ((isExternalReference || isNonEntryDocument || isReferenceElement(referencedElement) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
297
|
+
if ((isExternalReference || isNonEntryDocument || isReferenceElement(referencedElement) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
298
|
+
if (shouldDetectCircular) {
|
|
299
|
+
this.visited.add(referencedElement);
|
|
300
|
+
}
|
|
301
|
+
|
|
295
302
|
// append referencing reference to ancestors lineage
|
|
296
303
|
directAncestors.add(referencingElement);
|
|
297
304
|
const visitor = new OpenAPI3_0DereferenceVisitor({
|
|
@@ -299,10 +306,12 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
299
306
|
indirections: [...this.indirections],
|
|
300
307
|
options: this.options,
|
|
301
308
|
refractCache: this.refractCache,
|
|
309
|
+
visited: this.visited,
|
|
302
310
|
ancestors: ancestorsLineage
|
|
303
311
|
});
|
|
304
312
|
referencedElement = await traverseAsync(referencedElement, visitor, {
|
|
305
|
-
mutable: true
|
|
313
|
+
mutable: true,
|
|
314
|
+
skipVisited: true
|
|
306
315
|
});
|
|
307
316
|
|
|
308
317
|
// remove referencing reference from ancestors lineage
|
|
@@ -429,7 +438,11 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
429
438
|
*/
|
|
430
439
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
431
440
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
432
|
-
if ((isExternalReference || isNonEntryDocument || isPathItemElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
441
|
+
if ((isExternalReference || isNonEntryDocument || isPathItemElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
442
|
+
if (shouldDetectCircular) {
|
|
443
|
+
this.visited.add(referencedElement);
|
|
444
|
+
}
|
|
445
|
+
|
|
433
446
|
// append referencing reference to ancestors lineage
|
|
434
447
|
directAncestors.add(referencingElement);
|
|
435
448
|
const visitor = new OpenAPI3_0DereferenceVisitor({
|
|
@@ -437,10 +450,12 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
437
450
|
indirections: [...this.indirections],
|
|
438
451
|
options: this.options,
|
|
439
452
|
refractCache: this.refractCache,
|
|
453
|
+
visited: this.visited,
|
|
440
454
|
ancestors: ancestorsLineage
|
|
441
455
|
});
|
|
442
456
|
referencedElement = await traverseAsync(referencedElement, visitor, {
|
|
443
|
-
mutable: true
|
|
457
|
+
mutable: true,
|
|
458
|
+
skipVisited: true
|
|
444
459
|
});
|
|
445
460
|
|
|
446
461
|
// remove referencing reference from ancestors lineage
|
|
@@ -67,12 +67,16 @@ class OpenAPI3_1DereferenceStrategy extends _DereferenceStrategy.default {
|
|
|
67
67
|
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
68
68
|
refSet = mutableRefSet;
|
|
69
69
|
}
|
|
70
|
+
const shouldDetectCircular = ['error', 'replace'].includes(options.dereference.circular);
|
|
70
71
|
const visitor = new _visitor.default({
|
|
71
72
|
reference: reference,
|
|
72
73
|
options
|
|
73
74
|
});
|
|
74
75
|
const dereferencedElement = await (0, _apidomTraverse.traverseAsync)(refSet.rootRef.value, visitor, {
|
|
75
|
-
mutable: true
|
|
76
|
+
mutable: true,
|
|
77
|
+
...(shouldDetectCircular && {
|
|
78
|
+
skipVisited: true
|
|
79
|
+
})
|
|
76
80
|
});
|
|
77
81
|
|
|
78
82
|
/**
|
|
@@ -56,12 +56,16 @@ class OpenAPI3_1DereferenceStrategy extends DereferenceStrategy {
|
|
|
56
56
|
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
57
57
|
refSet = mutableRefSet;
|
|
58
58
|
}
|
|
59
|
+
const shouldDetectCircular = ['error', 'replace'].includes(options.dereference.circular);
|
|
59
60
|
const visitor = new OpenAPI3_1DereferenceVisitor({
|
|
60
61
|
reference: reference,
|
|
61
62
|
options
|
|
62
63
|
});
|
|
63
64
|
const dereferencedElement = await traverseAsync(refSet.rootRef.value, visitor, {
|
|
64
|
-
mutable: true
|
|
65
|
+
mutable: true,
|
|
66
|
+
...(shouldDetectCircular && {
|
|
67
|
+
skipVisited: true
|
|
68
|
+
})
|
|
65
69
|
});
|
|
66
70
|
|
|
67
71
|
/**
|
|
@@ -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();
|
|
@@ -303,17 +306,22 @@ class OpenAPI3_1DereferenceVisitor {
|
|
|
303
306
|
*/
|
|
304
307
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
305
308
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
306
|
-
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
|
+
}
|
|
307
313
|
directAncestors.add(referencingElement);
|
|
308
314
|
const visitor = new OpenAPI3_1DereferenceVisitor({
|
|
309
315
|
reference,
|
|
310
316
|
indirections: [...this.indirections],
|
|
311
317
|
options: this.options,
|
|
312
318
|
refractCache: this.refractCache,
|
|
319
|
+
visited: this.visited,
|
|
313
320
|
ancestors: ancestorsLineage
|
|
314
321
|
});
|
|
315
322
|
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
316
|
-
mutable: true
|
|
323
|
+
mutable: true,
|
|
324
|
+
skipVisited: true
|
|
317
325
|
});
|
|
318
326
|
directAncestors.delete(referencingElement);
|
|
319
327
|
}
|
|
@@ -456,17 +464,22 @@ class OpenAPI3_1DereferenceVisitor {
|
|
|
456
464
|
*/
|
|
457
465
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
458
466
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
459
|
-
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
|
+
}
|
|
460
471
|
directAncestors.add(referencingElement);
|
|
461
472
|
const visitor = new OpenAPI3_1DereferenceVisitor({
|
|
462
473
|
reference,
|
|
463
474
|
indirections: [...this.indirections],
|
|
464
475
|
options: this.options,
|
|
465
476
|
refractCache: this.refractCache,
|
|
477
|
+
visited: this.visited,
|
|
466
478
|
ancestors: ancestorsLineage
|
|
467
479
|
});
|
|
468
480
|
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
469
|
-
mutable: true
|
|
481
|
+
mutable: true,
|
|
482
|
+
skipVisited: true
|
|
470
483
|
});
|
|
471
484
|
directAncestors.delete(referencingElement);
|
|
472
485
|
}
|
|
@@ -813,17 +826,22 @@ class OpenAPI3_1DereferenceVisitor {
|
|
|
813
826
|
*/
|
|
814
827
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
815
828
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
816
|
-
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
|
+
}
|
|
817
833
|
directAncestors.add(referencingElement);
|
|
818
834
|
const visitor = new OpenAPI3_1DereferenceVisitor({
|
|
819
835
|
reference,
|
|
820
836
|
indirections: [...this.indirections],
|
|
821
837
|
options: this.options,
|
|
822
838
|
refractCache: this.refractCache,
|
|
839
|
+
visited: this.visited,
|
|
823
840
|
ancestors: ancestorsLineage
|
|
824
841
|
});
|
|
825
842
|
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
826
|
-
mutable: true
|
|
843
|
+
mutable: true,
|
|
844
|
+
skipVisited: true
|
|
827
845
|
});
|
|
828
846
|
directAncestors.delete(referencingElement);
|
|
829
847
|
}
|
|
@@ -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();
|
|
@@ -296,17 +299,22 @@ class OpenAPI3_1DereferenceVisitor {
|
|
|
296
299
|
*/
|
|
297
300
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
298
301
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
299
|
-
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
|
+
}
|
|
300
306
|
directAncestors.add(referencingElement);
|
|
301
307
|
const visitor = new OpenAPI3_1DereferenceVisitor({
|
|
302
308
|
reference,
|
|
303
309
|
indirections: [...this.indirections],
|
|
304
310
|
options: this.options,
|
|
305
311
|
refractCache: this.refractCache,
|
|
312
|
+
visited: this.visited,
|
|
306
313
|
ancestors: ancestorsLineage
|
|
307
314
|
});
|
|
308
315
|
referencedElement = await traverseAsync(referencedElement, visitor, {
|
|
309
|
-
mutable: true
|
|
316
|
+
mutable: true,
|
|
317
|
+
skipVisited: true
|
|
310
318
|
});
|
|
311
319
|
directAncestors.delete(referencingElement);
|
|
312
320
|
}
|
|
@@ -449,17 +457,22 @@ class OpenAPI3_1DereferenceVisitor {
|
|
|
449
457
|
*/
|
|
450
458
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
451
459
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
452
|
-
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
|
+
}
|
|
453
464
|
directAncestors.add(referencingElement);
|
|
454
465
|
const visitor = new OpenAPI3_1DereferenceVisitor({
|
|
455
466
|
reference,
|
|
456
467
|
indirections: [...this.indirections],
|
|
457
468
|
options: this.options,
|
|
458
469
|
refractCache: this.refractCache,
|
|
470
|
+
visited: this.visited,
|
|
459
471
|
ancestors: ancestorsLineage
|
|
460
472
|
});
|
|
461
473
|
referencedElement = await traverseAsync(referencedElement, visitor, {
|
|
462
|
-
mutable: true
|
|
474
|
+
mutable: true,
|
|
475
|
+
skipVisited: true
|
|
463
476
|
});
|
|
464
477
|
directAncestors.delete(referencingElement);
|
|
465
478
|
}
|
|
@@ -806,17 +819,22 @@ class OpenAPI3_1DereferenceVisitor {
|
|
|
806
819
|
*/
|
|
807
820
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
808
821
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
809
|
-
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
|
+
}
|
|
810
826
|
directAncestors.add(referencingElement);
|
|
811
827
|
const visitor = new OpenAPI3_1DereferenceVisitor({
|
|
812
828
|
reference,
|
|
813
829
|
indirections: [...this.indirections],
|
|
814
830
|
options: this.options,
|
|
815
831
|
refractCache: this.refractCache,
|
|
832
|
+
visited: this.visited,
|
|
816
833
|
ancestors: ancestorsLineage
|
|
817
834
|
});
|
|
818
835
|
referencedElement = await traverseAsync(referencedElement, visitor, {
|
|
819
|
-
mutable: true
|
|
836
|
+
mutable: true,
|
|
837
|
+
skipVisited: true
|
|
820
838
|
});
|
|
821
839
|
directAncestors.delete(referencingElement);
|
|
822
840
|
}
|
|
@@ -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>;
|