@speclynx/apidom-reference 5.1.1 → 5.2.1
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/README.md +26 -2
- package/dist/apidom-reference.browser.js +1029 -222
- package/dist/apidom-reference.browser.min.js +1 -1
- package/package.json +29 -29
- package/src/bundle/strategies/arazzo-1/visitor.cjs +24 -8
- package/src/bundle/strategies/arazzo-1/visitor.mjs +25 -9
- package/src/dereference/strategies/arazzo-1/index.cjs +12 -0
- package/src/dereference/strategies/arazzo-1/index.mjs +1 -1
- package/src/dereference/strategies/arazzo-1/source-descriptions.cjs +8 -3
- package/src/dereference/strategies/arazzo-1/source-descriptions.mjs +8 -3
- package/src/dereference/strategies/arazzo-1/util.cjs +41 -1
- package/src/dereference/strategies/arazzo-1/util.mjs +38 -1
- package/src/dereference/strategies/arazzo-1/visitor.cjs +21 -7
- package/src/dereference/strategies/arazzo-1/visitor.mjs +22 -8
- package/src/parse/parsers/arazzo-json-1/source-descriptions.cjs +7 -2
- package/src/parse/parsers/arazzo-json-1/source-descriptions.mjs +8 -3
- package/types/bundle/strategies/arazzo-1/visitor.d.ts +6 -0
- package/types/dereference/strategies/arazzo-1/index.d.ts +1 -1
- package/types/dereference/strategies/arazzo-1/util.d.ts +22 -0
- package/types/dereference/strategies/arazzo-1/visitor.d.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@speclynx/apidom-reference",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"description": "Advanced algorithms for semantic ApiDOM manipulations like dereferencing or resolution.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"apidom",
|
|
@@ -299,35 +299,35 @@
|
|
|
299
299
|
"license": "Apache-2.0",
|
|
300
300
|
"dependencies": {
|
|
301
301
|
"@babel/runtime-corejs3": "^8.0.0",
|
|
302
|
-
"@speclynx/apidom-core": "5.
|
|
303
|
-
"@speclynx/apidom-datamodel": "5.
|
|
304
|
-
"@speclynx/apidom-error": "5.
|
|
305
|
-
"@speclynx/apidom-json-pointer": "5.
|
|
306
|
-
"@speclynx/apidom-ns-arazzo-1": "5.
|
|
307
|
-
"@speclynx/apidom-ns-asyncapi-2": "5.
|
|
308
|
-
"@speclynx/apidom-ns-json-schema-2020-12": "5.
|
|
309
|
-
"@speclynx/apidom-ns-openapi-2": "5.
|
|
310
|
-
"@speclynx/apidom-ns-openapi-3-0": "5.
|
|
311
|
-
"@speclynx/apidom-ns-openapi-3-1": "5.
|
|
312
|
-
"@speclynx/apidom-ns-overlay-1": "5.
|
|
313
|
-
"@speclynx/apidom-parser-adapter-arazzo-json-1": "5.
|
|
314
|
-
"@speclynx/apidom-parser-adapter-arazzo-yaml-1": "5.
|
|
315
|
-
"@speclynx/apidom-parser-adapter-asyncapi-json-2": "5.
|
|
316
|
-
"@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "5.
|
|
317
|
-
"@speclynx/apidom-parser-adapter-json": "5.
|
|
318
|
-
"@speclynx/apidom-parser-adapter-openapi-json-2": "5.
|
|
319
|
-
"@speclynx/apidom-parser-adapter-openapi-json-3-0": "5.
|
|
320
|
-
"@speclynx/apidom-parser-adapter-openapi-json-3-1": "5.
|
|
321
|
-
"@speclynx/apidom-parser-adapter-openapi-yaml-2": "5.
|
|
322
|
-
"@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "5.
|
|
323
|
-
"@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "5.
|
|
324
|
-
"@speclynx/apidom-parser-adapter-overlay-json-1": "5.
|
|
325
|
-
"@speclynx/apidom-parser-adapter-overlay-yaml-1": "5.
|
|
326
|
-
"@speclynx/apidom-parser-adapter-yaml-1-2": "5.
|
|
327
|
-
"@speclynx/apidom-traverse": "5.
|
|
302
|
+
"@speclynx/apidom-core": "5.2.1",
|
|
303
|
+
"@speclynx/apidom-datamodel": "5.2.1",
|
|
304
|
+
"@speclynx/apidom-error": "5.2.1",
|
|
305
|
+
"@speclynx/apidom-json-pointer": "5.2.1",
|
|
306
|
+
"@speclynx/apidom-ns-arazzo-1": "5.2.1",
|
|
307
|
+
"@speclynx/apidom-ns-asyncapi-2": "5.2.1",
|
|
308
|
+
"@speclynx/apidom-ns-json-schema-2020-12": "5.2.1",
|
|
309
|
+
"@speclynx/apidom-ns-openapi-2": "5.2.1",
|
|
310
|
+
"@speclynx/apidom-ns-openapi-3-0": "5.2.1",
|
|
311
|
+
"@speclynx/apidom-ns-openapi-3-1": "5.2.1",
|
|
312
|
+
"@speclynx/apidom-ns-overlay-1": "5.2.1",
|
|
313
|
+
"@speclynx/apidom-parser-adapter-arazzo-json-1": "5.2.1",
|
|
314
|
+
"@speclynx/apidom-parser-adapter-arazzo-yaml-1": "5.2.1",
|
|
315
|
+
"@speclynx/apidom-parser-adapter-asyncapi-json-2": "5.2.1",
|
|
316
|
+
"@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "5.2.1",
|
|
317
|
+
"@speclynx/apidom-parser-adapter-json": "5.2.1",
|
|
318
|
+
"@speclynx/apidom-parser-adapter-openapi-json-2": "5.2.1",
|
|
319
|
+
"@speclynx/apidom-parser-adapter-openapi-json-3-0": "5.2.1",
|
|
320
|
+
"@speclynx/apidom-parser-adapter-openapi-json-3-1": "5.2.1",
|
|
321
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-2": "5.2.1",
|
|
322
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "5.2.1",
|
|
323
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "5.2.1",
|
|
324
|
+
"@speclynx/apidom-parser-adapter-overlay-json-1": "5.2.1",
|
|
325
|
+
"@speclynx/apidom-parser-adapter-overlay-yaml-1": "5.2.1",
|
|
326
|
+
"@speclynx/apidom-parser-adapter-yaml-1-2": "5.2.1",
|
|
327
|
+
"@speclynx/apidom-traverse": "5.2.1",
|
|
328
328
|
"@swaggerexpert/arazzo-runtime-expression": "^3.1.0",
|
|
329
329
|
"axios": "^1.19.0",
|
|
330
|
-
"picomatch": "^4.0.
|
|
330
|
+
"picomatch": "^4.0.7",
|
|
331
331
|
"process": "^0.11.10",
|
|
332
332
|
"ramda": "~0.32.0",
|
|
333
333
|
"ramda-adjunct": "^6.1.0"
|
|
@@ -346,5 +346,5 @@
|
|
|
346
346
|
"README.md",
|
|
347
347
|
"CHANGELOG.md"
|
|
348
348
|
],
|
|
349
|
-
"gitHead": "
|
|
349
|
+
"gitHead": "814e67e36b1e27546288c74a25eab8f9463943eb"
|
|
350
350
|
}
|
|
@@ -43,6 +43,13 @@ const cf = (0, _apidomCore.fixedFields)(_apidomNsArazzo.ComponentsElement, {
|
|
|
43
43
|
*/
|
|
44
44
|
class Arazzo1BundleVisitor {
|
|
45
45
|
reference;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Base URI of the current document for resolving relative references.
|
|
49
|
+
* Honors the Arazzo `$self` field when present, otherwise falls back
|
|
50
|
+
* to the retrieval URI (`this.reference.uri`).
|
|
51
|
+
*/
|
|
52
|
+
baseURI;
|
|
46
53
|
options;
|
|
47
54
|
|
|
48
55
|
/**
|
|
@@ -81,12 +88,13 @@ class Arazzo1BundleVisitor {
|
|
|
81
88
|
reservedNames = new Map()
|
|
82
89
|
}) {
|
|
83
90
|
this.reference = reference;
|
|
91
|
+
this.baseURI = (0, _util.resolveArazzo$selfField)(reference.uri, reference.value?.result);
|
|
84
92
|
this.options = options;
|
|
85
93
|
this.assignments = assignments;
|
|
86
94
|
this.reservedNames = reservedNames;
|
|
87
95
|
}
|
|
88
96
|
toBaseURI(uri) {
|
|
89
|
-
return url.resolve(this.
|
|
97
|
+
return url.resolve(this.baseURI, url.sanitize(url.stripHash(uri)));
|
|
90
98
|
}
|
|
91
99
|
async toReference(uri) {
|
|
92
100
|
// detect maximum depth of resolution
|
|
@@ -105,6 +113,12 @@ class Arazzo1BundleVisitor {
|
|
|
105
113
|
if (refSet.has(baseURI)) {
|
|
106
114
|
return refSet.find(ref => ref.uri === baseURI);
|
|
107
115
|
}
|
|
116
|
+
|
|
117
|
+
// identity-based referencing: URI matches `$self` of an already processed Arazzo document
|
|
118
|
+
const referenceBy$self = refSet.find((0, _util.identifiedBy$self)(baseURI));
|
|
119
|
+
if (referenceBy$self !== undefined) {
|
|
120
|
+
return referenceBy$self;
|
|
121
|
+
}
|
|
108
122
|
const parseResult = await (0, _index.default)(url.unsanitize(baseURI), {
|
|
109
123
|
...this.options,
|
|
110
124
|
parse: {
|
|
@@ -279,19 +293,18 @@ class Arazzo1BundleVisitor {
|
|
|
279
293
|
}
|
|
280
294
|
const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
|
|
281
295
|
try {
|
|
282
|
-
// compute baseURI using rules around $id and $ref keywords. The
|
|
283
|
-
// document's URI is
|
|
284
|
-
//
|
|
296
|
+
// compute baseURI using rules around $self, $id and $ref keywords. The
|
|
297
|
+
// current document's base URI is derived directly (not via toReference)
|
|
298
|
+
// so an internal $ref needs no resolution and never trips the
|
|
285
299
|
// resolve.maxDepth guard.
|
|
286
|
-
const
|
|
287
|
-
const $refBaseURI = (0, _util.resolveSchema$refField)(retrievalURI, referencingElement);
|
|
300
|
+
const $refBaseURI = (0, _util.resolveSchema$refField)(this.baseURI, referencingElement);
|
|
288
301
|
const $refBaseURIStrippedHash = url.stripHash($refBaseURI);
|
|
289
302
|
const file = new _File.default({
|
|
290
303
|
uri: $refBaseURIStrippedHash
|
|
291
304
|
});
|
|
292
305
|
const isUnknownURI = (0, _ramda.none)(r => r.canRead(file), this.options.resolve.resolvers);
|
|
293
306
|
const isURL = !isUnknownURI;
|
|
294
|
-
const isInternalReference =
|
|
307
|
+
const isInternalReference = this.baseURI === $refBaseURIStrippedHash;
|
|
295
308
|
const isExternalReference = !isInternalReference;
|
|
296
309
|
|
|
297
310
|
// internal Schema Object $refs resolve against the in-document $id graph;
|
|
@@ -345,7 +358,10 @@ class Arazzo1BundleVisitor {
|
|
|
345
358
|
// is internal even when its URI form (e.g. a URN or absolute $id) is not a
|
|
346
359
|
// bare fragment. Leave it untouched — it resolves against the in-document
|
|
347
360
|
// $id graph, and embedding the current document into itself would be wrong.
|
|
348
|
-
|
|
361
|
+
// The same holds for a $ref resolving into the entry document (e.g. by its
|
|
362
|
+
// `$self` identity) — it's already part of the bundle.
|
|
363
|
+
const schemaReferenceURI = url.stripHash(schemaReference.uri);
|
|
364
|
+
if (schemaReferenceURI === url.stripHash(this.reference.uri) || schemaReferenceURI === url.stripHash(this.reference.refSet.rootRef.uri)) {
|
|
349
365
|
return;
|
|
350
366
|
}
|
|
351
367
|
|
|
@@ -15,7 +15,7 @@ import Reference from "../../../Reference.mjs";
|
|
|
15
15
|
import File from "../../../File.mjs";
|
|
16
16
|
import { isAnchor, uriToAnchor, evaluate as $anchorEvaluate } from "../../../dereference/strategies/arazzo-1/selectors/$anchor.mjs";
|
|
17
17
|
import { evaluate as uriEvaluate } from "../../../dereference/strategies/arazzo-1/selectors/uri.mjs";
|
|
18
|
-
import { resolveSchema$refField, resolveSchema$idField, maybeRefractToJSONSchemaElement } from "../../../dereference/strategies/arazzo-1/util.mjs";
|
|
18
|
+
import { resolveSchema$refField, resolveSchema$idField, maybeRefractToJSONSchemaElement, resolveArazzo$selfField, identifiedBy$self } from "../../../dereference/strategies/arazzo-1/util.mjs";
|
|
19
19
|
import { toPascalCase, sanitizeComponentName, uniqueName as resolveUniqueName } from "../../util.mjs";
|
|
20
20
|
/**
|
|
21
21
|
* The Components Object field where embedded JSON Schema resources are hoisted.
|
|
@@ -35,6 +35,13 @@ const cf = fixedFields(ComponentsElement, {
|
|
|
35
35
|
*/
|
|
36
36
|
class Arazzo1BundleVisitor {
|
|
37
37
|
reference;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Base URI of the current document for resolving relative references.
|
|
41
|
+
* Honors the Arazzo `$self` field when present, otherwise falls back
|
|
42
|
+
* to the retrieval URI (`this.reference.uri`).
|
|
43
|
+
*/
|
|
44
|
+
baseURI;
|
|
38
45
|
options;
|
|
39
46
|
|
|
40
47
|
/**
|
|
@@ -73,12 +80,13 @@ class Arazzo1BundleVisitor {
|
|
|
73
80
|
reservedNames = new Map()
|
|
74
81
|
}) {
|
|
75
82
|
this.reference = reference;
|
|
83
|
+
this.baseURI = resolveArazzo$selfField(reference.uri, reference.value?.result);
|
|
76
84
|
this.options = options;
|
|
77
85
|
this.assignments = assignments;
|
|
78
86
|
this.reservedNames = reservedNames;
|
|
79
87
|
}
|
|
80
88
|
toBaseURI(uri) {
|
|
81
|
-
return url.resolve(this.
|
|
89
|
+
return url.resolve(this.baseURI, url.sanitize(url.stripHash(uri)));
|
|
82
90
|
}
|
|
83
91
|
async toReference(uri) {
|
|
84
92
|
// detect maximum depth of resolution
|
|
@@ -97,6 +105,12 @@ class Arazzo1BundleVisitor {
|
|
|
97
105
|
if (refSet.has(baseURI)) {
|
|
98
106
|
return refSet.find(ref => ref.uri === baseURI);
|
|
99
107
|
}
|
|
108
|
+
|
|
109
|
+
// identity-based referencing: URI matches `$self` of an already processed Arazzo document
|
|
110
|
+
const referenceBy$self = refSet.find(identifiedBy$self(baseURI));
|
|
111
|
+
if (referenceBy$self !== undefined) {
|
|
112
|
+
return referenceBy$self;
|
|
113
|
+
}
|
|
100
114
|
const parseResult = await parse(url.unsanitize(baseURI), {
|
|
101
115
|
...this.options,
|
|
102
116
|
parse: {
|
|
@@ -271,19 +285,18 @@ class Arazzo1BundleVisitor {
|
|
|
271
285
|
}
|
|
272
286
|
const $ref = toValue(referencingElement.$ref);
|
|
273
287
|
try {
|
|
274
|
-
// compute baseURI using rules around $id and $ref keywords. The
|
|
275
|
-
// document's URI is
|
|
276
|
-
//
|
|
288
|
+
// compute baseURI using rules around $self, $id and $ref keywords. The
|
|
289
|
+
// current document's base URI is derived directly (not via toReference)
|
|
290
|
+
// so an internal $ref needs no resolution and never trips the
|
|
277
291
|
// resolve.maxDepth guard.
|
|
278
|
-
const
|
|
279
|
-
const $refBaseURI = resolveSchema$refField(retrievalURI, referencingElement);
|
|
292
|
+
const $refBaseURI = resolveSchema$refField(this.baseURI, referencingElement);
|
|
280
293
|
const $refBaseURIStrippedHash = url.stripHash($refBaseURI);
|
|
281
294
|
const file = new File({
|
|
282
295
|
uri: $refBaseURIStrippedHash
|
|
283
296
|
});
|
|
284
297
|
const isUnknownURI = none(r => r.canRead(file), this.options.resolve.resolvers);
|
|
285
298
|
const isURL = !isUnknownURI;
|
|
286
|
-
const isInternalReference =
|
|
299
|
+
const isInternalReference = this.baseURI === $refBaseURIStrippedHash;
|
|
287
300
|
const isExternalReference = !isInternalReference;
|
|
288
301
|
|
|
289
302
|
// internal Schema Object $refs resolve against the in-document $id graph;
|
|
@@ -337,7 +350,10 @@ class Arazzo1BundleVisitor {
|
|
|
337
350
|
// is internal even when its URI form (e.g. a URN or absolute $id) is not a
|
|
338
351
|
// bare fragment. Leave it untouched — it resolves against the in-document
|
|
339
352
|
// $id graph, and embedding the current document into itself would be wrong.
|
|
340
|
-
|
|
353
|
+
// The same holds for a $ref resolving into the entry document (e.g. by its
|
|
354
|
+
// `$self` identity) — it's already part of the bundle.
|
|
355
|
+
const schemaReferenceURI = url.stripHash(schemaReference.uri);
|
|
356
|
+
if (schemaReferenceURI === url.stripHash(this.reference.uri) || schemaReferenceURI === url.stripHash(this.reference.refSet.rootRef.uri)) {
|
|
341
357
|
return;
|
|
342
358
|
}
|
|
343
359
|
|
|
@@ -17,12 +17,24 @@ Object.defineProperty(exports, "dereferenceSourceDescriptions", {
|
|
|
17
17
|
return _sourceDescriptions.dereferenceSourceDescriptions;
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
|
+
Object.defineProperty(exports, "identifiedBy$self", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () {
|
|
23
|
+
return _util.identifiedBy$self;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
20
26
|
Object.defineProperty(exports, "maybeRefractToJSONSchemaElement", {
|
|
21
27
|
enumerable: true,
|
|
22
28
|
get: function () {
|
|
23
29
|
return _util.maybeRefractToJSONSchemaElement;
|
|
24
30
|
}
|
|
25
31
|
});
|
|
32
|
+
Object.defineProperty(exports, "resolveArazzo$selfField", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () {
|
|
35
|
+
return _util.resolveArazzo$selfField;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
26
38
|
Object.defineProperty(exports, "resolveSchema$idField", {
|
|
27
39
|
enumerable: true,
|
|
28
40
|
get: function () {
|
|
@@ -104,6 +104,6 @@ class Arazzo1DereferenceStrategy extends DereferenceStrategy {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
export { Arazzo1DereferenceVisitor };
|
|
107
|
-
export { resolveSchema$refField, resolveSchema$idField, maybeRefractToJSONSchemaElement } from "./util.mjs";
|
|
107
|
+
export { resolveSchema$refField, resolveSchema$idField, resolveArazzo$selfField, identifiedBy$self, maybeRefractToJSONSchemaElement } from "./util.mjs";
|
|
108
108
|
export { dereferenceSourceDescriptions } from "./source-descriptions.mjs";
|
|
109
109
|
export default Arazzo1DereferenceStrategy;
|
|
@@ -14,6 +14,7 @@ var _apidomCore = require("@speclynx/apidom-core");
|
|
|
14
14
|
var url = _interopRequireWildcard(require("../../../util/url.cjs"));
|
|
15
15
|
var _util = require("../../../options/util.cjs");
|
|
16
16
|
var _index = _interopRequireWildcard(require("../../index.cjs"));
|
|
17
|
+
var _util2 = require("./util.cjs");
|
|
17
18
|
/**
|
|
18
19
|
* Dereferences a single source description element.
|
|
19
20
|
* Returns ParseResultElement on success, or with annotation if skipped.
|
|
@@ -183,7 +184,7 @@ async function dereferenceSourceDescription(sourceDescription, ctx) {
|
|
|
183
184
|
* @public
|
|
184
185
|
*/
|
|
185
186
|
async function dereferenceSourceDescriptions(parseResult, parseResultRetrievalURI, options, strategyName = 'arazzo-1') {
|
|
186
|
-
const
|
|
187
|
+
const retrievalURI = url.sanitize(url.stripHash(parseResultRetrievalURI));
|
|
187
188
|
const results = [];
|
|
188
189
|
|
|
189
190
|
// get API from dereferenced parse result
|
|
@@ -214,10 +215,14 @@ async function dereferenceSourceDescriptions(parseResult, parseResultRetrievalUR
|
|
|
214
215
|
const currentDepth = sharedOpts.sourceDescriptionsDepth ?? 0;
|
|
215
216
|
const visitedUrls = sharedOpts.sourceDescriptionsVisitedUrls ?? new Set();
|
|
216
217
|
|
|
217
|
-
//
|
|
218
|
+
// base URI for resolving source description URLs honors Arazzo `$self` field
|
|
219
|
+
const baseURI = (0, _util2.resolveArazzo$selfField)(retrievalURI, api);
|
|
220
|
+
|
|
221
|
+
// add current file to visited URLs to prevent cycles (by retrieval URI and by identity)
|
|
222
|
+
visitedUrls.add(retrievalURI);
|
|
218
223
|
visitedUrls.add(baseURI);
|
|
219
224
|
if (currentDepth >= maxDepth) {
|
|
220
|
-
const annotation = new _apidomDatamodel.AnnotationElement(`Maximum dereference depth of ${maxDepth} has been exceeded by file "${
|
|
225
|
+
const annotation = new _apidomDatamodel.AnnotationElement(`Maximum dereference depth of ${maxDepth} has been exceeded by file "${retrievalURI}"`);
|
|
221
226
|
annotation.classes.push('error');
|
|
222
227
|
const parseResult = new _apidomDatamodel.ParseResultElement([annotation]);
|
|
223
228
|
parseResult.classes.push('source-description');
|
|
@@ -7,6 +7,7 @@ import { toValue } from '@speclynx/apidom-core';
|
|
|
7
7
|
import * as url from "../../../util/url.mjs";
|
|
8
8
|
import { merge as mergeOptions } from "../../../options/util.mjs";
|
|
9
9
|
import dereference, { dereferenceApiDOM } from "../../index.mjs";
|
|
10
|
+
import { resolveArazzo$selfField } from "./util.mjs";
|
|
10
11
|
/**
|
|
11
12
|
* Dereferences a single source description element.
|
|
12
13
|
* Returns ParseResultElement on success, or with annotation if skipped.
|
|
@@ -176,7 +177,7 @@ async function dereferenceSourceDescription(sourceDescription, ctx) {
|
|
|
176
177
|
* @public
|
|
177
178
|
*/
|
|
178
179
|
export async function dereferenceSourceDescriptions(parseResult, parseResultRetrievalURI, options, strategyName = 'arazzo-1') {
|
|
179
|
-
const
|
|
180
|
+
const retrievalURI = url.sanitize(url.stripHash(parseResultRetrievalURI));
|
|
180
181
|
const results = [];
|
|
181
182
|
|
|
182
183
|
// get API from dereferenced parse result
|
|
@@ -207,10 +208,14 @@ export async function dereferenceSourceDescriptions(parseResult, parseResultRetr
|
|
|
207
208
|
const currentDepth = sharedOpts.sourceDescriptionsDepth ?? 0;
|
|
208
209
|
const visitedUrls = sharedOpts.sourceDescriptionsVisitedUrls ?? new Set();
|
|
209
210
|
|
|
210
|
-
//
|
|
211
|
+
// base URI for resolving source description URLs honors Arazzo `$self` field
|
|
212
|
+
const baseURI = resolveArazzo$selfField(retrievalURI, api);
|
|
213
|
+
|
|
214
|
+
// add current file to visited URLs to prevent cycles (by retrieval URI and by identity)
|
|
215
|
+
visitedUrls.add(retrievalURI);
|
|
211
216
|
visitedUrls.add(baseURI);
|
|
212
217
|
if (currentDepth >= maxDepth) {
|
|
213
|
-
const annotation = new AnnotationElement(`Maximum dereference depth of ${maxDepth} has been exceeded by file "${
|
|
218
|
+
const annotation = new AnnotationElement(`Maximum dereference depth of ${maxDepth} has been exceeded by file "${retrievalURI}"`);
|
|
214
219
|
annotation.classes.push('error');
|
|
215
220
|
const parseResult = new ParseResultElement([annotation]);
|
|
216
221
|
parseResult.classes.push('source-description');
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
|
|
3
4
|
Object.defineProperty(exports, "__esModule", {
|
|
4
5
|
value: true
|
|
5
6
|
});
|
|
6
|
-
exports.refractToJSONSchemaElement = exports.maybeRefractToJSONSchemaElement = void 0;
|
|
7
|
+
exports.resolveArazzo$selfField = exports.refractToJSONSchemaElement = exports.maybeRefractToJSONSchemaElement = exports.identifiedBy$self = void 0;
|
|
7
8
|
Object.defineProperty(exports, "resolveSchema$idField", {
|
|
8
9
|
enumerable: true,
|
|
9
10
|
get: function () {
|
|
@@ -17,11 +18,50 @@ Object.defineProperty(exports, "resolveSchema$refField", {
|
|
|
17
18
|
}
|
|
18
19
|
});
|
|
19
20
|
var _apidomDatamodel = require("@speclynx/apidom-datamodel");
|
|
21
|
+
var _apidomCore = require("@speclynx/apidom-core");
|
|
20
22
|
var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
|
|
23
|
+
var url = _interopRequireWildcard(require("../../../util/url.cjs"));
|
|
21
24
|
var _util = require("../openapi-3-1/util.cjs");
|
|
25
|
+
/**
|
|
26
|
+
* Computes the base URI of an Arazzo document per Arazzo 1.1.0 rules.
|
|
27
|
+
*
|
|
28
|
+
* When the Arazzo Object carries a `$self` field, it establishes the document's
|
|
29
|
+
* canonical identity and the base URI for resolving relative references. `$self`
|
|
30
|
+
* may itself be relative, in which case it's resolved against the retrieval URI.
|
|
31
|
+
* Any fragment is stripped, as `$self` MUST NOT contain one. When `$self` is
|
|
32
|
+
* absent (or `element` is not an Arazzo document), the retrieval URI is the base URI.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
const resolveArazzo$selfField = (retrievalURI, element) => {
|
|
37
|
+
if (!(0, _apidomNsArazzo.isArazzoSpecification1Element)(element)) {
|
|
38
|
+
return retrievalURI;
|
|
39
|
+
}
|
|
40
|
+
const $self = (0, _apidomCore.toValue)(element.$self);
|
|
41
|
+
if (typeof $self !== 'string' || $self === '') {
|
|
42
|
+
return retrievalURI;
|
|
43
|
+
}
|
|
44
|
+
return url.resolve(retrievalURI, url.sanitize(url.stripHash($self)));
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Predicate matching a Reference by the identity (`$self`) of the Arazzo
|
|
49
|
+
* document it holds, rather than by its retrieval URI. Implements identity-based
|
|
50
|
+
* referencing from Arazzo 1.1.0: a URI matching a loaded document's `$self`
|
|
51
|
+
* refers to that document, regardless of where it was retrieved from.
|
|
52
|
+
*
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
55
|
+
exports.resolveArazzo$selfField = resolveArazzo$selfField;
|
|
56
|
+
const identifiedBy$self = uri => reference => {
|
|
57
|
+
const result = reference.value?.result;
|
|
58
|
+
return (0, _apidomNsArazzo.isArazzoSpecification1Element)(result) && resolveArazzo$selfField(reference.uri, result) === uri;
|
|
59
|
+
};
|
|
60
|
+
|
|
22
61
|
/**
|
|
23
62
|
* Cached version of JSONSchemaElement.refract.
|
|
24
63
|
*/
|
|
64
|
+
exports.identifiedBy$self = identifiedBy$self;
|
|
25
65
|
const refractToJSONSchemaElement = element => {
|
|
26
66
|
if (refractToJSONSchemaElement.cache.has(element)) {
|
|
27
67
|
return refractToJSONSchemaElement.cache.get(element);
|
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
import { isPrimitiveElement } from '@speclynx/apidom-datamodel';
|
|
2
|
-
import {
|
|
2
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
3
|
+
import { refractJSONSchema, isArazzoSpecification1Element } from '@speclynx/apidom-ns-arazzo-1';
|
|
4
|
+
import * as url from "../../../util/url.mjs";
|
|
3
5
|
export { resolveSchema$refField, resolveSchema$idField } from "../openapi-3-1/util.mjs";
|
|
6
|
+
/**
|
|
7
|
+
* Computes the base URI of an Arazzo document per Arazzo 1.1.0 rules.
|
|
8
|
+
*
|
|
9
|
+
* When the Arazzo Object carries a `$self` field, it establishes the document's
|
|
10
|
+
* canonical identity and the base URI for resolving relative references. `$self`
|
|
11
|
+
* may itself be relative, in which case it's resolved against the retrieval URI.
|
|
12
|
+
* Any fragment is stripped, as `$self` MUST NOT contain one. When `$self` is
|
|
13
|
+
* absent (or `element` is not an Arazzo document), the retrieval URI is the base URI.
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export const resolveArazzo$selfField = (retrievalURI, element) => {
|
|
18
|
+
if (!isArazzoSpecification1Element(element)) {
|
|
19
|
+
return retrievalURI;
|
|
20
|
+
}
|
|
21
|
+
const $self = toValue(element.$self);
|
|
22
|
+
if (typeof $self !== 'string' || $self === '') {
|
|
23
|
+
return retrievalURI;
|
|
24
|
+
}
|
|
25
|
+
return url.resolve(retrievalURI, url.sanitize(url.stripHash($self)));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Predicate matching a Reference by the identity (`$self`) of the Arazzo
|
|
30
|
+
* document it holds, rather than by its retrieval URI. Implements identity-based
|
|
31
|
+
* referencing from Arazzo 1.1.0: a URI matching a loaded document's `$self`
|
|
32
|
+
* refers to that document, regardless of where it was retrieved from.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export const identifiedBy$self = uri => reference => {
|
|
37
|
+
const result = reference.value?.result;
|
|
38
|
+
return isArazzoSpecification1Element(result) && resolveArazzo$selfField(reference.uri, result) === uri;
|
|
39
|
+
};
|
|
40
|
+
|
|
4
41
|
/**
|
|
5
42
|
* Cached version of JSONSchemaElement.refract.
|
|
6
43
|
*/
|
|
@@ -37,6 +37,13 @@ var _EvaluationJsonSchemaUriError = _interopRequireDefault(require("../../../err
|
|
|
37
37
|
class Arazzo1DereferenceVisitor {
|
|
38
38
|
indirections;
|
|
39
39
|
reference;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Base URI of the current document for resolving relative references.
|
|
43
|
+
* Honors the Arazzo `$self` field when present, otherwise falls back
|
|
44
|
+
* to the retrieval URI (`this.reference.uri`).
|
|
45
|
+
*/
|
|
46
|
+
baseURI;
|
|
40
47
|
options;
|
|
41
48
|
visited;
|
|
42
49
|
|
|
@@ -55,6 +62,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
55
62
|
}) {
|
|
56
63
|
this.indirections = indirections;
|
|
57
64
|
this.reference = reference;
|
|
65
|
+
this.baseURI = (0, _util2.resolveArazzo$selfField)(reference.uri, reference.value?.result);
|
|
58
66
|
this.options = options;
|
|
59
67
|
this.ancestors = new _util3.AncestorLineage(...ancestors);
|
|
60
68
|
this.visited = visited;
|
|
@@ -66,7 +74,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
66
74
|
return [ancestorsLineage, directAncestors];
|
|
67
75
|
}
|
|
68
76
|
toBaseURI(uri) {
|
|
69
|
-
return url.resolve(this.
|
|
77
|
+
return url.resolve(this.baseURI, url.sanitize(url.stripHash(uri)));
|
|
70
78
|
}
|
|
71
79
|
async toReference(uri) {
|
|
72
80
|
// detect maximum depth of resolution
|
|
@@ -85,6 +93,12 @@ class Arazzo1DereferenceVisitor {
|
|
|
85
93
|
if (refSet.has(baseURI)) {
|
|
86
94
|
return refSet.find((0, _ramda.propEq)(baseURI, 'uri'));
|
|
87
95
|
}
|
|
96
|
+
|
|
97
|
+
// identity-based referencing: URI matches `$self` of an already processed Arazzo document
|
|
98
|
+
const referenceBy$self = refSet.find((0, _util2.identifiedBy$self)(baseURI));
|
|
99
|
+
if (referenceBy$self !== undefined) {
|
|
100
|
+
return referenceBy$self;
|
|
101
|
+
}
|
|
88
102
|
const parseResult = await (0, _index.default)(url.unsanitize(baseURI), {
|
|
89
103
|
...this.options,
|
|
90
104
|
parse: {
|
|
@@ -288,19 +302,19 @@ class Arazzo1DereferenceVisitor {
|
|
|
288
302
|
}
|
|
289
303
|
const indirectionsSize = this.indirections.length;
|
|
290
304
|
try {
|
|
291
|
-
// compute baseURI using rules around $id and $ref keywords
|
|
305
|
+
// compute baseURI using rules around $self, $id and $ref keywords
|
|
292
306
|
let reference = await this.toReference(url.unsanitize(this.reference.uri));
|
|
293
307
|
let {
|
|
294
308
|
uri: retrievalURI
|
|
295
309
|
} = reference;
|
|
296
|
-
const $refBaseURI = (0, _util.resolveSchema$refField)(
|
|
310
|
+
const $refBaseURI = (0, _util.resolveSchema$refField)(this.baseURI, referencingElement);
|
|
297
311
|
const $refBaseURIStrippedHash = url.stripHash($refBaseURI);
|
|
298
312
|
const file = new _File.default({
|
|
299
313
|
uri: $refBaseURIStrippedHash
|
|
300
314
|
});
|
|
301
315
|
const isUnknownURI = (0, _ramda.none)(r => r.canRead(file), this.options.resolve.resolvers);
|
|
302
316
|
const isURL = !isUnknownURI;
|
|
303
|
-
let isInternalReference =
|
|
317
|
+
let isInternalReference = this.baseURI === $refBaseURI;
|
|
304
318
|
let isExternalReference = !isInternalReference;
|
|
305
319
|
|
|
306
320
|
// determining reference, proper evaluation and selection mechanism
|
|
@@ -327,7 +341,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
327
341
|
} else {
|
|
328
342
|
// we're assuming here that we're dealing with JSON Pointer here
|
|
329
343
|
retrievalURI = this.toBaseURI($refBaseURI);
|
|
330
|
-
isInternalReference =
|
|
344
|
+
isInternalReference = this.baseURI === retrievalURI;
|
|
331
345
|
isExternalReference = !isInternalReference;
|
|
332
346
|
|
|
333
347
|
// ignore resolving internal Schema Objects
|
|
@@ -354,7 +368,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
354
368
|
if (isURL && error instanceof _EvaluationJsonSchemaUriError.default) {
|
|
355
369
|
if ((0, _$anchor.isAnchor)((0, _$anchor.uriToAnchor)($refBaseURI))) {
|
|
356
370
|
// we're dealing with JSON Schema $anchor here
|
|
357
|
-
isInternalReference =
|
|
371
|
+
isInternalReference = this.baseURI === retrievalURI;
|
|
358
372
|
isExternalReference = !isInternalReference;
|
|
359
373
|
|
|
360
374
|
// ignore resolving internal Schema Objects
|
|
@@ -375,7 +389,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
375
389
|
} else {
|
|
376
390
|
// we're assuming here that we're dealing with JSON Pointer here
|
|
377
391
|
retrievalURI = this.toBaseURI($refBaseURI);
|
|
378
|
-
isInternalReference =
|
|
392
|
+
isInternalReference = this.baseURI === retrievalURI;
|
|
379
393
|
isExternalReference = !isInternalReference;
|
|
380
394
|
|
|
381
395
|
// ignore resolving internal Schema Objects
|
|
@@ -9,7 +9,7 @@ import { parse as parseRuntimeExpression } from '@swaggerexpert/arazzo-runtime-e
|
|
|
9
9
|
import { isAnchor, uriToAnchor, evaluate as $anchorEvaluate } from "./selectors/$anchor.mjs";
|
|
10
10
|
import { evaluate as uriEvaluate } from "./selectors/uri.mjs";
|
|
11
11
|
import { resolveSchema$refField } from "../openapi-3-1/util.mjs";
|
|
12
|
-
import { maybeRefractToJSONSchemaElement } from "./util.mjs";
|
|
12
|
+
import { maybeRefractToJSONSchemaElement, resolveArazzo$selfField, identifiedBy$self } from "./util.mjs";
|
|
13
13
|
import UnresolvableReferenceError from "../../../errors/UnresolvableReferenceError.mjs";
|
|
14
14
|
import MaximumDereferenceDepthError from "../../../errors/MaximumDereferenceDepthError.mjs";
|
|
15
15
|
import MaximumResolveDepthError from "../../../errors/MaximumResolveDepthError.mjs";
|
|
@@ -28,6 +28,13 @@ import EvaluationJsonSchemaUriError from "../../../errors/EvaluationJsonSchemaUr
|
|
|
28
28
|
class Arazzo1DereferenceVisitor {
|
|
29
29
|
indirections;
|
|
30
30
|
reference;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Base URI of the current document for resolving relative references.
|
|
34
|
+
* Honors the Arazzo `$self` field when present, otherwise falls back
|
|
35
|
+
* to the retrieval URI (`this.reference.uri`).
|
|
36
|
+
*/
|
|
37
|
+
baseURI;
|
|
31
38
|
options;
|
|
32
39
|
visited;
|
|
33
40
|
|
|
@@ -46,6 +53,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
46
53
|
}) {
|
|
47
54
|
this.indirections = indirections;
|
|
48
55
|
this.reference = reference;
|
|
56
|
+
this.baseURI = resolveArazzo$selfField(reference.uri, reference.value?.result);
|
|
49
57
|
this.options = options;
|
|
50
58
|
this.ancestors = new AncestorLineage(...ancestors);
|
|
51
59
|
this.visited = visited;
|
|
@@ -57,7 +65,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
57
65
|
return [ancestorsLineage, directAncestors];
|
|
58
66
|
}
|
|
59
67
|
toBaseURI(uri) {
|
|
60
|
-
return url.resolve(this.
|
|
68
|
+
return url.resolve(this.baseURI, url.sanitize(url.stripHash(uri)));
|
|
61
69
|
}
|
|
62
70
|
async toReference(uri) {
|
|
63
71
|
// detect maximum depth of resolution
|
|
@@ -76,6 +84,12 @@ class Arazzo1DereferenceVisitor {
|
|
|
76
84
|
if (refSet.has(baseURI)) {
|
|
77
85
|
return refSet.find(propEq(baseURI, 'uri'));
|
|
78
86
|
}
|
|
87
|
+
|
|
88
|
+
// identity-based referencing: URI matches `$self` of an already processed Arazzo document
|
|
89
|
+
const referenceBy$self = refSet.find(identifiedBy$self(baseURI));
|
|
90
|
+
if (referenceBy$self !== undefined) {
|
|
91
|
+
return referenceBy$self;
|
|
92
|
+
}
|
|
79
93
|
const parseResult = await parse(url.unsanitize(baseURI), {
|
|
80
94
|
...this.options,
|
|
81
95
|
parse: {
|
|
@@ -279,19 +293,19 @@ class Arazzo1DereferenceVisitor {
|
|
|
279
293
|
}
|
|
280
294
|
const indirectionsSize = this.indirections.length;
|
|
281
295
|
try {
|
|
282
|
-
// compute baseURI using rules around $id and $ref keywords
|
|
296
|
+
// compute baseURI using rules around $self, $id and $ref keywords
|
|
283
297
|
let reference = await this.toReference(url.unsanitize(this.reference.uri));
|
|
284
298
|
let {
|
|
285
299
|
uri: retrievalURI
|
|
286
300
|
} = reference;
|
|
287
|
-
const $refBaseURI = resolveSchema$refField(
|
|
301
|
+
const $refBaseURI = resolveSchema$refField(this.baseURI, referencingElement);
|
|
288
302
|
const $refBaseURIStrippedHash = url.stripHash($refBaseURI);
|
|
289
303
|
const file = new File({
|
|
290
304
|
uri: $refBaseURIStrippedHash
|
|
291
305
|
});
|
|
292
306
|
const isUnknownURI = none(r => r.canRead(file), this.options.resolve.resolvers);
|
|
293
307
|
const isURL = !isUnknownURI;
|
|
294
|
-
let isInternalReference =
|
|
308
|
+
let isInternalReference = this.baseURI === $refBaseURI;
|
|
295
309
|
let isExternalReference = !isInternalReference;
|
|
296
310
|
|
|
297
311
|
// determining reference, proper evaluation and selection mechanism
|
|
@@ -318,7 +332,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
318
332
|
} else {
|
|
319
333
|
// we're assuming here that we're dealing with JSON Pointer here
|
|
320
334
|
retrievalURI = this.toBaseURI($refBaseURI);
|
|
321
|
-
isInternalReference =
|
|
335
|
+
isInternalReference = this.baseURI === retrievalURI;
|
|
322
336
|
isExternalReference = !isInternalReference;
|
|
323
337
|
|
|
324
338
|
// ignore resolving internal Schema Objects
|
|
@@ -345,7 +359,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
345
359
|
if (isURL && error instanceof EvaluationJsonSchemaUriError) {
|
|
346
360
|
if (isAnchor(uriToAnchor($refBaseURI))) {
|
|
347
361
|
// we're dealing with JSON Schema $anchor here
|
|
348
|
-
isInternalReference =
|
|
362
|
+
isInternalReference = this.baseURI === retrievalURI;
|
|
349
363
|
isExternalReference = !isInternalReference;
|
|
350
364
|
|
|
351
365
|
// ignore resolving internal Schema Objects
|
|
@@ -366,7 +380,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
366
380
|
} else {
|
|
367
381
|
// we're assuming here that we're dealing with JSON Pointer here
|
|
368
382
|
retrievalURI = this.toBaseURI($refBaseURI);
|
|
369
|
-
isInternalReference =
|
|
383
|
+
isInternalReference = this.baseURI === retrievalURI;
|
|
370
384
|
isExternalReference = !isInternalReference;
|
|
371
385
|
|
|
372
386
|
// ignore resolving internal Schema Objects
|