@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.
- package/CHANGELOG.md +12 -0
- package/dist/apidom-reference.browser.js +167 -37
- 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 +15 -3
- package/src/dereference/strategies/arazzo-1/visitor.mjs +15 -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 +23 -5
- package/src/dereference/strategies/asyncapi-2/visitor.mjs +23 -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 +33 -7
- package/src/dereference/strategies/openapi-2/visitor.mjs +33 -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 +23 -5
- package/src/dereference/strategies/openapi-3-0/visitor.mjs +23 -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 +29 -7
- package/src/dereference/strategies/openapi-3-1/visitor.mjs +29 -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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@speclynx/apidom-reference",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.0",
|
|
4
4
|
"description": "Advanced algorithms for semantic ApiDOM manipulations like dereferencing or resolution.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"apidom",
|
|
@@ -279,32 +279,32 @@
|
|
|
279
279
|
"license": "Apache-2.0",
|
|
280
280
|
"dependencies": {
|
|
281
281
|
"@babel/runtime-corejs3": "^7.28.4",
|
|
282
|
-
"@speclynx/apidom-core": "4.
|
|
283
|
-
"@speclynx/apidom-datamodel": "4.
|
|
284
|
-
"@speclynx/apidom-error": "4.
|
|
285
|
-
"@speclynx/apidom-json-pointer": "4.
|
|
286
|
-
"@speclynx/apidom-ns-arazzo-1": "4.
|
|
287
|
-
"@speclynx/apidom-ns-asyncapi-2": "4.
|
|
288
|
-
"@speclynx/apidom-ns-json-schema-2020-12": "4.
|
|
289
|
-
"@speclynx/apidom-ns-openapi-2": "4.
|
|
290
|
-
"@speclynx/apidom-ns-openapi-3-0": "4.
|
|
291
|
-
"@speclynx/apidom-ns-openapi-3-1": "4.
|
|
292
|
-
"@speclynx/apidom-ns-overlay-1": "4.
|
|
293
|
-
"@speclynx/apidom-parser-adapter-arazzo-json-1": "4.
|
|
294
|
-
"@speclynx/apidom-parser-adapter-arazzo-yaml-1": "4.
|
|
295
|
-
"@speclynx/apidom-parser-adapter-asyncapi-json-2": "4.
|
|
296
|
-
"@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "4.
|
|
297
|
-
"@speclynx/apidom-parser-adapter-json": "4.
|
|
298
|
-
"@speclynx/apidom-parser-adapter-openapi-json-2": "4.
|
|
299
|
-
"@speclynx/apidom-parser-adapter-openapi-json-3-0": "4.
|
|
300
|
-
"@speclynx/apidom-parser-adapter-openapi-json-3-1": "4.
|
|
301
|
-
"@speclynx/apidom-parser-adapter-openapi-yaml-2": "4.
|
|
302
|
-
"@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "4.
|
|
303
|
-
"@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "4.
|
|
304
|
-
"@speclynx/apidom-parser-adapter-overlay-json-1": "4.
|
|
305
|
-
"@speclynx/apidom-parser-adapter-overlay-yaml-1": "4.
|
|
306
|
-
"@speclynx/apidom-parser-adapter-yaml-1-2": "4.
|
|
307
|
-
"@speclynx/apidom-traverse": "4.
|
|
282
|
+
"@speclynx/apidom-core": "4.8.0",
|
|
283
|
+
"@speclynx/apidom-datamodel": "4.8.0",
|
|
284
|
+
"@speclynx/apidom-error": "4.8.0",
|
|
285
|
+
"@speclynx/apidom-json-pointer": "4.8.0",
|
|
286
|
+
"@speclynx/apidom-ns-arazzo-1": "4.8.0",
|
|
287
|
+
"@speclynx/apidom-ns-asyncapi-2": "4.8.0",
|
|
288
|
+
"@speclynx/apidom-ns-json-schema-2020-12": "4.8.0",
|
|
289
|
+
"@speclynx/apidom-ns-openapi-2": "4.8.0",
|
|
290
|
+
"@speclynx/apidom-ns-openapi-3-0": "4.8.0",
|
|
291
|
+
"@speclynx/apidom-ns-openapi-3-1": "4.8.0",
|
|
292
|
+
"@speclynx/apidom-ns-overlay-1": "4.8.0",
|
|
293
|
+
"@speclynx/apidom-parser-adapter-arazzo-json-1": "4.8.0",
|
|
294
|
+
"@speclynx/apidom-parser-adapter-arazzo-yaml-1": "4.8.0",
|
|
295
|
+
"@speclynx/apidom-parser-adapter-asyncapi-json-2": "4.8.0",
|
|
296
|
+
"@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "4.8.0",
|
|
297
|
+
"@speclynx/apidom-parser-adapter-json": "4.8.0",
|
|
298
|
+
"@speclynx/apidom-parser-adapter-openapi-json-2": "4.8.0",
|
|
299
|
+
"@speclynx/apidom-parser-adapter-openapi-json-3-0": "4.8.0",
|
|
300
|
+
"@speclynx/apidom-parser-adapter-openapi-json-3-1": "4.8.0",
|
|
301
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-2": "4.8.0",
|
|
302
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "4.8.0",
|
|
303
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "4.8.0",
|
|
304
|
+
"@speclynx/apidom-parser-adapter-overlay-json-1": "4.8.0",
|
|
305
|
+
"@speclynx/apidom-parser-adapter-overlay-yaml-1": "4.8.0",
|
|
306
|
+
"@speclynx/apidom-parser-adapter-yaml-1-2": "4.8.0",
|
|
307
|
+
"@speclynx/apidom-traverse": "4.8.0",
|
|
308
308
|
"@swaggerexpert/arazzo-runtime-expression": "^2.0.3",
|
|
309
309
|
"axios": "^1.15.0",
|
|
310
310
|
"picomatch": "^4.0.4",
|
|
@@ -326,5 +326,5 @@
|
|
|
326
326
|
"README.md",
|
|
327
327
|
"CHANGELOG.md"
|
|
328
328
|
],
|
|
329
|
-
"gitHead": "
|
|
329
|
+
"gitHead": "ef77101edfc6567d9b265bc30708bf2c65fd1d15"
|
|
330
330
|
}
|
|
@@ -68,12 +68,16 @@ class Arazzo1DereferenceStrategy extends _DereferenceStrategy.default {
|
|
|
68
68
|
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
69
69
|
refSet = mutableRefSet;
|
|
70
70
|
}
|
|
71
|
+
const shouldDetectCircular = ['error', 'replace'].includes(options.dereference.circular);
|
|
71
72
|
const visitor = new _visitor.default({
|
|
72
73
|
reference,
|
|
73
74
|
options
|
|
74
75
|
});
|
|
75
76
|
const dereferencedElement = await (0, _apidomTraverse.traverseAsync)(refSet.rootRef.value, visitor, {
|
|
76
|
-
mutable: true
|
|
77
|
+
mutable: true,
|
|
78
|
+
...(shouldDetectCircular && {
|
|
79
|
+
skipVisited: true
|
|
80
|
+
})
|
|
77
81
|
});
|
|
78
82
|
|
|
79
83
|
/**
|
|
@@ -56,12 +56,16 @@ class Arazzo1DereferenceStrategy 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 Arazzo1DereferenceVisitor({
|
|
60
61
|
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 Arazzo1DereferenceVisitor {
|
|
|
36
36
|
indirections;
|
|
37
37
|
reference;
|
|
38
38
|
options;
|
|
39
|
+
visited;
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* Tracks element ancestors across dive-deep traversal boundaries.
|
|
@@ -47,12 +48,14 @@ class Arazzo1DereferenceVisitor {
|
|
|
47
48
|
reference,
|
|
48
49
|
options,
|
|
49
50
|
indirections = [],
|
|
50
|
-
ancestors = new _util3.AncestorLineage()
|
|
51
|
+
ancestors = new _util3.AncestorLineage(),
|
|
52
|
+
visited = new WeakSet()
|
|
51
53
|
}) {
|
|
52
54
|
this.indirections = indirections;
|
|
53
55
|
this.reference = reference;
|
|
54
56
|
this.options = options;
|
|
55
57
|
this.ancestors = new _util3.AncestorLineage(...ancestors);
|
|
58
|
+
this.visited = visited;
|
|
56
59
|
}
|
|
57
60
|
toAncestorLineage(path) {
|
|
58
61
|
const ancestorNodes = path.getAncestorNodes();
|
|
@@ -266,6 +269,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
266
269
|
* Transclude referencing element with merged referenced element.
|
|
267
270
|
*/
|
|
268
271
|
path.replaceWith(mergedElement);
|
|
272
|
+
path.skip();
|
|
269
273
|
}
|
|
270
274
|
async JSONSchemaElement(path) {
|
|
271
275
|
const referencingElement = path.node;
|
|
@@ -426,6 +430,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
426
430
|
const replacer = this.options.dereference.strategyOpts['arazzo-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
|
|
427
431
|
const replacement = replacer(refElement);
|
|
428
432
|
path.replaceWith(replacement);
|
|
433
|
+
path.skip();
|
|
429
434
|
return;
|
|
430
435
|
}
|
|
431
436
|
}
|
|
@@ -441,17 +446,23 @@ class Arazzo1DereferenceVisitor {
|
|
|
441
446
|
*/
|
|
442
447
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
443
448
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
444
|
-
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsArazzo.isJSONSchemaElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
449
|
+
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsArazzo.isJSONSchemaElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
450
|
+
if (shouldDetectCircular) {
|
|
451
|
+
this.visited.add(referencedElement);
|
|
452
|
+
}
|
|
453
|
+
|
|
445
454
|
// append referencing reference to ancestors lineage
|
|
446
455
|
directAncestors.add(referencingElement);
|
|
447
456
|
const visitor = new Arazzo1DereferenceVisitor({
|
|
448
457
|
reference,
|
|
449
458
|
indirections: [...this.indirections],
|
|
450
459
|
options: this.options,
|
|
460
|
+
visited: this.visited,
|
|
451
461
|
ancestors: ancestorsLineage
|
|
452
462
|
});
|
|
453
463
|
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
454
|
-
mutable: true
|
|
464
|
+
mutable: true,
|
|
465
|
+
skipVisited: true
|
|
455
466
|
});
|
|
456
467
|
|
|
457
468
|
// remove referencing reference from ancestors lineage
|
|
@@ -469,6 +480,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
469
480
|
booleanJsonSchemaElement.meta.set('ref-origin', reference.uri);
|
|
470
481
|
booleanJsonSchemaElement.meta.set('ref-type', referencingElement.element);
|
|
471
482
|
path.replaceWith(booleanJsonSchemaElement);
|
|
483
|
+
path.skip();
|
|
472
484
|
return;
|
|
473
485
|
}
|
|
474
486
|
|
|
@@ -29,6 +29,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
29
29
|
indirections;
|
|
30
30
|
reference;
|
|
31
31
|
options;
|
|
32
|
+
visited;
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* Tracks element ancestors across dive-deep traversal boundaries.
|
|
@@ -40,12 +41,14 @@ class Arazzo1DereferenceVisitor {
|
|
|
40
41
|
reference,
|
|
41
42
|
options,
|
|
42
43
|
indirections = [],
|
|
43
|
-
ancestors = new AncestorLineage()
|
|
44
|
+
ancestors = new AncestorLineage(),
|
|
45
|
+
visited = new WeakSet()
|
|
44
46
|
}) {
|
|
45
47
|
this.indirections = indirections;
|
|
46
48
|
this.reference = reference;
|
|
47
49
|
this.options = options;
|
|
48
50
|
this.ancestors = new AncestorLineage(...ancestors);
|
|
51
|
+
this.visited = visited;
|
|
49
52
|
}
|
|
50
53
|
toAncestorLineage(path) {
|
|
51
54
|
const ancestorNodes = path.getAncestorNodes();
|
|
@@ -259,6 +262,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
259
262
|
* Transclude referencing element with merged referenced element.
|
|
260
263
|
*/
|
|
261
264
|
path.replaceWith(mergedElement);
|
|
265
|
+
path.skip();
|
|
262
266
|
}
|
|
263
267
|
async JSONSchemaElement(path) {
|
|
264
268
|
const referencingElement = path.node;
|
|
@@ -419,6 +423,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
419
423
|
const replacer = this.options.dereference.strategyOpts['arazzo-1']?.circularReplacer ?? this.options.dereference.circularReplacer;
|
|
420
424
|
const replacement = replacer(refElement);
|
|
421
425
|
path.replaceWith(replacement);
|
|
426
|
+
path.skip();
|
|
422
427
|
return;
|
|
423
428
|
}
|
|
424
429
|
}
|
|
@@ -434,17 +439,23 @@ class Arazzo1DereferenceVisitor {
|
|
|
434
439
|
*/
|
|
435
440
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
436
441
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
437
|
-
if ((isExternalReference || isNonEntryDocument || isJSONSchemaElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
442
|
+
if ((isExternalReference || isNonEntryDocument || isJSONSchemaElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
443
|
+
if (shouldDetectCircular) {
|
|
444
|
+
this.visited.add(referencedElement);
|
|
445
|
+
}
|
|
446
|
+
|
|
438
447
|
// append referencing reference to ancestors lineage
|
|
439
448
|
directAncestors.add(referencingElement);
|
|
440
449
|
const visitor = new Arazzo1DereferenceVisitor({
|
|
441
450
|
reference,
|
|
442
451
|
indirections: [...this.indirections],
|
|
443
452
|
options: this.options,
|
|
453
|
+
visited: this.visited,
|
|
444
454
|
ancestors: ancestorsLineage
|
|
445
455
|
});
|
|
446
456
|
referencedElement = await traverseAsync(referencedElement, visitor, {
|
|
447
|
-
mutable: true
|
|
457
|
+
mutable: true,
|
|
458
|
+
skipVisited: true
|
|
448
459
|
});
|
|
449
460
|
|
|
450
461
|
// remove referencing reference from ancestors lineage
|
|
@@ -462,6 +473,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
462
473
|
booleanJsonSchemaElement.meta.set('ref-origin', reference.uri);
|
|
463
474
|
booleanJsonSchemaElement.meta.set('ref-type', referencingElement.element);
|
|
464
475
|
path.replaceWith(booleanJsonSchemaElement);
|
|
476
|
+
path.skip();
|
|
465
477
|
return;
|
|
466
478
|
}
|
|
467
479
|
|
|
@@ -62,12 +62,16 @@ class AsyncAPI2DereferenceStrategy extends _DereferenceStrategy.default {
|
|
|
62
62
|
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
63
63
|
refSet = mutableRefSet;
|
|
64
64
|
}
|
|
65
|
+
const shouldDetectCircular = ['error', 'replace'].includes(options.dereference.circular);
|
|
65
66
|
const visitor = new _visitor.default({
|
|
66
67
|
reference,
|
|
67
68
|
options
|
|
68
69
|
});
|
|
69
70
|
const dereferencedElement = await (0, _apidomTraverse.traverseAsync)(refSet.rootRef.value, visitor, {
|
|
70
|
-
mutable: true
|
|
71
|
+
mutable: true,
|
|
72
|
+
...(shouldDetectCircular && {
|
|
73
|
+
skipVisited: true
|
|
74
|
+
})
|
|
71
75
|
});
|
|
72
76
|
|
|
73
77
|
/**
|
|
@@ -55,12 +55,16 @@ class AsyncAPI2DereferenceStrategy extends DereferenceStrategy {
|
|
|
55
55
|
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
56
56
|
refSet = mutableRefSet;
|
|
57
57
|
}
|
|
58
|
+
const shouldDetectCircular = ['error', 'replace'].includes(options.dereference.circular);
|
|
58
59
|
const visitor = new AsyncAPI2DereferenceVisitor({
|
|
59
60
|
reference,
|
|
60
61
|
options
|
|
61
62
|
});
|
|
62
63
|
const dereferencedElement = await traverseAsync(refSet.rootRef.value, visitor, {
|
|
63
|
-
mutable: true
|
|
64
|
+
mutable: true,
|
|
65
|
+
...(shouldDetectCircular && {
|
|
66
|
+
skipVisited: true
|
|
67
|
+
})
|
|
64
68
|
});
|
|
65
69
|
|
|
66
70
|
/**
|
|
@@ -30,6 +30,7 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
30
30
|
reference;
|
|
31
31
|
options;
|
|
32
32
|
refractCache;
|
|
33
|
+
visited;
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* Tracks element ancestors across dive-deep traversal boundaries.
|
|
@@ -42,13 +43,15 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
42
43
|
options,
|
|
43
44
|
indirections = [],
|
|
44
45
|
ancestors = new _util.AncestorLineage(),
|
|
45
|
-
refractCache = new WeakMap()
|
|
46
|
+
refractCache = new WeakMap(),
|
|
47
|
+
visited = new WeakSet()
|
|
46
48
|
}) {
|
|
47
49
|
this.indirections = indirections;
|
|
48
50
|
this.reference = reference;
|
|
49
51
|
this.options = options;
|
|
50
52
|
this.ancestors = new _util.AncestorLineage(...ancestors);
|
|
51
53
|
this.refractCache = refractCache;
|
|
54
|
+
this.visited = visited;
|
|
52
55
|
}
|
|
53
56
|
toAncestorLineage(path) {
|
|
54
57
|
const ancestorNodes = path.getAncestorNodes();
|
|
@@ -281,6 +284,7 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
281
284
|
const replacer = this.options.dereference.strategyOpts['asyncapi-2']?.circularReplacer ?? this.options.dereference.circularReplacer;
|
|
282
285
|
const replacement = replacer(refElement);
|
|
283
286
|
path.replaceWith(replacement);
|
|
287
|
+
path.skip();
|
|
284
288
|
return;
|
|
285
289
|
}
|
|
286
290
|
}
|
|
@@ -296,7 +300,11 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
296
300
|
*/
|
|
297
301
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
298
302
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
299
|
-
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsAsyncapi.isReferenceElement)(referencedElement) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
303
|
+
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsAsyncapi.isReferenceElement)(referencedElement) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
304
|
+
if (shouldDetectCircular) {
|
|
305
|
+
this.visited.add(referencedElement);
|
|
306
|
+
}
|
|
307
|
+
|
|
300
308
|
// append referencing reference to ancestors lineage
|
|
301
309
|
directAncestors.add(referencingElement);
|
|
302
310
|
const visitor = new AsyncAPI2DereferenceVisitor({
|
|
@@ -304,10 +312,12 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
304
312
|
indirections: [...this.indirections],
|
|
305
313
|
options: this.options,
|
|
306
314
|
refractCache: this.refractCache,
|
|
315
|
+
visited: this.visited,
|
|
307
316
|
ancestors: ancestorsLineage
|
|
308
317
|
});
|
|
309
318
|
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
310
|
-
mutable: true
|
|
319
|
+
mutable: true,
|
|
320
|
+
skipVisited: true
|
|
311
321
|
});
|
|
312
322
|
|
|
313
323
|
// remove referencing reference from ancestors lineage
|
|
@@ -325,6 +335,7 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
325
335
|
booleanJsonSchemaElement.meta.set('ref-origin', reference.uri);
|
|
326
336
|
booleanJsonSchemaElement.meta.set('ref-type', referencingElement.element);
|
|
327
337
|
path.replaceWith(booleanJsonSchemaElement);
|
|
338
|
+
path.skip();
|
|
328
339
|
return;
|
|
329
340
|
}
|
|
330
341
|
|
|
@@ -344,6 +355,7 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
344
355
|
* Transclude referencing element with merged referenced element.
|
|
345
356
|
*/
|
|
346
357
|
path.replaceWith(mergedElement);
|
|
358
|
+
path.skip();
|
|
347
359
|
} catch (error) {
|
|
348
360
|
const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
|
|
349
361
|
this.handleError(`Error while dereferencing Reference Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
|
|
@@ -446,7 +458,11 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
446
458
|
*/
|
|
447
459
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
448
460
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
449
|
-
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsAsyncapi.isChannelItemElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
461
|
+
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsAsyncapi.isChannelItemElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
462
|
+
if (shouldDetectCircular) {
|
|
463
|
+
this.visited.add(referencedElement);
|
|
464
|
+
}
|
|
465
|
+
|
|
450
466
|
// append referencing reference to ancestors lineage
|
|
451
467
|
directAncestors.add(referencingElement);
|
|
452
468
|
const visitor = new AsyncAPI2DereferenceVisitor({
|
|
@@ -454,10 +470,12 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
454
470
|
indirections: [...this.indirections],
|
|
455
471
|
options: this.options,
|
|
456
472
|
refractCache: this.refractCache,
|
|
473
|
+
visited: this.visited,
|
|
457
474
|
ancestors: ancestorsLineage
|
|
458
475
|
});
|
|
459
476
|
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
460
|
-
mutable: true
|
|
477
|
+
mutable: true,
|
|
478
|
+
skipVisited: true
|
|
461
479
|
});
|
|
462
480
|
|
|
463
481
|
// remove referencing reference from ancestors lineage
|
|
@@ -23,6 +23,7 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
23
23
|
reference;
|
|
24
24
|
options;
|
|
25
25
|
refractCache;
|
|
26
|
+
visited;
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Tracks element ancestors across dive-deep traversal boundaries.
|
|
@@ -35,13 +36,15 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
35
36
|
options,
|
|
36
37
|
indirections = [],
|
|
37
38
|
ancestors = new AncestorLineage(),
|
|
38
|
-
refractCache = new WeakMap()
|
|
39
|
+
refractCache = new WeakMap(),
|
|
40
|
+
visited = new WeakSet()
|
|
39
41
|
}) {
|
|
40
42
|
this.indirections = indirections;
|
|
41
43
|
this.reference = reference;
|
|
42
44
|
this.options = options;
|
|
43
45
|
this.ancestors = new AncestorLineage(...ancestors);
|
|
44
46
|
this.refractCache = refractCache;
|
|
47
|
+
this.visited = visited;
|
|
45
48
|
}
|
|
46
49
|
toAncestorLineage(path) {
|
|
47
50
|
const ancestorNodes = path.getAncestorNodes();
|
|
@@ -274,6 +277,7 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
274
277
|
const replacer = this.options.dereference.strategyOpts['asyncapi-2']?.circularReplacer ?? this.options.dereference.circularReplacer;
|
|
275
278
|
const replacement = replacer(refElement);
|
|
276
279
|
path.replaceWith(replacement);
|
|
280
|
+
path.skip();
|
|
277
281
|
return;
|
|
278
282
|
}
|
|
279
283
|
}
|
|
@@ -289,7 +293,11 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
289
293
|
*/
|
|
290
294
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
291
295
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
292
|
-
if ((isExternalReference || isNonEntryDocument || isReferenceElement(referencedElement) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
296
|
+
if ((isExternalReference || isNonEntryDocument || isReferenceElement(referencedElement) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
297
|
+
if (shouldDetectCircular) {
|
|
298
|
+
this.visited.add(referencedElement);
|
|
299
|
+
}
|
|
300
|
+
|
|
293
301
|
// append referencing reference to ancestors lineage
|
|
294
302
|
directAncestors.add(referencingElement);
|
|
295
303
|
const visitor = new AsyncAPI2DereferenceVisitor({
|
|
@@ -297,10 +305,12 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
297
305
|
indirections: [...this.indirections],
|
|
298
306
|
options: this.options,
|
|
299
307
|
refractCache: this.refractCache,
|
|
308
|
+
visited: this.visited,
|
|
300
309
|
ancestors: ancestorsLineage
|
|
301
310
|
});
|
|
302
311
|
referencedElement = await traverseAsync(referencedElement, visitor, {
|
|
303
|
-
mutable: true
|
|
312
|
+
mutable: true,
|
|
313
|
+
skipVisited: true
|
|
304
314
|
});
|
|
305
315
|
|
|
306
316
|
// remove referencing reference from ancestors lineage
|
|
@@ -318,6 +328,7 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
318
328
|
booleanJsonSchemaElement.meta.set('ref-origin', reference.uri);
|
|
319
329
|
booleanJsonSchemaElement.meta.set('ref-type', referencingElement.element);
|
|
320
330
|
path.replaceWith(booleanJsonSchemaElement);
|
|
331
|
+
path.skip();
|
|
321
332
|
return;
|
|
322
333
|
}
|
|
323
334
|
|
|
@@ -337,6 +348,7 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
337
348
|
* Transclude referencing element with merged referenced element.
|
|
338
349
|
*/
|
|
339
350
|
path.replaceWith(mergedElement);
|
|
351
|
+
path.skip();
|
|
340
352
|
} catch (error) {
|
|
341
353
|
const $ref = toValue(referencingElement.$ref);
|
|
342
354
|
this.handleError(`Error while dereferencing Reference Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
|
|
@@ -439,7 +451,11 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
439
451
|
*/
|
|
440
452
|
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
441
453
|
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
442
|
-
if ((isExternalReference || isNonEntryDocument || isChannelItemElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
454
|
+
if ((isExternalReference || isNonEntryDocument || isChannelItemElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
455
|
+
if (shouldDetectCircular) {
|
|
456
|
+
this.visited.add(referencedElement);
|
|
457
|
+
}
|
|
458
|
+
|
|
443
459
|
// append referencing reference to ancestors lineage
|
|
444
460
|
directAncestors.add(referencingElement);
|
|
445
461
|
const visitor = new AsyncAPI2DereferenceVisitor({
|
|
@@ -447,10 +463,12 @@ class AsyncAPI2DereferenceVisitor {
|
|
|
447
463
|
indirections: [...this.indirections],
|
|
448
464
|
options: this.options,
|
|
449
465
|
refractCache: this.refractCache,
|
|
466
|
+
visited: this.visited,
|
|
450
467
|
ancestors: ancestorsLineage
|
|
451
468
|
});
|
|
452
469
|
referencedElement = await traverseAsync(referencedElement, visitor, {
|
|
453
|
-
mutable: true
|
|
470
|
+
mutable: true,
|
|
471
|
+
skipVisited: true
|
|
454
472
|
});
|
|
455
473
|
|
|
456
474
|
// remove referencing reference from ancestors lineage
|
|
@@ -62,12 +62,16 @@ class OpenAPI2DereferenceStrategy extends _DereferenceStrategy.default {
|
|
|
62
62
|
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
63
63
|
refSet = mutableRefSet;
|
|
64
64
|
}
|
|
65
|
+
const shouldDetectCircular = ['error', 'replace'].includes(options.dereference.circular);
|
|
65
66
|
const visitor = new _visitor.default({
|
|
66
67
|
reference: reference,
|
|
67
68
|
options
|
|
68
69
|
});
|
|
69
70
|
const dereferencedElement = await (0, _apidomTraverse.traverseAsync)(refSet.rootRef.value, visitor, {
|
|
70
|
-
mutable: true
|
|
71
|
+
mutable: true,
|
|
72
|
+
...(shouldDetectCircular && {
|
|
73
|
+
skipVisited: true
|
|
74
|
+
})
|
|
71
75
|
});
|
|
72
76
|
|
|
73
77
|
/**
|
|
@@ -55,12 +55,16 @@ class OpenAPI2DereferenceStrategy extends DereferenceStrategy {
|
|
|
55
55
|
reference = mutableRefSet.find(ref => ref.uri === file.uri);
|
|
56
56
|
refSet = mutableRefSet;
|
|
57
57
|
}
|
|
58
|
+
const shouldDetectCircular = ['error', 'replace'].includes(options.dereference.circular);
|
|
58
59
|
const visitor = new OpenAPI2DereferenceVisitor({
|
|
59
60
|
reference: reference,
|
|
60
61
|
options
|
|
61
62
|
});
|
|
62
63
|
const dereferencedElement = await traverseAsync(refSet.rootRef.value, visitor, {
|
|
63
|
-
mutable: true
|
|
64
|
+
mutable: true,
|
|
65
|
+
...(shouldDetectCircular && {
|
|
66
|
+
skipVisited: true
|
|
67
|
+
})
|
|
64
68
|
});
|
|
65
69
|
|
|
66
70
|
/**
|