@speclynx/apidom-reference 2.6.1 → 2.8.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 (31) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +60 -33
  3. package/dist/apidom-reference.browser.js +349 -99
  4. package/dist/apidom-reference.browser.min.js +1 -1
  5. package/package.json +25 -25
  6. package/src/configuration/saturated.cjs +2 -4
  7. package/src/configuration/saturated.mjs +3 -5
  8. package/src/dereference/strategies/arazzo-1/index.cjs +10 -0
  9. package/src/dereference/strategies/arazzo-1/index.mjs +10 -0
  10. package/src/dereference/strategies/arazzo-1/source-description.cjs +179 -0
  11. package/src/dereference/strategies/arazzo-1/source-description.mjs +172 -0
  12. package/src/dereference/strategies/openapi-3-0/visitor.cjs +2 -2
  13. package/src/dereference/strategies/openapi-3-0/visitor.mjs +2 -2
  14. package/src/dereference/strategies/openapi-3-1/visitor.cjs +2 -2
  15. package/src/dereference/strategies/openapi-3-1/visitor.mjs +2 -2
  16. package/src/parse/parsers/arazzo-json-1/index.cjs +3 -5
  17. package/src/parse/parsers/arazzo-json-1/index.mjs +3 -5
  18. package/src/parse/parsers/arazzo-json-1/{source-description.cjs → source-descriptions.cjs} +47 -21
  19. package/src/parse/parsers/arazzo-json-1/{source-description.mjs → source-descriptions.mjs} +47 -22
  20. package/src/parse/parsers/arazzo-yaml-1/index.cjs +3 -5
  21. package/src/parse/parsers/arazzo-yaml-1/index.mjs +3 -5
  22. package/src/parse/parsers/arazzo-yaml-1/source-descriptions.cjs +12 -0
  23. package/src/parse/parsers/arazzo-yaml-1/source-descriptions.mjs +7 -0
  24. package/src/resolve/resolvers/file/index-browser.cjs +1 -1
  25. package/src/resolve/resolvers/file/index-browser.mjs +1 -1
  26. package/types/dereference/strategies/arazzo-1/source-description.d.ts +8 -0
  27. package/types/parse/parsers/arazzo-json-1/index.d.ts +1 -3
  28. package/types/parse/parsers/arazzo-json-1/source-descriptions.d.ts +31 -0
  29. package/types/parse/parsers/arazzo-yaml-1/index.d.ts +1 -3
  30. package/types/parse/parsers/arazzo-yaml-1/source-descriptions.d.ts +6 -0
  31. package/types/parse/parsers/arazzo-json-1/source-description.d.ts +0 -13
@@ -2,7 +2,7 @@ import { pick } from 'ramda';
2
2
  import { parse, mediaTypes as ArazzoJSON1MediaTypes, detect } from '@speclynx/apidom-parser-adapter-arazzo-json-1';
3
3
  import ParserError from "../../../errors/ParserError.mjs";
4
4
  import Parser from "../Parser.mjs";
5
- import { parseSourceDescriptions } from "./source-description.mjs";
5
+ import { parseSourceDescriptions } from "./source-descriptions.mjs";
6
6
  /**
7
7
  * @public
8
8
  */
@@ -11,10 +11,8 @@ import { parseSourceDescriptions } from "./source-description.mjs";
11
11
  */
