@speclynx/apidom-reference 1.12.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 (263) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/LICENSE +202 -0
  3. package/LICENSES/AFL-3.0.txt +182 -0
  4. package/LICENSES/Apache-2.0.txt +202 -0
  5. package/LICENSES/BSD-3-Clause.txt +26 -0
  6. package/LICENSES/MIT.txt +9 -0
  7. package/NOTICE +65 -0
  8. package/README.md +2107 -0
  9. package/dist/167.apidom-reference.browser.js +10 -0
  10. package/dist/167.apidom-reference.browser.min.js +1 -0
  11. package/dist/451.apidom-reference.browser.js +10 -0
  12. package/dist/451.apidom-reference.browser.min.js +1 -0
  13. package/dist/9786785aaddf11f37840fad896531940.wasm +0 -0
  14. package/dist/apidom-reference.browser.js +85376 -0
  15. package/dist/apidom-reference.browser.min.js +1 -0
  16. package/package.json +304 -0
  17. package/src/File.cjs +50 -0
  18. package/src/File.mjs +44 -0
  19. package/src/Reference.cjs +31 -0
  20. package/src/Reference.mjs +27 -0
  21. package/src/ReferenceSet.cjs +60 -0
  22. package/src/ReferenceSet.mjs +57 -0
  23. package/src/bundle/index.cjs +61 -0
  24. package/src/bundle/index.mjs +55 -0
  25. package/src/bundle/strategies/BundleStrategy.cjs +20 -0
  26. package/src/bundle/strategies/BundleStrategy.mjs +16 -0
  27. package/src/bundle/strategies/openapi-3-1/index.cjs +35 -0
  28. package/src/bundle/strategies/openapi-3-1/index.mjs +29 -0
  29. package/src/configuration/empty.cjs +9 -0
  30. package/src/configuration/empty.mjs +1 -0
  31. package/src/configuration/saturated.cjs +95 -0
  32. package/src/configuration/saturated.mjs +87 -0
  33. package/src/dereference/index.cjs +86 -0
  34. package/src/dereference/index.mjs +79 -0
  35. package/src/dereference/strategies/DereferenceStrategy.cjs +20 -0
  36. package/src/dereference/strategies/DereferenceStrategy.mjs +16 -0
  37. package/src/dereference/strategies/apidom/index.cjs +89 -0
  38. package/src/dereference/strategies/apidom/index.mjs +84 -0
  39. package/src/dereference/strategies/apidom/selectors/element-id.cjs +36 -0
  40. package/src/dereference/strategies/apidom/selectors/element-id.mjs +30 -0
  41. package/src/dereference/strategies/apidom/visitor.cjs +165 -0
  42. package/src/dereference/strategies/apidom/visitor.mjs +159 -0
  43. package/src/dereference/strategies/asyncapi-2/index.cjs +100 -0
  44. package/src/dereference/strategies/asyncapi-2/index.mjs +94 -0
  45. package/src/dereference/strategies/asyncapi-2/visitor.cjs +412 -0
  46. package/src/dereference/strategies/asyncapi-2/visitor.mjs +406 -0
  47. package/src/dereference/strategies/openapi-2/index.cjs +102 -0
  48. package/src/dereference/strategies/openapi-2/index.mjs +96 -0
  49. package/src/dereference/strategies/openapi-2/visitor.cjs +530 -0
  50. package/src/dereference/strategies/openapi-2/visitor.mjs +524 -0
  51. package/src/dereference/strategies/openapi-3-0/index.cjs +102 -0
  52. package/src/dereference/strategies/openapi-3-0/index.mjs +96 -0
  53. package/src/dereference/strategies/openapi-3-0/visitor.cjs +519 -0
  54. package/src/dereference/strategies/openapi-3-0/visitor.mjs +513 -0
  55. package/src/dereference/strategies/openapi-3-1/index.cjs +105 -0
  56. package/src/dereference/strategies/openapi-3-1/index.mjs +96 -0
  57. package/src/dereference/strategies/openapi-3-1/selectors/$anchor.cjs +66 -0
  58. package/src/dereference/strategies/openapi-3-1/selectors/$anchor.mjs +55 -0
  59. package/src/dereference/strategies/openapi-3-1/selectors/uri.cjs +50 -0
  60. package/src/dereference/strategies/openapi-3-1/selectors/uri.mjs +42 -0
  61. package/src/dereference/strategies/openapi-3-1/util.cjs +67 -0
  62. package/src/dereference/strategies/openapi-3-1/util.mjs +58 -0
  63. package/src/dereference/strategies/openapi-3-1/visitor.cjs +776 -0
  64. package/src/dereference/strategies/openapi-3-1/visitor.mjs +770 -0
  65. package/src/dereference/util.cjs +31 -0
  66. package/src/dereference/util.mjs +27 -0
  67. package/src/errors/BundleError.cjs +10 -0
  68. package/src/errors/BundleError.mjs +7 -0
  69. package/src/errors/DereferenceError.cjs +10 -0
  70. package/src/errors/DereferenceError.mjs +7 -0
  71. package/src/errors/EvaluationElementIdError.cjs +10 -0
  72. package/src/errors/EvaluationElementIdError.mjs +7 -0
  73. package/src/errors/EvaluationJsonSchema$anchorError.cjs +11 -0
  74. package/src/errors/EvaluationJsonSchema$anchorError.mjs +6 -0
  75. package/src/errors/EvaluationJsonSchemaUriError.cjs +11 -0
  76. package/src/errors/EvaluationJsonSchemaUriError.mjs +6 -0
  77. package/src/errors/InvalidJsonSchema$anchorError.cjs +15 -0
  78. package/src/errors/InvalidJsonSchema$anchorError.mjs +10 -0
  79. package/src/errors/JsonSchema$anchorError.cjs +10 -0
  80. package/src/errors/JsonSchema$anchorError.mjs +7 -0
  81. package/src/errors/JsonSchemaUriError.cjs +10 -0
  82. package/src/errors/JsonSchemaUriError.mjs +7 -0
  83. package/src/errors/MaximumBundleDepthError.cjs +11 -0
  84. package/src/errors/MaximumBundleDepthError.mjs +6 -0
  85. package/src/errors/MaximumDereferenceDepthError.cjs +11 -0
  86. package/src/errors/MaximumDereferenceDepthError.mjs +6 -0
  87. package/src/errors/MaximumResolveDepthError.cjs +11 -0
  88. package/src/errors/MaximumResolveDepthError.mjs +6 -0
  89. package/src/errors/ParseError.cjs +10 -0
  90. package/src/errors/ParseError.mjs +7 -0
  91. package/src/errors/ParserError.cjs +11 -0
  92. package/src/errors/ParserError.mjs +6 -0
  93. package/src/errors/PluginError.cjs +18 -0
  94. package/src/errors/PluginError.mjs +15 -0
  95. package/src/errors/ResolveError.cjs +10 -0
  96. package/src/errors/ResolveError.mjs +7 -0
  97. package/src/errors/ResolverError.cjs +11 -0
  98. package/src/errors/ResolverError.mjs +6 -0
  99. package/src/errors/UnmatchedBundleStrategyError.cjs +11 -0
  100. package/src/errors/UnmatchedBundleStrategyError.mjs +6 -0
  101. package/src/errors/UnmatchedDereferenceStrategyError.cjs +11 -0
  102. package/src/errors/UnmatchedDereferenceStrategyError.mjs +6 -0
  103. package/src/errors/UnmatchedResolveStrategyError.cjs +11 -0
  104. package/src/errors/UnmatchedResolveStrategyError.mjs +6 -0
  105. package/src/errors/UnmatchedResolverError.cjs +11 -0
  106. package/src/errors/UnmatchedResolverError.mjs +6 -0
  107. package/src/index.cjs +142 -0
  108. package/src/index.mjs +101 -0
  109. package/src/options/index.cjs +185 -0
  110. package/src/options/index.mjs +182 -0
  111. package/src/options/util.cjs +24 -0
  112. package/src/options/util.mjs +19 -0
  113. package/src/parse/index.cjs +69 -0
  114. package/src/parse/index.mjs +63 -0
  115. package/src/parse/parsers/Parser.cjs +48 -0
  116. package/src/parse/parsers/Parser.mjs +44 -0
  117. package/src/parse/parsers/api-design-systems-json/index.cjs +55 -0
  118. package/src/parse/parsers/api-design-systems-json/index.mjs +49 -0
  119. package/src/parse/parsers/api-design-systems-yaml/index.cjs +54 -0
  120. package/src/parse/parsers/api-design-systems-yaml/index.mjs +48 -0
  121. package/src/parse/parsers/apidom-json/index.cjs +70 -0
  122. package/src/parse/parsers/apidom-json/index.mjs +64 -0
  123. package/src/parse/parsers/arazzo-json-1/index.cjs +55 -0
  124. package/src/parse/parsers/arazzo-json-1/index.mjs +49 -0
  125. package/src/parse/parsers/arazzo-yaml-1/index.cjs +54 -0
  126. package/src/parse/parsers/arazzo-yaml-1/index.mjs +48 -0
  127. package/src/parse/parsers/asyncapi-json-2/index.cjs +55 -0
  128. package/src/parse/parsers/asyncapi-json-2/index.mjs +49 -0
  129. package/src/parse/parsers/asyncapi-yaml-2/index.cjs +54 -0
  130. package/src/parse/parsers/asyncapi-yaml-2/index.mjs +48 -0
  131. package/src/parse/parsers/binary/index-browser.cjs +56 -0
  132. package/src/parse/parsers/binary/index-browser.mjs +50 -0
  133. package/src/parse/parsers/binary/index-node.cjs +51 -0
  134. package/src/parse/parsers/binary/index-node.mjs +45 -0
  135. package/src/parse/parsers/json/index.cjs +54 -0
  136. package/src/parse/parsers/json/index.mjs +48 -0
  137. package/src/parse/parsers/openapi-json-2/index.cjs +55 -0
  138. package/src/parse/parsers/openapi-json-2/index.mjs +49 -0
  139. package/src/parse/parsers/openapi-json-3-0/index.cjs +55 -0
  140. package/src/parse/parsers/openapi-json-3-0/index.mjs +49 -0
  141. package/src/parse/parsers/openapi-json-3-1/index.cjs +55 -0
  142. package/src/parse/parsers/openapi-json-3-1/index.mjs +49 -0
  143. package/src/parse/parsers/openapi-yaml-2/index.cjs +54 -0
  144. package/src/parse/parsers/openapi-yaml-2/index.mjs +48 -0
  145. package/src/parse/parsers/openapi-yaml-3-0/index.cjs +54 -0
  146. package/src/parse/parsers/openapi-yaml-3-0/index.mjs +48 -0
  147. package/src/parse/parsers/openapi-yaml-3-1/index.cjs +54 -0
  148. package/src/parse/parsers/openapi-yaml-3-1/index.mjs +48 -0
  149. package/src/parse/parsers/yaml-1-2/index.cjs +54 -0
  150. package/src/parse/parsers/yaml-1-2/index.mjs +48 -0
  151. package/src/resolve/index.cjs +67 -0
  152. package/src/resolve/index.mjs +60 -0
  153. package/src/resolve/resolvers/HTTPResolver.cjs +38 -0
  154. package/src/resolve/resolvers/HTTPResolver.mjs +31 -0
  155. package/src/resolve/resolvers/Resolver.cjs +20 -0
  156. package/src/resolve/resolvers/Resolver.mjs +16 -0
  157. package/src/resolve/resolvers/file/index-browser.cjs +24 -0
  158. package/src/resolve/resolvers/file/index-browser.mjs +19 -0
  159. package/src/resolve/resolvers/file/index-node.cjs +49 -0
  160. package/src/resolve/resolvers/file/index-node.mjs +42 -0
  161. package/src/resolve/resolvers/http-axios/index.cjs +80 -0
  162. package/src/resolve/resolvers/http-axios/index.mjs +73 -0
  163. package/src/resolve/strategies/ResolveStrategy.cjs +20 -0
  164. package/src/resolve/strategies/ResolveStrategy.mjs +16 -0
  165. package/src/resolve/strategies/apidom/index.cjs +49 -0
  166. package/src/resolve/strategies/apidom/index.mjs +43 -0
  167. package/src/resolve/strategies/asyncapi-2/index.cjs +49 -0
  168. package/src/resolve/strategies/asyncapi-2/index.mjs +43 -0
  169. package/src/resolve/strategies/openapi-2/index.cjs +49 -0
  170. package/src/resolve/strategies/openapi-2/index.mjs +43 -0
  171. package/src/resolve/strategies/openapi-3-0/index.cjs +49 -0
  172. package/src/resolve/strategies/openapi-3-0/index.mjs +43 -0
  173. package/src/resolve/strategies/openapi-3-1/index.cjs +49 -0
  174. package/src/resolve/strategies/openapi-3-1/index.mjs +43 -0
  175. package/src/resolve/util.cjs +37 -0
  176. package/src/resolve/util.mjs +30 -0
  177. package/src/util/plugins.cjs +44 -0
  178. package/src/util/plugins.mjs +37 -0
  179. package/src/util/url.cjs +288 -0
  180. package/src/util/url.mjs +274 -0
  181. package/types/File.d.ts +24 -0
  182. package/types/Reference.d.ts +23 -0
  183. package/types/ReferenceSet.d.ts +25 -0
  184. package/types/apidom-reference.d.ts +584 -0
  185. package/types/bundle/index.d.ts +7 -0
  186. package/types/bundle/strategies/BundleStrategy.d.ts +19 -0
  187. package/types/bundle/strategies/openapi-3-1/index.d.ts +26 -0
  188. package/types/configuration/empty.d.ts +1 -0
  189. package/types/configuration/saturated.d.ts +1 -0
  190. package/types/dereference/index.d.ts +11 -0
  191. package/types/dereference/strategies/DereferenceStrategy.d.ts +19 -0
  192. package/types/dereference/strategies/apidom/index.d.ts +30 -0
  193. package/types/dereference/strategies/apidom/selectors/element-id.d.ts +11 -0
  194. package/types/dereference/strategies/apidom/visitor.d.ts +32 -0
  195. package/types/dereference/strategies/asyncapi-2/index.d.ts +31 -0
  196. package/types/dereference/strategies/asyncapi-2/visitor.d.ts +43 -0
  197. package/types/dereference/strategies/openapi-2/index.d.ts +32 -0
  198. package/types/dereference/strategies/openapi-2/visitor.d.ts +47 -0
  199. package/types/dereference/strategies/openapi-3-0/index.d.ts +31 -0
  200. package/types/dereference/strategies/openapi-3-0/visitor.d.ts +49 -0
  201. package/types/dereference/strategies/openapi-3-1/index.d.ts +32 -0
  202. package/types/dereference/strategies/openapi-3-1/selectors/$anchor.d.ts +22 -0
  203. package/types/dereference/strategies/openapi-3-1/selectors/uri.d.ts +12 -0
  204. package/types/dereference/strategies/openapi-3-1/util.d.ts +21 -0
  205. package/types/dereference/strategies/openapi-3-1/visitor.d.ts +52 -0
  206. package/types/dereference/util.d.ts +9 -0
  207. package/types/errors/BundleError.d.ts +7 -0
  208. package/types/errors/DereferenceError.d.ts +7 -0
  209. package/types/errors/EvaluationElementIdError.d.ts +7 -0
  210. package/types/errors/EvaluationJsonSchema$anchorError.d.ts +7 -0
  211. package/types/errors/EvaluationJsonSchemaUriError.d.ts +7 -0
  212. package/types/errors/InvalidJsonSchema$anchorError.d.ts +8 -0
  213. package/types/errors/JsonSchema$anchorError.d.ts +7 -0
  214. package/types/errors/JsonSchemaUriError.d.ts +7 -0
  215. package/types/errors/MaximumBundleDepthError.d.ts +7 -0
  216. package/types/errors/MaximumDereferenceDepthError.d.ts +7 -0
  217. package/types/errors/MaximumResolveDepthError.d.ts +7 -0
  218. package/types/errors/ParseError.d.ts +7 -0
  219. package/types/errors/ParserError.d.ts +7 -0
  220. package/types/errors/PluginError.d.ts +12 -0
  221. package/types/errors/ResolveError.d.ts +7 -0
  222. package/types/errors/ResolverError.d.ts +7 -0
  223. package/types/errors/UnmatchedBundleStrategyError.d.ts +7 -0
  224. package/types/errors/UnmatchedDereferenceStrategyError.d.ts +7 -0
  225. package/types/errors/UnmatchedResolveStrategyError.d.ts +7 -0
  226. package/types/errors/UnmatchedResolverError.d.ts +7 -0
  227. package/types/index.d.ts +75 -0
  228. package/types/options/index.d.ts +62 -0
  229. package/types/options/util.d.ts +5 -0
  230. package/types/parse/index.d.ts +7 -0
  231. package/types/parse/parsers/Parser.d.ts +38 -0
  232. package/types/parse/parsers/api-design-systems-json/index.d.ts +21 -0
  233. package/types/parse/parsers/api-design-systems-yaml/index.d.ts +20 -0
  234. package/types/parse/parsers/apidom-json/index.d.ts +24 -0
  235. package/types/parse/parsers/arazzo-json-1/index.d.ts +21 -0
  236. package/types/parse/parsers/arazzo-yaml-1/index.d.ts +20 -0
  237. package/types/parse/parsers/asyncapi-json-2/index.d.ts +21 -0
  238. package/types/parse/parsers/asyncapi-yaml-2/index.d.ts +20 -0
  239. package/types/parse/parsers/binary/index-browser.d.ts +21 -0
  240. package/types/parse/parsers/binary/index-node.d.ts +21 -0
  241. package/types/parse/parsers/json/index.d.ts +20 -0
  242. package/types/parse/parsers/openapi-json-2/index.d.ts +21 -0
  243. package/types/parse/parsers/openapi-json-3-0/index.d.ts +21 -0
  244. package/types/parse/parsers/openapi-json-3-1/index.d.ts +21 -0
  245. package/types/parse/parsers/openapi-yaml-2/index.d.ts +20 -0
  246. package/types/parse/parsers/openapi-yaml-3-0/index.d.ts +20 -0
  247. package/types/parse/parsers/openapi-yaml-3-1/index.d.ts +20 -0
  248. package/types/parse/parsers/yaml-1-2/index.d.ts +20 -0
  249. package/types/resolve/index.d.ts +12 -0
  250. package/types/resolve/resolvers/HTTPResolver.d.ts +22 -0
  251. package/types/resolve/resolvers/Resolver.d.ts +17 -0
  252. package/types/resolve/resolvers/file/index-browser.d.ts +12 -0
  253. package/types/resolve/resolvers/file/index-node.d.ts +20 -0
  254. package/types/resolve/resolvers/http-axios/index.d.ts +30 -0
  255. package/types/resolve/strategies/ResolveStrategy.d.ts +19 -0
  256. package/types/resolve/strategies/apidom/index.d.ts +27 -0
  257. package/types/resolve/strategies/asyncapi-2/index.d.ts +27 -0
  258. package/types/resolve/strategies/openapi-2/index.d.ts +27 -0
  259. package/types/resolve/strategies/openapi-3-0/index.d.ts +27 -0
  260. package/types/resolve/strategies/openapi-3-1/index.d.ts +27 -0
  261. package/types/resolve/util.d.ts +6 -0
  262. package/types/util/plugins.d.ts +14 -0
  263. package/types/util/url.d.ts +106 -0
