swagger-client 3.27.9 → 3.28.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.
Files changed (32) hide show
  1. package/dist/swagger-client.browser.js +12494 -12585
  2. package/dist/swagger-client.browser.min.js +1 -1
  3. package/dist/swagger-client.browser.min.js.map +1 -1
  4. package/es/index.js +2 -2
  5. package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/index.js +81 -119
  6. package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/all-of.js +66 -69
  7. package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/dereference.js +569 -588
  8. package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/parameters.js +31 -34
  9. package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/properties.js +25 -28
  10. package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/root.js +45 -0
  11. package/es/resolver/apidom/reference/parse/parsers/json/index.js +43 -42
  12. package/es/resolver/apidom/reference/parse/parsers/openapi-json-3-1/index.js +46 -45
  13. package/es/resolver/apidom/reference/parse/parsers/openapi-yaml-3-1/index.js +46 -45
  14. package/es/resolver/apidom/reference/parse/parsers/yaml-1-2/index.js +44 -43
  15. package/es/resolver/apidom/reference/resolve/resolvers/http-swagger-client/index.js +62 -60
  16. package/es/resolver/strategies/openapi-3-1-apidom/resolve.js +18 -18
  17. package/lib/index.js +1 -1
  18. package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/index.js +79 -117
  19. package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/all-of.js +66 -69
  20. package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/dereference.js +568 -587
  21. package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/parameters.js +31 -34
  22. package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/properties.js +25 -28
  23. package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/root.js +51 -0
  24. package/lib/resolver/apidom/reference/parse/parsers/json/index.js +43 -42
  25. package/lib/resolver/apidom/reference/parse/parsers/openapi-json-3-1/index.js +46 -45
  26. package/lib/resolver/apidom/reference/parse/parsers/openapi-yaml-3-1/index.js +46 -45
  27. package/lib/resolver/apidom/reference/parse/parsers/yaml-1-2/index.js +44 -43
  28. package/lib/resolver/apidom/reference/resolve/resolvers/http-swagger-client/index.js +61 -59
  29. package/lib/resolver/strategies/openapi-3-1-apidom/resolve.js +11 -11
  30. package/package.json +23 -22
  31. package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/utils/compose.js +0 -5
  32. package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/utils/compose.js +0 -11
@@ -4,7 +4,7 @@ import { ApiDOMError } from '@swagger-api/apidom-error';
4
4
  import { isReferenceLikeElement, isReferenceElement, isBooleanJsonSchemaElement, isPathItemElement, isSchemaElement, ReferenceElement, PathItemElement, SchemaElement, getNodeType, keyMap } from '@swagger-api/apidom-ns-openapi-3-1';
5
5
  import { evaluate as jsonPointerEvaluate, uriToPointer } from '@swagger-api/apidom-json-pointer';
6
6
  import { url, MaximumDereferenceDepthError, File } from '@swagger-api/apidom-reference/configuration/empty';
7
- import { OpenApi3_1DereferenceVisitor, resolveSchema$refField, maybeRefractToSchemaElement } from '@swagger-api/apidom-reference/dereference/strategies/openapi-3-1';
7
+ import { OpenAPI3_1DereferenceVisitor, resolveSchema$refField, maybeRefractToSchemaElement } from '@swagger-api/apidom-reference/dereference/strategies/openapi-3-1';
8
8
  import { isAnchor, uriToAnchor, evaluate as $anchorEvaluate } from '@swagger-api/apidom-reference/dereference/strategies/openapi-3-1/selectors/$anchor';
9
9
  import { evaluate as uriEvaluate, EvaluationJsonSchemaUriError } from '@swagger-api/apidom-reference/dereference/strategies/openapi-3-1/selectors/uri';
10
10
  import toPath from '../utils/to-path.js';
