@speclynx/apidom-reference 6.2.0 → 7.0.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 +49 -0
- package/README.md +45 -0
- package/dist/apidom-reference.browser.js +4701 -3478
- package/dist/apidom-reference.browser.min.js +1 -1
- package/package.json +29 -28
- package/src/File.cjs +5 -2
- package/src/File.mjs +5 -2
- package/src/bundle/strategies/arazzo-1/index.cjs +3 -2
- package/src/bundle/strategies/arazzo-1/index.mjs +3 -2
- package/src/bundle/strategies/asyncapi-2/index.cjs +3 -2
- package/src/bundle/strategies/asyncapi-2/index.mjs +3 -2
- package/src/bundle/strategies/openapi-2/index.cjs +3 -2
- package/src/bundle/strategies/openapi-2/index.mjs +3 -2
- package/src/bundle/strategies/openapi-3-0/index.cjs +3 -2
- package/src/bundle/strategies/openapi-3-0/index.mjs +3 -2
- package/src/bundle/strategies/openapi-3-1/index.cjs +3 -2
- package/src/bundle/strategies/openapi-3-1/index.mjs +3 -2
- package/src/dereference/strategies/DereferenceVisitor.cjs +588 -0
- package/src/dereference/strategies/DereferenceVisitor.mjs +580 -0
- package/src/dereference/strategies/arazzo-1/index.cjs +14 -39
- package/src/dereference/strategies/arazzo-1/index.mjs +15 -40
- package/src/dereference/strategies/arazzo-1/visitor.cjs +207 -331
- package/src/dereference/strategies/arazzo-1/visitor.mjs +215 -338
- package/src/dereference/strategies/asyncapi-2/index.cjs +11 -39
- package/src/dereference/strategies/asyncapi-2/index.mjs +11 -39
- package/src/dereference/strategies/asyncapi-2/visitor.cjs +133 -425
- package/src/dereference/strategies/asyncapi-2/visitor.mjs +137 -429
- package/src/dereference/strategies/openapi-2/index.cjs +12 -42
- package/src/dereference/strategies/openapi-2/index.mjs +12 -42
- package/src/dereference/strategies/openapi-2/visitor.cjs +168 -532
- package/src/dereference/strategies/openapi-2/visitor.mjs +172 -536
- package/src/dereference/strategies/openapi-3-0/index.cjs +12 -42
- package/src/dereference/strategies/openapi-3-0/index.mjs +12 -42
- package/src/dereference/strategies/openapi-3-0/visitor.cjs +194 -468
- package/src/dereference/strategies/openapi-3-0/visitor.mjs +199 -473
- package/src/dereference/strategies/openapi-3-1/index.cjs +16 -42
- package/src/dereference/strategies/openapi-3-1/index.mjs +16 -42
- package/src/dereference/strategies/openapi-3-1/visitor.cjs +350 -602
- package/src/dereference/strategies/openapi-3-1/visitor.mjs +357 -608
- package/src/dereference/strategies/overlay-1/index.cjs +3 -2
- package/src/dereference/strategies/overlay-1/index.mjs +3 -2
- package/src/index.cjs +0 -7
- package/src/index.mjs +0 -1
- package/src/parse/index.cjs +9 -1
- package/src/parse/index.mjs +9 -1
- package/src/parse/parsers/apidom-json/index.cjs +2 -1
- package/src/parse/parsers/apidom-json/index.mjs +2 -1
- package/src/parse/parsers/arazzo-json-1/index.cjs +2 -1
- package/src/parse/parsers/arazzo-json-1/index.mjs +2 -1
- package/src/parse/parsers/arazzo-yaml-1/index.cjs +2 -1
- package/src/parse/parsers/arazzo-yaml-1/index.mjs +2 -1
- package/src/parse/parsers/asyncapi-json-2/index.cjs +2 -1
- package/src/parse/parsers/asyncapi-json-2/index.mjs +2 -1
- package/src/parse/parsers/asyncapi-yaml-2/index.cjs +2 -1
- package/src/parse/parsers/asyncapi-yaml-2/index.mjs +2 -1
- package/src/parse/parsers/json/index.cjs +2 -1
- package/src/parse/parsers/json/index.mjs +2 -1
- package/src/parse/parsers/openapi-json-2/index.cjs +2 -1
- package/src/parse/parsers/openapi-json-2/index.mjs +2 -1
- package/src/parse/parsers/openapi-json-3-0/index.cjs +2 -1
- package/src/parse/parsers/openapi-json-3-0/index.mjs +2 -1
- package/src/parse/parsers/openapi-json-3-1/index.cjs +2 -1
- package/src/parse/parsers/openapi-json-3-1/index.mjs +2 -1
- package/src/parse/parsers/openapi-yaml-2/index.cjs +2 -1
- package/src/parse/parsers/openapi-yaml-2/index.mjs +2 -1
- package/src/parse/parsers/openapi-yaml-3-0/index.cjs +2 -1
- package/src/parse/parsers/openapi-yaml-3-0/index.mjs +2 -1
- package/src/parse/parsers/openapi-yaml-3-1/index.cjs +2 -1
- package/src/parse/parsers/openapi-yaml-3-1/index.mjs +2 -1
- package/src/parse/parsers/overlay-json-1/index.cjs +2 -1
- package/src/parse/parsers/overlay-json-1/index.mjs +2 -1
- package/src/parse/parsers/overlay-yaml-1/index.cjs +2 -1
- package/src/parse/parsers/overlay-yaml-1/index.mjs +2 -1
- package/src/parse/parsers/yaml-1-2/index.cjs +2 -1
- package/src/parse/parsers/yaml-1-2/index.mjs +2 -1
- package/types/apidom-reference.d.ts +0 -9
- package/types/dereference/strategies/DereferenceVisitor.d.ts +224 -0
- package/types/dereference/strategies/arazzo-1/index.d.ts +0 -1
- package/types/dereference/strategies/arazzo-1/visitor.d.ts +38 -38
- package/types/dereference/strategies/asyncapi-2/index.d.ts +0 -1
- package/types/dereference/strategies/asyncapi-2/visitor.d.ts +13 -29
- package/types/dereference/strategies/openapi-2/index.d.ts +0 -1
- package/types/dereference/strategies/openapi-2/visitor.d.ts +14 -29
- package/types/dereference/strategies/openapi-3-0/index.d.ts +0 -1
- package/types/dereference/strategies/openapi-3-0/visitor.d.ts +13 -28
- package/types/dereference/strategies/openapi-3-1/index.d.ts +0 -1
- package/types/dereference/strategies/openapi-3-1/visitor.d.ts +37 -33
- package/types/index.d.ts +0 -1
- package/src/dereference/util.cjs +0 -33
- package/src/dereference/util.mjs +0 -27
- package/types/dereference/util.d.ts +0 -9
|
@@ -19,240 +19,161 @@ var _uri = require("./selectors/uri.cjs");
|
|
|
19
19
|
var _jsonPointer = require("../openapi-3-1/selectors/json-pointer.cjs");
|
|
20
20
|
var _util = require("../openapi-3-1/util.cjs");
|
|
21
21
|
var _util2 = require("./util.cjs");
|
|
22
|
-
var
|
|
23
|
-
var _MaximumDereferenceDepthError = _interopRequireDefault(require("../../../errors/MaximumDereferenceDepthError.cjs"));
|
|
24
|
-
var _MaximumResolveDepthError = _interopRequireDefault(require("../../../errors/MaximumResolveDepthError.cjs"));
|
|
22
|
+
var _DereferenceVisitor = _interopRequireDefault(require("../DereferenceVisitor.cjs"));
|
|
25
23
|
var url = _interopRequireWildcard(require("../../../util/url.cjs"));
|
|
26
|
-
var _index = _interopRequireDefault(require("../../../parse/index.cjs"));
|
|
27
|
-
var _Reference = _interopRequireDefault(require("../../../Reference.cjs"));
|
|
28
24
|
var _File = _interopRequireDefault(require("../../../File.cjs"));
|
|
29
|
-
var _util3 = require("../../util.cjs");
|
|
30
25
|
var _EvaluationJsonSchemaUriError = _interopRequireDefault(require("../../../errors/EvaluationJsonSchemaUriError.cjs"));
|
|
31
26
|
/**
|
|
32
|
-
*
|
|
27
|
+
* Type a JSON Schema `$ref` expects its target to have.
|
|
33
28
|
*/
|
|
29
|
+
const JSON_SCHEMA_TYPE = 'JSONSchema';
|
|
34
30
|
|
|
35
31
|
/**
|
|
36
|
-
*
|
|
32
|
+
* Context of a source being dereferenced: the `$id`s of the JSON Schema elements enclosing it.
|
|
37
33
|
*/
|
|
38
|
-
class Arazzo1DereferenceVisitor {
|
|
39
|
-
indirections;
|
|
40
|
-
reference;
|
|
41
34
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
* to the retrieval URI (`this.reference.uri`).
|
|
46
|
-
*/
|
|
47
|
-
baseURI;
|
|
48
|
-
options;
|
|
35
|
+
/**
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
49
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Dereferences an Arazzo document. Reusable Objects expect the type of their
|
|
41
|
+
* `referenced-element` meta, JSON Schema `$ref`s expect a JSON Schema.
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
class Arazzo1DereferenceVisitor extends _DereferenceVisitor.default {
|
|
50
46
|
/**
|
|
51
|
-
* Index of `$id`-bearing schemas per document, shared across
|
|
52
|
-
* of a single dereference run
|
|
47
|
+
* Index of `$id`-bearing schemas per document, shared across the visitors
|
|
48
|
+
* of a single dereference run.
|
|
53
49
|
*/
|
|
54
50
|
schema$idIndex;
|
|
55
|
-
visited;
|
|
56
51
|
|
|
57
52
|
/**
|
|
58
53
|
* `$id`s of the JSON Schema elements enclosing the traversal root within its
|
|
59
54
|
* document (outermost first). Empty when the root is the document itself; a
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
55
|
+
* visitor traversing a fragment is seeded with the `$id`s of the schemas the
|
|
56
|
+
* fragment sits under, so the `$ref`s and `$id`s within resolve against the
|
|
57
|
+
* same base as they would from the document root.
|
|
63
58
|
*/
|
|
64
59
|
ancestorSchema$ids;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Tracks element ancestors across dive-deep traversal boundaries.
|
|
68
|
-
* Used for cycle detection: if a referenced element is found in
|
|
69
|
-
* the ancestor lineage, a circular reference is detected.
|
|
70
|
-
*/
|
|
71
|
-
ancestors;
|
|
72
60
|
constructor({
|
|
73
61
|
reference,
|
|
74
62
|
options,
|
|
75
|
-
indirections = [],
|
|
76
63
|
schema$idIndex = new WeakMap(),
|
|
77
|
-
ancestors = new _util3.AncestorLineage(),
|
|
78
|
-
visited = new WeakSet(),
|
|
79
64
|
ancestorSchema$ids = []
|
|
80
65
|
}) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
66
|
+
super({
|
|
67
|
+
reference,
|
|
68
|
+
options
|
|
69
|
+
});
|
|
85
70
|
this.schema$idIndex = schema$idIndex;
|
|
86
|
-
this.ancestors = new _util3.AncestorLineage(...ancestors);
|
|
87
|
-
this.visited = visited;
|
|
88
71
|
this.ancestorSchema$ids = ancestorSchema$ids;
|
|
89
72
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const directAncestors = new Set(ancestorNodes.filter(_apidomDatamodel.isElement));
|
|
93
|
-
const ancestorsLineage = new _util3.AncestorLineage(...this.ancestors, directAncestors);
|
|
94
|
-
return [ancestorsLineage, directAncestors];
|
|
73
|
+
get strategyName() {
|
|
74
|
+
return 'arazzo-1';
|
|
95
75
|
}
|
|
96
|
-
|
|
97
|
-
|
|
76
|
+
createVisitor(reference, {
|
|
77
|
+
ancestorSchema$ids
|
|
78
|
+
}) {
|
|
79
|
+
return new Arazzo1DereferenceVisitor({
|
|
80
|
+
reference,
|
|
81
|
+
options: this.options,
|
|
82
|
+
schema$idIndex: this.schema$idIndex,
|
|
83
|
+
ancestorSchema$ids
|
|
84
|
+
});
|
|
98
85
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
throw new _MaximumResolveDepthError.default(`Maximum resolution depth of ${this.options.resolve.maxDepth} has been exceeded by file "${this.reference.uri}"`, {
|
|
103
|
-
maxDepth: this.options.resolve.maxDepth,
|
|
104
|
-
uri: this.reference.uri
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
const baseURI = this.toBaseURI(uri);
|
|
108
|
-
const {
|
|
109
|
-
refSet
|
|
110
|
-
} = this.reference;
|
|
111
|
-
|
|
112
|
-
// we've already processed this Reference in past
|
|
113
|
-
if (refSet.has(baseURI)) {
|
|
114
|
-
return refSet.find((0, _ramda.propEq)(baseURI, 'uri'));
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// identity-based referencing: URI matches `$self` of an already processed Arazzo document
|
|
118
|
-
const referenceBy$self = refSet.find((0, _util2.identifiedBy$self)(baseURI));
|
|
119
|
-
if (referenceBy$self !== undefined) {
|
|
120
|
-
return referenceBy$self;
|
|
121
|
-
}
|
|
122
|
-
const parseResult = await (0, _index.default)(url.unsanitize(baseURI), {
|
|
123
|
-
...this.options,
|
|
124
|
-
parse: {
|
|
125
|
-
...this.options.parse,
|
|
126
|
-
mediaType: 'text/plain'
|
|
127
|
-
}
|
|
86
|
+
refractTo(element, type) {
|
|
87
|
+
return type === JSON_SCHEMA_TYPE ? (0, _apidomNsArazzo.refractJSONSchema)(element) : (0, _apidomNsArazzo.refract)(element, {
|
|
88
|
+
element: type
|
|
128
89
|
});
|
|
90
|
+
}
|
|
91
|
+
isOfType(element, type) {
|
|
92
|
+
return type === JSON_SCHEMA_TYPE ? (0, _apidomNsArazzo.isJSONSchemaElement)(element) || (0, _apidomNsArazzo.isBooleanJSONSchemaElement)(element) : element.element === type;
|
|
93
|
+
}
|
|
129
94
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// $ref. That resolved element was produced using the entry document's resolution context
|
|
136
|
-
// (ancestors, indirections), which may differ from the external document's context.
|
|
137
|
-
// This can affect cycle detection in rare cross-document circular reference patterns.
|
|
138
|
-
//
|
|
139
|
-
// Remediation: evaluate JSON pointers against the immutable (original) parse tree
|
|
140
|
-
// instead of the mutable working copy. The `immutable://` reference below preserves
|
|
141
|
-
// the original tree and could be used for pointer evaluation, ensuring every resolution
|
|
142
|
-
// context always sees raw, unresolved elements and processes them with its own
|
|
143
|
-
// ancestors/indirections. The trade-off is that elements referenced by multiple
|
|
144
|
-
// documents would be resolved once per context instead of being reused.
|
|
145
|
-
const mutableReference = new _Reference.default({
|
|
146
|
-
uri: baseURI,
|
|
147
|
-
value: this.options.dereference.immutable ? (0, _apidomDatamodel.cloneDeep)(parseResult) : parseResult,
|
|
148
|
-
depth: this.reference.depth + 1
|
|
149
|
-
});
|
|
150
|
-
refSet.add(mutableReference);
|
|
151
|
-
if (this.options.dereference.immutable) {
|
|
152
|
-
// register new immutable reference with a refSet
|
|
153
|
-
const immutableReference = new _Reference.default({
|
|
154
|
-
uri: `immutable://${baseURI}`,
|
|
155
|
-
value: parseResult,
|
|
156
|
-
depth: this.reference.depth + 1
|
|
157
|
-
});
|
|
158
|
-
refSet.add(immutableReference);
|
|
159
|
-
}
|
|
160
|
-
return mutableReference;
|
|
95
|
+
/**
|
|
96
|
+
* Honors the Arazzo `$self` field when present, otherwise falls back to the retrieval URI.
|
|
97
|
+
*/
|
|
98
|
+
toDocumentBaseURI(reference) {
|
|
99
|
+
return (0, _util2.resolveArazzo$selfField)(reference.uri, reference.value?.result);
|
|
161
100
|
}
|
|
162
101
|
|
|
163
102
|
/**
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* For new errors: wraps in UnresolvableReferenceError with structured context
|
|
167
|
-
* (type, uri, location, codeFrame, refFieldName, refFieldValue, trace).
|
|
168
|
-
* For errors already wrapped by a nested visitor: prepends the current hop to the trace.
|
|
169
|
-
*
|
|
170
|
-
* Inner/intermediate visitors always throw to let the trace accumulate.
|
|
171
|
-
* Only the entry document visitor respects continueOnError (callback/swallow/throw).
|
|
103
|
+
* Identity-based referencing: URI matches `$self` of an already processed Arazzo document.
|
|
172
104
|
*/
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
} = this.options.dereference;
|
|
177
|
-
const isEntryDocument = url.stripHash(this.reference.refSet?.rootRef?.uri ?? '') === this.reference.uri;
|
|
178
|
-
const uri = this.reference.uri;
|
|
179
|
-
const type = referencingElement.element;
|
|
180
|
-
const codeFrame = (0, _apidomCore.toYAML)(referencingElement);
|
|
105
|
+
findReferenceByIdentity(uri) {
|
|
106
|
+
return this.reference.refSet?.find((0, _util2.identifiedBy$self)(uri));
|
|
107
|
+
}
|
|
181
108
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
109
|
+
/**
|
|
110
|
+
* A document as JSON Schema for locating schemas within it: a generic document is
|
|
111
|
+
* refracted to JSON Schema once per dereference run, a semantic one is used as it is.
|
|
112
|
+
*/
|
|
113
|
+
toJSONSchemaDocument(document) {
|
|
114
|
+
if (!(0, _apidomDatamodel.isPrimitiveElement)(document)) return document;
|
|
115
|
+
let byType = this.run.refracted.get(document);
|
|
116
|
+
if (byType === undefined) {
|
|
117
|
+
byType = new Map();
|
|
118
|
+
this.run.refracted.set(document, byType);
|
|
119
|
+
}
|
|
120
|
+
let refracted = byType.get(JSON_SCHEMA_TYPE);
|
|
121
|
+
if (refracted === undefined) {
|
|
122
|
+
refracted = (0, _apidomNsArazzo.refractJSONSchema)(document);
|
|
123
|
+
byType.set(JSON_SCHEMA_TYPE, refracted);
|
|
197
124
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
uri,
|
|
201
|
-
type,
|
|
202
|
-
refFieldName,
|
|
203
|
-
refFieldValue,
|
|
204
|
-
location,
|
|
205
|
-
codeFrame
|
|
206
|
-
};
|
|
125
|
+
return refracted;
|
|
126
|
+
}
|
|
207
127
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Indexes the `$id`-bearing schemas of a document for the run. Transcluded elements aren't
|
|
130
|
+
* indexed: they're copies of structures indexed where they're defined,
|
|
131
|
+
* and in a document dereferenced in place their shared structure would be walked once per path.
|
|
132
|
+
*/
|
|
133
|
+
index$ids(element) {
|
|
134
|
+
if (this.schema$idIndex.has(element)) return;
|
|
135
|
+
const entries = [];
|
|
136
|
+
(0, _apidomTraverse.traverse)(element, {
|
|
137
|
+
enter: path => {
|
|
138
|
+
if (this.isTranscluded(path.node)) {
|
|
139
|
+
path.skip();
|
|
140
|
+
} else if ((0, _util.isJSONSchemaElementWith$id)(path.node)) {
|
|
141
|
+
entries.push({
|
|
142
|
+
schema: path.node,
|
|
143
|
+
$ids: (0, _util.collectSchema$ids)(path)
|
|
144
|
+
});
|
|
220
145
|
}
|
|
221
146
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
trace: []
|
|
235
|
-
});
|
|
147
|
+
});
|
|
148
|
+
this.schema$idIndex.set(element, entries);
|
|
149
|
+
}
|
|
150
|
+
enter(path) {
|
|
151
|
+
if (this.isTranscluded(path.node)) {
|
|
152
|
+
path.skip();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// a Source Description parsed into the document has its own components: it's dereferenced
|
|
156
|
+
// in its own context by the strategy, never by the document referencing it
|
|
157
|
+
if (path.parentPath !== null && (0, _apidomDatamodel.isParseResultElement)(path.node) && (0, _apidomDatamodel.includesClasses)(path.node, ['source-description'])) {
|
|
158
|
+
path.skip();
|
|
236
159
|
}
|
|
237
|
-
if (!isEntryDocument || continueOnError === false) throw unresolvedError;
|
|
238
|
-
if (typeof continueOnError === 'function') continueOnError(unresolvedError);
|
|
239
160
|
}
|
|
240
|
-
ReusableElement(path) {
|
|
161
|
+
async ReusableElement(path) {
|
|
241
162
|
const referencingElement = path.node;
|
|
242
163
|
|
|
164
|
+
// the fields of a Reusable Object hold no references
|
|
165
|
+
path.skip();
|
|
166
|
+
|
|
243
167
|
// skip current Reusable Object if reference field is not defined as a string
|
|
244
168
|
if (!(0, _apidomDatamodel.isStringElement)(referencingElement.reference)) {
|
|
245
|
-
path.skip();
|
|
246
169
|
return;
|
|
247
170
|
}
|
|
248
171
|
|
|
249
172
|
// ignore if resolve.internal is false (Reusable Objects are internal references only)
|
|
250
173
|
if (!this.options.resolve.internal) {
|
|
251
|
-
path.skip();
|
|
252
174
|
return;
|
|
253
175
|
}
|
|
254
176
|
const runtimeExpression = (0, _apidomCore.toValue)(referencingElement.reference);
|
|
255
|
-
let referencedElement;
|
|
256
177
|
try {
|
|
257
178
|
// parse the runtime expression
|
|
258
179
|
const {
|
|
@@ -274,6 +195,7 @@ class Arazzo1DereferenceVisitor {
|
|
|
274
195
|
|
|
275
196
|
// evaluate runtime expression as JSON Pointer to get the referenced element
|
|
276
197
|
const jsonPointer = (0, _apidomJsonPointer.compile)(['components', tree.componentType, tree.componentName]);
|
|
198
|
+
let referencedElement;
|
|
277
199
|
try {
|
|
278
200
|
referencedElement = (0, _apidomJsonPointer.evaluate)(this.reference.value.result, jsonPointer);
|
|
279
201
|
} catch {
|
|
@@ -281,50 +203,62 @@ class Arazzo1DereferenceVisitor {
|
|
|
281
203
|
runtimeExpression
|
|
282
204
|
});
|
|
283
205
|
}
|
|
206
|
+
|
|
207
|
+
// the reference decides the type of the referenced component
|
|
208
|
+
const type = (0, _apidomCore.toValue)(referencingElement.meta.get('referenced-element')) ?? referencedElement.element;
|
|
209
|
+
await this.addTransclusion(path, {
|
|
210
|
+
source: referencedElement,
|
|
211
|
+
type,
|
|
212
|
+
reference: this.reference,
|
|
213
|
+
context: {
|
|
214
|
+
ancestorSchema$ids: []
|
|
215
|
+
}
|
|
216
|
+
}, {
|
|
217
|
+
toTranscludedElement: (element, target) => {
|
|
218
|
+
const reusableElement = element;
|
|
219
|
+
const mergedElement = (0, _apidomDatamodel.cloneShallow)(target);
|
|
220
|
+
// annotate with info about original referencing element
|
|
221
|
+
mergedElement.meta.set('ref-fields', {
|
|
222
|
+
reference: runtimeExpression,
|
|
223
|
+
value: (0, _apidomCore.toValue)(reusableElement.value)
|
|
224
|
+
});
|
|
225
|
+
// annotate with info about origin
|
|
226
|
+
mergedElement.meta.set('ref-origin', this.reference.uri);
|
|
227
|
+
mergedElement.meta.set('ref-type', element.element);
|
|
228
|
+
|
|
229
|
+
// override value field if present for Parameter Objects
|
|
230
|
+
if ((0, _apidomNsArazzo.isParameterElement)(mergedElement) && reusableElement.hasKey('value')) {
|
|
231
|
+
mergedElement.remove('value');
|
|
232
|
+
mergedElement.set('value', reusableElement.get('value'));
|
|
233
|
+
}
|
|
234
|
+
return mergedElement;
|
|
235
|
+
},
|
|
236
|
+
circular: {
|
|
237
|
+
uri: runtimeExpression,
|
|
238
|
+
meta: {
|
|
239
|
+
uri: this.reference.uri,
|
|
240
|
+
reference: runtimeExpression
|
|
241
|
+
},
|
|
242
|
+
details: {
|
|
243
|
+
runtimeExpression
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
});
|
|
284
247
|
} catch (error) {
|
|
285
248
|
this.handleError(`Error while dereferencing Reusable Object. Cannot resolve reference "${runtimeExpression}": ${error.message}`, error, referencingElement, 'reference', runtimeExpression, path);
|
|
286
|
-
return;
|
|
287
249
|
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Create a shallow clone of the referenced element to avoid modifying the original.
|
|
291
|
-
*/
|
|
292
|
-
const mergedElement = (0, _apidomDatamodel.cloneShallow)(referencedElement);
|
|
293
|
-
// annotate with info about original referencing element
|
|
294
|
-
mergedElement.meta.set('ref-fields', {
|
|
295
|
-
reference: runtimeExpression,
|
|
296
|
-
value: (0, _apidomCore.toValue)(referencingElement.value)
|
|
297
|
-
});
|
|
298
|
-
// annotate with info about origin
|
|
299
|
-
mergedElement.meta.set('ref-origin', this.reference.uri);
|
|
300
|
-
mergedElement.meta.set('ref-type', referencingElement.element);
|
|
301
|
-
|
|
302
|
-
// override value field if present for Parameter Objects
|
|
303
|
-
if ((0, _apidomNsArazzo.isParameterElement)(mergedElement) && referencingElement.hasKey('value')) {
|
|
304
|
-
mergedElement.remove('value');
|
|
305
|
-
mergedElement.set('value', referencingElement.get('value'));
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Transclude referencing element with merged referenced element.
|
|
310
|
-
*/
|
|
311
|
-
path.replaceWith(mergedElement);
|
|
312
|
-
path.skip();
|
|
313
250
|
}
|
|
314
251
|
async JSONSchemaElement(path) {
|
|
315
252
|
const referencingElement = path.node;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
if (!(0, _apidomDatamodel.isStringElement)(referencingElement.$ref)) {
|
|
253
|
+
if (this.isTranscluded(referencingElement)) {
|
|
254
|
+
path.skip();
|
|
319
255
|
return;
|
|
320
256
|
}
|
|
321
257
|
|
|
322
|
-
// skip current referencing
|
|
323
|
-
if (
|
|
324
|
-
path.skip();
|
|
258
|
+
// skip current referencing schema as $ref keyword was not defined
|
|
259
|
+
if (!(0, _apidomDatamodel.isStringElement)(referencingElement.$ref)) {
|
|
325
260
|
return;
|
|
326
261
|
}
|
|
327
|
-
const indirectionsSize = this.indirections.length;
|
|
328
262
|
try {
|
|
329
263
|
// compute baseURI using rules around $self, $id and $ref keywords
|
|
330
264
|
let reference = await this.toReference(url.unsanitize(this.reference.uri));
|
|
@@ -355,11 +289,12 @@ class Arazzo1DereferenceVisitor {
|
|
|
355
289
|
retrievalURI = this.toBaseURI($refBaseURI);
|
|
356
290
|
const selector = $refBaseURI;
|
|
357
291
|
const documentElement = reference.value.result;
|
|
358
|
-
const referenceAsSchema =
|
|
292
|
+
const referenceAsSchema = this.toJSONSchemaDocument(documentElement);
|
|
293
|
+
this.index$ids(referenceAsSchema);
|
|
359
294
|
// a document that is itself a fragment detached from its source carries
|
|
360
295
|
// the $ids enclosing it only as `ancestorSchema$ids`: its $ids are then
|
|
361
296
|
// indexed against the base that chain leaves in effect, and the chain
|
|
362
|
-
// prefixes the one of the located schema. A
|
|
297
|
+
// prefixes the one of the located schema. A visitor rooted at a
|
|
363
298
|
// fragment of a whole document indexes that document against its own base.
|
|
364
299
|
const rootNode = path.getAncestorNodes().at(-1) ?? path.node;
|
|
365
300
|
const isDocumentRoot = ((0, _apidomDatamodel.isParseResultElement)(rootNode) ? rootNode.result : rootNode) === documentElement;
|
|
@@ -373,7 +308,6 @@ class Arazzo1DereferenceVisitor {
|
|
|
373
308
|
if (isDocumentRoot) {
|
|
374
309
|
ancestorSchema$ids = [...this.ancestorSchema$ids, ...ancestorSchema$ids];
|
|
375
310
|
}
|
|
376
|
-
referencedElement = (0, _util2.maybeRefractToJSONSchemaElement)(referencedElement);
|
|
377
311
|
|
|
378
312
|
// ignore resolving internal Schema Objects
|
|
379
313
|
if (!this.options.resolve.internal && isInternalReference) {
|
|
@@ -403,12 +337,11 @@ class Arazzo1DereferenceVisitor {
|
|
|
403
337
|
}
|
|
404
338
|
reference = await this.toReference(url.unsanitize($refBaseURI));
|
|
405
339
|
const selector = _apidomJsonPointer.URIFragmentIdentifier.fromURIReference($refBaseURI);
|
|
406
|
-
const referenceAsSchema =
|
|
340
|
+
const referenceAsSchema = this.toJSONSchemaDocument(reference.value.result);
|
|
407
341
|
({
|
|
408
342
|
element: referencedElement,
|
|
409
343
|
ancestorSchema$ids
|
|
410
344
|
} = (0, _jsonPointer.locate)(referenceAsSchema, selector));
|
|
411
|
-
referencedElement = (0, _util2.maybeRefractToJSONSchemaElement)(referencedElement);
|
|
412
345
|
}
|
|
413
346
|
} catch (error) {
|
|
414
347
|
/**
|
|
@@ -433,12 +366,11 @@ class Arazzo1DereferenceVisitor {
|
|
|
433
366
|
}
|
|
434
367
|
reference = await this.toReference(url.unsanitize($refBaseURI));
|
|
435
368
|
const selector = (0, _$anchor.uriToAnchor)($refBaseURI);
|
|
436
|
-
const referenceAsSchema =
|
|
369
|
+
const referenceAsSchema = this.toJSONSchemaDocument(reference.value.result);
|
|
437
370
|
({
|
|
438
371
|
element: referencedElement,
|
|
439
372
|
ancestorSchema$ids
|
|
440
373
|
} = (0, _$anchor.locate)(selector, referenceAsSchema));
|
|
441
|
-
referencedElement = (0, _util2.maybeRefractToJSONSchemaElement)(referencedElement);
|
|
442
374
|
} else {
|
|
443
375
|
// we're assuming here that we're dealing with JSON Pointer here
|
|
444
376
|
retrievalURI = this.toBaseURI($refBaseURI);
|
|
@@ -457,140 +389,84 @@ class Arazzo1DereferenceVisitor {
|
|
|
457
389
|
}
|
|
458
390
|
reference = await this.toReference(url.unsanitize($refBaseURI));
|
|
459
391
|
const selector = _apidomJsonPointer.URIFragmentIdentifier.fromURIReference($refBaseURI);
|
|
460
|
-
const referenceAsSchema =
|
|
392
|
+
const referenceAsSchema = this.toJSONSchemaDocument(reference.value.result);
|
|
461
393
|
({
|
|
462
394
|
element: referencedElement,
|
|
463
395
|
ancestorSchema$ids
|
|
464
396
|
} = (0, _jsonPointer.locate)(referenceAsSchema, selector));
|
|
465
|
-
referencedElement = (0, _util2.maybeRefractToJSONSchemaElement)(referencedElement);
|
|
466
397
|
}
|
|
467
398
|
} else {
|
|
468
399
|
throw error;
|
|
469
400
|
}
|
|
470
401
|
}
|
|
471
|
-
this.indirections.push(referencingElement);
|
|
472
402
|
|
|
473
|
-
// detect direct
|
|
403
|
+
// detect direct reference
|
|
474
404
|
if (referencingElement === referencedElement) {
|
|
475
405
|
throw new _apidomError.ApiDOMStructuredError('Recursive JSON Schema reference detected', {
|
|
476
406
|
$ref: (0, _apidomCore.toValue)(referencingElement.$ref)
|
|
477
407
|
});
|
|
478
408
|
}
|
|
479
409
|
|
|
480
|
-
//
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
410
|
+
// a JSON Schema $ref reads whatever it points at as a JSON Schema
|
|
411
|
+
const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
|
|
412
|
+
const origin = reference.uri;
|
|
413
|
+
await this.addTransclusion(path, {
|
|
414
|
+
source: referencedElement,
|
|
415
|
+
type: JSON_SCHEMA_TYPE,
|
|
416
|
+
reference,
|
|
417
|
+
context: {
|
|
418
|
+
ancestorSchema$ids
|
|
419
|
+
}
|
|
420
|
+
}, {
|
|
421
|
+
toTranscludedElement: (element, target) => {
|
|
422
|
+
// Boolean JSON Schemas
|
|
423
|
+
if ((0, _apidomNsArazzo.isBooleanJSONSchemaElement)(target)) {
|
|
424
|
+
const booleanJsonSchemaElement = (0, _apidomDatamodel.cloneDeep)(target);
|
|
425
|
+
// annotate referenced element with info about original referencing element
|
|
426
|
+
booleanJsonSchemaElement.meta.set('ref-fields', {
|
|
427
|
+
$ref
|
|
428
|
+
});
|
|
429
|
+
// annotate referenced element with info about origin
|
|
430
|
+
booleanJsonSchemaElement.meta.set('ref-origin', origin);
|
|
431
|
+
booleanJsonSchemaElement.meta.set('ref-type', element.element);
|
|
432
|
+
return booleanJsonSchemaElement;
|
|
433
|
+
}
|
|
434
|
+
if (!(0, _apidomNsArazzo.isJSONSchemaElement)(target)) return target;
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Creating a new version of JSON Schema by merging fields from referenced Schema with referencing one.
|
|
438
|
+
*/
|
|
439
|
+
const mergedElement = (0, _apidomDatamodel.cloneShallow)(target);
|
|
440
|
+
// existing keywords from referencing schema overrides ones from referenced schema
|
|
441
|
+
element.forEach((value, keyElement, item) => {
|
|
442
|
+
mergedElement.remove((0, _apidomCore.toValue)(keyElement));
|
|
443
|
+
mergedElement.content.push(item);
|
|
495
444
|
});
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
$ref: (0, _apidomCore.toValue)(referencingElement.$ref)
|
|
445
|
+
mergedElement.remove('$ref');
|
|
446
|
+
// annotate referenced element with info about original referencing element
|
|
447
|
+
mergedElement.meta.set('ref-fields', {
|
|
448
|
+
$ref
|
|
501
449
|
});
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
* 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
|
|
518
|
-
*/
|
|
519
|
-
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
520
|
-
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
521
|
-
// content transplanted into the referencing site is traversed under that
|
|
522
|
-
// site's $id chain; a fragment enclosed by a different chain has its own
|
|
523
|
-
// $refs resolved in place first, by a nested visitor seeded with that chain
|
|
524
|
-
const hasDifferentEnclosingBase = (0, _util.resolveSchema$ids)((0, _util2.resolveArazzo$selfField)(reference.uri, reference.value.result), ancestorSchema$ids) !== (0, _util.resolveSchema$ids)(rootBaseURI, (0, _util.schema$idsOf)(path.getAncestorNodes().reverse()));
|
|
525
|
-
if ((isExternalReference || isNonEntryDocument || hasDifferentEnclosingBase || (0, _apidomNsArazzo.isJSONSchemaElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
526
|
-
if (shouldDetectCircular) {
|
|
527
|
-
this.visited.add(referencedElement);
|
|
450
|
+
// annotate fragment with info about origin
|
|
451
|
+
mergedElement.meta.set('ref-origin', origin);
|
|
452
|
+
mergedElement.meta.set('ref-type', element.element);
|
|
453
|
+
return mergedElement;
|
|
454
|
+
},
|
|
455
|
+
aliasField: '$ref',
|
|
456
|
+
circular: {
|
|
457
|
+
uri: $refBaseURI,
|
|
458
|
+
meta: {
|
|
459
|
+
uri: origin,
|
|
460
|
+
$ref
|
|
461
|
+
},
|
|
462
|
+
details: {
|
|
463
|
+
$ref
|
|
464
|
+
}
|
|
528
465
|
}
|
|
529
|
-
|
|
530
|
-
// append referencing reference to ancestors lineage
|
|
531
|
-
directAncestors.add(referencingElement);
|
|
532
|
-
const visitor = new Arazzo1DereferenceVisitor({
|
|
533
|
-
reference,
|
|
534
|
-
indirections: [...this.indirections],
|
|
535
|
-
options: this.options,
|
|
536
|
-
schema$idIndex: this.schema$idIndex,
|
|
537
|
-
visited: this.visited,
|
|
538
|
-
ancestors: ancestorsLineage,
|
|
539
|
-
ancestorSchema$ids
|
|
540
|
-
});
|
|
541
|
-
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
542
|
-
mutable: true,
|
|
543
|
-
skipVisited: 'skip'
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
// remove referencing reference from ancestors lineage
|
|
547
|
-
directAncestors.delete(referencingElement);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
// Boolean JSON Schemas
|
|
551
|
-
if ((0, _apidomNsArazzo.isBooleanJSONSchemaElement)(referencedElement)) {
|
|
552
|
-
const booleanJsonSchemaElement = (0, _apidomDatamodel.cloneDeep)(referencedElement);
|
|
553
|
-
// annotate referenced element with info about original referencing element
|
|
554
|
-
booleanJsonSchemaElement.meta.set('ref-fields', {
|
|
555
|
-
$ref: (0, _apidomCore.toValue)(referencingElement.$ref)
|
|
556
|
-
});
|
|
557
|
-
// annotate referenced element with info about origin
|
|
558
|
-
booleanJsonSchemaElement.meta.set('ref-origin', reference.uri);
|
|
559
|
-
booleanJsonSchemaElement.meta.set('ref-type', referencingElement.element);
|
|
560
|
-
path.replaceWith(booleanJsonSchemaElement);
|
|
561
|
-
path.skip();
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* Creating a new version of JSON Schema by merging fields from referenced Schema with referencing one.
|
|
567
|
-
*/
|
|
568
|
-
if ((0, _apidomNsArazzo.isJSONSchemaElement)(referencedElement)) {
|
|
569
|
-
const mergedElement = (0, _apidomDatamodel.cloneShallow)(referencedElement);
|
|
570
|
-
// existing keywords from referencing schema overrides ones from referenced schema
|
|
571
|
-
referencingElement.forEach((value, keyElement, item) => {
|
|
572
|
-
mergedElement.remove((0, _apidomCore.toValue)(keyElement));
|
|
573
|
-
mergedElement.content.push(item);
|
|
574
|
-
});
|
|
575
|
-
mergedElement.remove('$ref');
|
|
576
|
-
// annotate referenced element with info about original referencing element
|
|
577
|
-
mergedElement.meta.set('ref-fields', {
|
|
578
|
-
$ref: (0, _apidomCore.toValue)(referencingElement.$ref)
|
|
579
|
-
});
|
|
580
|
-
// annotate fragment with info about origin
|
|
581
|
-
mergedElement.meta.set('ref-origin', reference.uri);
|
|
582
|
-
mergedElement.meta.set('ref-type', referencingElement.element);
|
|
583
|
-
referencedElement = mergedElement;
|
|
584
|
-
}
|
|
585
|
-
/**
|
|
586
|
-
* Transclude referencing element with merged referenced element.
|
|
587
|
-
*/
|
|
588
|
-
path.replaceWith(referencedElement);
|
|
466
|
+
});
|
|
589
467
|
} catch (error) {
|
|
590
468
|
const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
|
|
591
469
|
this.handleError(`Error while dereferencing Schema Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
|
|
592
|
-
} finally {
|
|
593
|
-
if (this.indirections.length > indirectionsSize) this.indirections.pop();
|
|
594
470
|
}
|
|
595
471
|
}
|
|
596
472
|
}
|