@@ -0,0 +1,96 @@
1
+ import { createNamespace, visit, cloneDeep } from '@speclynx/apidom-core';
2
+ import openApi3_0Namespace, { getNodeType, isOpenApi3_0Element, keyMap, mediaTypes } from '@speclynx/apidom-ns-openapi-3-0';
3
+ import DereferenceStrategy from "../DereferenceStrategy.mjs";
4
+ import Reference from "../../../Reference.mjs";
5
+ import ReferenceSet from "../../../ReferenceSet.mjs";
6
+ import OpenAPI3_0DereferenceVisitor from "./visitor.mjs";
7
+ // @ts-ignore
8
+ const visitAsync = visit[Symbol.for('nodejs.util.promisify.custom')];
9
+
10
+ /**
11
+ * @public
12
+ */
13
+
14
+ /**
15
+ * @public
16
+ */
17
+ class OpenAPI3_0DereferenceStrategy extends DereferenceStrategy {
18
+ constructor(options) {
19
+ super({
20
+ ...(options ?? {}),
21
+ name: 'openapi-3-0'
22
+ });
23
+ }
24
+ canDereference(file) {
25
+ // assert by media type
26
+ if (file.mediaType !== 'text/plain') {
27
+ return mediaTypes.includes(file.mediaType);
28
+ }
29
+
30
+ // assert by inspecting ApiDOM
31
+ return isOpenApi3_0Element(file.parseResult?.api);
32
+ }
33
+ async dereference(file, options) {
34
+ const namespace = createNamespace(openApi3_0Namespace);
35
+ const immutableRefSet = options.dereference.refSet ?? new ReferenceSet();
36
+ const mutableRefSet = new ReferenceSet();
37
+ let refSet = immutableRefSet;
38
+ let reference;
39
+
40
+ // determine the initial reference
41
+ if (!immutableRefSet.has(file.uri)) {
42
+ reference = new Reference({
43
+ uri: file.uri,
44
+ value: file.parseResult
45
+ });
46
+ immutableRefSet.add(reference);
47
+ } else {
48
+ // pre-computed refSet was provided as configuration option
49
+ reference = immutableRefSet.find(ref => ref.uri === file.uri);
50
+ }
51
+
52
+ /**
53
+ * Clone refSet due the dereferencing process being mutable.
54
+ * We don't want to mutate the original refSet and the references.
55
+ */
56
+ if (options.dereference.immutable) {
57
+ immutableRefSet.refs.map(ref => new Reference({
58
+ ...ref,
59
+ value: cloneDeep(ref.value)
60
+ })).forEach(ref => mutableRefSet.add(ref));
61
+ reference = mutableRefSet.find(ref => ref.uri === file.uri);
62
+ refSet = mutableRefSet;
63
+ }
64
+ const visitor = new OpenAPI3_0DereferenceVisitor({
65
+ reference: reference,
66
+ namespace,
67
+ options
68
+ });
69
+ const dereferencedElement = await visitAsync(refSet.rootRef.value, visitor, {
70
+ keyMap,
71
+ nodeTypeGetter: getNodeType
72
+ });
73
+
74
+ /**
75
+ * If immutable option is set, replay refs from the refSet.
76
+ */
77
+ if (options.dereference.immutable) {
78
+ mutableRefSet.refs.filter(ref => ref.uri.startsWith('immutable://')).map(ref => new Reference({
79
+ ...ref,
80
+ uri: ref.uri.replace(/^immutable:\/\//, '')
81
+ })).forEach(ref => immutableRefSet.add(ref));
82
+ }
83
+
84
+ /**
85
+ * Release all memory if this refSet was not provided as a configuration option.
86
+ * If provided as configuration option, then provider is responsible for cleanup.
87
+ */
88
+ if (options.dereference.refSet === null) {
89
+ immutableRefSet.clean();
90
+ }
91
+ mutableRefSet.clean();
92
+ return dereferencedElement;
93
+ }
94
+ }
95
+ export { OpenAPI3_0DereferenceVisitor };
96
+ export default OpenAPI3_0DereferenceStrategy;
@@ -0,0 +1,519 @@
1
+ "use strict";
2
+
3
+ var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
4
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
5
+ exports.__esModule = true;
6
+ exports.mutationReplacer = exports.default = void 0;
7
+ var _ramda = require("ramda");
8
+ var _ramdaAdjunct = require("ramda-adjunct");
9
+ var _apidomCore = require("@speclynx/apidom-core");
10
+ var _apidomError = require("@speclynx/apidom-error");
11
+ var _apidomJsonPointer = require("@speclynx/apidom-json-pointer");
12
+ var _apidomNsOpenapi = require("@speclynx/apidom-ns-openapi-3-0");
13
+ var _MaximumDereferenceDepthError = _interopRequireDefault(require("../../../errors/MaximumDereferenceDepthError.cjs"));
14
+ var _MaximumResolveDepthError = _interopRequireDefault(require("../../../errors/MaximumResolveDepthError.cjs"));
15
+ var url = _interopRequireWildcard(require("../../../util/url.cjs"));
16
+ var _index = _interopRequireDefault(require("../../../parse/index.cjs"));
17
+ var _Reference = _interopRequireDefault(require("../../../Reference.cjs"));
18
+ var _util = require("../../util.cjs");
19
+ // @ts-ignore
20
+ const visitAsync = _apidomCore.visit[Symbol.for('nodejs.util.promisify.custom')];
21
+
22
+ // initialize element identity manager
23
+ const identityManager = new _apidomCore.IdentityManager();
24
+
25
+ /**
26
+ * Custom mutation replacer.
27
+ * @public
28
+ */
29
+ const mutationReplacer = (newElement, oldElement, key, parent) => {
30
+ if ((0, _apidomCore.isMemberElement)(parent)) {
31
+ parent.value = newElement;
32
+ } else if (Array.isArray(parent)) {
33
+ parent[key] = newElement;
34
+ }
35
+ };
36
+
37
+ /**
38
+ * @public
39
+ */
40
+ exports.mutationReplacer = mutationReplacer;
41
+ /**
42
+ * @public
43
+ */
44
+ class OpenAPI3_0DereferenceVisitor {
45
+ indirections;
46
+ namespace;
47
+ reference;
48
+ options;
49
+ ancestors;
50
+ refractCache;
51
+ constructor({
52
+ reference,
53
+ namespace,
54
+ options,
55
+ indirections = [],
56
+ ancestors = new _util.AncestorLineage(),
57
+ refractCache = new Map()
58
+ }) {
59
+ this.indirections = indirections;
60
+ this.namespace = namespace;
61
+ this.reference = reference;
62
+ this.options = options;
63
+ this.ancestors = new _util.AncestorLineage(...ancestors);
64
+ this.refractCache = refractCache;
65
+ }
66
+ toBaseURI(uri) {
67
+ return url.resolve(this.reference.uri, url.sanitize(url.stripHash(uri)));
68
+ }
69
+ async toReference(uri) {
70
+ // detect maximum depth of resolution
71
+ if (this.reference.depth >= this.options.resolve.maxDepth) {
72
+ throw new _MaximumResolveDepthError.default(`Maximum resolution depth of ${this.options.resolve.maxDepth} has been exceeded by file "${this.reference.uri}"`);
73
+ }
74
+ const baseURI = this.toBaseURI(uri);
75
+ const {
76
+ refSet
77
+ } = this.reference;
78
+
79
+ // we've already processed this Reference in past
80
+ if (refSet.has(baseURI)) {
81
+ return refSet.find((0, _ramda.propEq)(baseURI, 'uri'));
82
+ }
83
+ const parseResult = await (0, _index.default)(url.unsanitize(baseURI), {
84
+ ...this.options,
85
+ parse: {
86
+ ...this.options.parse,
87
+ mediaType: 'text/plain'
88
+ }
89
+ });
90
+
91
+ // register new mutable reference with a refSet
92
+ const mutableReference = new _Reference.default({
93
+ uri: baseURI,
94
+ value: (0, _apidomCore.cloneDeep)(parseResult),
95
+ depth: this.reference.depth + 1
96
+ });
97
+ refSet.add(mutableReference);
98
+ if (this.options.dereference.immutable) {
99
+ // register new immutable reference with a refSet
100
+ const immutableReference = new _Reference.default({
101
+ uri: `immutable://${baseURI}`,
102
+ value: parseResult,
103
+ depth: this.reference.depth + 1
104
+ });
105
+ refSet.add(immutableReference);
106
+ }
107
+ return mutableReference;
108
+ }
109
+ toAncestorLineage(ancestors) {
110
+ /**
111
+ * Compute full ancestors lineage.
112
+ * Ancestors are flatten to unwrap all Element instances.
113
+ */
114
+ const directAncestors = new Set(ancestors.filter(_apidomCore.isElement));
115
+ const ancestorsLineage = new _util.AncestorLineage(...this.ancestors, directAncestors);
116
+ return [ancestorsLineage, directAncestors];
117
+ }
118
+ async ReferenceElement(referencingElement, key, parent, path, ancestors, link) {
119
+ // skip current referencing element as it's already been access
120
+ if (this.indirections.includes(referencingElement)) {
121
+ return false;
122
+ }
123
+ const [ancestorsLineage, directAncestors] = this.toAncestorLineage([...ancestors, parent]);
124
+ const retrievalURI = this.toBaseURI((0, _apidomCore.toValue)(referencingElement.$ref));
125
+ const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
126
+ const isExternalReference = !isInternalReference;
127
+
128
+ // ignore resolving internal Reference Objects
129
+ if (!this.options.resolve.internal && isInternalReference) {
130
+ // skip traversing this reference element
131
+ return false;
132
+ }
133
+ // ignore resolving external Reference Objects
134
+ if (!this.options.resolve.external && isExternalReference) {
135
+ // skip traversing this reference element
136
+ return false;
137
+ }
138
+ const reference = await this.toReference((0, _apidomCore.toValue)(referencingElement.$ref));
139
+ const $refBaseURI = url.resolve(retrievalURI, (0, _apidomCore.toValue)(referencingElement.$ref));
140
+ this.indirections.push(referencingElement);
141
+ const jsonPointer = _apidomJsonPointer.URIFragmentIdentifier.fromURIReference($refBaseURI);
142
+
143
+ // possibly non-semantic fragment
144
+ let referencedElement = (0, _apidomJsonPointer.evaluate)(reference.value.result, jsonPointer);
145
+ referencedElement.id = identityManager.identify(referencedElement);
146
+
147
+ /**
148
+ * Applying semantics to a referenced element if semantics are missing.
149
+ */
150
+ if ((0, _apidomCore.isPrimitiveElement)(referencedElement)) {
151
+ const referencedElementType = (0, _apidomCore.toValue)(referencingElement.meta.get('referenced-element'));
152
+ const cacheKey = `${referencedElementType}-${(0, _apidomCore.toValue)(identityManager.identify(referencedElement))}`;
153
+ if (this.refractCache.has(cacheKey)) {
154
+ referencedElement = this.refractCache.get(cacheKey);
155
+ } else if ((0, _apidomNsOpenapi.isReferenceLikeElement)(referencedElement)) {
156
+ // handling indirect references
157
+ referencedElement = _apidomNsOpenapi.ReferenceElement.refract(referencedElement);
158
+ referencedElement.setMetaProperty('referenced-element', referencedElementType);
159
+ this.refractCache.set(cacheKey, referencedElement);
160
+ } else {
161
+ // handling direct references
162
+ const ElementClass = this.namespace.getElementClass(referencedElementType);
163
+ referencedElement = ElementClass.refract(referencedElement);
164
+ this.refractCache.set(cacheKey, referencedElement);
165
+ }
166
+ }
167
+
168
+ // detect direct or circular reference
169
+ if (referencingElement === referencedElement) {
170
+ throw new _apidomError.ApiDOMError('Recursive Reference Object detected');
171
+ }
172
+
173
+ // detect maximum depth of dereferencing
174
+ if (this.indirections.length > this.options.dereference.maxDepth) {
175
+ throw new _MaximumDereferenceDepthError.default(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
176
+ }
177
+
178
+ // detect second deep dive into the same fragment and avoid it
179
+ if (ancestorsLineage.includes(referencedElement)) {
180
+ reference.refSet.circular = true;
181
+ if (this.options.dereference.circular === 'error') {
182
+ throw new _apidomError.ApiDOMError('Circular reference detected');
183
+ } else if (this.options.dereference.circular === 'replace') {
184
+ const refElement = new _apidomCore.RefElement(referencedElement.id, {
185
+ type: 'reference',
186
+ uri: reference.uri,
187
+ $ref: (0, _apidomCore.toValue)(referencingElement.$ref)
188
+ });
189
+ const replacer = this.options.dereference.strategyOpts['openapi-3-0']?.circularReplacer ?? this.options.dereference.circularReplacer;
190
+ const replacement = replacer(refElement);
191
+ link.replaceWith(replacement, mutationReplacer);
192
+ return !parent ? replacement : false;
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Dive deep into the fragment.
198
+ *
199
+ * Cases to consider:
200
+ * 1. We're crossing document boundary
201
+ * 2. Fragment is from non-entry document
202
+ * 3. Fragment is a Reference Object. We need to follow it to get the eventual value
203
+ * 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
204
+ */
205
+ const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
206
+ const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
207
+ if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isReferenceElement)(referencedElement) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
208
+ // append referencing reference to ancestors lineage
209
+ directAncestors.add(referencingElement);
210
+ const visitor = new OpenAPI3_0DereferenceVisitor({
211
+ reference,
212
+ namespace: this.namespace,
213
+ indirections: [...this.indirections],
214
+ options: this.options,
215
+ refractCache: this.refractCache,
216
+ ancestors: ancestorsLineage
217
+ });
218
+ referencedElement = await visitAsync(referencedElement, visitor, {
219
+ keyMap: _apidomNsOpenapi.keyMap,
220
+ nodeTypeGetter: _apidomNsOpenapi.getNodeType
221
+ });
222
+
223
+ // remove referencing reference from ancestors lineage
224
+ directAncestors.delete(referencingElement);
225
+ }
226
+ this.indirections.pop();
227
+
228
+ /**
229
+ * Creating a new version of referenced element to avoid modifying the original one.
230
+ */
231
+ const mergedElement = (0, _apidomCore.cloneShallow)(referencedElement);
232
+ // assign unique id to merged element
233
+ mergedElement.setMetaProperty('id', identityManager.generateId());
234
+ // annotate referenced element with info about original referencing element
235
+ mergedElement.setMetaProperty('ref-fields', {
236
+ $ref: (0, _apidomCore.toValue)(referencingElement.$ref)
237
+ });
238
+ // annotate fragment with info about origin
239
+ mergedElement.setMetaProperty('ref-origin', reference.uri);
240
+ // annotate fragment with info about referencing element
241
+ mergedElement.setMetaProperty('ref-referencing-element-id', (0, _apidomCore.cloneDeep)(identityManager.identify(referencingElement)));
242
+
243
+ /**
244
+ * Transclude referencing element with merged referenced element.
245
+ */
246
+ link.replaceWith(mergedElement, mutationReplacer);
247
+
248
+ /**
249
+ * We're at the root of the tree, so we're just replacing the entire tree.
250
+ */
251
+ return !parent ? mergedElement : false;
252
+ }
253
+ async PathItemElement(referencingElement, key, parent, path, ancestors, link) {
254
+ // ignore PathItemElement without $ref field
255
+ if (!(0, _apidomCore.isStringElement)(referencingElement.$ref)) {
256
+ return undefined;
257
+ }
258
+
259
+ // skip current referencing element as it's already been access
260
+ if (this.indirections.includes(referencingElement)) {
261
+ return false;
262
+ }
263
+ const [ancestorsLineage, directAncestors] = this.toAncestorLineage([...ancestors, parent]);
264
+ const retrievalURI = this.toBaseURI((0, _apidomCore.toValue)(referencingElement.$ref));
265
+ const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
266
+ const isExternalReference = !isInternalReference;
267
+
268
+ // ignore resolving internal Path Item Objects
269
+ if (!this.options.resolve.internal && isInternalReference) {
270
+ // skip traversing this Path Item element but traverse all it's child elements
271
+ return undefined;
272
+ }
273
+ // ignore resolving external Path Item Objects
274
+ if (!this.options.resolve.external && isExternalReference) {
275
+ // skip traversing this Path Item element but traverse all it's child elements
276
+ return undefined;
277
+ }
278
+ const reference = await this.toReference((0, _apidomCore.toValue)(referencingElement.$ref));
279
+ const $refBaseURI = url.resolve(retrievalURI, (0, _apidomCore.toValue)(referencingElement.$ref));
280
+ this.indirections.push(referencingElement);
281
+ const jsonPointer = _apidomJsonPointer.URIFragmentIdentifier.fromURIReference($refBaseURI);
282
+
283
+ // possibly non-semantic referenced element
284
+ let referencedElement = (0, _apidomJsonPointer.evaluate)(reference.value.result, jsonPointer);
285
+ referencedElement.id = identityManager.identify(referencedElement);
286
+
287
+ /**
288
+ * Applying semantics to a referenced element if semantics are missing.
289
+ */
290
+ if (!(0, _apidomNsOpenapi.isPathItemElement)(referencedElement)) {
291
+ const cacheKey = `path-item-${(0, _apidomCore.toValue)(identityManager.identify(referencedElement))}`;
292
+ if (this.refractCache.has(cacheKey)) {
293
+ referencedElement = this.refractCache.get(cacheKey);
294
+ } else {
295
+ referencedElement = _apidomNsOpenapi.PathItemElement.refract(referencedElement);
296
+ this.refractCache.set(cacheKey, referencedElement);
297
+ }
298
+ }
299
+
300
+ // detect direct or circular reference
301
+ if (referencingElement === referencedElement) {
302
+ throw new _apidomError.ApiDOMError('Recursive Path Item Object reference detected');
303
+ }
304
+
305
+ // detect maximum depth of dereferencing
306
+ if (this.indirections.length > this.options.dereference.maxDepth) {
307
+ throw new _MaximumDereferenceDepthError.default(`Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`);
308
+ }
309
+
310
+ // detect second deep dive into the same fragment and avoid it
311
+ if (ancestorsLineage.includes(referencedElement)) {
312
+ reference.refSet.circular = true;
313
+ if (this.options.dereference.circular === 'error') {
314
+ throw new _apidomError.ApiDOMError('Circular reference detected');
315
+ } else if (this.options.dereference.circular === 'replace') {
316
+ const refElement = new _apidomCore.RefElement(referencedElement.id, {
317
+ type: 'path-item',
318
+ uri: reference.uri,
319
+ $ref: (0, _apidomCore.toValue)(referencingElement.$ref)
320
+ });
321
+ const replacer = this.options.dereference.strategyOpts['openapi-3-0']?.circularReplacer ?? this.options.dereference.circularReplacer;
322
+ const replacement = replacer(refElement);
323
+ link.replaceWith(replacement, mutationReplacer);
324
+ return !parent ? replacement : undefined;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Dive deep into the fragment.
330
+ *
331
+ * Cases to consider:
332
+ * 1. We're crossing document boundary
333
+ * 2. Fragment is from non-entry document
334
+ * 3. Fragment is a Path Item Object with $ref field. We need to follow it to get the eventual value
335
+ * 4. We are dereferencing the fragment lazily/eagerly depending on circular mode
336
+ */
337
+ const isNonEntryDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
338
+ const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
339
+ if ((isExternalReference || isNonEntryDocument || (0, _apidomNsOpenapi.isPathItemElement)(referencedElement) && (0, _apidomCore.isStringElement)(referencedElement.$ref) || shouldDetectCircular) && !ancestorsLineage.includesCycle(referencedElement)) {
340
+ // append referencing reference to ancestors lineage
341
+ directAncestors.add(referencingElement);
342
+ const visitor = new OpenAPI3_0DereferenceVisitor({
343
+ reference,
344
+ namespace: this.namespace,
345
+ indirections: [...this.indirections],
346
+ options: this.options,
347
+ refractCache: this.refractCache,
348
+ ancestors: ancestorsLineage
349
+ });
350
+ referencedElement = await visitAsync(referencedElement, visitor, {
351
+ keyMap: _apidomNsOpenapi.keyMap,
352
+ nodeTypeGetter: _apidomNsOpenapi.getNodeType
353
+ });
354
+
355
+ // remove referencing reference from ancestors lineage
356
+ directAncestors.delete(referencingElement);
357
+ }
358
+ this.indirections.pop();
359
+
360
+ /**
361
+ * Creating a new version of Path Item by merging fields from referenced Path Item with referencing one.
362
+ */
363
+ if ((0, _apidomNsOpenapi.isPathItemElement)(referencedElement)) {
364
+ const mergedElement = new _apidomNsOpenapi.PathItemElement([...referencedElement.content], (0, _apidomCore.cloneDeep)(referencedElement.meta), (0, _apidomCore.cloneDeep)(referencedElement.attributes));
365
+ // assign unique id to merged element
366
+ mergedElement.setMetaProperty('id', identityManager.generateId());
367
+ // existing keywords from referencing PathItemElement overrides ones from referenced element
368
+ referencingElement.forEach((value, keyElement, item) => {
369
+ mergedElement.remove((0, _apidomCore.toValue)(keyElement));
370
+ mergedElement.content.push(item);
371
+ });
372
+ mergedElement.remove('$ref');
373
+
374
+ // annotate referenced element with info about original referencing element
375
+ mergedElement.setMetaProperty('ref-fields', {
376
+ $ref: (0, _apidomCore.toValue)(referencingElement.$ref)
377
+ });
378
+ // annotate referenced element with info about origin
379
+ mergedElement.setMetaProperty('ref-origin', reference.uri);
380
+ // annotate fragment with info about referencing element
381
+ mergedElement.setMetaProperty('ref-referencing-element-id', (0, _apidomCore.cloneDeep)(identityManager.identify(referencingElement)));
382
+ referencedElement = mergedElement;
383
+ }
384
+
385
+ /**
386
+ * Transclude referencing element with merged referenced element.
387
+ */
388
+ link.replaceWith(referencedElement, mutationReplacer);
389
+
390
+ /**
391
+ * We're at the root of the tree, so we're just replacing the entire tree.
392
+ */
393
+ return !parent ? referencedElement : undefined;
394
+ }
395
+ async LinkElement(linkElement, key, parent, path, ancestors, link) {
396
+ // ignore LinkElement without operationRef or operationId field
397
+ if (!(0, _apidomCore.isStringElement)(linkElement.operationRef) && !(0, _apidomCore.isStringElement)(linkElement.operationId)) {
398
+ return undefined;
399
+ }
400
+
401
+ // operationRef and operationId fields are mutually exclusive
402
+ if ((0, _apidomCore.isStringElement)(linkElement.operationRef) && (0, _apidomCore.isStringElement)(linkElement.operationId)) {
403
+ throw new _apidomError.ApiDOMError('LinkElement operationRef and operationId fields are mutually exclusive.');
404
+ }
405
+ let operationElement;
406
+ if ((0, _apidomCore.isStringElement)(linkElement.operationRef)) {
407
+ // possibly non-semantic referenced element
408
+ const jsonPointer = _apidomJsonPointer.URIFragmentIdentifier.fromURIReference((0, _apidomCore.toValue)(linkElement.operationRef));
409
+ const retrievalURI = this.toBaseURI((0, _apidomCore.toValue)(linkElement.operationRef));
410
+ const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
411
+ const isExternalReference = !isInternalReference;
412
+
413
+ // ignore resolving internal Operation Object reference
414
+ if (!this.options.resolve.internal && isInternalReference) {
415
+ // skip traversing this Link element but traverse all it's child elements
416
+ return undefined;
417
+ }
418
+ // ignore resolving external Operation Object reference
419
+ if (!this.options.resolve.external && isExternalReference) {
420
+ // skip traversing this Link element but traverse all it's child elements
421
+ return undefined;
422
+ }
423
+ const reference = await this.toReference((0, _apidomCore.toValue)(linkElement.operationRef));
424
+ operationElement = (0, _apidomJsonPointer.evaluate)(reference.value.result, jsonPointer);
425
+ // applying semantics to a referenced element
426
+ if ((0, _apidomCore.isPrimitiveElement)(operationElement)) {
427
+ const cacheKey = `operation-${(0, _apidomCore.toValue)(identityManager.identify(operationElement))}`;
428
+ if (this.refractCache.has(cacheKey)) {
429
+ operationElement = this.refractCache.get(cacheKey);
430
+ } else {
431
+ operationElement = _apidomNsOpenapi.OperationElement.refract(operationElement);
432
+ this.refractCache.set(cacheKey, operationElement);
433
+ }
434
+ }
435
+ // create shallow clone to be able to annotate with metadata
436
+ operationElement = (0, _apidomCore.cloneShallow)(operationElement);
437
+ // annotate operation element with info about origin
438
+ operationElement.setMetaProperty('ref-origin', reference.uri);
439
+ const linkElementCopy = (0, _apidomCore.cloneShallow)(linkElement);
440
+ linkElementCopy.operationRef?.meta.set('operation', operationElement);
441
+
442
+ /**
443
+ * Transclude Link Object containing Operation Object in its meta.
444
+ */
445
+ link.replaceWith(linkElementCopy, mutationReplacer);
446
+
447
+ /**
448
+ * We're at the root of the tree, so we're just replacing the entire tree.
449
+ */
450
+ return !parent ? linkElementCopy : undefined;
451
+ }
452
+ if ((0, _apidomCore.isStringElement)(linkElement.operationId)) {
453
+ const operationId = (0, _apidomCore.toValue)(linkElement.operationId);
454
+ const reference = await this.toReference(url.unsanitize(this.reference.uri));
455
+ operationElement = (0, _apidomCore.find)(e => (0, _apidomNsOpenapi.isOperationElement)(e) && (0, _apidomCore.isElement)(e.operationId) && e.operationId.equals(operationId), reference.value.result);
456
+ // OperationElement not found by its operationId
457
+ if ((0, _ramdaAdjunct.isUndefined)(operationElement)) {
458
+ throw new _apidomError.ApiDOMError(`OperationElement(operationId=${operationId}) not found.`);
459
+ }
460
+ const linkElementCopy = (0, _apidomCore.cloneShallow)(linkElement);
461
+ linkElementCopy.operationId?.meta.set('operation', operationElement);
462
+
463
+ /**
464
+ * Transclude Link Object containing Operation Object in its meta.
465
+ */
466
+ link.replaceWith(linkElementCopy, mutationReplacer);
467
+
468
+ /**
469
+ * We're at the root of the tree, so we're just replacing the entire tree.
470
+ */
471
+ return !parent ? linkElementCopy : undefined;
472
+ }
473
+ return undefined;
474
+ }
475
+ async ExampleElement(exampleElement, key, parent, path, ancestors, link) {
476
+ // ignore ExampleElement without externalValue field
477
+ if (!(0, _apidomCore.isStringElement)(exampleElement.externalValue)) {
478
+ return undefined;
479
+ }
480
+
481
+ // value and externalValue fields are mutually exclusive
482
+ if (exampleElement.hasKey('value') && (0, _apidomCore.isStringElement)(exampleElement.externalValue)) {
483
+ throw new _apidomError.ApiDOMError('ExampleElement value and externalValue fields are mutually exclusive.');
484
+ }
485
+ const retrievalURI = this.toBaseURI((0, _apidomCore.toValue)(exampleElement.externalValue));
486
+ const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
487
+ const isExternalReference = !isInternalReference;
488
+
489
+ // ignore resolving external Example Objects
490
+ if (!this.options.resolve.internal && isInternalReference) {
491
+ // skip traversing this Example element but traverse all it's child elements
492
+ return undefined;
493
+ }
494
+ // ignore resolving external Example Objects
495
+ if (!this.options.resolve.external && isExternalReference) {
496
+ // skip traversing this Example element but traverse all it's child elements
497
+ return undefined;
498
+ }
499
+ const reference = await this.toReference((0, _apidomCore.toValue)(exampleElement.externalValue));
500
+
501
+ // shallow clone of the referenced element
502
+ const valueElement = (0, _apidomCore.cloneShallow)(reference.value.result);
503
+ // annotate operation element with info about origin
504
+ valueElement.setMetaProperty('ref-origin', reference.uri);
505
+ const exampleElementCopy = (0, _apidomCore.cloneShallow)(exampleElement);
506
+ exampleElementCopy.value = valueElement;
507
+
508
+ /**
509
+ * Transclude Example Object containing external value.
510
+ */
511
+ link.replaceWith(exampleElementCopy, mutationReplacer);
512
+
513
+ /**
514
+ * We're at the root of the tree, so we're just replacing the entire tree.
515
+ */
516
+ return !parent ? exampleElementCopy : undefined;
517
+ }
518
+ }
519
+ var _default = exports.default = OpenAPI3_0DereferenceVisitor;