@speclynx/apidom-reference 2.6.0 → 2.7.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 (56) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +60 -33
  3. package/dist/apidom-reference.browser.js +79395 -79177
  4. package/dist/apidom-reference.browser.min.js +1 -1
  5. package/package.json +25 -25
  6. package/src/bundle/index.cjs +1 -1
  7. package/src/bundle/index.mjs +1 -1
  8. package/src/configuration/saturated.cjs +2 -4
  9. package/src/configuration/saturated.mjs +3 -5
  10. package/src/dereference/index.cjs +1 -1
  11. package/src/dereference/index.mjs +1 -1
  12. package/src/dereference/strategies/arazzo-1/index.cjs +10 -0
  13. package/src/dereference/strategies/arazzo-1/index.mjs +10 -0
  14. package/src/dereference/strategies/arazzo-1/source-description.cjs +179 -0
  15. package/src/dereference/strategies/arazzo-1/source-description.mjs +172 -0
  16. package/src/dereference/strategies/openapi-3-0/visitor.cjs +3 -3
  17. package/src/dereference/strategies/openapi-3-0/visitor.mjs +3 -3
  18. package/src/dereference/strategies/openapi-3-1/visitor.cjs +3 -3
  19. package/src/dereference/strategies/openapi-3-1/visitor.mjs +3 -3
  20. package/src/errors/InvalidJsonSchema$anchorError.cjs +1 -1
  21. package/src/errors/InvalidJsonSchema$anchorError.mjs +1 -1
  22. package/src/errors/UnmatchedParserError.cjs +11 -0
  23. package/src/errors/UnmatchedParserError.mjs +6 -0
  24. package/src/index.cjs +3 -1
  25. package/src/index.mjs +1 -0
  26. package/src/parse/index.cjs +3 -3
  27. package/src/parse/index.mjs +3 -3
  28. package/src/parse/parsers/arazzo-json-1/index.cjs +1 -4
  29. package/src/parse/parsers/arazzo-json-1/index.mjs +1 -4
  30. package/src/parse/parsers/arazzo-json-1/source-description.cjs +14 -19
  31. package/src/parse/parsers/arazzo-json-1/source-description.mjs +14 -20
  32. package/src/parse/parsers/arazzo-yaml-1/index.cjs +1 -4
  33. package/src/parse/parsers/arazzo-yaml-1/index.mjs +1 -4
  34. package/src/resolve/index.cjs +2 -2
  35. package/src/resolve/index.mjs +2 -2
  36. package/src/resolve/resolvers/file/index-browser.cjs +1 -1
  37. package/src/resolve/resolvers/file/index-browser.mjs +1 -1
  38. package/src/resolve/strategies/apidom/index.cjs +1 -1
  39. package/src/resolve/strategies/apidom/index.mjs +1 -1
  40. package/src/resolve/strategies/asyncapi-2/index.cjs +1 -1
  41. package/src/resolve/strategies/asyncapi-2/index.mjs +1 -1
  42. package/src/resolve/strategies/openapi-2/index.cjs +1 -1
  43. package/src/resolve/strategies/openapi-2/index.mjs +1 -1
  44. package/src/resolve/strategies/openapi-3-0/index.cjs +1 -1
  45. package/src/resolve/strategies/openapi-3-0/index.mjs +1 -1
  46. package/src/resolve/strategies/openapi-3-1/index.cjs +1 -1
  47. package/src/resolve/strategies/openapi-3-1/index.mjs +1 -1
  48. package/src/resolve/util.cjs +1 -1
  49. package/src/resolve/util.mjs +1 -1
  50. package/types/apidom-reference.d.ts +6 -0
  51. package/types/dereference/strategies/arazzo-1/source-description.d.ts +8 -0
  52. package/types/errors/UnmatchedParserError.d.ts +7 -0
  53. package/types/index.d.ts +1 -0
  54. package/types/parse/parsers/arazzo-json-1/index.d.ts +0 -3
  55. package/types/parse/parsers/arazzo-json-1/source-description.d.ts +1 -6
  56. package/types/parse/parsers/arazzo-yaml-1/index.d.ts +0 -3