12
12
  class ArazzoJSON1Parser extends Parser {
13
13
  refractorOpts;
14
- parseFn;
15
14
  constructor(options) {
16
15
  const {
17
- parseFn,
18
16
  fileExtensions = [],
19
17
  mediaTypes = ArazzoJSON1MediaTypes,
20
18
  ...rest
@@ -25,7 +23,6 @@ class ArazzoJSON1Parser extends Parser {
25
23
  fileExtensions,
26
24
  mediaTypes
27
25
  });
28
- this.parseFn = parseFn;
29
26
  }
30
27
  async canParse(file) {
31
28
  const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
@@ -44,7 +41,7 @@ class ArazzoJSON1Parser extends Parser {
44
41
  const parseResult = await parse(source, parserOpts);
45
42
  const shouldParseSourceDescriptions = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
46
43
  if (shouldParseSourceDescriptions) {
47
- const sourceDescriptions = await parseSourceDescriptions.call(this, parseResult.api, file, options);
44
+ const sourceDescriptions = await parseSourceDescriptions(parseResult, file.uri, options, this.name);
48
45
  parseResult.push(...sourceDescriptions);
49
46
  }
50
47
  return parseResult;
@@ -55,4 +52,5 @@ class ArazzoJSON1Parser extends Parser {
55
52
  }
56
53
  }
57
54
  }
55
+ export { parseSourceDescriptions } from "./source-descriptions.mjs";
58
56
  export default ArazzoJSON1Parser;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
4
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
5
  exports.__esModule = true;
5
6
  exports.parseSourceDescriptions = parseSourceDescriptions;
6
7
  var _apidomDatamodel = require("@speclynx/apidom-datamodel");
@@ -9,8 +10,10 @@ var _apidomNsOpenapi = require("@speclynx/apidom-ns-openapi-2");
9
10
  var _apidomNsOpenapi2 = require("@speclynx/apidom-ns-openapi-3-0");
10
11
  var _apidomNsOpenapi3 = require("@speclynx/apidom-ns-openapi-3-1");
11
12
  var _apidomCore = require("@speclynx/apidom-core");
13
+ var _File = _interopRequireDefault(require("../../../File.cjs"));
12
14
  var url = _interopRequireWildcard(require("../../../util/url.cjs"));
13
15
  var _util = require("../../../options/util.cjs");
16
+ var _index = _interopRequireDefault(require("../../index.cjs"));
14
17
  // shared key for recursion state (works across JSON/YAML parsers)
15
18
  const ARAZZO_RECURSION_KEY = 'arazzo-1';
16
19
  /**
@@ -20,7 +23,7 @@ const ARAZZO_RECURSION_KEY = 'arazzo-1';
20
23
  async function parseSourceDescription(sourceDescription, ctx) {
21
24
  const parseResult = new _apidomDatamodel.ParseResultElement();
22
25
  if (!(0, _apidomNsArazzo.isSourceDescriptionElement)(sourceDescription)) {
23
- const annotation = new _apidomDatamodel.AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping.');
26
+ const annotation = new _apidomDatamodel.AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping');
24
27
  annotation.classes.push('warning');
25
28
  parseResult.push(annotation);
26
29
  return parseResult;
@@ -32,7 +35,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
32
35
  if ((0, _apidomDatamodel.isStringElement)(sourceDescription.type)) parseResult.setMetaProperty('type', (0, _apidomDatamodel.cloneDeep)(sourceDescription.type));
33
36
  const sourceDescriptionURI = (0, _apidomCore.toValue)(sourceDescription.url);
34
37
  if (typeof sourceDescriptionURI !== 'string') {
35
- const annotation = new _apidomDatamodel.AnnotationElement('Source description URL is missing or not a string. Skipping.');
38
+ const annotation = new _apidomDatamodel.AnnotationElement('Source description URL is missing or not a string. Skipping');
36
39
  annotation.classes.push('warning');
37
40
  parseResult.push(annotation);
38
41
  return parseResult;
@@ -41,14 +44,14 @@ async function parseSourceDescription(sourceDescription, ctx) {
41
44
 
42
45
  // skip if already visited (cycle detection)
43
46
  if (ctx.visitedUrls.has(retrievalURI)) {
44
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle.`);
47
+ const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle`);
45
48
  annotation.classes.push('warning');
46
49
  parseResult.push(annotation);
47
50
  return parseResult;
48
51
  }
49
52
  ctx.visitedUrls.add(retrievalURI);
50
53
  try {
51
- const sdParseResult = await ctx.parseFn(retrievalURI, (0, _util.merge)(ctx.options, {
54
+ const sourceDescriptionParseResult = await (0, _index.default)(retrievalURI, (0, _util.merge)(ctx.options, {
52
55
  parse: {
53
56
  mediaType: 'text/plain',
54
57
  // allow parser plugin detection
@@ -61,7 +64,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
61
64
  }
62
65
  }));
63
66
  // merge parsed result into our parse result
64
- for (const item of sdParseResult) {
67
+ for (const item of sourceDescriptionParseResult) {
65
68
  parseResult.push(item);
66
69
  }
67
70
  } catch (error) {
@@ -80,7 +83,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
80
83
  const isOpenApi = (0, _apidomNsOpenapi.isSwaggerElement)(sourceDescriptionAPI) || (0, _apidomNsOpenapi2.isOpenApi3_0Element)(sourceDescriptionAPI) || (0, _apidomNsOpenapi3.isOpenApi3_1Element)(sourceDescriptionAPI);
81
84
  const isArazzo = (0, _apidomNsArazzo.isArazzoSpecification1Element)(sourceDescriptionAPI);
82
85
  if (!isOpenApi && !isArazzo) {
83
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document. Skipping.`);
86
+ const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document`);
84
87
  annotation.classes.push('warning');
85
88
  parseResult.push(annotation);
86
89
  return parseResult;
@@ -90,11 +93,11 @@ async function parseSourceDescription(sourceDescription, ctx) {
90
93
  const declaredType = (0, _apidomCore.toValue)(sourceDescription.type);
91
94
  if (typeof declaredType === 'string') {
92
95
  if (declaredType === 'openapi' && !isOpenApi) {
93
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document.`);
96
+ const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document`);
94
97
  annotation.classes.push('warning');
95
98
  parseResult.push(annotation);
96
99
  } else if (declaredType === 'arazzo' && !isArazzo) {
97
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document.`);
100
+ const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document`);
98
101
  annotation.classes.push('warning');
99
102
  parseResult.push(annotation);
100
103
  }
@@ -103,11 +106,40 @@ async function parseSourceDescription(sourceDescription, ctx) {
103
106
  }
104
107
 
105
108
  /**
106
- * Shared function for parsing source descriptions.
107
- * Call with `.call(this, ...)` where `this` has `name` and `parseFn` properties.
109
+ * Parses source descriptions from an Arazzo document's ParseResult.
110
+ *
111
+ * @param parseResult - ParseResult containing an Arazzo specification
112
+ * @param parseResultRetrievalURI - URI from which the parseResult was retrieved
113
+ * @param options - Full ReferenceOptions (caller responsibility to construct)
114
+ * @param parserName - Parser name for options lookup (defaults to 'arazzo-json-1')
115
+ * @returns Array of ParseResultElements. On success, returns one ParseResultElement per
116
+ * source description (each with class 'source-description' and name/type metadata).
117
+ * May return early with a single-element array containing a warning annotation when:
118
+ * - The API is not an Arazzo specification
119
+ * - The sourceDescriptions field is missing or not an array
120
+ * - Maximum parse depth is exceeded (error annotation)
121
+ * Returns an empty array when sourceDescriptions option is disabled or no names match.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * import { options, mergeOptions } from '@speclynx/apidom-reference';
126
+ * import { parseSourceDescriptions } from '@speclynx/apidom-reference/parse/parsers/arazzo-json-1';
127
+ *
128
+ * const fullOptions = mergeOptions(options, {
129
+ * parse: { parserOpts: { sourceDescriptions: true } }
130
+ * });
131
+ * const results = await parseSourceDescriptions(parseResult, uri, fullOptions);
132
+ * ```
133
+ *
108
134
  * @public
109
135
  */
110
- async function parseSourceDescriptions(api, file, options) {
136
+ async function parseSourceDescriptions(parseResult, parseResultRetrievalURI, options, parserName = 'arazzo-json-1') {
137
+ const {
138
+ api
139
+ } = parseResult;
140
+ const file = new _File.default({
141
+ uri: url.sanitize(url.stripHash(parseResultRetrievalURI))
142
+ });
111
143
  const results = [];
112
144
 
113
145
  /**
@@ -115,23 +147,18 @@ async function parseSourceDescriptions(api, file, options) {
115
147
  * Return warning annotations if validation fails.
116
148
  */
117
149
  if (!(0, _apidomNsArazzo.isArazzoSpecification1Element)(api)) {
118
- const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification.');
150
+ const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification');
119
151
  annotation.classes.push('warning');
120
152
  return [new _apidomDatamodel.ParseResultElement([annotation])];
121
153
  }
122
154
  if (!(0, _apidomDatamodel.isArrayElement)(api.sourceDescriptions)) {
123
- const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array.');
155
+ const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array');
124
156
  annotation.classes.push('warning');
125
157
  return [new _apidomDatamodel.ParseResultElement([annotation])];
126
158
  }
127
- if (typeof this.parseFn !== 'function') {
128
- const annotation = new _apidomDatamodel.AnnotationElement('Source descriptions found but parseFn is not configured. Skipping source description parsing.');
129
- annotation.classes.push('error');
130
- return [new _apidomDatamodel.ParseResultElement([annotation])];
131
- }
132
159
 
133
160
  // user config: parser-specific options take precedence over global parserOpts
134
- const maxDepth = options?.parse?.parserOpts?.[this.name]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
161
+ const maxDepth = options?.parse?.parserOpts?.[parserName]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
135
162
 
136
163
  // recursion state comes from shared key (works across JSON/YAML)
137
164
  const sharedOpts = options?.parse?.parserOpts?.[ARAZZO_RECURSION_KEY] ?? {};
@@ -148,7 +175,6 @@ async function parseSourceDescriptions(api, file, options) {
148
175
  return [parseResult];
149
176
  }
150
177
  const ctx = {
151
- parseFn: this.parseFn,
152
178
  baseURI: file.uri,
153
179
  options,
154
180
  currentDepth,
@@ -156,7 +182,7 @@ async function parseSourceDescriptions(api, file, options) {
156
182
  };
157
183
 
158
184
  // determine which source descriptions to parse
159
- const sourceDescriptionsOption = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
185
+ const sourceDescriptionsOption = options?.parse?.parserOpts?.[parserName]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
160
186
 
161
187
  // handle false or other falsy values - no source descriptions should be parsed
162
188
  if (!sourceDescriptionsOption) {
@@ -4,8 +4,10 @@ import { isSwaggerElement } from '@speclynx/apidom-ns-openapi-2';
4
4
  import { isOpenApi3_0Element } from '@speclynx/apidom-ns-openapi-3-0';
5
5
  import { isOpenApi3_1Element } from '@speclynx/apidom-ns-openapi-3-1';
6
6
  import { toValue } from '@speclynx/apidom-core';
7
+ import File from "../../../File.mjs";
7
8
  import * as url from "../../../util/url.mjs";
8
- import { merge as mergeOptions } from "../../../options/util.mjs"; // shared key for recursion state (works across JSON/YAML parsers)
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)
9
11
  const ARAZZO_RECURSION_KEY = 'arazzo-1';
10
12
  /**
11
13
  * Parses a single source description element.
@@ -14,7 +16,7 @@ const ARAZZO_RECURSION_KEY = 'arazzo-1';
14
16
  async function parseSourceDescription(sourceDescription, ctx) {
15
17
  const parseResult = new ParseResultElement();
16
18
  if (!isSourceDescriptionElement(sourceDescription)) {
17
- const annotation = new AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping.');
19
+ const annotation = new AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping');
18
20
  annotation.classes.push('warning');
19
21
  parseResult.push(annotation);
20
22
  return parseResult;
@@ -26,7 +28,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
26
28
  if (isStringElement(sourceDescription.type)) parseResult.setMetaProperty('type', cloneDeep(sourceDescription.type));
27
29
  const sourceDescriptionURI = toValue(sourceDescription.url);
28
30
  if (typeof sourceDescriptionURI !== 'string') {
29
- const annotation = new AnnotationElement('Source description URL is missing or not a string. Skipping.');
31
+ const annotation = new AnnotationElement('Source description URL is missing or not a string. Skipping');
30
32
  annotation.classes.push('warning');
31
33
  parseResult.push(annotation);
32
34
  return parseResult;
@@ -35,14 +37,14 @@ async function parseSourceDescription(sourceDescription, ctx) {
35
37
 
36
38
  // skip if already visited (cycle detection)
37
39
  if (ctx.visitedUrls.has(retrievalURI)) {
38
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle.`);
40
+ const annotation = new AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle`);
39
41
  annotation.classes.push('warning');
40
42
  parseResult.push(annotation);
41
43
  return parseResult;
42
44
  }
43
45
  ctx.visitedUrls.add(retrievalURI);
44
46
  try {
45
- const sdParseResult = await ctx.parseFn(retrievalURI, mergeOptions(ctx.options, {
47
+ const sourceDescriptionParseResult = await parse(retrievalURI, mergeOptions(ctx.options, {
46
48
  parse: {
47
49
  mediaType: 'text/plain',
48
50
  // allow parser plugin detection
@@ -55,7 +57,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
55
57
  }
56
58
  }));
57
59
  // merge parsed result into our parse result
58
- for (const item of sdParseResult) {
60
+ for (const item of sourceDescriptionParseResult) {
59
61
  parseResult.push(item);
60
62
  }
61
63
  } catch (error) {
@@ -74,7 +76,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
74
76
  const isOpenApi = isSwaggerElement(sourceDescriptionAPI) || isOpenApi3_0Element(sourceDescriptionAPI) || isOpenApi3_1Element(sourceDescriptionAPI);
75
77
  const isArazzo = isArazzoSpecification1Element(sourceDescriptionAPI);
76
78
  if (!isOpenApi && !isArazzo) {
77
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document. Skipping.`);
79
+ const annotation = new AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document`);
78
80
  annotation.classes.push('warning');
79
81
  parseResult.push(annotation);
80
82
  return parseResult;
@@ -84,11 +86,11 @@ async function parseSourceDescription(sourceDescription, ctx) {
84
86
  const declaredType = toValue(sourceDescription.type);
85
87
  if (typeof declaredType === 'string') {
86
88
  if (declaredType === 'openapi' && !isOpenApi) {
87
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document.`);
89
+ const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document`);
88
90
  annotation.classes.push('warning');
89
91
  parseResult.push(annotation);
90
92
  } else if (declaredType === 'arazzo' && !isArazzo) {
91
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document.`);
93
+ const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document`);
92
94
  annotation.classes.push('warning');
93
95
  parseResult.push(annotation);
94
96
  }
@@ -97,11 +99,40 @@ async function parseSourceDescription(sourceDescription, ctx) {
97
99
  }
98
100
 
99
101
  /**
100
- * Shared function for parsing source descriptions.
101
- * Call with `.call(this, ...)` where `this` has `name` and `parseFn` properties.
102
+ * Parses source descriptions from an Arazzo document's ParseResult.
103
+ *
104
+ * @param parseResult - ParseResult containing an Arazzo specification
105
+ * @param parseResultRetrievalURI - URI from which the parseResult was retrieved
106
+ * @param options - Full ReferenceOptions (caller responsibility to construct)
107
+ * @param parserName - Parser name for options lookup (defaults to 'arazzo-json-1')
108
+ * @returns Array of ParseResultElements. On success, returns one ParseResultElement per
109
+ * source description (each with class 'source-description' and name/type metadata).
110
+ * May return early with a single-element array containing a warning annotation when:
111
+ * - The API is not an Arazzo specification
112
+ * - The sourceDescriptions field is missing or not an array
113
+ * - Maximum parse depth is exceeded (error annotation)
114
+ * Returns an empty array when sourceDescriptions option is disabled or no names match.
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * import { options, mergeOptions } from '@speclynx/apidom-reference';
119
+ * import { parseSourceDescriptions } from '@speclynx/apidom-reference/parse/parsers/arazzo-json-1';
120
+ *
121
+ * const fullOptions = mergeOptions(options, {
122
+ * parse: { parserOpts: { sourceDescriptions: true } }
123
+ * });
124
+ * const results = await parseSourceDescriptions(parseResult, uri, fullOptions);
125
+ * ```
126
+ *
102
127
  * @public
103
128
  */
104
- export async function parseSourceDescriptions(api, file, options) {
129
+ export async function parseSourceDescriptions(parseResult, parseResultRetrievalURI, options, parserName = 'arazzo-json-1') {
130
+ const {
131
+ api
132
+ } = parseResult;
133
+ const file = new File({
134
+ uri: url.sanitize(url.stripHash(parseResultRetrievalURI))
135
+ });
105
136
  const results = [];
106
137
 
107
138
  /**
@@ -109,23 +140,18 @@ export async function parseSourceDescriptions(api, file, options) {
109
140
  * Return warning annotations if validation fails.
110
141
  */
111
142
  if (!isArazzoSpecification1Element(api)) {
112
- const annotation = new AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification.');
143
+ const annotation = new AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification');
113
144
  annotation.classes.push('warning');
114
145
  return [new ParseResultElement([annotation])];
115
146
  }
116
147
  if (!isArrayElement(api.sourceDescriptions)) {
117
- const annotation = new AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array.');
148
+ const annotation = new AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array');
118
149
  annotation.classes.push('warning');
119
150
  return [new ParseResultElement([annotation])];
120
151
  }
121
- if (typeof this.parseFn !== 'function') {
122
- const annotation = new AnnotationElement('Source descriptions found but parseFn is not configured. Skipping source description parsing.');
123
- annotation.classes.push('error');
124
- return [new ParseResultElement([annotation])];
125
- }
126
152
 
127
153
  // user config: parser-specific options take precedence over global parserOpts
128
- const maxDepth = options?.parse?.parserOpts?.[this.name]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
154
+ const maxDepth = options?.parse?.parserOpts?.[parserName]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
129
155
 
130
156
  // recursion state comes from shared key (works across JSON/YAML)
131
157
  const sharedOpts = options?.parse?.parserOpts?.[ARAZZO_RECURSION_KEY] ?? {};
@@ -142,7 +168,6 @@ export async function parseSourceDescriptions(api, file, options) {
142
168
  return [parseResult];
143
169
  }
144
170
  const ctx = {
145
- parseFn: this.parseFn,
146
171
  baseURI: file.uri,
147
172
  options,
148
173
  currentDepth,
@@ -150,7 +175,7 @@ export async function parseSourceDescriptions(api, file, options) {
150
175
  };
151
176
 
152
177
  // determine which source descriptions to parse
153
- const sourceDescriptionsOption = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
178
+ const sourceDescriptionsOption = options?.parse?.parserOpts?.[parserName]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
154
179
 
155
180
  // handle false or other falsy values - no source descriptions should be parsed
156
181
  if (!sourceDescriptionsOption) {
@@ -7,7 +7,8 @@ var _ramda = require("ramda");
7
7
  var _apidomParserAdapterArazzoYaml = require("@speclynx/apidom-parser-adapter-arazzo-yaml-1");
8
8
  var _ParserError = _interopRequireDefault(require("../../../errors/ParserError.cjs"));
9
9
  var _Parser = _interopRequireDefault(require("../Parser.cjs"));
10
- var _sourceDescription = require("../arazzo-json-1/source-description.cjs");
10
+ var _sourceDescriptions = require("./source-descriptions.cjs");
11
+ exports.parseSourceDescriptions = _sourceDescriptions.parseSourceDescriptions;
11
12
  /**
12
13
  * @public
13
14
  */
@@ -17,10 +18,8 @@ var _sourceDescription = require("../arazzo-json-1/source-description.cjs");
17
18
  */
18
19
  class ArazzoYAML1Parser extends _Parser.default {
19
20
  refractorOpts;
20
- parseFn;
21
21
  constructor(options) {
22
22
  const {
23
- parseFn,
24
23
  fileExtensions = [],
25
24
  mediaTypes = _apidomParserAdapterArazzoYaml.mediaTypes,
26
25
  ...rest
@@ -31,7 +30,6 @@ class ArazzoYAML1Parser extends _Parser.default {
31
30
  fileExtensions,
32
31
  mediaTypes
33
32
  });
34
- this.parseFn = parseFn;
35
33
  }
36
34
  async canParse(file) {
37
35
  const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
@@ -50,7 +48,7 @@ class ArazzoYAML1Parser extends _Parser.default {
50
48
  const parseResult = await (0, _apidomParserAdapterArazzoYaml.parse)(source, parserOpts);
51
49
  const shouldParseSourceDescriptions = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
52
50
  if (shouldParseSourceDescriptions) {
53
- const sourceDescriptions = await _sourceDescription.parseSourceDescriptions.call(this, parseResult.api, file, options);
51
+ const sourceDescriptions = await (0, _sourceDescriptions.parseSourceDescriptions)(parseResult, file.uri, options, this.name);
54
52
  parseResult.push(...sourceDescriptions);
55
53
  }
56
54
  return parseResult;
@@ -2,7 +2,7 @@ import { pick } from 'ramda';
2
2
  import { parse, mediaTypes as ArazzoYAML1MediaTypes, detect } from '@speclynx/apidom-parser-adapter-arazzo-yaml-1';
3
3
  import ParserError from "../../../errors/ParserError.mjs";
4
4
  import Parser from "../Parser.mjs";
5
- import { parseSourceDescriptions } from "../arazzo-json-1/source-description.mjs";
5
+ import { parseSourceDescriptions } from "./source-descriptions.mjs";
6
6
  /**
7
7
  * @public
8
8
  */
@@ -11,10 +11,8 @@ import { parseSourceDescriptions } from "../arazzo-json-1/source-description.mjs
11
11
  */
12
12
  class ArazzoYAML1Parser extends Parser {
13
13
  refractorOpts;
14
- parseFn;
15
14
  constructor(options) {
16
15
  const {
17
- parseFn,
18
16
  fileExtensions = [],
19
17
  mediaTypes = ArazzoYAML1MediaTypes,
20
18
  ...rest
@@ -25,7 +23,6 @@ class ArazzoYAML1Parser extends Parser {
25
23
  fileExtensions,
26
24
  mediaTypes
27
25
  });
28
- this.parseFn = parseFn;
29
26
  }
30
27
  async canParse(file) {
31
28
  const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
@@ -44,7 +41,7 @@ class ArazzoYAML1Parser extends Parser {
44
41
  const parseResult = await parse(source, parserOpts);
45
42
  const shouldParseSourceDescriptions = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
46
43
  if (shouldParseSourceDescriptions) {
47
- const sourceDescriptions = await parseSourceDescriptions.call(this, parseResult.api, file, options);
44
+ const sourceDescriptions = await parseSourceDescriptions(parseResult, file.uri, options, this.name);
48
45
  parseResult.push(...sourceDescriptions);
49
46
  }
50
47
  return parseResult;
@@ -55,4 +52,5 @@ class ArazzoYAML1Parser extends Parser {
55
52
  }
56
53
  }
57
54
  }
55
+ export { parseSourceDescriptions } from "./source-descriptions.mjs";
58
56
  export default ArazzoYAML1Parser;
@@ -0,0 +1,12 @@
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;
@@ -0,0 +1,7 @@
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
+ };
@@ -18,7 +18,7 @@ class FileResolver extends _Resolver.default {
18
18
  return false;
19
19
  }
20
20
  read() {
21
- throw new _ResolverError.default('FileResolver is not intended to be used in browser context.');
21
+ throw new _ResolverError.default('FileResolver is not intended to be used in browser context');
22
22
  }
23
23
  }
24
24
  var _default = exports.default = FileResolver;
@@ -13,7 +13,7 @@ class FileResolver extends Resolver {
13
13
  return false;
14
14
  }
15
15
  read() {
16
- throw new ResolverError('FileResolver is not intended to be used in browser context.');
16
+ throw new ResolverError('FileResolver is not intended to be used in browser context');
17
17
  }
18
18
  }
19
19
  export default FileResolver;
@@ -0,0 +1,8 @@
1
+ import { ParseResultElement } from '@speclynx/apidom-datamodel';
2
+ import Reference from '../../../Reference.ts';
3
+ import type { ReferenceOptions } from '../../../options/index.ts';
4
+ /**
5
+ * Dereferences source descriptions from an Arazzo document.
6
+ * @public
7
+ */
8
+ export declare function dereferenceSourceDescriptions(parseResult: ParseResultElement, reference: Reference, options: ReferenceOptions): Promise<ParseResultElement[]>;
@@ -2,23 +2,21 @@ import { ParseResultElement } from '@speclynx/apidom-datamodel';
2
2
  import Parser, { ParserOptions } from '../Parser.ts';
3
3
  import File from '../../../File.ts';
4
4
  import type { ReferenceOptions } from '../../../options/index.ts';
5
- import type ParseFn from '../../index.ts';
6
5
  export type { default as Parser, ParserOptions } from '../Parser.ts';
7
6
  export type { default as File, FileOptions } from '../../../File.ts';
8
7
  /**
9
8
  * @public
10
9
  */
11
10
  export interface ArazzoJSON1ParserOptions extends Omit<ParserOptions, 'name'> {
12
- readonly parseFn?: typeof ParseFn;
13
11
  }
14
12
  /**
15
13
  * @public
16
14
  */
17
15
  declare class ArazzoJSON1Parser extends Parser {
18
16
  refractorOpts: object;
19
- parseFn?: typeof ParseFn;
20
17
  constructor(options?: ArazzoJSON1ParserOptions);
21
18
  canParse(file: File): Promise<boolean>;
22
19
  parse(file: File, options?: ReferenceOptions): Promise<ParseResultElement>;
23
20
  }
21
+ export { parseSourceDescriptions } from './source-descriptions.ts';
24
22
  export default ArazzoJSON1Parser;
@@ -0,0 +1,31 @@
1
+ import { ParseResultElement } from '@speclynx/apidom-datamodel';
2
+ import type { ReferenceOptions } from '../../../options/index.ts';
3
+ /**
4
+ * Parses source descriptions from an Arazzo document's ParseResult.
5
+ *
6
+ * @param parseResult - ParseResult containing an Arazzo specification
7
+ * @param parseResultRetrievalURI - URI from which the parseResult was retrieved
8
+ * @param options - Full ReferenceOptions (caller responsibility to construct)
9
+ * @param parserName - Parser name for options lookup (defaults to 'arazzo-json-1')
10
+ * @returns Array of ParseResultElements. On success, returns one ParseResultElement per
11
+ * source description (each with class 'source-description' and name/type metadata).
12
+ * May return early with a single-element array containing a warning annotation when:
13
+ * - The API is not an Arazzo specification
14
+ * - The sourceDescriptions field is missing or not an array
15
+ * - Maximum parse depth is exceeded (error annotation)
16
+ * Returns an empty array when sourceDescriptions option is disabled or no names match.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { options, mergeOptions } from '@speclynx/apidom-reference';
21
+ * import { parseSourceDescriptions } from '@speclynx/apidom-reference/parse/parsers/arazzo-json-1';
22
+ *
23
+ * const fullOptions = mergeOptions(options, {
24
+ * parse: { parserOpts: { sourceDescriptions: true } }
25
+ * });
26
+ * const results = await parseSourceDescriptions(parseResult, uri, fullOptions);
27
+ * ```
28
+ *
29
+ * @public
30
+ */
31
+ export declare function parseSourceDescriptions(parseResult: ParseResultElement, parseResultRetrievalURI: string, options: ReferenceOptions, parserName?: string): Promise<ParseResultElement[]>;
@@ -2,23 +2,21 @@ import { ParseResultElement } from '@speclynx/apidom-datamodel';
2
2
  import Parser, { ParserOptions } from '../Parser.ts';
3
3
  import File from '../../../File.ts';
4
4
  import type { ReferenceOptions } from '../../../options/index.ts';
5
- import type ParseFn from '../../index.ts';
6
5
  export type { default as Parser, ParserOptions } from '../Parser.ts';
7
6
  export type { default as File, FileOptions } from '../../../File.ts';
8
7
  /**
9
8
  * @public
10
9
  */
11
10
  export interface ArazzoYAML1ParserOptions extends Omit<ParserOptions, 'name'> {
12
- readonly parseFn?: typeof ParseFn;
13
11
  }
14
12
  /**
15
13
  * @public
16
14
  */
17
15
  declare class ArazzoYAML1Parser extends Parser {
18
16
  refractorOpts: object;
19
- parseFn?: typeof ParseFn;
20
17
  constructor(options?: ArazzoYAML1ParserOptions);
21
18
  canParse(file: File): Promise<boolean>;
22
19
  parse(file: File, options?: ReferenceOptions): Promise<ParseResultElement>;
23
20
  }
21
+ export { parseSourceDescriptions } from './source-descriptions.ts';
24
22
  export default ArazzoYAML1Parser;
@@ -0,0 +1,6 @@
1
+ import { ParseResultElement } from '@speclynx/apidom-datamodel';
2
+ import type { ReferenceOptions } from '../../../options/index.ts';
3
+ /**
4
+ * @public
5
+ */
6
+ export declare const parseSourceDescriptions: (parseResult: ParseResultElement, parseResultRetrievalURI: string, options: ReferenceOptions, parserName?: string) => Promise<ParseResultElement[]>;
@@ -1,13 +0,0 @@
1
- import { Element, ParseResultElement } from '@speclynx/apidom-datamodel';
2
- import File from '../../../File.ts';
3
- import type { ReferenceOptions } from '../../../options/index.ts';
4
- import type ParseFn from '../../index.ts';
5
- /**
6
- * Shared function for parsing source descriptions.
7
- * Call with `.call(this, ...)` where `this` has `name` and `parseFn` properties.
8
- * @public
9
- */
10
- export declare function parseSourceDescriptions(this: {
11
- name: string;
12
- parseFn?: typeof ParseFn;
13
- }, api: Element | undefined, file: File, options: ReferenceOptions): Promise<ParseResultElement[]>;