source: node_modules/@swagger-api/apidom-reference/cjs/resolve/strategies/asyncapi-2/visitor.cjs

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 16 months ago

Initial commit

  • Property mode set to 100644
File size: 8.5 KB
Line 
1"use strict";
2
3var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
4var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
5exports.__esModule = true;
6exports.default = void 0;
7var _stampit = _interopRequireDefault(require("stampit"));
8var _ramda = require("ramda");
9var _ramdaAdjunct = require("ramda-adjunct");
10var _apidomCore = require("@swagger-api/apidom-core");
11var _apidomError = require("@swagger-api/apidom-error");
12var _apidomJsonPointer = require("@swagger-api/apidom-json-pointer");
13var _apidomNsAsyncapi = require("@swagger-api/apidom-ns-asyncapi-2");
14var _MaximumDereferenceDepthError = _interopRequireDefault(require("../../../errors/MaximumDereferenceDepthError.cjs"));
15var _MaximumResolveDepthError = _interopRequireDefault(require("../../../errors/MaximumResolveDepthError.cjs"));
16var url = _interopRequireWildcard(require("../../../util/url.cjs"));
17var _index = _interopRequireDefault(require("../../../parse/index.cjs"));
18var _Reference = _interopRequireDefault(require("../../../Reference.cjs"));
19// @ts-ignore
20const visitAsync = _apidomCore.visit[Symbol.for('nodejs.util.promisify.custom')];
21const AsyncApi2ResolveVisitor = (0, _stampit.default)({
22 props: {
23 indirections: [],
24 namespace: null,
25 reference: null,
26 crawledElements: null,
27 crawlingMap: null,
28 options: null
29 },
30 init({
31 reference,
32 namespace,
33 indirections = [],
34 options
35 }) {
36 this.indirections = indirections;
37 this.namespace = namespace;
38 this.reference = reference;
39 this.crawledElements = [];
40 this.crawlingMap = {};
41 this.options = options;
42 },
43 methods: {
44 toBaseURI(uri) {
45 return url.resolve(this.reference.uri, url.sanitize(url.stripHash(uri)));
46 },
47 async toReference(uri) {
48 // detect maximum depth of resolution
49 if (this.reference.depth >= this.options.resolve.maxDepth) {
50 throw new _MaximumResolveDepthError.default(`Maximum resolution depth of ${this.options.resolve.maxDepth} has been exceeded by file "${this.reference.uri}"`);
51 }
52 const baseURI = this.toBaseURI(uri);
53 const {
54 refSet
55 } = this.reference;
56
57 // we've already processed this Reference in past
58 if (refSet.has(baseURI)) {
59 return refSet.find((0, _ramda.propEq)(baseURI, 'uri'));
60 }
61 const parseResult = await (0, _index.default)(url.unsanitize(baseURI), {
62 ...this.options,
63 parse: {
64 ...this.options.parse,
65 mediaType: 'text/plain'
66 }
67 });
68
69 // register new Reference with ReferenceSet
70 const reference = (0, _Reference.default)({
71 uri: baseURI,
72 value: parseResult,
73 depth: this.reference.depth + 1
74 });
75 refSet.add(reference);
76 return reference;
77 },
78 ReferenceElement(referenceElement) {
79 const uri = (0, _apidomCore.toValue)(referenceElement.$ref);
80 const retrievalURI = this.toBaseURI(uri);
81
82 // ignore resolving external Reference Objects
83 if (!this.options.resolve.external && url.stripHash(this.reference.uri) !== retrievalURI) {
84 return false;
85 }
86 if (!(0, _ramda.has)(retrievalURI, this.crawlingMap)) {
87 this.crawlingMap[retrievalURI] = this.toReference(uri);
88 }
89 this.crawledElements.push(referenceElement);
90 return undefined;
91 },
92 ChannelItemElement(channelItemElement) {
93 // ignore PathItemElement without $ref field
94 if (!(0, _apidomCore.isStringElement)(channelItemElement.$ref)) {
95 return undefined;
96 }
97 const uri = (0, _apidomCore.toValue)(channelItemElement.$ref);
98 const retrievalURI = this.toBaseURI(uri);
99
100 // ignore resolving external Channel Item Objects
101 if (!this.options.resolve.external && url.stripHash(this.reference.uri) !== retrievalURI) {
102 return undefined;
103 }
104 if (!(0, _ramda.has)(retrievalURI, this.crawlingMap)) {
105 this.crawlingMap[retrievalURI] = this.toReference(uri);
106 }
107 this.crawledElements.push(channelItemElement);
108 return undefined;
109 },
110 async crawlReferenceElement(referenceElement) {
111 // @ts-ignore
112 const reference = await this.toReference((0, _apidomCore.toValue)(referenceElement.$ref));
113 this.indirections.push(referenceElement);
114 const jsonPointer = (0, _apidomJsonPointer.uriToPointer)((0, _apidomCore.toValue)(referenceElement.$ref));
115
116 // possibly non-semantic fragment
117 let fragment = (0, _apidomJsonPointer.evaluate)(jsonPointer, reference.value.result);
118
119 // applying semantics to a fragment
120 if ((0, _apidomCore.isPrimitiveElement)(fragment)) {
121 const referencedElementType = (0, _apidomCore.toValue)(referenceElement.meta.get('referenced-element'));
122 if ((0, _apidomNsAsyncapi.isReferenceLikeElement)(fragment)) {
123 // handling indirect references
124 fragment = _apidomNsAsyncapi.ReferenceElement.refract(fragment);
125 fragment.setMetaProperty('referenced-element', referencedElementType);
126 } else {
127 // handling direct references
128 const ElementClass = this.namespace.getElementClass(referencedElementType);
129 fragment = ElementClass.refract(fragment);
130 }
131 }
132
133 // detect direct or circular reference
134 if (this.indirections.includes(fragment)) {
135 throw new _apidomError.ApiDOMError('Recursive Reference Object detected');
136 }
137
138 // detect maximum depth of dereferencing
139 if (this.indirections.length > this.options.dereference.maxDepth) {
140 throw new _MaximumDereferenceDepthError.default(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
141 }
142
143 // dive deep into the fragment
144 const visitor = AsyncApi2ResolveVisitor({
145 reference,
146 namespace: this.namespace,
147 indirections: [...this.indirections],
148 options: this.options
149 });
150 await visitAsync(fragment, visitor, {
151 keyMap: _apidomNsAsyncapi.keyMap,
152 nodeTypeGetter: _apidomNsAsyncapi.getNodeType
153 });
154 await visitor.crawl();
155 this.indirections.pop();
156 },
157 async crawlChannelItemElement(channelItemElement) {
158 const reference = await this.toReference((0, _apidomCore.toValue)(channelItemElement.$ref));
159 this.indirections.push(channelItemElement);
160 const jsonPointer = (0, _apidomJsonPointer.uriToPointer)((0, _apidomCore.toValue)(channelItemElement.$ref));
161
162 // possibly non-semantic referenced element
163 let referencedElement = (0, _apidomJsonPointer.evaluate)(jsonPointer, reference.value.result);
164
165 // applying semantics to a referenced element
166 if ((0, _apidomCore.isPrimitiveElement)(referencedElement)) {
167 referencedElement = _apidomNsAsyncapi.ChannelItemElement.refract(referencedElement);
168 }
169
170 // detect direct or indirect reference
171 if (this.indirections.includes(referencedElement)) {
172 throw new _apidomError.ApiDOMError('Recursive Channel Item Object reference detected');
173 }
174
175 // detect maximum depth of dereferencing
176 if (this.indirections.length > this.options.dereference.maxDepth) {
177 throw new _MaximumDereferenceDepthError.default(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
178 }
179
180 // dive deep into the referenced element
181 const visitor = AsyncApi2ResolveVisitor({
182 reference,
183 namespace: this.namespace,
184 indirections: [...this.indirections],
185 options: this.options
186 });
187 await visitAsync(referencedElement, visitor, {
188 keyMap: _apidomNsAsyncapi.keyMap,
189 nodeTypeGetter: _apidomNsAsyncapi.getNodeType
190 });
191 await visitor.crawl();
192 this.indirections.pop();
193 },
194 async crawl() {
195 /**
196 * Synchronize all parallel resolutions in this place.
197 * After synchronization happened we can be sure that refSet
198 * contains resolved Reference objects.
199 */
200 await (0, _ramda.pipe)(_ramda.values, _ramdaAdjunct.allP)(this.crawlingMap);
201 this.crawlingMap = null;
202
203 /* eslint-disable no-await-in-loop */
204 for (const element of this.crawledElements) {
205 if ((0, _apidomNsAsyncapi.isReferenceElement)(element)) {
206 await this.crawlReferenceElement(element);
207 } else if ((0, _apidomNsAsyncapi.isChannelItemElement)(element)) {
208 await this.crawlChannelItemElement(element);
209 }
210 }
211 /* eslint-enabled */
212 }
213 }
214});
215var _default = exports.default = AsyncApi2ResolveVisitor;
Note: See TracBrowser for help on using the repository browser.