@@ -405,7 +405,7 @@ class OpenAPI3_1DereferenceVisitor {
405
405
 
406
406
  // operationRef and operationId fields are mutually exclusive
407
407
  if (isStringElement(linkElement.operationRef) && isStringElement(linkElement.operationId)) {
408
- throw new ApiDOMError('LinkElement operationRef and operationId fields are mutually exclusive.');
408
+ throw new ApiDOMError('LinkElement operationRef and operationId fields are mutually exclusive');
409
409
  }
410
410
  let operationElement;
411
411
  if (isStringElement(linkElement.operationRef)) {
@@ -456,7 +456,7 @@ class OpenAPI3_1DereferenceVisitor {
456
456
  operationElement = find(reference.value.result, e => isOperationElement(e) && isElement(e.operationId) && e.operationId.equals(operationId));
457
457
  // OperationElement not found by its operationId
458
458
  if (isUndefined(operationElement)) {
459
- throw new ApiDOMError(`OperationElement(operationId=${operationId}) not found.`);
459
+ throw new ApiDOMError(`OperationElement(operationId=${operationId}) not found`);
460
460
  }
461
461
  const linkElementCopy = cloneShallow(linkElement);
462
462
  linkElementCopy.operationId?.meta.set('operation', operationElement);
@@ -477,7 +477,7 @@ class OpenAPI3_1DereferenceVisitor {
477
477
 
478
478
  // value and externalValue fields are mutually exclusive
479
479
  if (exampleElement.hasKey('value') && isStringElement(exampleElement.externalValue)) {
480
- throw new ApiDOMError('ExampleElement value and externalValue fields are mutually exclusive.');
480
+ throw new ApiDOMError('ExampleElement value and externalValue fields are mutually exclusive');
481
481
  }
482
482
  const retrievalURI = this.toBaseURI(toValue(exampleElement.externalValue));
483
483
  const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
@@ -9,7 +9,7 @@ var _JsonSchema$anchorError = _interopRequireDefault(require("./JsonSchema$ancho
9
9
  */
10
10
  class InvalidJsonSchema$anchorError extends _JsonSchema$anchorError.default {
11
11
  constructor(anchor) {
12
- super(`Invalid JSON Schema $anchor "${anchor}".`);
12
+ super(`Invalid JSON Schema $anchor "${anchor}"`);
13
13
  }
14
14
  }
15
15
  var _default = exports.default = InvalidJsonSchema$anchorError;
@@ -4,7 +4,7 @@ import JsonSchema$anchorError from "./JsonSchema$anchorError.mjs";
4
4
  */
5
5
  class InvalidJsonSchema$anchorError extends JsonSchema$anchorError {
6
6
  constructor(anchor) {
7
- super(`Invalid JSON Schema $anchor "${anchor}".`);
7
+ super(`Invalid JSON Schema $anchor "${anchor}"`);
8
8
  }
9
9
  }
10
10
  export default InvalidJsonSchema$anchorError;
@@ -0,0 +1,11 @@
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 _ParserError = _interopRequireDefault(require("./ParserError.cjs"));
7
+ /**
8
+ * @public
9
+ */
10
+ class UnmatchedParserError extends _ParserError.default {}
11
+ var _default = exports.default = UnmatchedParserError;
@@ -0,0 +1,6 @@
1
+ import ParserError from "./ParserError.mjs";
2
+ /**
3
+ * @public
4
+ */
5
+ class UnmatchedParserError extends ParserError {}
6
+ export default UnmatchedParserError;
package/src/index.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
4
4
  var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
5
5
  exports.__esModule = true;
6
- exports.url = exports.resolveApiDOM = exports.resolve = exports.readFile = exports.parse = exports.options = exports.mergeOptions = exports.dereferenceApiDOM = exports.dereference = exports.bundle = exports.UnmatchedResolverError = exports.UnmatchedResolveStrategyError = exports.UnmatchedDereferenceStrategyError = exports.UnmatchedBundleStrategyError = exports.ResolverError = exports.Resolver = exports.ResolveStrategy = exports.ResolveError = exports.Reference = exports.PluginError = exports.ParserError = exports.Parser = exports.ParseError = exports.MaximumResolveDepthError = exports.MaximumDereferenceDepthError = exports.MaximumBundleDepthError = exports.JsonSchemaURIError = exports.JsonSchema$anchorError = exports.InvalidJsonSchema$anchorError = exports.HTTPResolver = exports.EvaluationJsonSchemaUriError = exports.EvaluationJsonSchema$anchorError = exports.EvaluationElementIdError = exports.DereferenceStrategy = exports.DereferenceError = exports.DereferenceAncestorLineage = exports.BundleStrategy = exports.BundleError = void 0;
6
+ exports.url = exports.resolveApiDOM = exports.resolve = exports.readFile = exports.parse = exports.options = exports.mergeOptions = exports.dereferenceApiDOM = exports.dereference = exports.bundle = exports.UnmatchedResolverError = exports.UnmatchedResolveStrategyError = exports.UnmatchedParserError = exports.UnmatchedDereferenceStrategyError = exports.UnmatchedBundleStrategyError = exports.ResolverError = exports.Resolver = exports.ResolveStrategy = exports.ResolveError = exports.Reference = exports.PluginError = exports.ParserError = exports.Parser = exports.ParseError = exports.MaximumResolveDepthError = exports.MaximumDereferenceDepthError = exports.MaximumBundleDepthError = exports.JsonSchemaURIError = exports.JsonSchema$anchorError = exports.InvalidJsonSchema$anchorError = exports.HTTPResolver = exports.EvaluationJsonSchemaUriError = exports.EvaluationJsonSchema$anchorError = exports.EvaluationElementIdError = exports.DereferenceStrategy = exports.DereferenceError = exports.DereferenceAncestorLineage = exports.BundleStrategy = exports.BundleError = void 0;
7
7
  var _File = _interopRequireDefault(require("./File.cjs"));
8
8
  exports.File = _File.default;
9
9
  var _ReferenceSet = _interopRequireDefault(require("./ReferenceSet.cjs"));
@@ -75,6 +75,8 @@ var _UnmatchedResolveStrategyError = _interopRequireDefault(require("./errors/Un
75
75
  exports.UnmatchedResolveStrategyError = _UnmatchedResolveStrategyError.default;
76
76
  var _UnmatchedResolverError = _interopRequireDefault(require("./errors/UnmatchedResolverError.cjs"));
77
77
  exports.UnmatchedResolverError = _UnmatchedResolverError.default;
78
+ var _UnmatchedParserError = _interopRequireDefault(require("./errors/UnmatchedParserError.cjs"));
79
+ exports.UnmatchedParserError = _UnmatchedParserError.default;
78
80
  /**
79
81
  * @public
80
82
  */
package/src/index.mjs CHANGED
@@ -41,6 +41,7 @@ export { default as ResolverError } from "./errors/ResolverError.mjs";
41
41
  export { default as UnmatchedDereferenceStrategyError } from "./errors/UnmatchedDereferenceStrategyError.mjs";
42
42
  export { default as UnmatchedResolveStrategyError } from "./errors/UnmatchedResolveStrategyError.mjs";
43
43
  export { default as UnmatchedResolverError } from "./errors/UnmatchedResolverError.mjs";
44
+ export { default as UnmatchedParserError } from "./errors/UnmatchedParserError.mjs";
44
45
  /**
45
46
  * @public
46
47
  */
@@ -9,7 +9,7 @@ var url = _interopRequireWildcard(require("../util/url.cjs"));
9
9
  var _File = _interopRequireDefault(require("../File.cjs"));
10
10
  var plugins = _interopRequireWildcard(require("../util/plugins.cjs"));
11
11
  var _ParseError = _interopRequireDefault(require("../errors/ParseError.cjs"));
12
- var _UnmatchedResolverError = _interopRequireDefault(require("../errors/UnmatchedResolverError.cjs"));
12
+ var _UnmatchedParserError = _interopRequireDefault(require("../errors/UnmatchedParserError.cjs"));
13
13
  var _util = require("../resolve/util.cjs");
14
14
  /**
15
15
  * Parses the given file's contents, using the configured parser plugins.
@@ -23,7 +23,7 @@ const parseFile = async (file, options) => {
23
23
 
24
24
  // we couldn't find any parser for this File
25
25
  if ((0, _ramda.isEmpty)(parsers)) {
26
- throw new _UnmatchedResolverError.default(file.uri);
26
+ throw new _UnmatchedParserError.default(`Could not find a parser that can parse the file "${file.uri}"`);
27
27
  }
28
28
  try {
29
29
  const {
@@ -33,7 +33,7 @@ const parseFile = async (file, options) => {
33
33
 
34
34
  // empty files handling
35
35
  if (!plugin.allowEmpty && result.isEmpty) {
36
- return Promise.reject(new _ParseError.default(`Error while parsing file "${file.uri}". File is empty.`));
36
+ return Promise.reject(new _ParseError.default(`Error while parsing file "${file.uri}": file is empty`));
37
37
  }
38
38
  return result;
39
39
  } catch (error) {
@@ -3,7 +3,7 @@ import * as url from "../util/url.mjs";
3
3
  import File from "../File.mjs";
4
4
  import * as plugins from "../util/plugins.mjs";
5
5
  import ParseError from "../errors/ParseError.mjs";
6
- import UnmatchedResolverError from "../errors/UnmatchedResolverError.mjs";
6
+ import UnmatchedParserError from "../errors/UnmatchedParserError.mjs";
7
7
  import { readFile } from "../resolve/util.mjs";
8
8
  /**
9
9
  * Parses the given file's contents, using the configured parser plugins.
@@ -17,7 +17,7 @@ const parseFile = async (file, options) => {
17
17
 
18
18
  // we couldn't find any parser for this File
19
19
  if (isEmpty(parsers)) {
20
- throw new UnmatchedResolverError(file.uri);
20
+ throw new UnmatchedParserError(`Could not find a parser that can parse the file "${file.uri}"`);
21
21
  }
22
22
  try {
23
23
  const {
@@ -27,7 +27,7 @@ const parseFile = async (file, options) => {
27
27
 
28
28
  // empty files handling
29
29
  if (!plugin.allowEmpty && result.isEmpty) {
30
- return Promise.reject(new ParseError(`Error while parsing file "${file.uri}". File is empty.`));
30
+ return Promise.reject(new ParseError(`Error while parsing file "${file.uri}": file is empty`));
31
31
  }
32
32
  return result;
33
33
  } catch (error) {
@@ -17,10 +17,8 @@ var _sourceDescription = require("./source-description.cjs");
17
17
  */
18
18
  class ArazzoJSON1Parser extends _Parser.default {
19
19
  refractorOpts;
20
- parseFn;
21
20
  constructor(options) {
22
21
  const {
23
- parseFn,
24
22
  fileExtensions = [],
25
23
  mediaTypes = _apidomParserAdapterArazzoJson.mediaTypes,
26
24
  ...rest
@@ -31,7 +29,6 @@ class ArazzoJSON1Parser extends _Parser.default {
31
29
  fileExtensions,
32
30
  mediaTypes
33
31
  });
34
- this.parseFn = parseFn;
35
32
  }
36
33
  async canParse(file) {
37
34
  const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
@@ -50,7 +47,7 @@ class ArazzoJSON1Parser extends _Parser.default {
50
47
  const parseResult = await (0, _apidomParserAdapterArazzoJson.parse)(source, parserOpts);
51
48
  const shouldParseSourceDescriptions = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
52
49
  if (shouldParseSourceDescriptions) {
53
- const sourceDescriptions = await _sourceDescription.parseSourceDescriptions.call(this, parseResult.api, file, options);
50
+ const sourceDescriptions = await (0, _sourceDescription.parseSourceDescriptions)(this.name, parseResult.api, file, options);
54
51
  parseResult.push(...sourceDescriptions);
55
52
  }
56
53
  return parseResult;
@@ -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(this.name, parseResult.api, file, options);
48
45
  parseResult.push(...sourceDescriptions);
49
46
  }
50
47
  return parseResult;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
3
4
  var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
4
5
  exports.__esModule = true;
5
6
  exports.parseSourceDescriptions = parseSourceDescriptions;
@@ -11,6 +12,7 @@ var _apidomNsOpenapi3 = require("@speclynx/apidom-ns-openapi-3-1");
11
12
  var _apidomCore = require("@speclynx/apidom-core");
12
13
  var url = _interopRequireWildcard(require("../../../util/url.cjs"));
13
14
  var _util = require("../../../options/util.cjs");
15
+ var _index = _interopRequireDefault(require("../../index.cjs"));
14
16
  // shared key for recursion state (works across JSON/YAML parsers)
15
17
  const ARAZZO_RECURSION_KEY = 'arazzo-1';
16
18
  /**
@@ -20,7 +22,7 @@ const ARAZZO_RECURSION_KEY = 'arazzo-1';
20
22
  async function parseSourceDescription(sourceDescription, ctx) {
21
23
  const parseResult = new _apidomDatamodel.ParseResultElement();
22
24
  if (!(0, _apidomNsArazzo.isSourceDescriptionElement)(sourceDescription)) {
23
- const annotation = new _apidomDatamodel.AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping.');
25
+ const annotation = new _apidomDatamodel.AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping');
24
26
  annotation.classes.push('warning');
25
27
  parseResult.push(annotation);
26
28
  return parseResult;
@@ -32,7 +34,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
32
34
  if ((0, _apidomDatamodel.isStringElement)(sourceDescription.type)) parseResult.setMetaProperty('type', (0, _apidomDatamodel.cloneDeep)(sourceDescription.type));
33
35
  const sourceDescriptionURI = (0, _apidomCore.toValue)(sourceDescription.url);
34
36
  if (typeof sourceDescriptionURI !== 'string') {
35
- const annotation = new _apidomDatamodel.AnnotationElement('Source description URL is missing or not a string. Skipping.');
37
+ const annotation = new _apidomDatamodel.AnnotationElement('Source description URL is missing or not a string. Skipping');
36
38
  annotation.classes.push('warning');
37
39
  parseResult.push(annotation);
38
40
  return parseResult;
@@ -41,14 +43,14 @@ async function parseSourceDescription(sourceDescription, ctx) {
41
43
 
42
44
  // skip if already visited (cycle detection)
43
45
  if (ctx.visitedUrls.has(retrievalURI)) {
44
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle.`);
46
+ const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle`);
45
47
  annotation.classes.push('warning');
46
48
  parseResult.push(annotation);
47
49
  return parseResult;
48
50
  }
49
51
  ctx.visitedUrls.add(retrievalURI);
50
52
  try {
51
- const sdParseResult = await ctx.parseFn(retrievalURI, (0, _util.merge)(ctx.options, {
53
+ const sdParseResult = await (0, _index.default)(retrievalURI, (0, _util.merge)(ctx.options, {
52
54
  parse: {
53
55
  mediaType: 'text/plain',
54
56
  // allow parser plugin detection
@@ -80,7 +82,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
80
82
  const isOpenApi = (0, _apidomNsOpenapi.isSwaggerElement)(sourceDescriptionAPI) || (0, _apidomNsOpenapi2.isOpenApi3_0Element)(sourceDescriptionAPI) || (0, _apidomNsOpenapi3.isOpenApi3_1Element)(sourceDescriptionAPI);
81
83
  const isArazzo = (0, _apidomNsArazzo.isArazzoSpecification1Element)(sourceDescriptionAPI);
82
84
  if (!isOpenApi && !isArazzo) {
83
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document. Skipping.`);
85
+ const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document`);
84
86
  annotation.classes.push('warning');
85
87
  parseResult.push(annotation);
86
88
  return parseResult;
@@ -90,11 +92,11 @@ async function parseSourceDescription(sourceDescription, ctx) {
90
92
  const declaredType = (0, _apidomCore.toValue)(sourceDescription.type);
91
93
  if (typeof declaredType === 'string') {
92
94
  if (declaredType === 'openapi' && !isOpenApi) {
93
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document.`);
95
+ const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document`);
94
96
  annotation.classes.push('warning');
95
97
  parseResult.push(annotation);
96
98
  } else if (declaredType === 'arazzo' && !isArazzo) {
97
- const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document.`);
99
+ const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document`);
98
100
  annotation.classes.push('warning');
99
101
  parseResult.push(annotation);
100
102
  }
@@ -104,10 +106,9 @@ async function parseSourceDescription(sourceDescription, ctx) {
104
106
 
105
107
  /**
106
108
  * Shared function for parsing source descriptions.
107
- * Call with `.call(this, ...)` where `this` has `name` and `parseFn` properties.
108
109
  * @public
109
110
  */
110
- async function parseSourceDescriptions(api, file, options) {
111
+ async function parseSourceDescriptions(parserName, api, file, options) {
111
112
  const results = [];
112
113
 
113
114
  /**
@@ -115,23 +116,18 @@ async function parseSourceDescriptions(api, file, options) {
115
116
  * Return warning annotations if validation fails.
116
117
  */
117
118
  if (!(0, _apidomNsArazzo.isArazzoSpecification1Element)(api)) {
118
- const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification.');
119
+ const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification');
119
120
  annotation.classes.push('warning');
120
121
  return [new _apidomDatamodel.ParseResultElement([annotation])];
121
122
  }
122
123
  if (!(0, _apidomDatamodel.isArrayElement)(api.sourceDescriptions)) {
123
- const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array.');
124
+ const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array');
124
125
  annotation.classes.push('warning');
125
126
  return [new _apidomDatamodel.ParseResultElement([annotation])];
126
127
  }
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
128
 
133
129
  // user config: parser-specific options take precedence over global parserOpts
134
- const maxDepth = options?.parse?.parserOpts?.[this.name]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
130
+ const maxDepth = options?.parse?.parserOpts?.[parserName]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
135
131
 
136
132
  // recursion state comes from shared key (works across JSON/YAML)
137
133
  const sharedOpts = options?.parse?.parserOpts?.[ARAZZO_RECURSION_KEY] ?? {};
@@ -148,7 +144,6 @@ async function parseSourceDescriptions(api, file, options) {
148
144
  return [parseResult];
149
145
  }
150
146
  const ctx = {
151
- parseFn: this.parseFn,
152
147
  baseURI: file.uri,
153
148
  options,
154
149
  currentDepth,
@@ -156,7 +151,7 @@ async function parseSourceDescriptions(api, file, options) {
156
151
  };
157
152
 
158
153
  // determine which source descriptions to parse
159
- const sourceDescriptionsOption = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
154
+ const sourceDescriptionsOption = options?.parse?.parserOpts?.[parserName]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
160
155
 
161
156
  // handle false or other falsy values - no source descriptions should be parsed
162
157
  if (!sourceDescriptionsOption) {
@@ -5,7 +5,8 @@ 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
7
  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)
8
+ import { merge as mergeOptions } from "../../../options/util.mjs";
9
+ import parse from "../../index.mjs"; // shared key for recursion state (works across JSON/YAML parsers)
9
10
  const ARAZZO_RECURSION_KEY = 'arazzo-1';
10
11
  /**
11
12
  * Parses a single source description element.
@@ -14,7 +15,7 @@ const ARAZZO_RECURSION_KEY = 'arazzo-1';
14
15
  async function parseSourceDescription(sourceDescription, ctx) {
15
16
  const parseResult = new ParseResultElement();
16
17
  if (!isSourceDescriptionElement(sourceDescription)) {
17
- const annotation = new AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping.');
18
+ const annotation = new AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping');
18
19
  annotation.classes.push('warning');
19
20
  parseResult.push(annotation);
20
21
  return parseResult;
@@ -26,7 +27,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
26
27
  if (isStringElement(sourceDescription.type)) parseResult.setMetaProperty('type', cloneDeep(sourceDescription.type));
27
28
  const sourceDescriptionURI = toValue(sourceDescription.url);
28
29
  if (typeof sourceDescriptionURI !== 'string') {
29
- const annotation = new AnnotationElement('Source description URL is missing or not a string. Skipping.');
30
+ const annotation = new AnnotationElement('Source description URL is missing or not a string. Skipping');
30
31
  annotation.classes.push('warning');
31
32
  parseResult.push(annotation);
32
33
  return parseResult;
@@ -35,14 +36,14 @@ async function parseSourceDescription(sourceDescription, ctx) {
35
36
 
36
37
  // skip if already visited (cycle detection)
37
38
  if (ctx.visitedUrls.has(retrievalURI)) {
38
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle.`);
39
+ const annotation = new AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle`);
39
40
  annotation.classes.push('warning');
40
41
  parseResult.push(annotation);
41
42
  return parseResult;
42
43
  }
43
44
  ctx.visitedUrls.add(retrievalURI);
44
45
  try {
45
- const sdParseResult = await ctx.parseFn(retrievalURI, mergeOptions(ctx.options, {
46
+ const sdParseResult = await parse(retrievalURI, mergeOptions(ctx.options, {
46
47
  parse: {
47
48
  mediaType: 'text/plain',
48
49
  // allow parser plugin detection
@@ -74,7 +75,7 @@ async function parseSourceDescription(sourceDescription, ctx) {
74
75
  const isOpenApi = isSwaggerElement(sourceDescriptionAPI) || isOpenApi3_0Element(sourceDescriptionAPI) || isOpenApi3_1Element(sourceDescriptionAPI);
75
76
  const isArazzo = isArazzoSpecification1Element(sourceDescriptionAPI);
76
77
  if (!isOpenApi && !isArazzo) {
77
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document. Skipping.`);
78
+ const annotation = new AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document`);
78
79
  annotation.classes.push('warning');
79
80
  parseResult.push(annotation);
80
81
  return parseResult;
@@ -84,11 +85,11 @@ async function parseSourceDescription(sourceDescription, ctx) {
84
85
  const declaredType = toValue(sourceDescription.type);
85
86
  if (typeof declaredType === 'string') {
86
87
  if (declaredType === 'openapi' && !isOpenApi) {
87
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document.`);
88
+ const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document`);
88
89
  annotation.classes.push('warning');
89
90
  parseResult.push(annotation);
90
91
  } else if (declaredType === 'arazzo' && !isArazzo) {
91
- const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document.`);
92
+ const annotation = new AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document`);
92
93
  annotation.classes.push('warning');
93
94
  parseResult.push(annotation);
94
95
  }
@@ -98,10 +99,9 @@ async function parseSourceDescription(sourceDescription, ctx) {
98
99
 
99
100
  /**
100
101
  * Shared function for parsing source descriptions.
101
- * Call with `.call(this, ...)` where `this` has `name` and `parseFn` properties.
102
102
  * @public
103
103
  */
104
- export async function parseSourceDescriptions(api, file, options) {
104
+ export async function parseSourceDescriptions(parserName, api, file, options) {
105
105
  const results = [];
106
106
 
107
107
  /**
@@ -109,23 +109,18 @@ export async function parseSourceDescriptions(api, file, options) {
109
109
  * Return warning annotations if validation fails.
110
110
  */
111
111
  if (!isArazzoSpecification1Element(api)) {
112
- const annotation = new AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification.');
112
+ const annotation = new AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification');
113
113
  annotation.classes.push('warning');
114
114
  return [new ParseResultElement([annotation])];
115
115
  }
116
116
  if (!isArrayElement(api.sourceDescriptions)) {
117
- const annotation = new AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array.');
117
+ const annotation = new AnnotationElement('Cannot parse source descriptions: sourceDescriptions field is missing or not an array');
118
118
  annotation.classes.push('warning');
119
119
  return [new ParseResultElement([annotation])];
120
120
  }
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
121
 
127
122
  // user config: parser-specific options take precedence over global parserOpts
128
- const maxDepth = options?.parse?.parserOpts?.[this.name]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
123
+ const maxDepth = options?.parse?.parserOpts?.[parserName]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
129
124
 
130
125
  // recursion state comes from shared key (works across JSON/YAML)
131
126
  const sharedOpts = options?.parse?.parserOpts?.[ARAZZO_RECURSION_KEY] ?? {};
@@ -142,7 +137,6 @@ export async function parseSourceDescriptions(api, file, options) {
142
137
  return [parseResult];
143
138
  }
144
139
  const ctx = {
145
- parseFn: this.parseFn,
146
140
  baseURI: file.uri,
147
141
  options,
148
142
  currentDepth,
@@ -150,7 +144,7 @@ export async function parseSourceDescriptions(api, file, options) {
150
144
  };
151
145
 
152
146
  // determine which source descriptions to parse
153
- const sourceDescriptionsOption = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
147
+ const sourceDescriptionsOption = options?.parse?.parserOpts?.[parserName]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
154
148
 
155
149
  // handle false or other falsy values - no source descriptions should be parsed
156
150
  if (!sourceDescriptionsOption) {
@@ -17,10 +17,8 @@ var _sourceDescription = require("../arazzo-json-1/source-description.cjs");
17
17
  */
18
18
  class ArazzoYAML1Parser extends _Parser.default {
19
19
  refractorOpts;
20
- parseFn;
21
20
  constructor(options) {
22
21
  const {
23
- parseFn,
24
22
  fileExtensions = [],
25
23
  mediaTypes = _apidomParserAdapterArazzoYaml.mediaTypes,
26
24
  ...rest
@@ -31,7 +29,6 @@ class ArazzoYAML1Parser extends _Parser.default {
31
29
  fileExtensions,
32
30
  mediaTypes
33
31
  });
34
- this.parseFn = parseFn;
35
32
  }
36
33
  async canParse(file) {
37
34
  const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
@@ -50,7 +47,7 @@ class ArazzoYAML1Parser extends _Parser.default {
50
47
  const parseResult = await (0, _apidomParserAdapterArazzoYaml.parse)(source, parserOpts);
51
48
  const shouldParseSourceDescriptions = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
52
49
  if (shouldParseSourceDescriptions) {
53
- const sourceDescriptions = await _sourceDescription.parseSourceDescriptions.call(this, parseResult.api, file, options);
50
+ const sourceDescriptions = await (0, _sourceDescription.parseSourceDescriptions)(this.name, parseResult.api, file, options);
54
51
  parseResult.push(...sourceDescriptions);
55
52
  }
56
53
  return parseResult;
@@ -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(this.name, parseResult.api, file, options);
48
45
  parseResult.push(...sourceDescriptions);
49
46
  }
50
47
  return parseResult;
@@ -35,9 +35,9 @@ const resolveApiDOM = async (element, options) => {
35
35
  });
36
36
  const resolveStrategies = await plugins.filter('canResolve', [file, options], options.resolve.strategies);
37
37
 
38
- // we couldn't find any resolver for this File
38
+ // we couldn't find any resolve strategy for this File
39
39
  if ((0, _ramda.isEmpty)(resolveStrategies)) {
40
- throw new _UnmatchedResolveStrategyError.default(file.uri);
40
+ throw new _UnmatchedResolveStrategyError.default(`Could not find a resolve strategy that can resolve the file "${file.uri}"`);
41
41
  }
42
42
  try {
43
43
  const {
@@ -29,9 +29,9 @@ export const resolveApiDOM = async (element, options) => {
29
29
  });
30
30
  const resolveStrategies = await plugins.filter('canResolve', [file, options], options.resolve.strategies);
31
31
 
32
- // we couldn't find any resolver for this File
32
+ // we couldn't find any resolve strategy for this File
33
33
  if (isEmpty(resolveStrategies)) {
34
- throw new UnmatchedResolveStrategyError(file.uri);
34
+ throw new UnmatchedResolveStrategyError(`Could not find a resolve strategy that can resolve the file "${file.uri}"`);
35
35
  }
36
36
  try {
37
37
  const {
@@ -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;
@@ -31,7 +31,7 @@ class ApiDOMResolveStrategy extends _ResolveStrategy.default {
31
31
  async resolve(file, options) {
32
32
  const dereferenceStrategy = options.dereference.strategies.find(strategy => strategy.name === 'apidom');
33
33
  if (dereferenceStrategy === undefined) {
34
- throw new _UnmatchedDereferenceStrategyError.default('"apidom" dereference strategy is not available.');
34
+ throw new _UnmatchedDereferenceStrategyError.default(`"apidom" resolve strategy requires "apidom" dereference strategy to be configured for file "${file.uri}"`);
35
35
  }
36
36
  const refSet = new _ReferenceSet.default();
37
37
  const mergedOptions = (0, _util.merge)(options, {
@@ -25,7 +25,7 @@ class ApiDOMResolveStrategy extends ResolveStrategy {
25
25
  async resolve(file, options) {
26
26
  const dereferenceStrategy = options.dereference.strategies.find(strategy => strategy.name === 'apidom');
27
27
  if (dereferenceStrategy === undefined) {
28
- throw new UnmatchedDereferenceStrategyError('"apidom" dereference strategy is not available.');
28
+ throw new UnmatchedDereferenceStrategyError(`"apidom" resolve strategy requires "apidom" dereference strategy to be configured for file "${file.uri}"`);
29
29
  }
30
30
  const refSet = new ReferenceSet();
31
31
  const mergedOptions = mergeOptions(options, {
@@ -31,7 +31,7 @@ class AsyncAPI2ResolveStrategy extends _ResolveStrategy.default {
31
31
  async resolve(file, options) {
32
32
  const dereferenceStrategy = options.dereference.strategies.find(strategy => strategy.name === 'asyncapi-2');
33
33
  if (dereferenceStrategy === undefined) {
34
- throw new _UnmatchedDereferenceStrategyError.default('"asyncapi-2" dereference strategy is not available.');
34
+ throw new _UnmatchedDereferenceStrategyError.default(`"asyncapi-2" resolve strategy requires "asyncapi-2" dereference strategy to be configured for file "${file.uri}"`);
35
35
  }
36
36
  const refSet = new _ReferenceSet.default();
37
37
  const mergedOptions = (0, _util.merge)(options, {
@@ -25,7 +25,7 @@ class AsyncAPI2ResolveStrategy extends ResolveStrategy {
25
25
  async resolve(file, options) {
26
26
  const dereferenceStrategy = options.dereference.strategies.find(strategy => strategy.name === 'asyncapi-2');
27
27
  if (dereferenceStrategy === undefined) {
28
- throw new UnmatchedDereferenceStrategyError('"asyncapi-2" dereference strategy is not available.');
28
+ throw new UnmatchedDereferenceStrategyError(`"asyncapi-2" resolve strategy requires "asyncapi-2" dereference strategy to be configured for file "${file.uri}"`);
29
29
  }
30
30
  const refSet = new ReferenceSet();
31
31
  const mergedOptions = mergeOptions(options, {
@@ -31,7 +31,7 @@ class OpenAPI2ResolveStrategy extends _ResolveStrategy.default {
31
31
  async resolve(file, options) {
32
32
  const dereferenceStrategy = options.dereference.strategies.find(strategy => strategy.name === 'openapi-2');
33
33
  if (dereferenceStrategy === undefined) {
34
- throw new _UnmatchedDereferenceStrategyError.default('"openapi-2" dereference strategy is not available.');
34
+ throw new _UnmatchedDereferenceStrategyError.default(`"openapi-2" resolve strategy requires "openapi-2" dereference strategy to be configured for file "${file.uri}"`);
35
35
  }
36
36
  const refSet = new _ReferenceSet.default();
37
37
  const mergedOptions = (0, _util.merge)(options, {
@@ -25,7 +25,7 @@ class OpenAPI2ResolveStrategy extends ResolveStrategy {
25
25
  async resolve(file, options) {
26
26
  const dereferenceStrategy = options.dereference.strategies.find(strategy => strategy.name === 'openapi-2');
27
27
  if (dereferenceStrategy === undefined) {
28
- throw new UnmatchedDereferenceStrategyError('"openapi-2" dereference strategy is not available.');
28
+ throw new UnmatchedDereferenceStrategyError(`"openapi-2" resolve strategy requires "openapi-2" dereference strategy to be configured for file "${file.uri}"`);
29
29
  }
30
30
  const refSet = new ReferenceSet();
31
31
  const mergedOptions = mergeOptions(options, {