@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
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
8
|
exports.default = void 0;
|
|
9
|
-
var _ramda = require("ramda");
|
|
10
9
|
var _ramdaAdjunct = require("ramda-adjunct");
|
|
11
10
|
var _apidomDatamodel = require("@speclynx/apidom-datamodel");
|
|
12
11
|
var _apidomCore = require("@speclynx/apidom-core");
|
|
@@ -14,362 +13,141 @@ var _apidomError = require("@speclynx/apidom-error");
|
|
|
14
13
|
var _apidomTraverse = require("@speclynx/apidom-traverse");
|
|
15
14
|
var _apidomJsonPointer = require("@speclynx/apidom-json-pointer");
|
|
16
15
|
var _apidomNsOpenapi = require("@speclynx/apidom-ns-openapi-3-0");
|
|
17
|
-
var
|
|
18
|
-
var _MaximumDereferenceDepthError = _interopRequireDefault(require("../../../errors/MaximumDereferenceDepthError.cjs"));
|
|
19
|
-
var _MaximumResolveDepthError = _interopRequireDefault(require("../../../errors/MaximumResolveDepthError.cjs"));
|
|
16
|
+
var _DereferenceVisitor = _interopRequireDefault(require("../DereferenceVisitor.cjs"));
|
|
20
17
|
var url = _interopRequireWildcard(require("../../../util/url.cjs"));
|
|
21
|
-
var _index = _interopRequireDefault(require("../../../parse/index.cjs"));
|
|
22
|
-
var _Reference = _interopRequireDefault(require("../../../Reference.cjs"));
|
|
23
|
-
var _util = require("../../util.cjs");
|
|
24
18
|
/**
|
|
25
19
|
* @public
|
|
26
20
|
*/
|
|
27
21
|
|
|
28
22
|
/**
|
|
23
|
+
* Dereferences an OpenAPI 3.0 document. Reference Objects expect the type of their
|
|
24
|
+
* `referenced-element` meta, Path Item `$ref`s a Path Item Object. Link Objects get the
|
|
25
|
+
* Operation Object they point at attached, Example Objects the external value.
|
|
26
|
+
*
|
|
29
27
|
* @public
|
|
30
28
|
*/
|
|
31
|
-
class OpenAPI3_0DereferenceVisitor {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
options;
|
|
35
|
-
refractCache;
|
|
36
|
-
visited;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Tracks element ancestors across dive-deep traversal boundaries.
|
|
40
|
-
* Used for cycle detection: if a referenced element is found in
|
|
41
|
-
* the ancestor lineage, a circular reference is detected.
|
|
42
|
-
*/
|
|
43
|
-
ancestors;
|
|
44
|
-
constructor({
|
|
45
|
-
reference,
|
|
46
|
-
options,
|
|
47
|
-
indirections = [],
|
|
48
|
-
ancestors = new _util.AncestorLineage(),
|
|
49
|
-
refractCache = new WeakMap(),
|
|
50
|
-
visited = new WeakSet()
|
|
51
|
-
}) {
|
|
52
|
-
this.indirections = indirections;
|
|
53
|
-
this.reference = reference;
|
|
54
|
-
this.options = options;
|
|
55
|
-
this.ancestors = new _util.AncestorLineage(...ancestors);
|
|
56
|
-
this.refractCache = refractCache;
|
|
57
|
-
this.visited = visited;
|
|
58
|
-
}
|
|
59
|
-
toAncestorLineage(path) {
|
|
60
|
-
const ancestorNodes = path.getAncestorNodes();
|
|
61
|
-
const directAncestors = new Set(ancestorNodes.filter(_apidomDatamodel.isElement));
|
|
62
|
-
const ancestorsLineage = new _util.AncestorLineage(...this.ancestors, directAncestors);
|
|
63
|
-
return [ancestorsLineage, directAncestors];
|
|
29
|
+
class OpenAPI3_0DereferenceVisitor extends _DereferenceVisitor.default {
|
|
30
|
+
get strategyName() {
|
|
31
|
+
return 'openapi-3-0';
|
|
64
32
|
}
|
|
65
|
-
|
|
66
|
-
return
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// detect maximum depth of resolution
|
|
70
|
-
if (this.reference.depth >= this.options.resolve.maxDepth) {
|
|
71
|
-
throw new _MaximumResolveDepthError.default(`Maximum resolution depth of ${this.options.resolve.maxDepth} has been exceeded by file "${this.reference.uri}"`, {
|
|
72
|
-
maxDepth: this.options.resolve.maxDepth,
|
|
73
|
-
uri: this.reference.uri
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
const baseURI = this.toBaseURI(uri);
|
|
77
|
-
const {
|
|
78
|
-
refSet
|
|
79
|
-
} = this.reference;
|
|
80
|
-
|
|
81
|
-
// we've already processed this Reference in past
|
|
82
|
-
if (refSet.has(baseURI)) {
|
|
83
|
-
return refSet.find((0, _ramda.propEq)(baseURI, 'uri'));
|
|
84
|
-
}
|
|
85
|
-
const parseResult = await (0, _index.default)(url.unsanitize(baseURI), {
|
|
86
|
-
...this.options,
|
|
87
|
-
parse: {
|
|
88
|
-
...this.options.parse,
|
|
89
|
-
mediaType: 'text/plain'
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// register new mutable reference with a refSet
|
|
94
|
-
//
|
|
95
|
-
// NOTE(known limitation): the mutable reference is mutated in place during traversal
|
|
96
|
-
// (via `{ mutable: true }`). When an external document evaluates a JSON pointer back
|
|
97
|
-
// into this document, it may receive an already-resolved element instead of the original
|
|
98
|
-
// $ref. That resolved element was produced using the entry document's resolution context
|
|
99
|
-
// (ancestors, indirections), which may differ from the external document's context.
|
|
100
|
-
// This can affect cycle detection in rare cross-document circular reference patterns.
|
|
101
|
-
//
|
|
102
|
-
// Remediation: evaluate JSON pointers against the immutable (original) parse tree
|
|
103
|
-
// instead of the mutable working copy. The `immutable://` reference below preserves
|
|
104
|
-
// the original tree and could be used for pointer evaluation, ensuring every resolution
|
|
105
|
-
// context always sees raw, unresolved elements and processes them with its own
|
|
106
|
-
// ancestors/indirections. The trade-off is that elements referenced by multiple
|
|
107
|
-
// documents would be resolved once per context instead of being reused.
|
|
108
|
-
const mutableReference = new _Reference.default({
|
|
109
|
-
uri: baseURI,
|
|
110
|
-
value: this.options.dereference.immutable ? (0, _apidomDatamodel.cloneDeep)(parseResult) : parseResult,
|
|
111
|
-
depth: this.reference.depth + 1
|
|
33
|
+
createVisitor(reference) {
|
|
34
|
+
return new OpenAPI3_0DereferenceVisitor({
|
|
35
|
+
reference,
|
|
36
|
+
options: this.options
|
|
112
37
|
});
|
|
113
|
-
refSet.add(mutableReference);
|
|
114
|
-
if (this.options.dereference.immutable) {
|
|
115
|
-
// register new immutable reference with a refSet
|
|
116
|
-
const immutableReference = new _Reference.default({
|
|
117
|
-
uri: `immutable://${baseURI}`,
|
|
118
|
-
value: parseResult,
|
|
119
|
-
depth: this.reference.depth + 1
|
|
120
|
-
});
|
|
121
|
-
refSet.add(immutableReference);
|
|
122
|
-
}
|
|
123
|
-
return mutableReference;
|
|
124
38
|
}
|
|
125
39
|
|
|
126
40
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* For new errors: wraps in UnresolvableReferenceError with structured context
|
|
130
|
-
* (type, uri, location, codeFrame, refFieldName, refFieldValue, trace).
|
|
131
|
-
* For errors already wrapped by a nested visitor: prepends the current hop to the trace.
|
|
132
|
-
*
|
|
133
|
-
* Inner/intermediate visitors always throw to let the trace accumulate.
|
|
134
|
-
* Only the entry document visitor respects continueOnError (callback/swallow/throw).
|
|
41
|
+
* A Reference Object stands for the type its reference expects: it's dereferenced as that type.
|
|
135
42
|
*/
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
} = this.options.dereference;
|
|
140
|
-
const isEntryDocument = url.stripHash(this.reference.refSet?.rootRef?.uri ?? '') === this.reference.uri;
|
|
141
|
-
const uri = this.reference.uri;
|
|
142
|
-
const type = referencingElement.element;
|
|
143
|
-
const codeFrame = (0, _apidomCore.toYAML)(referencingElement);
|
|
144
|
-
|
|
145
|
-
// find element location by identity in the document tree.
|
|
146
|
-
// guarded: this.reference.value may not be a ParseResultElement or may lack a result.
|
|
147
|
-
// falls back to visitorPath which may produce an incomplete path when
|
|
148
|
-
// dereferenceApiDOM is called with a fragment (cloneShallow creates a new root identity).
|
|
149
|
-
let location;
|
|
150
|
-
const root = this.reference.value.result;
|
|
151
|
-
if ((0, _apidomDatamodel.isElement)(root)) {
|
|
152
|
-
(0, _apidomTraverse.traverse)(root, {
|
|
153
|
-
enter: p => {
|
|
154
|
-
if (p.node === referencingElement || this.refractCache.get(p.node) === referencingElement) {
|
|
155
|
-
location = p.formatPath();
|
|
156
|
-
p.stop();
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
location ??= visitorPath.formatPath();
|
|
162
|
-
const hop = {
|
|
163
|
-
uri,
|
|
164
|
-
type,
|
|
165
|
-
refFieldName,
|
|
166
|
-
refFieldValue,
|
|
167
|
-
location,
|
|
168
|
-
codeFrame
|
|
169
|
-
};
|
|
43
|
+
isOfType(element, type) {
|
|
44
|
+
return (0, _apidomNsOpenapi.isReferenceElement)(element) || element.element === type;
|
|
45
|
+
}
|
|
170
46
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
for (const h of error.trace) {
|
|
182
|
-
if (h.uri === refBaseURI && h.location) h.location = fragment + h.location;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
// @ts-ignore
|
|
186
|
-
error.trace = [hop, ...error.trace];
|
|
187
|
-
unresolvedError = error;
|
|
188
|
-
} else {
|
|
189
|
-
unresolvedError = new _UnresolvableReferenceError.default(message, {
|
|
190
|
-
cause: error,
|
|
191
|
-
type,
|
|
192
|
-
uri,
|
|
193
|
-
location,
|
|
194
|
-
codeFrame,
|
|
195
|
-
refFieldName,
|
|
196
|
-
refFieldValue,
|
|
197
|
-
trace: []
|
|
198
|
-
});
|
|
47
|
+
/**
|
|
48
|
+
* A generic structure holding a `$ref` is a Reference Object to the expected type,
|
|
49
|
+
* unless the type has its own `$ref` field (Path Item Object).
|
|
50
|
+
*/
|
|
51
|
+
refractTo(element, type) {
|
|
52
|
+
if (type !== 'pathItem' && (0, _apidomNsOpenapi.isReferenceLikeElement)(element)) {
|
|
53
|
+
const referenceElement = (0, _apidomNsOpenapi.refractReference)(element);
|
|
54
|
+
referenceElement.meta.set('referenced-element', type);
|
|
55
|
+
return referenceElement;
|
|
199
56
|
}
|
|
200
|
-
|
|
201
|
-
|
|
57
|
+
return (0, _apidomNsOpenapi.refract)(element, {
|
|
58
|
+
element: type
|
|
59
|
+
});
|
|
202
60
|
}
|
|
203
61
|
async ReferenceElement(path) {
|
|
204
62
|
const referencingElement = path.node;
|
|
205
63
|
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
64
|
+
// the fields of a Reference Object hold no references
|
|
65
|
+
path.skip();
|
|
210
66
|
|
|
211
|
-
//
|
|
212
|
-
if (this.
|
|
213
|
-
path.skip();
|
|
67
|
+
// ignore Reference Object without a string $ref, e.g. an empty YAML value
|
|
68
|
+
if (this.isTranscluded(referencingElement) || !(0, _apidomDatamodel.isStringElement)(referencingElement.$ref)) {
|
|
214
69
|
return;
|
|
215
70
|
}
|
|
216
|
-
const
|
|
71
|
+
const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
|
|
72
|
+
const retrievalURI = this.toBaseURI($ref);
|
|
217
73
|
const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
|
|
218
74
|
const isExternalReference = !isInternalReference;
|
|
219
75
|
|
|
220
76
|
// ignore resolving internal Reference Objects
|
|
221
77
|
if (!this.options.resolve.internal && isInternalReference) {
|
|
222
|
-
// skip traversing this reference element and all it's child elements
|
|
223
|
-
path.skip();
|
|
224
78
|
return;
|
|
225
79
|
}
|
|
226
80
|
// ignore resolving external Reference Objects
|
|
227
81
|
if (!this.options.resolve.external && isExternalReference) {
|
|
228
|
-
// skip traversing this reference element and all it's child elements
|
|
229
|
-
path.skip();
|
|
230
82
|
return;
|
|
231
83
|
}
|
|
232
|
-
const $refBaseURI = url.resolve(retrievalURI,
|
|
233
|
-
const indirectionsSize = this.indirections.length;
|
|
84
|
+
const $refBaseURI = url.resolve(retrievalURI, $ref);
|
|
234
85
|
try {
|
|
235
|
-
const reference = await this.toReference(
|
|
236
|
-
this.indirections.push(referencingElement);
|
|
86
|
+
const reference = await this.toReference($ref);
|
|
237
87
|
const jsonPointer = _apidomJsonPointer.URIFragmentIdentifier.fromURIReference($refBaseURI);
|
|
238
|
-
|
|
239
88
|
// possibly non-semantic fragment
|
|
240
|
-
|
|
89
|
+
const referencedElement = (0, _apidomJsonPointer.evaluate)(reference.value.result, jsonPointer);
|
|
241
90
|
|
|
242
|
-
//
|
|
243
|
-
const referencedElementType = referencingElement.meta.get('referenced-element');
|
|
244
|
-
if (referencedElement.element !== referencedElementType && !(0, _apidomNsOpenapi.isReferenceElement)(referencedElement)) {
|
|
245
|
-
if (this.refractCache.has(referencedElement)) {
|
|
246
|
-
referencedElement = this.refractCache.get(referencedElement);
|
|
247
|
-
} else if ((0, _apidomNsOpenapi.isReferenceLikeElement)(referencedElement)) {
|
|
248
|
-
// handling generic indirect references
|
|
249
|
-
const sourceElement = referencedElement;
|
|
250
|
-
referencedElement = (0, _apidomNsOpenapi.refractReference)(referencedElement);
|
|
251
|
-
referencedElement.meta.set('referenced-element', referencedElementType);
|
|
252
|
-
this.refractCache.set(sourceElement, referencedElement);
|
|
253
|
-
} else {
|
|
254
|
-
// handling direct references
|
|
255
|
-
const sourceElement = referencedElement;
|
|
256
|
-
referencedElement = (0, _apidomNsOpenapi.refract)(referencedElement, {
|
|
257
|
-
element: referencedElementType
|
|
258
|
-
});
|
|
259
|
-
this.refractCache.set(sourceElement, referencedElement);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// detect direct or indirect reference
|
|
91
|
+
// detect direct reference
|
|
264
92
|
if (referencingElement === referencedElement) {
|
|
265
93
|
throw new _apidomError.ApiDOMStructuredError('Recursive Reference Object detected', {
|
|
266
|
-
$ref
|
|
94
|
+
$ref
|
|
267
95
|
});
|
|
268
96
|
}
|
|
269
97
|
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
98
|
+
// a reference without an expected type reads its target as its own type
|
|
99
|
+
const type = (0, _apidomCore.toValue)(referencingElement.meta.get('referenced-element')) ?? referencedElement.element;
|
|
100
|
+
await this.addTransclusion(path, {
|
|
101
|
+
source: referencedElement,
|
|
102
|
+
type,
|
|
103
|
+
reference,
|
|
104
|
+
context: undefined
|
|
105
|
+
}, {
|
|
106
|
+
toTranscludedElement: (element, target) => {
|
|
107
|
+
// a chain of Reference Objects leading back to itself never reaches a value
|
|
108
|
+
if ((0, _apidomNsOpenapi.isReferenceElement)(target)) return element;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Creating a new version of referenced element to avoid modifying the original one.
|
|
112
|
+
*/
|
|
113
|
+
const mergedElement = (0, _apidomDatamodel.cloneShallow)(target);
|
|
114
|
+
// annotate referenced element with info about original referencing element
|
|
115
|
+
mergedElement.meta.set('ref-fields', {
|
|
116
|
+
$ref
|
|
285
117
|
});
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
118
|
+
// annotate fragment with info about origin
|
|
119
|
+
mergedElement.meta.set('ref-origin', reference.uri);
|
|
120
|
+
mergedElement.meta.set('ref-type', element.element);
|
|
121
|
+
return mergedElement;
|
|
122
|
+
},
|
|
123
|
+
circular: {
|
|
124
|
+
uri: $refBaseURI,
|
|
125
|
+
meta: {
|
|
289
126
|
uri: reference.uri,
|
|
290
|
-
$ref
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
path.skip();
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Dive deep into the fragment.
|
|
302
|
-
*
|
|
303
|
-
* Cases to consider:
|
|
304
|
-
* 1. We're crossing document boundary
|
|
305
|
-
* 2. Fragment is from non-entry document
|
|
306
|
-
* 3. Fragment is a Reference Object. We need to follow it to get the eventual value
|
|
307
|
-
* 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
|
|
308
|
-
*/
|
|
309
|
-
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
310
|
-
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
311
|
-
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isReferenceElement)(referencedElement) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
312
|
-
if (shouldDetectCircular) {
|
|
313
|
-
this.visited.add(referencedElement);
|
|
127
|
+
$ref
|
|
128
|
+
},
|
|
129
|
+
details: {
|
|
130
|
+
$ref
|
|
131
|
+
}
|
|
314
132
|
}
|
|
315
|
-
|
|
316
|
-
// append referencing reference to ancestors lineage
|
|
317
|
-
directAncestors.add(referencingElement);
|
|
318
|
-
const visitor = new OpenAPI3_0DereferenceVisitor({
|
|
319
|
-
reference,
|
|
320
|
-
indirections: [...this.indirections],
|
|
321
|
-
options: this.options,
|
|
322
|
-
refractCache: this.refractCache,
|
|
323
|
-
visited: this.visited,
|
|
324
|
-
ancestors: ancestorsLineage
|
|
325
|
-
});
|
|
326
|
-
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
327
|
-
mutable: true,
|
|
328
|
-
skipVisited: 'skip'
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
// remove referencing reference from ancestors lineage
|
|
332
|
-
directAncestors.delete(referencingElement);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Creating a new version of referenced element to avoid modifying the original one.
|
|
337
|
-
*/
|
|
338
|
-
const mergedElement = (0, _apidomDatamodel.cloneShallow)(referencedElement);
|
|
339
|
-
// annotate referenced element with info about original referencing element
|
|
340
|
-
mergedElement.meta.set('ref-fields', {
|
|
341
|
-
$ref: (0, _apidomCore.toValue)(referencingElement.$ref)
|
|
342
133
|
});
|
|
343
|
-
// annotate fragment with info about origin
|
|
344
|
-
mergedElement.meta.set('ref-origin', reference.uri);
|
|
345
|
-
mergedElement.meta.set('ref-type', referencingElement.element);
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Transclude referencing element with merged referenced element.
|
|
349
|
-
*/
|
|
350
|
-
path.replaceWith(mergedElement);
|
|
351
|
-
path.skip();
|
|
352
134
|
} catch (error) {
|
|
353
|
-
const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
|
|
354
135
|
this.handleError(`Error while dereferencing Reference Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
|
|
355
|
-
} finally {
|
|
356
|
-
if (this.indirections.length > indirectionsSize) this.indirections.pop();
|
|
357
136
|
}
|
|
358
137
|
}
|
|
359
138
|
async PathItemElement(path) {
|
|
360
139
|
const referencingElement = path.node;
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
if (!(0, _apidomDatamodel.isStringElement)(referencingElement.$ref)) {
|
|
140
|
+
if (this.isTranscluded(referencingElement)) {
|
|
141
|
+
path.skip();
|
|
364
142
|
return;
|
|
365
143
|
}
|
|
366
144
|
|
|
367
|
-
//
|
|
368
|
-
if (
|
|
369
|
-
path.skip();
|
|
145
|
+
// ignore PathItemElement without $ref field
|
|
146
|
+
if (!(0, _apidomDatamodel.isStringElement)(referencingElement.$ref)) {
|
|
370
147
|
return;
|
|
371
148
|
}
|
|
372
|
-
const
|
|
149
|
+
const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
|
|
150
|
+
const retrievalURI = this.toBaseURI($ref);
|
|
373
151
|
const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
|
|
374
152
|
const isExternalReference = !isInternalReference;
|
|
375
153
|
|
|
@@ -383,134 +161,70 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
383
161
|
// skip traversing this Path Item element but traverse all it's child elements
|
|
384
162
|
return;
|
|
385
163
|
}
|
|
386
|
-
const $refBaseURI = url.resolve(retrievalURI,
|
|
387
|
-
const indirectionsSize = this.indirections.length;
|
|
164
|
+
const $refBaseURI = url.resolve(retrievalURI, $ref);
|
|
388
165
|
try {
|
|
389
|
-
const reference = await this.toReference(
|
|
390
|
-
this.indirections.push(referencingElement);
|
|
166
|
+
const reference = await this.toReference($ref);
|
|
391
167
|
const jsonPointer = _apidomJsonPointer.URIFragmentIdentifier.fromURIReference($refBaseURI);
|
|
392
|
-
|
|
393
168
|
// possibly non-semantic referenced element
|
|
394
|
-
|
|
169
|
+
const referencedElement = (0, _apidomJsonPointer.evaluate)(reference.value.result, jsonPointer);
|
|
395
170
|
|
|
396
|
-
//
|
|
397
|
-
if (!(0, _apidomNsOpenapi.isPathItemElement)(referencedElement)) {
|
|
398
|
-
if (this.refractCache.has(referencedElement)) {
|
|
399
|
-
referencedElement = this.refractCache.get(referencedElement);
|
|
400
|
-
} else {
|
|
401
|
-
const sourceElement = referencedElement;
|
|
402
|
-
referencedElement = (0, _apidomNsOpenapi.refractPathItem)(referencedElement);
|
|
403
|
-
this.refractCache.set(sourceElement, referencedElement);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// detect direct or indirect reference
|
|
171
|
+
// detect direct reference
|
|
408
172
|
if (referencingElement === referencedElement) {
|
|
409
173
|
throw new _apidomError.ApiDOMStructuredError('Recursive Path Item Object reference detected', {
|
|
410
|
-
$ref
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// detect maximum depth of dereferencing
|
|
415
|
-
if (this.indirections.length > this.options.dereference.maxDepth) {
|
|
416
|
-
throw new _MaximumDereferenceDepthError.default(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`, {
|
|
417
|
-
maxDepth: this.options.dereference.maxDepth,
|
|
418
|
-
uri: this.reference.uri
|
|
174
|
+
$ref
|
|
419
175
|
});
|
|
420
176
|
}
|
|
177
|
+
await this.addTransclusion(path, {
|
|
178
|
+
source: referencedElement,
|
|
179
|
+
type: 'pathItem',
|
|
180
|
+
reference,
|
|
181
|
+
context: undefined
|
|
182
|
+
}, {
|
|
183
|
+
toTranscludedElement: (element, target) => {
|
|
184
|
+
if (!(0, _apidomNsOpenapi.isPathItemElement)(target)) return target;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Creating a new version of Path Item by merging fields from referenced Path Item with referencing one.
|
|
188
|
+
*/
|
|
189
|
+
const mergedElement = (0, _apidomDatamodel.cloneShallow)(target);
|
|
190
|
+
// existing keywords from referencing PathItemElement overrides ones from referenced element
|
|
191
|
+
element.forEach((value, keyElement, item) => {
|
|
192
|
+
mergedElement.remove((0, _apidomCore.toValue)(keyElement));
|
|
193
|
+
mergedElement.content.push(item);
|
|
194
|
+
});
|
|
195
|
+
mergedElement.remove('$ref');
|
|
421
196
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
reference.refSet.circular = true;
|
|
426
|
-
if (this.options.dereference.circular === 'error') {
|
|
427
|
-
throw new _apidomError.ApiDOMStructuredError('Circular reference detected', {
|
|
428
|
-
$ref: (0, _apidomCore.toValue)(referencingElement.$ref)
|
|
197
|
+
// annotate referenced element with info about original referencing element
|
|
198
|
+
mergedElement.meta.set('ref-fields', {
|
|
199
|
+
$ref
|
|
429
200
|
});
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
201
|
+
// annotate referenced element with info about origin and type
|
|
202
|
+
mergedElement.meta.set('ref-origin', reference.uri);
|
|
203
|
+
mergedElement.meta.set('ref-type', element.element);
|
|
204
|
+
return mergedElement;
|
|
205
|
+
},
|
|
206
|
+
aliasField: '$ref',
|
|
207
|
+
circular: {
|
|
208
|
+
uri: $refBaseURI,
|
|
209
|
+
meta: {
|
|
433
210
|
uri: reference.uri,
|
|
434
|
-
$ref
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
path.skip();
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
* Dive deep into the fragment.
|
|
446
|
-
*
|
|
447
|
-
* Cases to consider:
|
|
448
|
-
* 1. We're crossing document boundary
|
|
449
|
-
* 2. Fragment is from non-entry document
|
|
450
|
-
* 3. Fragment is a Path Item Object with $ref field. We need to follow it to get the eventual value
|
|
451
|
-
* 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
|
|
452
|
-
*/
|
|
453
|
-
const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
|
|
454
|
-
const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
|
|
455
|
-
if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isPathItemElement)(referencedElement) && (0, _apidomDatamodel.isStringElement)(referencedElement.$ref) || shouldDetectCircular && !this.visited.has(referencedElement)) && !ancestorsLineage.includesCycle(referencedElement)) {
|
|
456
|
-
if (shouldDetectCircular) {
|
|
457
|
-
this.visited.add(referencedElement);
|
|
211
|
+
$ref
|
|
212
|
+
},
|
|
213
|
+
details: {
|
|
214
|
+
$ref
|
|
215
|
+
}
|
|
458
216
|
}
|
|
459
|
-
|
|
460
|
-
// append referencing reference to ancestors lineage
|
|
461
|
-
directAncestors.add(referencingElement);
|
|
462
|
-
const visitor = new OpenAPI3_0DereferenceVisitor({
|
|
463
|
-
reference,
|
|
464
|
-
indirections: [...this.indirections],
|
|
465
|
-
options: this.options,
|
|
466
|
-
refractCache: this.refractCache,
|
|
467
|
-
visited: this.visited,
|
|
468
|
-
ancestors: ancestorsLineage
|
|
469
|
-
});
|
|
470
|
-
referencedElement = await (0, _apidomTraverse.traverseAsync)(referencedElement, visitor, {
|
|
471
|
-
mutable: true,
|
|
472
|
-
skipVisited: 'skip'
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
// remove referencing reference from ancestors lineage
|
|
476
|
-
directAncestors.delete(referencingElement);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Creating a new version of Path Item by merging fields from referenced Path Item with referencing one.
|
|
481
|
-
*/
|
|
482
|
-
if ((0, _apidomNsOpenapi.isPathItemElement)(referencedElement)) {
|
|
483
|
-
const mergedElement = (0, _apidomDatamodel.cloneShallow)(referencedElement);
|
|
484
|
-
// existing keywords from referencing PathItemElement overrides ones from referenced element
|
|
485
|
-
referencingElement.forEach((value, keyElement, item) => {
|
|
486
|
-
mergedElement.remove((0, _apidomCore.toValue)(keyElement));
|
|
487
|
-
mergedElement.content.push(item);
|
|
488
|
-
});
|
|
489
|
-
mergedElement.remove('$ref');
|
|
490
|
-
|
|
491
|
-
// annotate referenced element with info about original referencing element
|
|
492
|
-
mergedElement.meta.set('ref-fields', {
|
|
493
|
-
$ref: (0, _apidomCore.toValue)(referencingElement.$ref)
|
|
494
|
-
});
|
|
495
|
-
// annotate referenced element with info about origin and type
|
|
496
|
-
mergedElement.meta.set('ref-origin', reference.uri);
|
|
497
|
-
mergedElement.meta.set('ref-type', referencingElement.element);
|
|
498
|
-
referencedElement = mergedElement;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* Transclude referencing element with merged referenced element.
|
|
503
|
-
*/
|
|
504
|
-
path.replaceWith(referencedElement);
|
|
217
|
+
});
|
|
505
218
|
} catch (error) {
|
|
506
|
-
const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
|
|
507
219
|
this.handleError(`Error while dereferencing Path Item Object. Cannot resolve $ref "${$ref}": ${error.message}`, error, referencingElement, '$ref', $ref, path);
|
|
508
|
-
} finally {
|
|
509
|
-
if (this.indirections.length > indirectionsSize) this.indirections.pop();
|
|
510
220
|
}
|
|
511
221
|
}
|
|
512
222
|
async LinkElement(path) {
|
|
513
223
|
const linkElement = path.node;
|
|
224
|
+
if (this.isTranscluded(linkElement)) {
|
|
225
|
+
path.skip();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
514
228
|
|
|
515
229
|
// ignore LinkElement without operationRef or operationId field
|
|
516
230
|
if (!(0, _apidomDatamodel.isStringElement)(linkElement.operationRef) && !(0, _apidomDatamodel.isStringElement)(linkElement.operationId)) {
|
|
@@ -525,11 +239,11 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
525
239
|
});
|
|
526
240
|
}
|
|
527
241
|
try {
|
|
528
|
-
let operationElement;
|
|
529
242
|
if ((0, _apidomDatamodel.isStringElement)(linkElement.operationRef)) {
|
|
243
|
+
const operationRef = (0, _apidomCore.toValue)(linkElement.operationRef);
|
|
530
244
|
// possibly non-semantic referenced element
|
|
531
|
-
const jsonPointer = _apidomJsonPointer.URIFragmentIdentifier.fromURIReference(
|
|
532
|
-
const retrievalURI = this.toBaseURI(
|
|
245
|
+
const jsonPointer = _apidomJsonPointer.URIFragmentIdentifier.fromURIReference(operationRef);
|
|
246
|
+
const retrievalURI = this.toBaseURI(operationRef);
|
|
533
247
|
const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
|
|
534
248
|
const isExternalReference = !isInternalReference;
|
|
535
249
|
|
|
@@ -543,51 +257,52 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
543
257
|
// skip traversing this Link element but traverse all it's child elements
|
|
544
258
|
return;
|
|
545
259
|
}
|
|
546
|
-
const reference = await this.toReference(
|
|
547
|
-
operationElement = (0, _apidomJsonPointer.evaluate)(reference.value.result, jsonPointer);
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
* Transclude Link Object containing Operation Object in its meta.
|
|
568
|
-
*/
|
|
569
|
-
path.replaceWith(linkElementCopy);
|
|
260
|
+
const reference = await this.toReference(operationRef);
|
|
261
|
+
const operationElement = (0, _apidomJsonPointer.evaluate)(reference.value.result, jsonPointer);
|
|
262
|
+
await this.addAttachment(path, {
|
|
263
|
+
source: operationElement,
|
|
264
|
+
type: 'operation',
|
|
265
|
+
reference,
|
|
266
|
+
context: undefined
|
|
267
|
+
}, (element, target) => {
|
|
268
|
+
// create shallow clone to be able to annotate with metadata
|
|
269
|
+
const operationCopy = (0, _apidomDatamodel.cloneShallow)(target);
|
|
270
|
+
// annotate operation element with info about origin and type
|
|
271
|
+
operationCopy.meta.set('ref-origin', reference.uri);
|
|
272
|
+
operationCopy.meta.set('ref-type', element.element);
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Transclude Link Object containing Operation Object in its meta.
|
|
276
|
+
*/
|
|
277
|
+
const linkElementCopy = (0, _apidomDatamodel.cloneShallow)(element);
|
|
278
|
+
linkElementCopy.operationRef?.meta.set('operation', operationCopy);
|
|
279
|
+
return linkElementCopy;
|
|
280
|
+
});
|
|
570
281
|
return;
|
|
571
282
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
283
|
+
const operationId = (0, _apidomCore.toValue)(linkElement.operationId);
|
|
284
|
+
const reference = await this.toReference(url.unsanitize(this.reference.uri));
|
|
285
|
+
const operationPath = (0, _apidomTraverse.find)(reference.value.result, p => (0, _apidomNsOpenapi.isOperationElement)(p.node) && (0, _apidomDatamodel.isElement)(p.node.operationId) && p.node.operationId.equals(operationId));
|
|
286
|
+
const operationElement = operationPath?.node;
|
|
287
|
+
// OperationElement not found by its operationId
|
|
288
|
+
if ((0, _ramdaAdjunct.isUndefined)(operationElement)) {
|
|
289
|
+
throw new _apidomError.ApiDOMStructuredError(`OperationElement(operationId=${operationId}) not found`, {
|
|
290
|
+
operationId
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
await this.addAttachment(path, {
|
|
294
|
+
source: operationElement,
|
|
295
|
+
type: 'operation',
|
|
296
|
+
reference,
|
|
297
|
+
context: undefined
|
|
298
|
+
}, (element, target) => {
|
|
586
299
|
/**
|
|
587
300
|
* Transclude Link Object containing Operation Object in its meta.
|
|
588
301
|
*/
|
|
589
|
-
|
|
590
|
-
|
|
302
|
+
const linkElementCopy = (0, _apidomDatamodel.cloneShallow)(element);
|
|
303
|
+
linkElementCopy.operationId?.meta.set('operation', target);
|
|
304
|
+
return linkElementCopy;
|
|
305
|
+
});
|
|
591
306
|
} catch (error) {
|
|
592
307
|
const refFieldName = (0, _apidomDatamodel.isStringElement)(linkElement.operationRef) ? 'operationRef' : 'operationId';
|
|
593
308
|
const refFieldValue = (0, _apidomDatamodel.isStringElement)(linkElement.operationRef) ? (0, _apidomCore.toValue)(linkElement.operationRef) : (0, _apidomCore.toValue)(linkElement.operationId);
|
|
@@ -596,6 +311,10 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
596
311
|
}
|
|
597
312
|
async ExampleElement(path) {
|
|
598
313
|
const exampleElement = path.node;
|
|
314
|
+
if (this.isTranscluded(exampleElement)) {
|
|
315
|
+
path.skip();
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
599
318
|
|
|
600
319
|
// ignore ExampleElement without externalValue field
|
|
601
320
|
if (!(0, _apidomDatamodel.isStringElement)(exampleElement.externalValue)) {
|
|
@@ -609,11 +328,12 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
609
328
|
externalValue: (0, _apidomCore.toValue)(exampleElement.externalValue)
|
|
610
329
|
});
|
|
611
330
|
}
|
|
612
|
-
const
|
|
331
|
+
const externalValue = (0, _apidomCore.toValue)(exampleElement.externalValue);
|
|
332
|
+
const retrievalURI = this.toBaseURI(externalValue);
|
|
613
333
|
const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
|
|
614
334
|
const isExternalReference = !isInternalReference;
|
|
615
335
|
|
|
616
|
-
// ignore resolving
|
|
336
|
+
// ignore resolving internal Example Objects
|
|
617
337
|
if (!this.options.resolve.internal && isInternalReference) {
|
|
618
338
|
// skip traversing this Example element but traverse all it's child elements
|
|
619
339
|
return;
|
|
@@ -624,22 +344,28 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
624
344
|
return;
|
|
625
345
|
}
|
|
626
346
|
try {
|
|
627
|
-
const reference = await this.toReference(
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
347
|
+
const reference = await this.toReference(externalValue);
|
|
348
|
+
const valueSource = reference.value.result;
|
|
349
|
+
await this.addAttachment(path, {
|
|
350
|
+
source: valueSource,
|
|
351
|
+
type: valueSource.element,
|
|
352
|
+
reference,
|
|
353
|
+
context: undefined
|
|
354
|
+
}, (element, target) => {
|
|
355
|
+
// shallow clone of the referenced element
|
|
356
|
+
const valueElement = (0, _apidomDatamodel.cloneShallow)(target);
|
|
357
|
+
// annotate element with info about origin and type
|
|
358
|
+
valueElement.meta.set('ref-origin', reference.uri);
|
|
359
|
+
valueElement.meta.set('ref-type', element.element);
|
|
636
360
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
361
|
+
/**
|
|
362
|
+
* Transclude Example Object containing external value.
|
|
363
|
+
*/
|
|
364
|
+
const exampleElementCopy = (0, _apidomDatamodel.cloneShallow)(element);
|
|
365
|
+
exampleElementCopy.value = valueElement;
|
|
366
|
+
return exampleElementCopy;
|
|
367
|
+
});
|
|
641
368
|
} catch (error) {
|
|
642
|
-
const externalValue = (0, _apidomCore.toValue)(exampleElement.externalValue);
|
|
643
369
|
this.handleError(`Error while dereferencing Example Object. Cannot resolve externalValue "${externalValue}": ${error.message}`, error, exampleElement, 'externalValue', externalValue, path);
|
|
644
370
|
}
|
|
645
371
|
}
|