@speclynx/apidom-reference 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/apidom-reference.browser.js +162 -127
  3. package/dist/apidom-reference.browser.min.js +1 -1
  4. package/package.json +25 -25
  5. package/types/dereference/strategies/apidom/visitor.d.ts +1 -1
  6. package/types/dereference/strategies/arazzo-1/visitor.d.ts +1 -1
  7. package/types/dereference/strategies/asyncapi-2/visitor.d.ts +1 -1
  8. package/types/dereference/strategies/openapi-2/visitor.d.ts +1 -1
  9. package/types/dereference/strategies/openapi-3-0/visitor.d.ts +1 -1
  10. package/types/dereference/strategies/openapi-3-1/visitor.d.ts +1 -1
  11. package/src/File.cjs +0 -50
  12. package/src/File.mjs +0 -44
  13. package/src/Reference.cjs +0 -31
  14. package/src/Reference.mjs +0 -27
  15. package/src/ReferenceSet.cjs +0 -60
  16. package/src/ReferenceSet.mjs +0 -57
  17. package/src/bundle/index.cjs +0 -61
  18. package/src/bundle/index.mjs +0 -55
  19. package/src/bundle/strategies/BundleStrategy.cjs +0 -20
  20. package/src/bundle/strategies/BundleStrategy.mjs +0 -16
  21. package/src/bundle/strategies/openapi-3-1/index.cjs +0 -35
  22. package/src/bundle/strategies/openapi-3-1/index.mjs +0 -29
  23. package/src/configuration/empty.cjs +0 -9
  24. package/src/configuration/empty.mjs +0 -1
  25. package/src/configuration/saturated.cjs +0 -88
  26. package/src/configuration/saturated.mjs +0 -80
  27. package/src/dereference/index.cjs +0 -90
  28. package/src/dereference/index.mjs +0 -83
  29. package/src/dereference/strategies/DereferenceStrategy.cjs +0 -20
  30. package/src/dereference/strategies/DereferenceStrategy.mjs +0 -16
  31. package/src/dereference/strategies/apidom/index.cjs +0 -89
  32. package/src/dereference/strategies/apidom/index.mjs +0 -83
  33. package/src/dereference/strategies/apidom/selectors/element-id.cjs +0 -47
  34. package/src/dereference/strategies/apidom/selectors/element-id.mjs +0 -41
  35. package/src/dereference/strategies/apidom/visitor.cjs +0 -259
  36. package/src/dereference/strategies/apidom/visitor.mjs +0 -252
  37. package/src/dereference/strategies/arazzo-1/index.cjs +0 -109
  38. package/src/dereference/strategies/arazzo-1/index.mjs +0 -100
  39. package/src/dereference/strategies/arazzo-1/selectors/$anchor.cjs +0 -12
  40. package/src/dereference/strategies/arazzo-1/selectors/$anchor.mjs +0 -1
  41. package/src/dereference/strategies/arazzo-1/selectors/uri.cjs +0 -8
  42. package/src/dereference/strategies/arazzo-1/selectors/uri.mjs +0 -1
  43. package/src/dereference/strategies/arazzo-1/source-descriptions.cjs +0 -248
  44. package/src/dereference/strategies/arazzo-1/source-descriptions.mjs +0 -243
  45. package/src/dereference/strategies/arazzo-1/util.cjs +0 -37
  46. package/src/dereference/strategies/arazzo-1/util.mjs +0 -29
  47. package/src/dereference/strategies/arazzo-1/visitor.cjs +0 -501
  48. package/src/dereference/strategies/arazzo-1/visitor.mjs +0 -494
  49. package/src/dereference/strategies/asyncapi-2/index.cjs +0 -94
  50. package/src/dereference/strategies/asyncapi-2/index.mjs +0 -88
  51. package/src/dereference/strategies/asyncapi-2/visitor.cjs +0 -495
  52. package/src/dereference/strategies/asyncapi-2/visitor.mjs +0 -488
  53. package/src/dereference/strategies/openapi-2/index.cjs +0 -96
  54. package/src/dereference/strategies/openapi-2/index.mjs +0 -90
  55. package/src/dereference/strategies/openapi-2/visitor.cjs +0 -623
  56. package/src/dereference/strategies/openapi-2/visitor.mjs +0 -616
  57. package/src/dereference/strategies/openapi-3-0/index.cjs +0 -96
  58. package/src/dereference/strategies/openapi-3-0/index.mjs +0 -90
  59. package/src/dereference/strategies/openapi-3-0/visitor.cjs +0 -615
  60. package/src/dereference/strategies/openapi-3-0/visitor.mjs +0 -608
  61. package/src/dereference/strategies/openapi-3-1/index.cjs +0 -99
  62. package/src/dereference/strategies/openapi-3-1/index.mjs +0 -90
  63. package/src/dereference/strategies/openapi-3-1/selectors/$anchor.cjs +0 -67
  64. package/src/dereference/strategies/openapi-3-1/selectors/$anchor.mjs +0 -56
  65. package/src/dereference/strategies/openapi-3-1/selectors/uri.cjs +0 -50
  66. package/src/dereference/strategies/openapi-3-1/selectors/uri.mjs +0 -42
  67. package/src/dereference/strategies/openapi-3-1/util.cjs +0 -68
  68. package/src/dereference/strategies/openapi-3-1/util.mjs +0 -59
  69. package/src/dereference/strategies/openapi-3-1/visitor.cjs +0 -867
  70. package/src/dereference/strategies/openapi-3-1/visitor.mjs +0 -860
  71. package/src/dereference/util.cjs +0 -31
  72. package/src/dereference/util.mjs +0 -27
  73. package/src/errors/BundleError.cjs +0 -10
  74. package/src/errors/BundleError.mjs +0 -7
  75. package/src/errors/DereferenceError.cjs +0 -10
  76. package/src/errors/DereferenceError.mjs +0 -7
  77. package/src/errors/EvaluationElementIdError.cjs +0 -10
  78. package/src/errors/EvaluationElementIdError.mjs +0 -7
  79. package/src/errors/EvaluationJsonSchema$anchorError.cjs +0 -11
  80. package/src/errors/EvaluationJsonSchema$anchorError.mjs +0 -6
  81. package/src/errors/EvaluationJsonSchemaUriError.cjs +0 -11
  82. package/src/errors/EvaluationJsonSchemaUriError.mjs +0 -6
  83. package/src/errors/InvalidJsonSchema$anchorError.cjs +0 -15
  84. package/src/errors/InvalidJsonSchema$anchorError.mjs +0 -10
  85. package/src/errors/JsonSchema$anchorError.cjs +0 -10
  86. package/src/errors/JsonSchema$anchorError.mjs +0 -7
  87. package/src/errors/JsonSchemaUriError.cjs +0 -10
  88. package/src/errors/JsonSchemaUriError.mjs +0 -7
  89. package/src/errors/MaximumBundleDepthError.cjs +0 -11
  90. package/src/errors/MaximumBundleDepthError.mjs +0 -6
  91. package/src/errors/MaximumDereferenceDepthError.cjs +0 -11
  92. package/src/errors/MaximumDereferenceDepthError.mjs +0 -6
  93. package/src/errors/MaximumResolveDepthError.cjs +0 -11
  94. package/src/errors/MaximumResolveDepthError.mjs +0 -6
  95. package/src/errors/ParseError.cjs +0 -10
  96. package/src/errors/ParseError.mjs +0 -7
  97. package/src/errors/ParserError.cjs +0 -11
  98. package/src/errors/ParserError.mjs +0 -6
  99. package/src/errors/PluginError.cjs +0 -18
  100. package/src/errors/PluginError.mjs +0 -15
  101. package/src/errors/ResolveError.cjs +0 -10
  102. package/src/errors/ResolveError.mjs +0 -7
  103. package/src/errors/ResolverError.cjs +0 -11
  104. package/src/errors/ResolverError.mjs +0 -6
  105. package/src/errors/UnmatchedBundleStrategyError.cjs +0 -11
  106. package/src/errors/UnmatchedBundleStrategyError.mjs +0 -6
  107. package/src/errors/UnmatchedDereferenceStrategyError.cjs +0 -11
  108. package/src/errors/UnmatchedDereferenceStrategyError.mjs +0 -6
  109. package/src/errors/UnmatchedParserError.cjs +0 -11
  110. package/src/errors/UnmatchedParserError.mjs +0 -6
  111. package/src/errors/UnmatchedResolveStrategyError.cjs +0 -11
  112. package/src/errors/UnmatchedResolveStrategyError.mjs +0 -6
  113. package/src/errors/UnmatchedResolverError.cjs +0 -11
  114. package/src/errors/UnmatchedResolverError.mjs +0 -6
  115. package/src/errors/UnresolvableReferenceError.cjs +0 -11
  116. package/src/errors/UnresolvableReferenceError.mjs +0 -6
  117. package/src/index.cjs +0 -146
  118. package/src/index.mjs +0 -103
  119. package/src/options/index.cjs +0 -194
  120. package/src/options/index.mjs +0 -191
  121. package/src/options/util.cjs +0 -24
  122. package/src/options/util.mjs +0 -19
  123. package/src/parse/index.cjs +0 -69
  124. package/src/parse/index.mjs +0 -63
  125. package/src/parse/parsers/Parser.cjs +0 -62
  126. package/src/parse/parsers/Parser.mjs +0 -58
  127. package/src/parse/parsers/apidom-json/index.cjs +0 -70
  128. package/src/parse/parsers/apidom-json/index.mjs +0 -64
  129. package/src/parse/parsers/arazzo-json-1/index.cjs +0 -62
  130. package/src/parse/parsers/arazzo-json-1/index.mjs +0 -56
  131. package/src/parse/parsers/arazzo-json-1/source-descriptions.cjs +0 -221
  132. package/src/parse/parsers/arazzo-json-1/source-descriptions.mjs +0 -214
  133. package/src/parse/parsers/arazzo-yaml-1/index.cjs +0 -62
  134. package/src/parse/parsers/arazzo-yaml-1/index.mjs +0 -56
  135. package/src/parse/parsers/arazzo-yaml-1/source-descriptions.cjs +0 -12
  136. package/src/parse/parsers/arazzo-yaml-1/source-descriptions.mjs +0 -7
  137. package/src/parse/parsers/asyncapi-json-2/index.cjs +0 -54
  138. package/src/parse/parsers/asyncapi-json-2/index.mjs +0 -48
  139. package/src/parse/parsers/asyncapi-yaml-2/index.cjs +0 -54
  140. package/src/parse/parsers/asyncapi-yaml-2/index.mjs +0 -48
  141. package/src/parse/parsers/binary/index-browser.cjs +0 -56
  142. package/src/parse/parsers/binary/index-browser.mjs +0 -50
  143. package/src/parse/parsers/binary/index-node.cjs +0 -51
  144. package/src/parse/parsers/binary/index-node.mjs +0 -45
  145. package/src/parse/parsers/json/index.cjs +0 -53
  146. package/src/parse/parsers/json/index.mjs +0 -47
  147. package/src/parse/parsers/openapi-json-2/index.cjs +0 -54
  148. package/src/parse/parsers/openapi-json-2/index.mjs +0 -48
  149. package/src/parse/parsers/openapi-json-3-0/index.cjs +0 -54
  150. package/src/parse/parsers/openapi-json-3-0/index.mjs +0 -48
  151. package/src/parse/parsers/openapi-json-3-1/index.cjs +0 -54
  152. package/src/parse/parsers/openapi-json-3-1/index.mjs +0 -48
  153. package/src/parse/parsers/openapi-yaml-2/index.cjs +0 -54
  154. package/src/parse/parsers/openapi-yaml-2/index.mjs +0 -48
  155. package/src/parse/parsers/openapi-yaml-3-0/index.cjs +0 -54
  156. package/src/parse/parsers/openapi-yaml-3-0/index.mjs +0 -48
  157. package/src/parse/parsers/openapi-yaml-3-1/index.cjs +0 -54
  158. package/src/parse/parsers/openapi-yaml-3-1/index.mjs +0 -48
  159. package/src/parse/parsers/yaml-1-2/index.cjs +0 -56
  160. package/src/parse/parsers/yaml-1-2/index.mjs +0 -50
  161. package/src/resolve/index.cjs +0 -67
  162. package/src/resolve/index.mjs +0 -60
  163. package/src/resolve/resolvers/HTTPResolver.cjs +0 -45
  164. package/src/resolve/resolvers/HTTPResolver.mjs +0 -37
  165. package/src/resolve/resolvers/Resolver.cjs +0 -20
  166. package/src/resolve/resolvers/Resolver.mjs +0 -16
  167. package/src/resolve/resolvers/file/index-browser.cjs +0 -24
  168. package/src/resolve/resolvers/file/index-browser.mjs +0 -19
  169. package/src/resolve/resolvers/file/index-node.cjs +0 -49
  170. package/src/resolve/resolvers/file/index-node.mjs +0 -42
  171. package/src/resolve/resolvers/http-axios/cache/MemoryCache.cjs +0 -41
  172. package/src/resolve/resolvers/http-axios/cache/MemoryCache.mjs +0 -37
  173. package/src/resolve/resolvers/http-axios/index.cjs +0 -113
  174. package/src/resolve/resolvers/http-axios/index.mjs +0 -105
  175. package/src/resolve/strategies/ResolveStrategy.cjs +0 -20
  176. package/src/resolve/strategies/ResolveStrategy.mjs +0 -16
  177. package/src/resolve/strategies/apidom/index.cjs +0 -49
  178. package/src/resolve/strategies/apidom/index.mjs +0 -43
  179. package/src/resolve/strategies/asyncapi-2/index.cjs +0 -49
  180. package/src/resolve/strategies/asyncapi-2/index.mjs +0 -43
  181. package/src/resolve/strategies/openapi-2/index.cjs +0 -49
  182. package/src/resolve/strategies/openapi-2/index.mjs +0 -43
  183. package/src/resolve/strategies/openapi-3-0/index.cjs +0 -49
  184. package/src/resolve/strategies/openapi-3-0/index.mjs +0 -43
  185. package/src/resolve/strategies/openapi-3-1/index.cjs +0 -49
  186. package/src/resolve/strategies/openapi-3-1/index.mjs +0 -43
  187. package/src/resolve/util.cjs +0 -37
  188. package/src/resolve/util.mjs +0 -30
  189. package/src/util/plugins.cjs +0 -39
  190. package/src/util/plugins.mjs +0 -34
  191. package/src/util/url.cjs +0 -288
  192. package/src/util/url.mjs +0 -274