@@ -17,420 +17,456 @@ const {
17
17
  const visitAsync = visit[Symbol.for('nodejs.util.promisify.custom')];
18
18
 
19
19
  // initialize element identity manager
20
- const identityManager = IdentityManager();
21
- const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.compose({
22
- props: {
23
- useCircularStructures: true,
24
- allowMetaPatches: false,
25
- basePath: null
26
- },
27
- init({
28
- allowMetaPatches = this.allowMetaPatches,
29
- useCircularStructures = this.useCircularStructures,
30
- basePath = this.basePath
20
+ const identityManager = new IdentityManager();
21
+
22
+ // custom mutation replacer
23
+ const mutationReplacer = (newElement, oldElement, key, parent) => {
24
+ if (isMemberElement(parent)) {
25
+ parent.value = newElement; // eslint-disable-line no-param-reassign
26
+ } else if (Array.isArray(parent)) {
27
+ parent[key] = newElement; // eslint-disable-line no-param-reassign
28
+ }
29
+ };
30
+ class OpenAPI3_1SwaggerClientDereferenceVisitor extends OpenAPI3_1DereferenceVisitor {
31
+ useCircularStructures;
32
+ allowMetaPatches;
33
+ basePath;
34
+ constructor({
35
+ allowMetaPatches = true,
36
+ useCircularStructures = false,
37
+ basePath = null,
38
+ ...rest
31
39
  }) {
40
+ super(rest);
32
41
  this.allowMetaPatches = allowMetaPatches;
33
42
  this.useCircularStructures = useCircularStructures;
34
43
  this.basePath = basePath;
35
- },
36
- methods: {
37
- async ReferenceElement(referencingElement, key, parent, path, ancestors) {
38
- try {
39
- // skip current referencing element as it's already been access
40
- if (this.indirections.includes(referencingElement)) {
41
- return false;
42
- }
43
- const [ancestorsLineage, directAncestors] = this.toAncestorLineage([...ancestors, parent]);
44
- const retrievalURI = this.toBaseURI(toValue(referencingElement.$ref));
45
- const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
46
- const isExternalReference = !isInternalReference;
47
-
48
- // ignore resolving internal Reference Objects
49
- if (!this.options.resolve.internal && isInternalReference) {
50
- return false;
51
- }
52
- // ignore resolving external Reference Objects
53
- if (!this.options.resolve.external && isExternalReference) {
54
- return false;
55
- }
56
- const reference = await this.toReference(toValue(referencingElement.$ref));
57
- const $refBaseURI = url.resolve(retrievalURI, toValue(referencingElement.$ref));
58
- this.indirections.push(referencingElement);
59
- const jsonPointer = uriToPointer($refBaseURI);
60
-
61
- // possibly non-semantic fragment
62
- let referencedElement = jsonPointerEvaluate(jsonPointer, reference.value.result);
63
- referencedElement.id = identityManager.identify(referencedElement);
64
-
65
- // applying semantics to a fragment
66
- if (isPrimitiveElement(referencedElement)) {
67
- const referencedElementType = toValue(referencingElement.meta.get('referenced-element'));
68
- const cacheKey = `${referencedElementType}-${toValue(identityManager.identify(referencedElement))}`;
69
- if (this.refractCache.has(cacheKey)) {
70
- referencedElement = this.refractCache.get(cacheKey);
71
- } else if (isReferenceLikeElement(referencedElement)) {
72
- // handling indirect references
73
- referencedElement = ReferenceElement.refract(referencedElement);
74
- referencedElement.setMetaProperty('referenced-element', referencedElementType);
75
- this.refractCache.set(cacheKey, referencedElement);
76
- } else {
77
- // handling direct references
78
- const ElementClass = this.namespace.getElementClass(referencedElementType);
79
- referencedElement = ElementClass.refract(referencedElement);
80
- this.refractCache.set(cacheKey, referencedElement);
81
- }
82
- }
83
-
84
- // detect direct or indirect reference
85
- if (referencingElement === referencedElement) {
86
- throw new ApiDOMError('Recursive Reference Object detected');
44
+ }
45
+ async ReferenceElement(referencingElement, key, parent, path, ancestors, link) {
46
+ try {
47
+ // skip current referencing element as it's already been access
48
+ if (this.indirections.includes(referencingElement)) {
49
+ return false;
50
+ }
51
+ const [ancestorsLineage, directAncestors] = this.toAncestorLineage([...ancestors, parent]);
52
+ const retrievalURI = this.toBaseURI(toValue(referencingElement.$ref));
53
+ const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
54
+ const isExternalReference = !isInternalReference;
55
+
56
+ // ignore resolving internal Reference Objects
57
+ if (!this.options.resolve.internal && isInternalReference) {
58
+ return false;
59
+ }
60
+ // ignore resolving external Reference Objects
61
+ if (!this.options.resolve.external && isExternalReference) {
62
+ return false;
63
+ }
64
+ const reference = await this.toReference(toValue(referencingElement.$ref));
65
+ const $refBaseURI = url.resolve(retrievalURI, toValue(referencingElement.$ref));
66
+ this.indirections.push(referencingElement);
67
+ const jsonPointer = uriToPointer($refBaseURI);
68
+
69
+ // possibly non-semantic fragment
70
+ let referencedElement = jsonPointerEvaluate(jsonPointer, reference.value.result);
71
+ referencedElement.id = identityManager.identify(referencedElement);
72
+
73
+ // applying semantics to a fragment
74
+ if (isPrimitiveElement(referencedElement)) {
75
+ const referencedElementType = toValue(referencingElement.meta.get('referenced-element'));
76
+ const cacheKey = `${referencedElementType}-${toValue(identityManager.identify(referencedElement))}`;
77
+ if (this.refractCache.has(cacheKey)) {
78
+ referencedElement = this.refractCache.get(cacheKey);
79
+ } else if (isReferenceLikeElement(referencedElement)) {
80
+ // handling indirect references
81
+ referencedElement = ReferenceElement.refract(referencedElement);
82
+ referencedElement.setMetaProperty('referenced-element', referencedElementType);
83
+ this.refractCache.set(cacheKey, referencedElement);
84
+ } else {
85
+ // handling direct references
86
+ const ElementClass = this.namespace.getElementClass(referencedElementType);
87
+ referencedElement = ElementClass.refract(referencedElement);
88
+ this.refractCache.set(cacheKey, referencedElement);
87
89
  }
90
+ }
88
91
 
89
- // detect maximum depth of dereferencing
90
- if (this.indirections.length > this.options.dereference.maxDepth) {
91
- throw new MaximumDereferenceDepthError(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
92
- }
92
+ // detect direct or indirect reference
93
+ if (referencingElement === referencedElement) {
94
+ throw new ApiDOMError('Recursive Reference Object detected');
95
+ }
93
96
 
94
- // detect second deep dive into the same fragment and avoid it
95
- if (ancestorsLineage.includes(referencedElement)) {
96
- reference.refSet.circular = true;
97
- if (this.options.dereference.circular === 'error') {
98
- throw new ApiDOMError('Circular reference detected');
99
- } else if (this.options.dereference.circular === 'replace') {
100
- var _this$options$derefer, _this$options$derefer2;
101
- const refElement = new RefElement(referencedElement.id, {
102
- type: 'reference',
103
- uri: reference.uri,
104
- $ref: toValue(referencingElement.$ref),
105
- baseURI: $refBaseURI,
106
- referencingElement
107
- });
108
- const replacer = (_this$options$derefer = (_this$options$derefer2 = this.options.dereference.strategyOpts['openapi-3-1']) === null || _this$options$derefer2 === void 0 ? void 0 : _this$options$derefer2.circularReplacer) !== null && _this$options$derefer !== void 0 ? _this$options$derefer : this.options.dereference.circularReplacer;
109
- const replacement = replacer(refElement);
110
- if (isMemberElement(parent)) {
111
- parent.value = replacement; // eslint-disable-line no-param-reassign
112
- } else if (Array.isArray(parent)) {
113
- parent[key] = replacement; // eslint-disable-line no-param-reassign
114
- }
115
- return !parent ? replacement : false;
116
- }
117
- }
97
+ // detect maximum depth of dereferencing
98
+ if (this.indirections.length > this.options.dereference.maxDepth) {
99
+ throw new MaximumDereferenceDepthError(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
100
+ }
118
101
 
119
- /**
120
- * Dive deep into the fragment.
121
- *
122
- * Cases to consider:
123
- * 1. We're crossing document boundary
124
- * 2. Fragment is from non-root document
125
- * 3. Fragment is a Reference Object. We need to follow it to get the eventual value
126
- * 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
127
- */
128
- const isNonRootDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
129
- const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
130
- if ((isExternalReference || isNonRootDocument || isReferenceElement(referencedElement) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
131
- var _this$basePath;
132
- // append referencing reference to ancestors lineage
133
- directAncestors.add(referencingElement);
134
- const visitor = OpenApi3_1SwaggerClientDereferenceVisitor({
135
- reference,
136
- namespace: this.namespace,
137
- indirections: [...this.indirections],
138
- options: this.options,
139
- refractCache: this.refractCache,
140
- ancestors: ancestorsLineage,
141
- allowMetaPatches: this.allowMetaPatches,
142
- useCircularStructures: this.useCircularStructures,
143
- basePath: (_this$basePath = this.basePath) !== null && _this$basePath !== void 0 ? _this$basePath : [...toPath([...ancestors, parent, referencingElement]), '$ref']
144
- });
145
- referencedElement = await visitAsync(referencedElement, visitor, {
146
- keyMap,
147
- nodeTypeGetter: getNodeType
102
+ // detect second deep dive into the same fragment and avoid it
103
+ if (ancestorsLineage.includes(referencedElement)) {
104
+ reference.refSet.circular = true;
105
+ if (this.options.dereference.circular === 'error') {
106
+ throw new ApiDOMError('Circular reference detected');
107
+ } else if (this.options.dereference.circular === 'replace') {
108
+ var _this$options$derefer, _this$options$derefer2;
109
+ const refElement = new RefElement(referencedElement.id, {
110
+ type: 'reference',
111
+ uri: reference.uri,
112
+ $ref: toValue(referencingElement.$ref),
113
+ baseURI: $refBaseURI,
114
+ referencingElement
148
115
  });
149
-
150
- // remove referencing reference from ancestors lineage
151
- directAncestors.delete(referencingElement);
116
+ const replacer = (_this$options$derefer = (_this$options$derefer2 = this.options.dereference.strategyOpts['openapi-3-1']) === null || _this$options$derefer2 === void 0 ? void 0 : _this$options$derefer2.circularReplacer) !== null && _this$options$derefer !== void 0 ? _this$options$derefer : this.options.dereference.circularReplacer;
117
+ const replacement = replacer(refElement);
118
+ link.replaceWith(refElement, mutationReplacer);
119
+ return !parent ? replacement : false;
152
120
  }
153
- this.indirections.pop();
154
- const mergedElement = cloneShallow(referencedElement);
121
+ }
155
122
 
156
- // annotate fragment with info about original Reference element
157
- mergedElement.setMetaProperty('ref-fields', {
158
- $ref: toValue(referencingElement.$ref),
159
- description: toValue(referencingElement.description),
160
- summary: toValue(referencingElement.summary)
123
+ /**
124
+ * Dive deep into the fragment.
125
+ *
126
+ * Cases to consider:
127
+ * 1. We're crossing document boundary
128
+ * 2. Fragment is from non-root document
129
+ * 3. Fragment is a Reference Object. We need to follow it to get the eventual value
130
+ * 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
131
+ */
132
+ const isNonRootDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
133
+ const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
134
+ if ((isExternalReference || isNonRootDocument || isReferenceElement(referencedElement) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
135
+ var _this$basePath;
136
+ // append referencing reference to ancestors lineage
137
+ directAncestors.add(referencingElement);
138
+ const visitor = new OpenAPI3_1SwaggerClientDereferenceVisitor({
139
+ reference,
140
+ namespace: this.namespace,
141
+ indirections: [...this.indirections],
142
+ options: this.options,
143
+ refractCache: this.refractCache,
144
+ ancestors: ancestorsLineage,
145
+ allowMetaPatches: this.allowMetaPatches,
146
+ useCircularStructures: this.useCircularStructures,
147
+ basePath: (_this$basePath = this.basePath) !== null && _this$basePath !== void 0 ? _this$basePath : [...toPath([...ancestors, parent, referencingElement]), '$ref']
148
+ });
149
+ referencedElement = await visitAsync(referencedElement, visitor, {
150
+ keyMap,
151
+ nodeTypeGetter: getNodeType
161
152
  });
162
- // annotate fragment with info about origin
163
- mergedElement.setMetaProperty('ref-origin', reference.uri);
164
- // annotate fragment with info about referencing element
165
- mergedElement.setMetaProperty('ref-referencing-element-id', cloneDeep(identityManager.identify(referencingElement)));
166
153
 
167
- // override description and summary (outer has higher priority then inner)
168
- if (isObjectElement(referencedElement)) {
169
- if (referencingElement.hasKey('description') && 'description' in referencedElement) {
170
- mergedElement.remove('description');
171
- mergedElement.set('description', referencingElement.get('description'));
172
- }
173
- if (referencingElement.hasKey('summary') && 'summary' in referencedElement) {
174
- mergedElement.remove('summary');
175
- mergedElement.set('summary', referencingElement.get('summary'));
176
- }
154
+ // remove referencing reference from ancestors lineage
155
+ directAncestors.delete(referencingElement);
156
+ }
157
+ this.indirections.pop();
158
+ const mergedElement = cloneShallow(referencedElement);
159
+
160
+ // annotate fragment with info about original Reference element
161
+ mergedElement.setMetaProperty('ref-fields', {
162
+ $ref: toValue(referencingElement.$ref),
163
+ description: toValue(referencingElement.description),
164
+ summary: toValue(referencingElement.summary)
165
+ });
166
+ // annotate fragment with info about origin
167
+ mergedElement.setMetaProperty('ref-origin', reference.uri);
168
+ // annotate fragment with info about referencing element
169
+ mergedElement.setMetaProperty('ref-referencing-element-id', cloneDeep(identityManager.identify(referencingElement)));
170
+
171
+ // override description and summary (outer has higher priority then inner)
172
+ if (isObjectElement(referencedElement)) {
173
+ if (referencingElement.hasKey('description') && 'description' in referencedElement) {
174
+ mergedElement.remove('description');
175
+ mergedElement.set('description', referencingElement.get('description'));
176
+ }
177
+ if (referencingElement.hasKey('summary') && 'summary' in referencedElement) {
178
+ mergedElement.remove('summary');
179
+ mergedElement.set('summary', referencingElement.get('summary'));
177
180
  }
181
+ }
178
182
 
179
- // apply meta patches
180
- if (this.allowMetaPatches && isObjectElement(mergedElement)) {
181
- // apply meta patch only when not already applied
182
- if (!mergedElement.hasKey('$$ref')) {
183
- const baseURI = url.resolve(retrievalURI, $refBaseURI);
184
- mergedElement.set('$$ref', baseURI);
185
- }
183
+ // apply meta patches
184
+ if (this.allowMetaPatches && isObjectElement(mergedElement)) {
185
+ // apply meta patch only when not already applied
186
+ if (!mergedElement.hasKey('$$ref')) {
187
+ const baseURI = url.resolve(retrievalURI, $refBaseURI);
188
+ mergedElement.set('$$ref', baseURI);
186
189
  }
190
+ }
187
191
 
188
- /**
189
- * Transclude referencing element with merged referenced element.
190
- */
191
- if (isMemberElement(parent)) {
192
- parent.value = mergedElement; // eslint-disable-line no-param-reassign
193
- } else if (Array.isArray(parent)) {
194
- parent[key] = mergedElement; // eslint-disable-line no-param-reassign
195
- }
192
+ /**
193
+ * Transclude referencing element with merged referenced element.
194
+ */
195
+ link.replaceWith(mergedElement, mutationReplacer);
196
196
 
197
- /**
198
- * We're at the root of the tree, so we're just replacing the entire tree.
199
- */
200
- return !parent ? mergedElement : false;
201
- } catch (error) {
202
- var _this$basePath2, _this$options$derefer3, _this$options$derefer4;
203
- const rootCause = getRootCause(error);
204
- const wrappedError = wrapError(rootCause, {
205
- baseDoc: this.reference.uri,
206
- $ref: toValue(referencingElement.$ref),
207
- pointer: uriToPointer(toValue(referencingElement.$ref)),
208
- fullPath: (_this$basePath2 = this.basePath) !== null && _this$basePath2 !== void 0 ? _this$basePath2 : [...toPath([...ancestors, parent, referencingElement]), '$ref']
209
- });
210
- (_this$options$derefer3 = this.options.dereference.dereferenceOpts) === null || _this$options$derefer3 === void 0 || (_this$options$derefer3 = _this$options$derefer3.errors) === null || _this$options$derefer3 === void 0 || (_this$options$derefer4 = _this$options$derefer3.push) === null || _this$options$derefer4 === void 0 || _this$options$derefer4.call(_this$options$derefer3, wrappedError);
197
+ /**
198
+ * We're at the root of the tree, so we're just replacing the entire tree.
199
+ */
200
+ return !parent ? mergedElement : false;
201
+ } catch (error) {
202
+ var _this$basePath2, _this$options$derefer3, _this$options$derefer4;
203
+ const rootCause = getRootCause(error);
204
+ const wrappedError = wrapError(rootCause, {
205
+ baseDoc: this.reference.uri,
206
+ $ref: toValue(referencingElement.$ref),
207
+ pointer: uriToPointer(toValue(referencingElement.$ref)),
208
+ fullPath: (_this$basePath2 = this.basePath) !== null && _this$basePath2 !== void 0 ? _this$basePath2 : [...toPath([...ancestors, parent, referencingElement]), '$ref']
209
+ });
210
+ (_this$options$derefer3 = this.options.dereference.dereferenceOpts) === null || _this$options$derefer3 === void 0 || (_this$options$derefer3 = _this$options$derefer3.errors) === null || _this$options$derefer3 === void 0 || (_this$options$derefer4 = _this$options$derefer3.push) === null || _this$options$derefer4 === void 0 || _this$options$derefer4.call(_this$options$derefer3, wrappedError);
211
+ return undefined;
212
+ }
213
+ }
214
+ async PathItemElement(pathItemElement, key, parent, path, ancestors, link) {
215
+ try {
216
+ // ignore PathItemElement without $ref field
217
+ if (!isStringElement(pathItemElement.$ref)) {
211
218
  return undefined;
212
219
  }
213
- },
214
- async PathItemElement(pathItemElement, key, parent, path, ancestors) {
215
- try {
216
- // ignore PathItemElement without $ref field
217
- if (!isStringElement(pathItemElement.$ref)) {
218
- return undefined;
219
- }
220
220
 
221
- // skip current referencing element as it's already been access
222
- if (this.indirections.includes(pathItemElement)) {
223
- return false;
224
- }
221
+ // skip current referencing element as it's already been access
222
+ if (this.indirections.includes(pathItemElement)) {
223
+ return false;
224
+ }
225
225
 
226
- // skip already identified cycled Path Item Objects
227
- if (includesClasses(['cycle'], pathItemElement.$ref)) {
228
- return false;
229
- }
230
- const [ancestorsLineage, directAncestors] = this.toAncestorLineage([...ancestors, parent]);
231
- const retrievalURI = this.toBaseURI(toValue(pathItemElement.$ref));
232
- const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
233
- const isExternalReference = !isInternalReference;
234
-
235
- // ignore resolving internal Path Item Elements
236
- if (!this.options.resolve.internal && isInternalReference) {
237
- return undefined;
238
- }
239
- // ignore resolving external Path Item Elements
240
- if (!this.options.resolve.external && isExternalReference) {
241
- return undefined;
242
- }
243
- const reference = await this.toReference(toValue(pathItemElement.$ref));
244
- const $refBaseURI = url.resolve(retrievalURI, toValue(pathItemElement.$ref));
245
- this.indirections.push(pathItemElement);
246
- const jsonPointer = uriToPointer($refBaseURI);
247
-
248
- // possibly non-semantic referenced element
249
- let referencedElement = jsonPointerEvaluate(jsonPointer, reference.value.result);
250
- referencedElement.id = identityManager.identify(referencedElement);
251
-
252
- // applying semantics to a referenced element
253
- if (isPrimitiveElement(referencedElement)) {
254
- const cacheKey = `path-item-${toValue(identityManager.identify(referencedElement))}`;
255
- if (this.refractCache.has(cacheKey)) {
256
- referencedElement = this.refractCache.get(cacheKey);
257
- } else {
258
- referencedElement = PathItemElement.refract(referencedElement);
259
- this.refractCache.set(cacheKey, referencedElement);
260
- }
261
- }
226
+ // skip already identified cycled Path Item Objects
227
+ if (includesClasses(['cycle'], pathItemElement.$ref)) {
228
+ return false;
229
+ }
230
+ const [ancestorsLineage, directAncestors] = this.toAncestorLineage([...ancestors, parent]);
231
+ const retrievalURI = this.toBaseURI(toValue(pathItemElement.$ref));
232
+ const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
233
+ const isExternalReference = !isInternalReference;
262
234
 
263
- // detect direct or indirect reference
264
- if (pathItemElement === referencedElement) {
265
- throw new ApiDOMError('Recursive Path Item Object reference detected');
235
+ // ignore resolving internal Path Item Elements
236
+ if (!this.options.resolve.internal && isInternalReference) {
237
+ return undefined;
238
+ }
239
+ // ignore resolving external Path Item Elements
240
+ if (!this.options.resolve.external && isExternalReference) {
241
+ return undefined;
242
+ }
243
+ const reference = await this.toReference(toValue(pathItemElement.$ref));
244
+ const $refBaseURI = url.resolve(retrievalURI, toValue(pathItemElement.$ref));
245
+ this.indirections.push(pathItemElement);
246
+ const jsonPointer = uriToPointer($refBaseURI);
247
+
248
+ // possibly non-semantic referenced element
249
+ let referencedElement = jsonPointerEvaluate(jsonPointer, reference.value.result);
250
+ referencedElement.id = identityManager.identify(referencedElement);
251
+
252
+ // applying semantics to a referenced element
253
+ if (isPrimitiveElement(referencedElement)) {
254
+ const cacheKey = `path-item-${toValue(identityManager.identify(referencedElement))}`;
255
+ if (this.refractCache.has(cacheKey)) {
256
+ referencedElement = this.refractCache.get(cacheKey);
257
+ } else {
258
+ referencedElement = PathItemElement.refract(referencedElement);
259
+ this.refractCache.set(cacheKey, referencedElement);
266
260
  }
261
+ }
267
262
 
268
- // detect maximum depth of dereferencing
269
- if (this.indirections.length > this.options.dereference.maxDepth) {
270
- throw new MaximumDereferenceDepthError(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
271
- }
263
+ // detect direct or indirect reference
264
+ if (pathItemElement === referencedElement) {
265
+ throw new ApiDOMError('Recursive Path Item Object reference detected');
266
+ }
272
267
 
273
- // detect second deep dive into the same fragment and avoid it
274
- if (ancestorsLineage.includes(referencedElement)) {
275
- reference.refSet.circular = true;
276
- if (this.options.dereference.circular === 'error') {
277
- throw new ApiDOMError('Circular reference detected');
278
- } else if (this.options.dereference.circular === 'replace') {
279
- var _this$options$derefer5, _this$options$derefer6;
280
- const refElement = new RefElement(referencedElement.id, {
281
- type: 'path-item',
282
- uri: reference.uri,
283
- $ref: toValue(pathItemElement.$ref),
284
- baseURI: $refBaseURI,
285
- referencingElement: pathItemElement
286
- });
287
- const replacer = (_this$options$derefer5 = (_this$options$derefer6 = this.options.dereference.strategyOpts['openapi-3-1']) === null || _this$options$derefer6 === void 0 ? void 0 : _this$options$derefer6.circularReplacer) !== null && _this$options$derefer5 !== void 0 ? _this$options$derefer5 : this.options.dereference.circularReplacer;
288
- const replacement = replacer(refElement);
289
- if (isMemberElement(parent)) {
290
- parent.value = replacement; // eslint-disable-line no-param-reassign
291
- } else if (Array.isArray(parent)) {
292
- parent[key] = replacement; // eslint-disable-line no-param-reassign
293
- }
294
- return !parent ? replacement : false;
295
- }
296
- }
268
+ // detect maximum depth of dereferencing
269
+ if (this.indirections.length > this.options.dereference.maxDepth) {
270
+ throw new MaximumDereferenceDepthError(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
271
+ }
297
272
 
298
- /**
299
- * Dive deep into the fragment.
300
- *
301
- * Cases to consider:
302
- * 1. We're crossing document boundary
303
- * 2. Fragment is from non-root document
304
- * 3. Fragment is a Path Item Object with $ref field. We need to follow it to get the eventual value
305
- * 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
306
- */
307
- const isNonRootDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
308
- const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
309
- if ((isExternalReference || isNonRootDocument || isPathItemElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
310
- var _this$basePath3;
311
- // append referencing schema to ancestors lineage
312
- directAncestors.add(pathItemElement);
313
-
314
- // dive deep into the referenced element
315
- const visitor = OpenApi3_1SwaggerClientDereferenceVisitor({
316
- reference,
317
- namespace: this.namespace,
318
- indirections: [...this.indirections],
319
- options: this.options,
320
- ancestors: ancestorsLineage,
321
- allowMetaPatches: this.allowMetaPatches,
322
- useCircularStructures: this.useCircularStructures,
323
- basePath: (_this$basePath3 = this.basePath) !== null && _this$basePath3 !== void 0 ? _this$basePath3 : [...toPath([...ancestors, parent, pathItemElement]), '$ref']
324
- });
325
- referencedElement = await visitAsync(referencedElement, visitor, {
326
- keyMap,
327
- nodeTypeGetter: getNodeType
273
+ // detect second deep dive into the same fragment and avoid it
274
+ if (ancestorsLineage.includes(referencedElement)) {
275
+ reference.refSet.circular = true;
276
+ if (this.options.dereference.circular === 'error') {
277
+ throw new ApiDOMError('Circular reference detected');
278
+ } else if (this.options.dereference.circular === 'replace') {
279
+ var _this$options$derefer5, _this$options$derefer6;
280
+ const refElement = new RefElement(referencedElement.id, {
281
+ type: 'path-item',
282
+ uri: reference.uri,
283
+ $ref: toValue(pathItemElement.$ref),
284
+ baseURI: $refBaseURI,
285
+ referencingElement: pathItemElement
328
286
  });
329
-
330
- // remove referencing schema from ancestors lineage
331
- directAncestors.delete(pathItemElement);
287
+ const replacer = (_this$options$derefer5 = (_this$options$derefer6 = this.options.dereference.strategyOpts['openapi-3-1']) === null || _this$options$derefer6 === void 0 ? void 0 : _this$options$derefer6.circularReplacer) !== null && _this$options$derefer5 !== void 0 ? _this$options$derefer5 : this.options.dereference.circularReplacer;
288
+ const replacement = replacer(refElement);
289
+ link.replaceWith(refElement, mutationReplacer);
290
+ return !parent ? replacement : false;
332
291
  }
333
- this.indirections.pop();
292
+ }
334
293
 
335
- /**
336
- * Creating a new version of Path Item by merging fields from referenced Path Item with referencing one.
337
- */
338
- if (isPathItemElement(referencedElement)) {
339
- const mergedElement = new PathItemElement([...referencedElement.content], cloneDeep(referencedElement.meta), cloneDeep(referencedElement.attributes));
340
- // existing keywords from referencing PathItemElement overrides ones from referenced element
341
- pathItemElement.forEach((value, keyElement, item) => {
342
- mergedElement.remove(toValue(keyElement));
343
- mergedElement.content.push(item);
344
- });
345
- mergedElement.remove('$ref');
294
+ /**
295
+ * Dive deep into the fragment.
296
+ *
297
+ * Cases to consider:
298
+ * 1. We're crossing document boundary
299
+ * 2. Fragment is from non-root document
300
+ * 3. Fragment is a Path Item Object with $ref field. We need to follow it to get the eventual value
301
+ * 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
302
+ */
303
+ const isNonRootDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
304
+ const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
305
+ if ((isExternalReference || isNonRootDocument || isPathItemElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
306
+ var _this$basePath3;
307
+ // append referencing schema to ancestors lineage
308
+ directAncestors.add(pathItemElement);
309
+
310
+ // dive deep into the referenced element
311
+ const visitor = new OpenAPI3_1SwaggerClientDereferenceVisitor({
312
+ reference,
313
+ namespace: this.namespace,
314
+ indirections: [...this.indirections],
315
+ options: this.options,
316
+ ancestors: ancestorsLineage,
317
+ allowMetaPatches: this.allowMetaPatches,
318
+ useCircularStructures: this.useCircularStructures,
319
+ basePath: (_this$basePath3 = this.basePath) !== null && _this$basePath3 !== void 0 ? _this$basePath3 : [...toPath([...ancestors, parent, pathItemElement]), '$ref']
320
+ });
321
+ referencedElement = await visitAsync(referencedElement, visitor, {
322
+ keyMap,
323
+ nodeTypeGetter: getNodeType
324
+ });
346
325
 
347
- // annotate referenced element with info about original referencing element
348
- mergedElement.setMetaProperty('ref-fields', {
349
- $ref: toValue(pathItemElement.$ref)
350
- });
351
- // annotate referenced element with info about origin
352
- mergedElement.setMetaProperty('ref-origin', reference.uri);
353
- // annotate fragment with info about referencing element
354
- mergedElement.setMetaProperty('ref-referencing-element-id', cloneDeep(identityManager.identify(pathItemElement)));
355
-
356
- // apply meta patches
357
- if (this.allowMetaPatches) {
358
- // apply meta patch only when not already applied
359
- if (typeof mergedElement.get('$$ref') === 'undefined') {
360
- const baseURI = url.resolve(retrievalURI, $refBaseURI);
361
- mergedElement.set('$$ref', baseURI);
362
- }
326
+ // remove referencing schema from ancestors lineage
327
+ directAncestors.delete(pathItemElement);
328
+ }
329
+ this.indirections.pop();
330
+
331
+ /**
332
+ * Creating a new version of Path Item by merging fields from referenced Path Item with referencing one.
333
+ */
334
+ if (isPathItemElement(referencedElement)) {
335
+ const mergedElement = new PathItemElement([...referencedElement.content], cloneDeep(referencedElement.meta), cloneDeep(referencedElement.attributes));
336
+ // existing keywords from referencing PathItemElement overrides ones from referenced element
337
+ pathItemElement.forEach((value, keyElement, item) => {
338
+ mergedElement.remove(toValue(keyElement));
339
+ mergedElement.content.push(item);
340
+ });
341
+ mergedElement.remove('$ref');
342
+
343
+ // annotate referenced element with info about original referencing element
344
+ mergedElement.setMetaProperty('ref-fields', {
345
+ $ref: toValue(pathItemElement.$ref)
346
+ });
347
+ // annotate referenced element with info about origin
348
+ mergedElement.setMetaProperty('ref-origin', reference.uri);
349
+ // annotate fragment with info about referencing element
350
+ mergedElement.setMetaProperty('ref-referencing-element-id', cloneDeep(identityManager.identify(pathItemElement)));
351
+
352
+ // apply meta patches
353
+ if (this.allowMetaPatches) {
354
+ // apply meta patch only when not already applied
355
+ if (typeof mergedElement.get('$$ref') === 'undefined') {
356
+ const baseURI = url.resolve(retrievalURI, $refBaseURI);
357
+ mergedElement.set('$$ref', baseURI);
363
358
  }
364
- referencedElement = mergedElement;
365
359
  }
360
+ referencedElement = mergedElement;
361
+ }
366
362
 
367
- /**
368
- * Transclude referencing element with merged referenced element.
369
- */
370
- if (isMemberElement(parent)) {
371
- parent.value = referencedElement; // eslint-disable-line no-param-reassign
372
- } else if (Array.isArray(parent)) {
373
- parent[key] = referencedElement; // eslint-disable-line no-param-reassign
374
- }
363
+ /**
364
+ * Transclude referencing element with merged referenced element.
365
+ */
366
+ link.replaceWith(referencedElement, mutationReplacer);
375
367
 
376
- /**
377
- * We're at the root of the tree, so we're just replacing the entire tree.
378
- */
379
- return !parent ? referencedElement : undefined;
380
- } catch (error) {
381
- var _this$basePath4, _this$options$derefer7, _this$options$derefer8;
382
- const rootCause = getRootCause(error);
383
- const wrappedError = wrapError(rootCause, {
384
- baseDoc: this.reference.uri,
385
- $ref: toValue(pathItemElement.$ref),
386
- pointer: uriToPointer(toValue(pathItemElement.$ref)),
387
- fullPath: (_this$basePath4 = this.basePath) !== null && _this$basePath4 !== void 0 ? _this$basePath4 : [...toPath([...ancestors, parent, pathItemElement]), '$ref']
388
- });
389
- (_this$options$derefer7 = this.options.dereference.dereferenceOpts) === null || _this$options$derefer7 === void 0 || (_this$options$derefer7 = _this$options$derefer7.errors) === null || _this$options$derefer7 === void 0 || (_this$options$derefer8 = _this$options$derefer7.push) === null || _this$options$derefer8 === void 0 || _this$options$derefer8.call(_this$options$derefer7, wrappedError);
368
+ /**
369
+ * We're at the root of the tree, so we're just replacing the entire tree.
370
+ */
371
+ return !parent ? referencedElement : undefined;
372
+ } catch (error) {
373
+ var _this$basePath4, _this$options$derefer7, _this$options$derefer8;
374
+ const rootCause = getRootCause(error);
375
+ const wrappedError = wrapError(rootCause, {
376
+ baseDoc: this.reference.uri,
377
+ $ref: toValue(pathItemElement.$ref),
378
+ pointer: uriToPointer(toValue(pathItemElement.$ref)),
379
+ fullPath: (_this$basePath4 = this.basePath) !== null && _this$basePath4 !== void 0 ? _this$basePath4 : [...toPath([...ancestors, parent, pathItemElement]), '$ref']
380
+ });
381
+ (_this$options$derefer7 = this.options.dereference.dereferenceOpts) === null || _this$options$derefer7 === void 0 || (_this$options$derefer7 = _this$options$derefer7.errors) === null || _this$options$derefer7 === void 0 || (_this$options$derefer8 = _this$options$derefer7.push) === null || _this$options$derefer8 === void 0 || _this$options$derefer8.call(_this$options$derefer7, wrappedError);
382
+ return undefined;
383
+ }
384
+ }
385
+ async SchemaElement(referencingElement, key, parent, path, ancestors, link) {
386
+ try {
387
+ // skip current referencing schema as $ref keyword was not defined
388
+ if (!isStringElement(referencingElement.$ref)) {
389
+ // skip traversing this schema but traverse all it's child schemas
390
390
  return undefined;
391
391
  }
392
- },
393
- async SchemaElement(referencingElement, key, parent, path, ancestors) {
394
- try {
395
- // skip current referencing schema as $ref keyword was not defined
396
- if (!isStringElement(referencingElement.$ref)) {
397
- // skip traversing this schema but traverse all it's child schemas
398
- return undefined;
399
- }
400
392
 
401
- // skip current referencing element as it's already been access
402
- if (this.indirections.includes(referencingElement)) {
403
- return false;
393
+ // skip current referencing element as it's already been access
394
+ if (this.indirections.includes(referencingElement)) {
395
+ return false;
396
+ }
397
+ const [ancestorsLineage, directAncestors] = this.toAncestorLineage([...ancestors, parent]);
398
+
399
+ // compute baseURI using rules around $id and $ref keywords
400
+ let reference = await this.toReference(url.unsanitize(this.reference.uri));
401
+ let {
402
+ uri: retrievalURI
403
+ } = reference;
404
+ const $refBaseURI = resolveSchema$refField(retrievalURI, referencingElement);
405
+ const $refBaseURIStrippedHash = url.stripHash($refBaseURI);
406
+ const file = new File({
407
+ uri: $refBaseURIStrippedHash
408
+ });
409
+ const isUnknownURI = !this.options.resolve.resolvers.some(r => r.canRead(file));
410
+ const isURL = !isUnknownURI;
411
+ let isInternalReference = url.stripHash(this.reference.uri) === $refBaseURI;
412
+ let isExternalReference = !isInternalReference;
413
+ this.indirections.push(referencingElement);
414
+
415
+ // determining reference, proper evaluation and selection mechanism
416
+ let referencedElement;
417
+ try {
418
+ if (isUnknownURI || isURL) {
419
+ // we're dealing with canonical URI or URL with possible fragment
420
+ retrievalURI = this.toBaseURI($refBaseURI);
421
+ const selector = $refBaseURI;
422
+ const referenceAsSchema = maybeRefractToSchemaElement(reference.value.result);
423
+ referencedElement = uriEvaluate(selector, referenceAsSchema);
424
+ referencedElement = maybeRefractToSchemaElement(referencedElement);
425
+ referencedElement.id = identityManager.identify(referencedElement);
426
+
427
+ // ignore resolving internal Schema Objects
428
+ if (!this.options.resolve.internal && isInternalReference) {
429
+ // skip traversing this schema element but traverse all it's child elements
430
+ return undefined;
431
+ }
432
+ // ignore resolving external Schema Objects
433
+ if (!this.options.resolve.external && isExternalReference) {
434
+ // skip traversing this schema element but traverse all it's child elements
435
+ return undefined;
436
+ }
437
+ } else {
438
+ // we're assuming here that we're dealing with JSON Pointer here
439
+ retrievalURI = this.toBaseURI($refBaseURI);
440
+ isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
441
+ isExternalReference = !isInternalReference;
442
+
443
+ // ignore resolving internal Schema Objects
444
+ if (!this.options.resolve.internal && isInternalReference) {
445
+ // skip traversing this schema element but traverse all it's child elements
446
+ return undefined;
447
+ }
448
+ // ignore resolving external Schema Objects
449
+ if (!this.options.resolve.external && isExternalReference) {
450
+ // skip traversing this schema element but traverse all it's child elements
451
+ return undefined;
452
+ }
453
+ reference = await this.toReference(url.unsanitize($refBaseURI));
454
+ const selector = uriToPointer($refBaseURI);
455
+ const referenceAsSchema = maybeRefractToSchemaElement(reference.value.result);
456
+ referencedElement = jsonPointerEvaluate(selector, referenceAsSchema);
457
+ referencedElement = maybeRefractToSchemaElement(referencedElement);
458
+ referencedElement.id = identityManager.identify(referencedElement);
404
459
  }
405
- const [ancestorsLineage, directAncestors] = this.toAncestorLineage([...ancestors, parent]);
406
-
407
- // compute baseURI using rules around $id and $ref keywords
408
- let reference = await this.toReference(url.unsanitize(this.reference.uri));
409
- let {
410
- uri: retrievalURI
411
- } = reference;
412
- const $refBaseURI = resolveSchema$refField(retrievalURI, referencingElement);
413
- const $refBaseURIStrippedHash = url.stripHash($refBaseURI);
414
- const file = File({
415
- uri: $refBaseURIStrippedHash
416
- });
417
- const isUnknownURI = !this.options.resolve.resolvers.some(r => r.canRead(file));
418
- const isURL = !isUnknownURI;
419
- let isInternalReference = url.stripHash(this.reference.uri) === $refBaseURI;
420
- let isExternalReference = !isInternalReference;
421
- this.indirections.push(referencingElement);
422
-
423
- // determining reference, proper evaluation and selection mechanism
424
- let referencedElement;
425
- try {
426
- if (isUnknownURI || isURL) {
427
- // we're dealing with canonical URI or URL with possible fragment
428
- retrievalURI = this.toBaseURI($refBaseURI);
429
- const selector = $refBaseURI;
430
- const referenceAsSchema = maybeRefractToSchemaElement(reference.value.result);
431
- referencedElement = uriEvaluate(selector, referenceAsSchema);
432
- referencedElement = maybeRefractToSchemaElement(referencedElement);
433
- referencedElement.id = identityManager.identify(referencedElement);
460
+ } catch (error) {
461
+ /**
462
+ * No SchemaElement($id=URL) was not found, so we're going to try to resolve
463
+ * the URL and assume the returned response is a JSON Schema.
464
+ */
465
+ if (isURL && error instanceof EvaluationJsonSchemaUriError) {
466
+ if (isAnchor(uriToAnchor($refBaseURI))) {
467
+ // we're dealing with JSON Schema $anchor here
468
+ isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
469
+ isExternalReference = !isInternalReference;
434
470
 
435
471
  // ignore resolving internal Schema Objects
436
472
  if (!this.options.resolve.internal && isInternalReference) {
@@ -442,9 +478,15 @@ const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.c
442
478
  // skip traversing this schema element but traverse all it's child elements
443
479
  return undefined;
444
480
  }
481
+ reference = await this.toReference(url.unsanitize($refBaseURI));
482
+ const selector = uriToAnchor($refBaseURI);
483
+ const referenceAsSchema = maybeRefractToSchemaElement(reference.value.result);
484
+ referencedElement = $anchorEvaluate(selector, referenceAsSchema);
485
+ referencedElement = maybeRefractToSchemaElement(referencedElement);
486
+ referencedElement.id = identityManager.identify(referencedElement);
445
487
  } else {
446
488
  // we're assuming here that we're dealing with JSON Pointer here
447
- retrievalURI = this.toBaseURI($refBaseURI);
489
+ retrievalURI = this.toBaseURI(toValue($refBaseURI));
448
490
  isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
449
491
  isExternalReference = !isInternalReference;
450
492
 
@@ -465,232 +507,171 @@ const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.c
465
507
  referencedElement = maybeRefractToSchemaElement(referencedElement);
466
508
  referencedElement.id = identityManager.identify(referencedElement);
467
509
  }
468
- } catch (error) {
469
- /**
470
- * No SchemaElement($id=URL) was not found, so we're going to try to resolve
471
- * the URL and assume the returned response is a JSON Schema.
472
- */
473
- if (isURL && error instanceof EvaluationJsonSchemaUriError) {
474
- if (isAnchor(uriToAnchor($refBaseURI))) {
475
- // we're dealing with JSON Schema $anchor here
476
- isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
477
- isExternalReference = !isInternalReference;
478
-
479
- // ignore resolving internal Schema Objects
480
- if (!this.options.resolve.internal && isInternalReference) {
481
- // skip traversing this schema element but traverse all it's child elements
482
- return undefined;
483
- }
484
- // ignore resolving external Schema Objects
485
- if (!this.options.resolve.external && isExternalReference) {
486
- // skip traversing this schema element but traverse all it's child elements
487
- return undefined;
488
- }
489
- reference = await this.toReference(url.unsanitize($refBaseURI));
490
- const selector = uriToAnchor($refBaseURI);
491
- const referenceAsSchema = maybeRefractToSchemaElement(reference.value.result);
492
- referencedElement = $anchorEvaluate(selector, referenceAsSchema);
493
- referencedElement = maybeRefractToSchemaElement(referencedElement);
494
- referencedElement.id = identityManager.identify(referencedElement);
495
- } else {
496
- // we're assuming here that we're dealing with JSON Pointer here
497
- retrievalURI = this.toBaseURI(toValue($refBaseURI));
498
- isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
499
- isExternalReference = !isInternalReference;
500
-
501
- // ignore resolving internal Schema Objects
502
- if (!this.options.resolve.internal && isInternalReference) {
503
- // skip traversing this schema element but traverse all it's child elements
504
- return undefined;
505
- }
506
- // ignore resolving external Schema Objects
507
- if (!this.options.resolve.external && isExternalReference) {
508
- // skip traversing this schema element but traverse all it's child elements
509
- return undefined;
510
- }
511
- reference = await this.toReference(url.unsanitize($refBaseURI));
512
- const selector = uriToPointer($refBaseURI);
513
- const referenceAsSchema = maybeRefractToSchemaElement(reference.value.result);
514
- referencedElement = jsonPointerEvaluate(selector, referenceAsSchema);
515
- referencedElement = maybeRefractToSchemaElement(referencedElement);
516
- referencedElement.id = identityManager.identify(referencedElement);
517
- }
518
- } else {
519
- throw error;
520
- }
510
+ } else {
511
+ throw error;
521
512
  }
513
+ }
522
514
 
523
- // detect direct or indirect reference
524
- if (referencingElement === referencedElement) {
525
- throw new ApiDOMError('Recursive Schema Object reference detected');
526
- }
515
+ // detect direct or indirect reference
516
+ if (referencingElement === referencedElement) {
517
+ throw new ApiDOMError('Recursive Schema Object reference detected');
518
+ }
527
519
 
528
- // detect maximum depth of dereferencing
529
- if (this.indirections.length > this.options.dereference.maxDepth) {
530
- throw new MaximumDereferenceDepthError(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
531
- }
520
+ // detect maximum depth of dereferencing
521
+ if (this.indirections.length > this.options.dereference.maxDepth) {
522
+ throw new MaximumDereferenceDepthError(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
523
+ }
532
524
 
533
- // detect second deep dive into the same fragment and avoid it
534
- if (ancestorsLineage.includes(referencedElement)) {
535
- reference.refSet.circular = true;
536
- if (this.options.dereference.circular === 'error') {
537
- throw new ApiDOMError('Circular reference detected');
538
- } else if (this.options.dereference.circular === 'replace') {
539
- var _this$options$derefer9, _this$options$derefer10;
540
- const refElement = new RefElement(referencedElement.id, {
541
- type: 'json-schema',
542
- uri: reference.uri,
543
- $ref: toValue(referencingElement.$ref),
544
- baseURI: url.resolve(retrievalURI, $refBaseURI),
545
- referencingElement
546
- });
547
- const replacer = (_this$options$derefer9 = (_this$options$derefer10 = this.options.dereference.strategyOpts['openapi-3-1']) === null || _this$options$derefer10 === void 0 ? void 0 : _this$options$derefer10.circularReplacer) !== null && _this$options$derefer9 !== void 0 ? _this$options$derefer9 : this.options.dereference.circularReplacer;
548
- const replacement = replacer(refElement);
549
- if (isMemberElement(parent)) {
550
- parent.value = replacement; // eslint-disable-line no-param-reassign
551
- } else if (Array.isArray(parent)) {
552
- parent[key] = replacement; // eslint-disable-line no-param-reassign
553
- }
554
- return !parent ? replacement : false;
555
- }
525
+ // detect second deep dive into the same fragment and avoid it
526
+ if (ancestorsLineage.includes(referencedElement)) {
527
+ reference.refSet.circular = true;
528
+ if (this.options.dereference.circular === 'error') {
529
+ throw new ApiDOMError('Circular reference detected');
530
+ } else if (this.options.dereference.circular === 'replace') {
531
+ var _this$options$derefer9, _this$options$derefer10;
532
+ const refElement = new RefElement(referencedElement.id, {
533
+ type: 'json-schema',
534
+ uri: reference.uri,
535
+ $ref: toValue(referencingElement.$ref),
536
+ baseURI: url.resolve(retrievalURI, $refBaseURI),
537
+ referencingElement
538
+ });
539
+ const replacer = (_this$options$derefer9 = (_this$options$derefer10 = this.options.dereference.strategyOpts['openapi-3-1']) === null || _this$options$derefer10 === void 0 ? void 0 : _this$options$derefer10.circularReplacer) !== null && _this$options$derefer9 !== void 0 ? _this$options$derefer9 : this.options.dereference.circularReplacer;
540
+ const replacement = replacer(refElement);
541
+ link.replaceWith(replacement, mutationReplacer);
542
+ return !parent ? replacement : false;
556
543
  }
544
+ }
557
545
 
558
- /**
559
- * Dive deep into the fragment.
560
- *
561
- * Cases to consider:
562
- * 1. We're crossing document boundary
563
- * 2. Fragment is from non-root document
564
- * 3. Fragment is a Schema Object with $ref field. We need to follow it to get the eventual value
565
- * 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
566
- */
567
- const isNonRootDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
568
- const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
569
- if ((isExternalReference || isNonRootDocument || isSchemaElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
570
- var _this$basePath5;
571
- // append referencing schema to ancestors lineage
572
- directAncestors.add(referencingElement);
573
-
574
- // dive deep into the fragment
575
- const mergeVisitor = OpenApi3_1SwaggerClientDereferenceVisitor({
576
- reference,
577
- namespace: this.namespace,
578
- indirections: [...this.indirections],
579
- options: this.options,
580
- useCircularStructures: this.useCircularStructures,
581
- allowMetaPatches: this.allowMetaPatches,
582
- ancestors: ancestorsLineage,
583
- basePath: (_this$basePath5 = this.basePath) !== null && _this$basePath5 !== void 0 ? _this$basePath5 : [...toPath([...ancestors, parent, referencingElement]), '$ref']
584
- });
585
- referencedElement = await visitAsync(referencedElement, mergeVisitor, {
586
- keyMap,
587
- nodeTypeGetter: getNodeType
588
- });
546
+ /**
547
+ * Dive deep into the fragment.
548
+ *
549
+ * Cases to consider:
550
+ * 1. We're crossing document boundary
551
+ * 2. Fragment is from non-root document
552
+ * 3. Fragment is a Schema Object with $ref field. We need to follow it to get the eventual value
553
+ * 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
554
+ */
555
+ const isNonRootDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
556
+ const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
557
+ if ((isExternalReference || isNonRootDocument || isSchemaElement(referencedElement) && isStringElement(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
558
+ var _this$basePath5;
559
+ // append referencing schema to ancestors lineage
560
+ directAncestors.add(referencingElement);
561
+
562
+ // dive deep into the fragment
563
+ const mergeVisitor = new OpenAPI3_1SwaggerClientDereferenceVisitor({
564
+ reference,
565
+ namespace: this.namespace,
566
+ indirections: [...this.indirections],
567
+ options: this.options,
568
+ useCircularStructures: this.useCircularStructures,
569
+ allowMetaPatches: this.allowMetaPatches,
570
+ ancestors: ancestorsLineage,
571
+ basePath: (_this$basePath5 = this.basePath) !== null && _this$basePath5 !== void 0 ? _this$basePath5 : [...toPath([...ancestors, parent, referencingElement]), '$ref']
572
+ });
573
+ referencedElement = await visitAsync(referencedElement, mergeVisitor, {
574
+ keyMap,
575
+ nodeTypeGetter: getNodeType
576
+ });
589
577
 
590
- // remove referencing schema from ancestors lineage
591
- directAncestors.delete(referencingElement);
592
- }
593
- this.indirections.pop();
594
- if (isBooleanJsonSchemaElement(referencedElement)) {
595
- const booleanJsonSchemaElement = cloneDeep(referencedElement);
596
- // annotate referenced element with info about original referencing element
597
- booleanJsonSchemaElement.setMetaProperty('ref-fields', {
598
- $ref: toValue(referencingElement.$ref)
599
- });
600
- // annotate referenced element with info about origin
601
- booleanJsonSchemaElement.setMetaProperty('ref-origin', reference.uri);
602
- // annotate fragment with info about referencing element
603
- booleanJsonSchemaElement.setMetaProperty('ref-referencing-element-id', cloneDeep(identityManager.identify(referencingElement)));
604
- if (isMemberElement(parent)) {
605
- parent.value = booleanJsonSchemaElement; // eslint-disable-line no-param-reassign
606
- } else if (Array.isArray(parent)) {
607
- parent[key] = booleanJsonSchemaElement; // eslint-disable-line no-param-reassign
608
- }
609
- return !parent ? booleanJsonSchemaElement : false;
610
- }
578
+ // remove referencing schema from ancestors lineage
579
+ directAncestors.delete(referencingElement);
580
+ }
581
+ this.indirections.pop();
582
+ if (isBooleanJsonSchemaElement(referencedElement)) {
583
+ const booleanJsonSchemaElement = cloneDeep(referencedElement);
584
+ // annotate referenced element with info about original referencing element
585
+ booleanJsonSchemaElement.setMetaProperty('ref-fields', {
586
+ $ref: toValue(referencingElement.$ref)
587
+ });
588
+ // annotate referenced element with info about origin
589
+ booleanJsonSchemaElement.setMetaProperty('ref-origin', reference.uri);
590
+ // annotate fragment with info about referencing element
591
+ booleanJsonSchemaElement.setMetaProperty('ref-referencing-element-id', cloneDeep(identityManager.identify(referencingElement)));
592
+ link.replaceWith(booleanJsonSchemaElement, mutationReplacer);
593
+ return !parent ? booleanJsonSchemaElement : false;
594
+ }
611
595
 
612
- /**
613
- * Creating a new version of Schema Object by merging fields from referenced Schema Object with referencing one.
614
- */
615
- if (isSchemaElement(referencedElement)) {
616
- // Schema Object - merge keywords from referenced schema with referencing schema
617
- const mergedElement = new SchemaElement([...referencedElement.content], cloneDeep(referencedElement.meta), cloneDeep(referencedElement.attributes));
618
- // existing keywords from referencing schema overrides ones from referenced schema
619
- referencingElement.forEach((value, keyElement, item) => {
620
- mergedElement.remove(toValue(keyElement));
621
- mergedElement.content.push(item);
622
- });
623
- mergedElement.remove('$ref');
624
- // annotate referenced element with info about original referencing element
625
- mergedElement.setMetaProperty('ref-fields', {
626
- $ref: toValue(referencingElement.$ref)
627
- });
628
- // annotate fragment with info about origin
629
- mergedElement.setMetaProperty('ref-origin', reference.uri);
630
- // annotate fragment with info about referencing element
631
- mergedElement.setMetaProperty('ref-referencing-element-id', cloneDeep(identityManager.identify(referencingElement)));
632
-
633
- // allowMetaPatches option processing
634
- if (this.allowMetaPatches) {
635
- // apply meta patch only when not already applied
636
- if (typeof mergedElement.get('$$ref') === 'undefined') {
637
- const baseURI = url.resolve(retrievalURI, $refBaseURI);
638
- mergedElement.set('$$ref', baseURI);
639
- }
596
+ /**
597
+ * Creating a new version of Schema Object by merging fields from referenced Schema Object with referencing one.
598
+ */
599
+ if (isSchemaElement(referencedElement)) {
600
+ // Schema Object - merge keywords from referenced schema with referencing schema
601
+ const mergedElement = new SchemaElement([...referencedElement.content], cloneDeep(referencedElement.meta), cloneDeep(referencedElement.attributes));
602
+ // existing keywords from referencing schema overrides ones from referenced schema
603
+ referencingElement.forEach((value, keyElement, item) => {
604
+ mergedElement.remove(toValue(keyElement));
605
+ mergedElement.content.push(item);
606
+ });
607
+ mergedElement.remove('$ref');
608
+ // annotate referenced element with info about original referencing element
609
+ mergedElement.setMetaProperty('ref-fields', {
610
+ $ref: toValue(referencingElement.$ref)
611
+ });
612
+ // annotate fragment with info about origin
613
+ mergedElement.setMetaProperty('ref-origin', reference.uri);
614
+ // annotate fragment with info about referencing element
615
+ mergedElement.setMetaProperty('ref-referencing-element-id', cloneDeep(identityManager.identify(referencingElement)));
616
+
617
+ // allowMetaPatches option processing
618
+ if (this.allowMetaPatches) {
619
+ // apply meta patch only when not already applied
620
+ if (typeof mergedElement.get('$$ref') === 'undefined') {
621
+ const baseURI = url.resolve(retrievalURI, $refBaseURI);
622
+ mergedElement.set('$$ref', baseURI);
640
623
  }
641
- referencedElement = mergedElement;
642
624
  }
625
+ referencedElement = mergedElement;
626
+ }
643
627
 
644
- /**
645
- * Transclude referencing element with merged referenced element.
646
- */
647
- if (isMemberElement(parent)) {
648
- parent.value = referencedElement; // eslint-disable-line no-param-reassign
649
- } else if (Array.isArray(parent)) {
650
- parent[key] = referencedElement; // eslint-disable-line no-param-reassign
651
- }
628
+ /**
629
+ * Transclude referencing element with merged referenced element.
630
+ */
631
+ link.replaceWith(referencedElement, mutationReplacer);
652
632
 
653
- /**
654
- * We're at the root of the tree, so we're just replacing the entire tree.
655
- */
656
- return !parent ? referencedElement : undefined;
657
- } catch (error) {
658
- var _this$basePath6, _this$options$derefer11, _this$options$derefer12;
659
- const rootCause = getRootCause(error);
660
- const wrappedError = new SchemaRefError(`Could not resolve reference: ${rootCause.message}`, {
661
- baseDoc: this.reference.uri,
662
- $ref: toValue(referencingElement.$ref),
663
- fullPath: (_this$basePath6 = this.basePath) !== null && _this$basePath6 !== void 0 ? _this$basePath6 : [...toPath([...ancestors, parent, referencingElement]), '$ref'],
664
- cause: rootCause
665
- });
666
- (_this$options$derefer11 = this.options.dereference.dereferenceOpts) === null || _this$options$derefer11 === void 0 || (_this$options$derefer11 = _this$options$derefer11.errors) === null || _this$options$derefer11 === void 0 || (_this$options$derefer12 = _this$options$derefer11.push) === null || _this$options$derefer12 === void 0 || _this$options$derefer12.call(_this$options$derefer11, wrappedError);
667
- return undefined;
668
- }
669
- },
670
- async LinkElement() {
671
633
  /**
672
- * OpenApi3_1DereferenceVisitor is doing lookup of Operation Objects
673
- * and assigns them to Link Object metadata. This is not needed in
674
- * swagger-client context, so we're disabling it here.
634
+ * We're at the root of the tree, so we're just replacing the entire tree.
675
635
  */
636
+ return !parent ? referencedElement : undefined;
637
+ } catch (error) {
638
+ var _this$basePath6, _this$options$derefer11, _this$options$derefer12;
639
+ const rootCause = getRootCause(error);
640
+ const wrappedError = new SchemaRefError(`Could not resolve reference: ${rootCause.message}`, {
641
+ baseDoc: this.reference.uri,
642
+ $ref: toValue(referencingElement.$ref),
643
+ fullPath: (_this$basePath6 = this.basePath) !== null && _this$basePath6 !== void 0 ? _this$basePath6 : [...toPath([...ancestors, parent, referencingElement]), '$ref'],
644
+ cause: rootCause
645
+ });
646
+ (_this$options$derefer11 = this.options.dereference.dereferenceOpts) === null || _this$options$derefer11 === void 0 || (_this$options$derefer11 = _this$options$derefer11.errors) === null || _this$options$derefer11 === void 0 || (_this$options$derefer12 = _this$options$derefer11.push) === null || _this$options$derefer12 === void 0 || _this$options$derefer12.call(_this$options$derefer11, wrappedError);
647
+ return undefined;
648
+ }
649
+ }
650
+
651
+ // eslint-disable-next-line class-methods-use-this
652
+ async LinkElement() {
653
+ /**
654
+ * OpenApi3_1DereferenceVisitor is doing lookup of Operation Objects
655
+ * and assigns them to Link Object metadata. This is not needed in
656
+ * swagger-client context, so we're disabling it here.
657
+ */
658
+ return undefined;
659
+ }
660
+ async ExampleElement(exampleElement, key, parent, path, ancestors, link) {
661
+ try {
662
+ return await super.ExampleElement(exampleElement, key, parent, path, ancestors, link);
663
+ } catch (error) {
664
+ var _this$basePath7, _this$options$derefer13, _this$options$derefer14;
665
+ const rootCause = getRootCause(error);
666
+ const wrappedError = wrapError(rootCause, {
667
+ baseDoc: this.reference.uri,
668
+ externalValue: toValue(exampleElement.externalValue),
669
+ fullPath: (_this$basePath7 = this.basePath) !== null && _this$basePath7 !== void 0 ? _this$basePath7 : [...toPath([...ancestors, parent, exampleElement]), 'externalValue']
670
+ });
671
+ (_this$options$derefer13 = this.options.dereference.dereferenceOpts) === null || _this$options$derefer13 === void 0 || (_this$options$derefer13 = _this$options$derefer13.errors) === null || _this$options$derefer13 === void 0 || (_this$options$derefer14 = _this$options$derefer13.push) === null || _this$options$derefer14 === void 0 || _this$options$derefer14.call(_this$options$derefer13, wrappedError);
676
672
  return undefined;
677
- },
678
- async ExampleElement(exampleElement, key, parent, path, ancestors) {
679
- try {
680
- return await OpenApi3_1DereferenceVisitor.compose.methods.ExampleElement.call(this, exampleElement, key, parent, path, ancestors);
681
- } catch (error) {
682
- var _this$basePath7, _this$options$derefer13, _this$options$derefer14;
683
- const rootCause = getRootCause(error);
684
- const wrappedError = wrapError(rootCause, {
685
- baseDoc: this.reference.uri,
686
- externalValue: toValue(exampleElement.externalValue),
687
- fullPath: (_this$basePath7 = this.basePath) !== null && _this$basePath7 !== void 0 ? _this$basePath7 : [...toPath([...ancestors, parent, exampleElement]), 'externalValue']
688
- });
689
- (_this$options$derefer13 = this.options.dereference.dereferenceOpts) === null || _this$options$derefer13 === void 0 || (_this$options$derefer13 = _this$options$derefer13.errors) === null || _this$options$derefer13 === void 0 || (_this$options$derefer14 = _this$options$derefer13.push) === null || _this$options$derefer14 === void 0 || _this$options$derefer14.call(_this$options$derefer13, wrappedError);
690
- return undefined;
691
- }
692
673
  }
693
674
  }
694
- });
695
- export default OpenApi3_1SwaggerClientDereferenceVisitor;
675
+ }
676
+ export default OpenAPI3_1SwaggerClientDereferenceVisitor;
696
677
  /* eslint-enable camelcase */