@@ -1,221 +0,0 @@
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.parseSourceDescriptions = parseSourceDescriptions;
7
- var _apidomDatamodel = require("@speclynx/apidom-datamodel");
8
- var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
9
- var _apidomNsOpenapi = require("@speclynx/apidom-ns-openapi-2");
10
- var _apidomNsOpenapi2 = require("@speclynx/apidom-ns-openapi-3-0");
11
- var _apidomNsOpenapi3 = require("@speclynx/apidom-ns-openapi-3-1");
12
- var _apidomCore = require("@speclynx/apidom-core");
13
- var _File = _interopRequireDefault(require("../../../File.cjs"));
14
- var url = _interopRequireWildcard(require("../../../util/url.cjs"));
15
- var _util = require("../../../options/util.cjs");
16
- var _index = _interopRequireDefault(require("../../index.cjs"));
17
- // shared key for recursion state (works across JSON/YAML parsers)
18
- const ARAZZO_RECURSION_KEY = 'arazzo-1';
19
- /**
20
- * Parses a single source description element.
21
- * Returns ParseResultElement on success, or undefined if skipped.
22
- */
23
- async function parseSourceDescription(sourceDescription, ctx) {
24
- const parseResult = new _apidomDatamodel.ParseResultElement();
25
- if (!(0, _apidomNsArazzo.isSourceDescriptionElement)(sourceDescription)) {
26
- const annotation = new _apidomDatamodel.AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping');
27
- annotation.classes.push('warning');
28
- parseResult.push(annotation);
29
- return parseResult;
30
- }
31
-
32
- // set class and metadata from source description element
33
- parseResult.classes.push('source-description');
34
- if ((0, _apidomDatamodel.isStringElement)(sourceDescription.name)) parseResult.setMetaProperty('name', (0, _apidomCore.toValue)(sourceDescription.name));
35
- if ((0, _apidomDatamodel.isStringElement)(sourceDescription.type)) parseResult.setMetaProperty('type', (0, _apidomCore.toValue)(sourceDescription.type));
36
- const sourceDescriptionURI = (0, _apidomCore.toValue)(sourceDescription.url);
37
- if (typeof sourceDescriptionURI !== 'string') {
38
- const annotation = new _apidomDatamodel.AnnotationElement('Source description URL is missing or not a string. Skipping');
39
- annotation.classes.push('warning');
40
- parseResult.push(annotation);
41
- return parseResult;
42
- }
43
-
44
- // normalize URI for consistent cycle detection and cache key matching
45
- const retrievalURI = url.sanitize(url.stripHash(url.resolve(ctx.baseURI, sourceDescriptionURI)));
46
- parseResult.setMetaProperty('retrievalURI', retrievalURI);
47
-
48
- // skip if already visited (cycle detection)
49
- if (ctx.visitedUrls.has(retrievalURI)) {
50
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle`);
51
- annotation.classes.push('warning');
52
- parseResult.push(annotation);
53
- return parseResult;
54
- }
55
- ctx.visitedUrls.add(retrievalURI);
56
- try {
57
- const sourceDescriptionParseResult = await (0, _index.default)(retrievalURI, (0, _util.merge)(ctx.options, {
58
- parse: {
59
- mediaType: 'text/plain',
60
- // allow parser plugin detection
61
- parserOpts: {
62
- // nested documents should parse all their source descriptions
63
- // (parent's name filter doesn't apply to nested documents)
64
- sourceDescriptions: true,
65
- [ARAZZO_RECURSION_KEY]: {
66
- sourceDescriptionsDepth: ctx.currentDepth + 1,
67
- sourceDescriptionsVisitedUrls: ctx.visitedUrls
68
- }
69
- }
70
- }
71
- }));
72
- // merge parsed result into our parse result
73
- for (const item of sourceDescriptionParseResult) {
74
- parseResult.push(item);
75
- }
76
- } catch (error) {
77
- // create error annotation instead of failing entire parse
78
- const message = error instanceof Error ? error.message : String(error);
79
- const annotation = new _apidomDatamodel.AnnotationElement(`Error parsing source description "${retrievalURI}": ${message}`);
80
- annotation.classes.push('error');
81
- parseResult.push(annotation);
82
- return parseResult;
83
- }
84
-
85
- // only allow OpenAPI and Arazzo as source descriptions
86
- const {
87
- api: sourceDescriptionAPI
88
- } = parseResult;
89
- const isOpenApi = (0, _apidomNsOpenapi.isSwaggerElement)(sourceDescriptionAPI) || (0, _apidomNsOpenapi2.isOpenApi3_0Element)(sourceDescriptionAPI) || (0, _apidomNsOpenapi3.isOpenApi3_1Element)(sourceDescriptionAPI);
90
- const isArazzo = (0, _apidomNsArazzo.isArazzoSpecification1Element)(sourceDescriptionAPI);
91
- if (!isOpenApi && !isArazzo) {
92
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document`);
93
- annotation.classes.push('warning');
94
- parseResult.push(annotation);
95
- return parseResult;
96
- }
97
-
98
- // validate declared type matches actual parsed type
99
- const declaredType = (0, _apidomCore.toValue)(sourceDescription.type);
100
- if (typeof declaredType === 'string') {
101
- if (declaredType === 'openapi' && !isOpenApi) {
102
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document`);
103
- annotation.classes.push('warning');
104
- parseResult.push(annotation);
105
- } else if (declaredType === 'arazzo' && !isArazzo) {
106
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document`);
107
- annotation.classes.push('warning');
108
- parseResult.push(annotation);
109
- }
110
- }
111
- return parseResult;
112
- }
113
-
114
- /**
115
- * Parses source descriptions from an Arazzo document's ParseResult.
116
- *
117
- * Each source description result is attached to its corresponding
118
- * SourceDescriptionElement's meta as 'parseResult' for easy access,
119
- * regardless of success or failure. On failure, the ParseResultElement
120
- * contains annotations explaining what went wrong.
121
- *
122
- * @param parseResult - ParseResult containing an Arazzo specification
123
- * @param parseResultRetrievalURI - URI from which the parseResult was retrieved
124
- * @param options - Full ReferenceOptions. Pass `sourceDescriptions` as an array of names
125
- * in `parse.parserOpts` to filter which source descriptions to process.
126
- * @param parserName - Parser name for options lookup (defaults to 'arazzo-json-1')
127
- * @returns Array of ParseResultElements. Returns one ParseResultElement per source description
128
- * (each with class 'source-description' and metadata: name, type, retrievalURI).
129
- * May return early with a single-element array containing a warning annotation when:
130
- * - The API is not an Arazzo specification
131
- * - The sourceDescriptions field is missing or not an array
132
- * - Maximum parse depth is exceeded (error annotation)
133
- * Returns an empty array when no source description names match the filter.
134
- *
135
- * @example
136
- * ```typescript
137
- * import { toValue } from '@speclynx/apidom-core';
138
- * import { options, mergeOptions } from '@speclynx/apidom-reference';
139
- * import { parseSourceDescriptions } from '@speclynx/apidom-reference/parse/parsers/arazzo-json-1';
140
- *
141
- * // Parse all source descriptions
142
- * const results = await parseSourceDescriptions(parseResult, uri, options);
143
- *
144
- * // Filter by name
145
- * const filtered = await parseSourceDescriptions(parseResult, uri, mergeOptions(options, {
146
- * parse: { parserOpts: { sourceDescriptions: ['petStore'] } }
147
- * }));
148
- *
149
- * // Access parsed document from source description element
150
- * const sourceDesc = parseResult.api.sourceDescriptions.get(0);
151
- * const parsedDoc = sourceDesc.meta.get('parseResult');
152
- * const retrievalURI = toValue(parsedDoc.meta.get('retrievalURI'));
153
- * ```
154
- *
155
- * @public
156
- */
157
- async function parseSourceDescriptions(parseResult, parseResultRetrievalURI, options, parserName = 'arazzo-json-1') {
158
- const {
159
- api
160
- } = parseResult;
161
- const file = new _File.default({
162
- uri: url.sanitize(url.stripHash(parseResultRetrievalURI))
163
- });
164
- const results = [];
165
-
166
- /**
167
- * Validate prerequisites for parsing source descriptions.
168
- * Return warning annotations if validation fails.
169
- */
170
- if (!(0, _apidomNsArazzo.isArazzoSpecification1Element)(api)) {
171
- const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification');
172
- annotation.classes.push('warning');
173
- return [new _apidomDatamodel.ParseResultElement([annotation])];
174
- }
175
- if (!(0, _apidomDatamodel.isArrayElement)(api.sourceDescriptions)) {
176
- const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array');
177
- annotation.classes.push('warning');
178
- return [new _apidomDatamodel.ParseResultElement([annotation])];
179
- }
180
-
181
- // user config: parser-specific options take precedence over global parserOpts
182
- const maxDepth = options?.parse?.parserOpts?.[parserName]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
183
-
184
- // recursion state comes from shared key (works across JSON/YAML)
185
- const sharedOpts = options?.parse?.parserOpts?.[ARAZZO_RECURSION_KEY] ?? {};
186
- const currentDepth = sharedOpts.sourceDescriptionsDepth ?? 0;
187
- const visitedUrls = sharedOpts.sourceDescriptionsVisitedUrls ?? new Set();
188
-
189
- // add current file to visited URLs to prevent cycles
190
- visitedUrls.add(file.uri);
191
- if (currentDepth >= maxDepth) {
192
- const annotation = new _apidomDatamodel.AnnotationElement(`Maximum parse depth of ${maxDepth} has been exceeded by file "${file.uri}"`);
193
- annotation.classes.push('error');
194
- const parseResult = new _apidomDatamodel.ParseResultElement([annotation]);
195
- parseResult.classes.push('source-description');
196
- return [parseResult];
197
- }
198
- const ctx = {
199
- baseURI: file.uri,
200
- options,
201
- currentDepth,
202
- visitedUrls
203
- };
204
-
205
- // determine which source descriptions to parse (array filters by name)
206
- const sourceDescriptionsOption = options?.parse?.parserOpts?.[parserName]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
207
- const sourceDescriptions = Array.isArray(sourceDescriptionsOption) ? api.sourceDescriptions.filter(sd => {
208
- if (!(0, _apidomNsArazzo.isSourceDescriptionElement)(sd)) return false;
209
- const name = (0, _apidomCore.toValue)(sd.name);
210
- return typeof name === 'string' && sourceDescriptionsOption.includes(name);
211
- }) : api.sourceDescriptions;
212
-
213
- // process sequentially to ensure proper cycle detection with shared visitedUrls
214
- for (const sourceDescription of sourceDescriptions) {
215
- const sourceDescriptionParseResult = await parseSourceDescription(sourceDescription, ctx);
216
- // always attach result (even on failure - contains annotations)
217
- sourceDescription.meta.set('parseResult', sourceDescriptionParseResult);
218
- results.push(sourceDescriptionParseResult);
219
- }
220
- return results;
221
- }
@@ -1,214 +0,0 @@
1
- import { ParseResultElement, AnnotationElement, isArrayElement, isStringElement } from '@speclynx/apidom-datamodel';
2
- import { isArazzoSpecification1Element, isSourceDescriptionElement } from '@speclynx/apidom-ns-arazzo-1';
3
- import { isSwaggerElement } from '@speclynx/apidom-ns-openapi-2';
4
- import { isOpenApi3_0Element } from '@speclynx/apidom-ns-openapi-3-0';
5
- import { isOpenApi3_1Element } from '@speclynx/apidom-ns-openapi-3-1';
6
- import { toValue } from '@speclynx/apidom-core';
7
- import File from "../../../File.mjs";
8
- import * as url from "../../../util/url.mjs";
9
- import { merge as mergeOptions } from "../../../options/util.mjs";
10
- import parse from "../../index.mjs"; // shared key for recursion state (works across JSON/YAML parsers)
11
- const ARAZZO_RECURSION_KEY = 'arazzo-1';
12
- /**
13
- * Parses a single source description element.
14
- * Returns ParseResultElement on success, or undefined if skipped.
15
- */
16
- async function parseSourceDescription(sourceDescription, ctx) {
17
- const parseResult = new ParseResultElement();
18
- if (!isSourceDescriptionElement(sourceDescription)) {
19
- const annotation = new AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping');
20
- annotation.classes.push('warning');
21
- parseResult.push(annotation);
22
- return parseResult;
23
- }
24
-
25
- // set class and metadata from source description element
26
- parseResult.classes.push('source-description');
27
- if (isStringElement(sourceDescription.name)) parseResult.setMetaProperty('name', toValue(sourceDescription.name));
28
- if (isStringElement(sourceDescription.type)) parseResult.setMetaProperty('type', toValue(sourceDescription.type));
29
- const sourceDescriptionURI = toValue(sourceDescription.url);
30
- if (typeof sourceDescriptionURI !== 'string') {
31
- const annotation = new AnnotationElement('Source description URL is missing or not a string. Skipping');
32
- annotation.classes.push('warning');
33
- parseResult.push(annotation);
34
- return parseResult;
35
- }
36
-
37
- // normalize URI for consistent cycle detection and cache key matching
38
- const retrievalURI = url.sanitize(url.stripHash(url.resolve(ctx.baseURI, sourceDescriptionURI)));
39
- parseResult.setMetaProperty('retrievalURI', retrievalURI);
40
-
41
- // skip if already visited (cycle detection)
42
- if (ctx.visitedUrls.has(retrievalURI)) {
43
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle`);
44
- annotation.classes.push('warning');
45
- parseResult.push(annotation);
46
- return parseResult;
47
- }
48
- ctx.visitedUrls.add(retrievalURI);
49
- try {
50
- const sourceDescriptionParseResult = await parse(retrievalURI, mergeOptions(ctx.options, {
51
- parse: {
52
- mediaType: 'text/plain',
53
- // allow parser plugin detection
54
- parserOpts: {
55
- // nested documents should parse all their source descriptions
56
- // (parent's name filter doesn't apply to nested documents)
57
- sourceDescriptions: true,
58
- [ARAZZO_RECURSION_KEY]: {
59
- sourceDescriptionsDepth: ctx.currentDepth + 1,
60
- sourceDescriptionsVisitedUrls: ctx.visitedUrls
61
- }
62
- }
63
- }
64
- }));
65
- // merge parsed result into our parse result
66
- for (const item of sourceDescriptionParseResult) {
67
- parseResult.push(item);
68
- }
69
- } catch (error) {
70
- // create error annotation instead of failing entire parse
71
- const message = error instanceof Error ? error.message : String(error);
72
- const annotation = new AnnotationElement(`Error parsing source description "${retrievalURI}": ${message}`);
73
- annotation.classes.push('error');
74
- parseResult.push(annotation);
75
- return parseResult;
76
- }
77
-
78
- // only allow OpenAPI and Arazzo as source descriptions
79
- const {
80
- api: sourceDescriptionAPI
81
- } = parseResult;
82
- const isOpenApi = isSwaggerElement(sourceDescriptionAPI) || isOpenApi3_0Element(sourceDescriptionAPI) || isOpenApi3_1Element(sourceDescriptionAPI);
83
- const isArazzo = isArazzoSpecification1Element(sourceDescriptionAPI);
84
- if (!isOpenApi && !isArazzo) {
85
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document`);
86
- annotation.classes.push('warning');
87
- parseResult.push(annotation);
88
- return parseResult;
89
- }
90
-
91
- // validate declared type matches actual parsed type
92
- const declaredType = toValue(sourceDescription.type);
93
- if (typeof declaredType === 'string') {
94
- if (declaredType === 'openapi' && !isOpenApi) {
95
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document`);
96
- annotation.classes.push('warning');
97
- parseResult.push(annotation);
98
- } else if (declaredType === 'arazzo' && !isArazzo) {
99
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document`);
100
- annotation.classes.push('warning');
101
- parseResult.push(annotation);
102
- }
103
- }
104
- return parseResult;
105
- }
106
-
107
- /**
108
- * Parses source descriptions from an Arazzo document's ParseResult.
109
- *
110
- * Each source description result is attached to its corresponding
111
- * SourceDescriptionElement's meta as 'parseResult' for easy access,
112
- * regardless of success or failure. On failure, the ParseResultElement
113
- * contains annotations explaining what went wrong.
114
- *
115
- * @param parseResult - ParseResult containing an Arazzo specification
116
- * @param parseResultRetrievalURI - URI from which the parseResult was retrieved
117
- * @param options - Full ReferenceOptions. Pass `sourceDescriptions` as an array of names
118
- * in `parse.parserOpts` to filter which source descriptions to process.
119
- * @param parserName - Parser name for options lookup (defaults to 'arazzo-json-1')
120
- * @returns Array of ParseResultElements. Returns one ParseResultElement per source description
121
- * (each with class 'source-description' and metadata: name, type, retrievalURI).
122
- * May return early with a single-element array containing a warning annotation when:
123
- * - The API is not an Arazzo specification
124
- * - The sourceDescriptions field is missing or not an array
125
- * - Maximum parse depth is exceeded (error annotation)
126
- * Returns an empty array when no source description names match the filter.
127
- *
128
- * @example
129
- * ```typescript
130
- * import { toValue } from '@speclynx/apidom-core';
131
- * import { options, mergeOptions } from '@speclynx/apidom-reference';
132
- * import { parseSourceDescriptions } from '@speclynx/apidom-reference/parse/parsers/arazzo-json-1';
133
- *
134
- * // Parse all source descriptions
135
- * const results = await parseSourceDescriptions(parseResult, uri, options);
136
- *
137
- * // Filter by name
138
- * const filtered = await parseSourceDescriptions(parseResult, uri, mergeOptions(options, {
139
- * parse: { parserOpts: { sourceDescriptions: ['petStore'] } }
140
- * }));
141
- *
142
- * // Access parsed document from source description element
143
- * const sourceDesc = parseResult.api.sourceDescriptions.get(0);
144
- * const parsedDoc = sourceDesc.meta.get('parseResult');
145
- * const retrievalURI = toValue(parsedDoc.meta.get('retrievalURI'));
146
- * ```
147
- *
148
- * @public
149
- */
150
- export async function parseSourceDescriptions(parseResult, parseResultRetrievalURI, options, parserName = 'arazzo-json-1') {
151
- const {
152
- api
153
- } = parseResult;
154
- const file = new File({
155
- uri: url.sanitize(url.stripHash(parseResultRetrievalURI))
156
- });
157
- const results = [];
158
-
159
- /**
160
- * Validate prerequisites for parsing source descriptions.
161
- * Return warning annotations if validation fails.
162
- */
163
- if (!isArazzoSpecification1Element(api)) {
164
- const annotation = new AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification');
165
- annotation.classes.push('warning');
166
- return [new ParseResultElement([annotation])];
167
- }
168
- if (!isArrayElement(api.sourceDescriptions)) {
169
- const annotation = new AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array');
170
- annotation.classes.push('warning');
171
- return [new ParseResultElement([annotation])];
172
- }
173
-
174
- // user config: parser-specific options take precedence over global parserOpts
175
- const maxDepth = options?.parse?.parserOpts?.[parserName]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
176
-
177
- // recursion state comes from shared key (works across JSON/YAML)
178
- const sharedOpts = options?.parse?.parserOpts?.[ARAZZO_RECURSION_KEY] ?? {};
179
- const currentDepth = sharedOpts.sourceDescriptionsDepth ?? 0;
180
- const visitedUrls = sharedOpts.sourceDescriptionsVisitedUrls ?? new Set();
181
-
182
- // add current file to visited URLs to prevent cycles
183
- visitedUrls.add(file.uri);
184
- if (currentDepth >= maxDepth) {
185
- const annotation = new AnnotationElement(`Maximum parse depth of ${maxDepth} has been exceeded by file "${file.uri}"`);
186
- annotation.classes.push('error');
187
- const parseResult = new ParseResultElement([annotation]);
188
- parseResult.classes.push('source-description');
189
- return [parseResult];
190
- }
191
- const ctx = {
192
- baseURI: file.uri,
193
- options,
194
- currentDepth,
195
- visitedUrls
196
- };
197
-
198
- // determine which source descriptions to parse (array filters by name)
199
- const sourceDescriptionsOption = options?.parse?.parserOpts?.[parserName]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
200
- const sourceDescriptions = Array.isArray(sourceDescriptionsOption) ? api.sourceDescriptions.filter(sd => {
201
- if (!isSourceDescriptionElement(sd)) return false;
202
- const name = toValue(sd.name);
203
- return typeof name === 'string' && sourceDescriptionsOption.includes(name);
204
- }) : api.sourceDescriptions;
205
-
206
- // process sequentially to ensure proper cycle detection with shared visitedUrls
207
- for (const sourceDescription of sourceDescriptions) {
208
- const sourceDescriptionParseResult = await parseSourceDescription(sourceDescription, ctx);
209
- // always attach result (even on failure - contains annotations)
210
- sourceDescription.meta.set('parseResult', sourceDescriptionParseResult);
211
- results.push(sourceDescriptionParseResult);
212
- }
213
- return results;
214
- }
@@ -1,62 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
- exports.__esModule = true;
5
- exports.default = void 0;
6
- var _ramda = require("ramda");
7
- var _apidomParserAdapterArazzoYaml = require("@speclynx/apidom-parser-adapter-arazzo-yaml-1");
8
- var _ParserError = _interopRequireDefault(require("../../../errors/ParserError.cjs"));
9
- var _Parser = _interopRequireDefault(require("../Parser.cjs"));
10
- var _sourceDescriptions = require("./source-descriptions.cjs");
11
- exports.parseSourceDescriptions = _sourceDescriptions.parseSourceDescriptions;
12
- /**
13
- * @public
14
- */
15
-
16
- /**
17
- * @public
18
- */
19
- class ArazzoYAML1Parser extends _Parser.default {
20
- refractorOpts;
21
- constructor(options) {
22
- const {
23
- fileExtensions = [],
24
- mediaTypes = _apidomParserAdapterArazzoYaml.mediaTypes,
25
- ...rest
26
- } = options ?? {};
27
- super({
28
- ...rest,
29
- name: 'arazzo-yaml-1',
30
- fileExtensions,
31
- mediaTypes
32
- });
33
- }
34
- async canParse(file) {
35
- const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
36
- const hasSupportedMediaType = this.mediaTypes.includes(file.mediaType);
37
- if (!hasSupportedFileExtension) return false;
38
- if (hasSupportedMediaType) return true;
39
- if (!hasSupportedMediaType) {
40
- return (0, _apidomParserAdapterArazzoYaml.detect)(file.toString());
41
- }
42
- return false;
43
- }
44
- async parse(file, options) {
45
- const source = file.toString();
46
- try {
47
- const parserOpts = (0, _ramda.pick)(['sourceMap', 'style', 'strict', 'refractorOpts'], this);
48
- const parseResult = await (0, _apidomParserAdapterArazzoYaml.parse)(source, parserOpts);
49
- const shouldParseSourceDescriptions = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
50
- if (shouldParseSourceDescriptions) {
51
- const sourceDescriptions = await (0, _sourceDescriptions.parseSourceDescriptions)(parseResult, file.uri, options, this.name);
52
- parseResult.push(...sourceDescriptions);
53
- }
54
- return parseResult;
55
- } catch (error) {
56
- throw new _ParserError.default(`Error parsing "${file.uri}"`, {
57
- cause: error
58
- });
59
- }
60
- }
61
- }
62
- var _default = exports.default = ArazzoYAML1Parser;
@@ -1,56 +0,0 @@
1
- import { pick } from 'ramda';
2
- import { parse, mediaTypes as ArazzoYAML1MediaTypes, detect } from '@speclynx/apidom-parser-adapter-arazzo-yaml-1';
3
- import ParserError from "../../../errors/ParserError.mjs";
4
- import Parser from "../Parser.mjs";
5
- import { parseSourceDescriptions } from "./source-descriptions.mjs";
6
- /**
7
- * @public
8
- */
9
- /**
10
- * @public
11
- */
12
- class ArazzoYAML1Parser extends Parser {
13
- refractorOpts;
14
- constructor(options) {
15
- const {
16
- fileExtensions = [],
17
- mediaTypes = ArazzoYAML1MediaTypes,
18
- ...rest
19
- } = options ?? {};
20
- super({
21
- ...rest,
22
- name: 'arazzo-yaml-1',
23
- fileExtensions,
24
- mediaTypes
25
- });
26
- }
27
- async canParse(file) {
28
- const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
29
- const hasSupportedMediaType = this.mediaTypes.includes(file.mediaType);
30
- if (!hasSupportedFileExtension) return false;
31
- if (hasSupportedMediaType) return true;
32
- if (!hasSupportedMediaType) {
33
- return detect(file.toString());
34
- }
35
- return false;
36
- }
37
- async parse(file, options) {
38
- const source = file.toString();
39
- try {
40
- const parserOpts = pick(['sourceMap', 'style', 'strict', 'refractorOpts'], this);
41
- const parseResult = await parse(source, parserOpts);
42
- const shouldParseSourceDescriptions = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
43
- if (shouldParseSourceDescriptions) {
44
- const sourceDescriptions = await parseSourceDescriptions(parseResult, file.uri, options, this.name);
45
- parseResult.push(...sourceDescriptions);
46
- }
47
- return parseResult;
48
- } catch (error) {
49
- throw new ParserError(`Error parsing "${file.uri}"`, {
50
- cause: error
51
- });
52
- }
53
- }
54
- }
55
- export { parseSourceDescriptions } from "./source-descriptions.mjs";
56
- export default ArazzoYAML1Parser;
@@ -1,12 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.parseSourceDescriptions = void 0;
5
- var _sourceDescriptions = require("../arazzo-json-1/source-descriptions.cjs");
6
- /**
7
- * @public
8
- */
9
- const parseSourceDescriptions = (parseResult, parseResultRetrievalURI, options, parserName = 'arazzo-yaml-1') => {
10
- return (0, _sourceDescriptions.parseSourceDescriptions)(parseResult, parseResultRetrievalURI, options, parserName);
11
- };
12
- exports.parseSourceDescriptions = parseSourceDescriptions;
@@ -1,7 +0,0 @@
1
- import { parseSourceDescriptions as parseSourceDescriptionsBase } from "../arazzo-json-1/source-descriptions.mjs";
2
- /**
3
- * @public
4
- */
5
- export const parseSourceDescriptions = (parseResult, parseResultRetrievalURI, options, parserName = 'arazzo-yaml-1') => {
6
- return parseSourceDescriptionsBase(parseResult, parseResultRetrievalURI, options, parserName);
7
- };
@@ -1,54 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
- exports.__esModule = true;
5
- exports.default = void 0;
6
- var _ramda = require("ramda");
7
- var _apidomParserAdapterAsyncapiJson = require("@speclynx/apidom-parser-adapter-asyncapi-json-2");
8
- var _ParserError = _interopRequireDefault(require("../../../errors/ParserError.cjs"));
9
- var _Parser = _interopRequireDefault(require("../Parser.cjs"));
10
- /**
11
- * @public
12
- */
13
-
14
- /**
15
- * @public
16
- */
17
- class AsyncAPIJSON2Parser extends _Parser.default {
18
- refractorOpts;
19
- constructor(options) {
20
- const {
21
- fileExtensions = [],
22
- mediaTypes = _apidomParserAdapterAsyncapiJson.mediaTypes,
23
- ...rest
24
- } = options ?? {};
25
- super({
26
- ...rest,
27
- name: 'asyncapi-json-2',
28
- fileExtensions,
29
- mediaTypes
30
- });
31
- }
32
- async canParse(file) {
33
- const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
34
- const hasSupportedMediaType = this.mediaTypes.includes(file.mediaType);
35
- if (!hasSupportedFileExtension) return false;
36
- if (hasSupportedMediaType) return true;
37
- if (!hasSupportedMediaType) {
38
- return (0, _apidomParserAdapterAsyncapiJson.detect)(file.toString());
39
- }
40
- return false;
41
- }
42
- async parse(file) {
43
- const source = file.toString();
44
- try {
45
- const parserOpts = (0, _ramda.pick)(['sourceMap', 'style', 'strict', 'refractorOpts'], this);
46
- return await (0, _apidomParserAdapterAsyncapiJson.parse)(source, parserOpts);
47
- } catch (error) {
48
- throw new _ParserError.default(`Error parsing "${file.uri}"`, {
49
- cause: error
50
- });
51
- }
52
- }
53
- }
54
- var _default = exports.default = AsyncAPIJSON2Parser;
@@ -1,48 +0,0 @@
1
- import { pick } from 'ramda';
2
- import { parse, mediaTypes as AsyncAPI2MediaTypes, detect } from '@speclynx/apidom-parser-adapter-asyncapi-json-2';
3
- import ParserError from "../../../errors/ParserError.mjs";
4
- import Parser from "../Parser.mjs";
5
- /**
6
- * @public
7
- */
8
- /**
9
- * @public
10
- */
11
- class AsyncAPIJSON2Parser extends Parser {
12
- refractorOpts;
13
- constructor(options) {
14
- const {
15
- fileExtensions = [],
16
- mediaTypes = AsyncAPI2MediaTypes,
17
- ...rest
18
- } = options ?? {};
19
- super({
20
- ...rest,
21
- name: 'asyncapi-json-2',
22
- fileExtensions,
23
- mediaTypes
24
- });
25
- }
26
- async canParse(file) {
27
- const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
28
- const hasSupportedMediaType = this.mediaTypes.includes(file.mediaType);
29
- if (!hasSupportedFileExtension) return false;
30
- if (hasSupportedMediaType) return true;
31
- if (!hasSupportedMediaType) {
32
- return detect(file.toString());
33
- }
34
- return false;
35
- }
36
- async parse(file) {
37
- const source = file.toString();
38
- try {
39
- const parserOpts = pick(['sourceMap', 'style', 'strict', 'refractorOpts'], this);
40
- return await parse(source, parserOpts);
41
- } catch (error) {
42
- throw new ParserError(`Error parsing "${file.uri}"`, {
43
- cause: error
44
- });
45
- }
46
- }
47
- }
48
- export default AsyncAPIJSON2Parser;