@speclynx/apidom-reference 2.5.1 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +109 -6
- package/dist/apidom-reference.browser.js +78639 -78397
- package/dist/apidom-reference.browser.min.js +1 -1
- package/package.json +25 -25
- package/src/bundle/index.cjs +1 -1
- package/src/bundle/index.mjs +1 -1
- package/src/configuration/saturated.cjs +4 -2
- package/src/configuration/saturated.mjs +5 -3
- package/src/dereference/index.cjs +1 -1
- package/src/dereference/index.mjs +1 -1
- package/src/dereference/strategies/openapi-3-0/visitor.cjs +1 -1
- package/src/dereference/strategies/openapi-3-0/visitor.mjs +1 -1
- package/src/dereference/strategies/openapi-3-1/visitor.cjs +1 -1
- package/src/dereference/strategies/openapi-3-1/visitor.mjs +1 -1
- package/src/errors/InvalidJsonSchema$anchorError.cjs +1 -1
- package/src/errors/InvalidJsonSchema$anchorError.mjs +1 -1
- package/src/errors/UnmatchedParserError.cjs +11 -0
- package/src/errors/UnmatchedParserError.mjs +6 -0
- package/src/index.cjs +3 -1
- package/src/index.mjs +1 -0
- package/src/parse/index.cjs +3 -3
- package/src/parse/index.mjs +3 -3
- package/src/parse/parsers/arazzo-json-1/index.cjs +12 -2
- package/src/parse/parsers/arazzo-json-1/index.mjs +14 -4
- package/src/parse/parsers/arazzo-json-1/source-description.cjs +177 -0
- package/src/parse/parsers/arazzo-json-1/source-description.mjs +171 -0
- package/src/parse/parsers/arazzo-yaml-1/index.cjs +12 -2
- package/src/parse/parsers/arazzo-yaml-1/index.mjs +12 -2
- package/src/resolve/index.cjs +2 -2
- package/src/resolve/index.mjs +2 -2
- package/src/resolve/strategies/apidom/index.cjs +1 -1
- package/src/resolve/strategies/apidom/index.mjs +1 -1
- package/src/resolve/strategies/asyncapi-2/index.cjs +1 -1
- package/src/resolve/strategies/asyncapi-2/index.mjs +1 -1
- package/src/resolve/strategies/openapi-2/index.cjs +1 -1
- package/src/resolve/strategies/openapi-2/index.mjs +1 -1
- package/src/resolve/strategies/openapi-3-0/index.cjs +1 -1
- package/src/resolve/strategies/openapi-3-0/index.mjs +1 -1
- package/src/resolve/strategies/openapi-3-1/index.cjs +1 -1
- package/src/resolve/strategies/openapi-3-1/index.mjs +1 -1
- package/src/resolve/util.cjs +2 -2
- package/src/resolve/util.mjs +2 -2
- package/types/apidom-reference.d.ts +10 -4
- package/types/errors/UnmatchedParserError.d.ts +7 -0
- package/types/index.d.ts +1 -0
- package/types/parse/parsers/Parser.d.ts +3 -2
- package/types/parse/parsers/arazzo-json-1/index.d.ts +5 -1
- package/types/parse/parsers/arazzo-json-1/source-description.d.ts +13 -0
- package/types/parse/parsers/arazzo-yaml-1/index.d.ts +5 -1
- package/types/resolve/resolvers/Resolver.d.ts +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@speclynx/apidom-reference",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "Advanced algorithms for semantic ApiDOM manipulations like dereferencing or resolution.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -231,29 +231,29 @@
|
|
|
231
231
|
"license": "Apache-2.0",
|
|
232
232
|
"dependencies": {
|
|
233
233
|
"@babel/runtime-corejs3": "^7.28.4",
|
|
234
|
-
"@speclynx/apidom-core": "^2.
|
|
235
|
-
"@speclynx/apidom-datamodel": "^2.
|
|
236
|
-
"@speclynx/apidom-error": "^2.
|
|
237
|
-
"@speclynx/apidom-json-pointer": "^2.
|
|
238
|
-
"@speclynx/apidom-ns-arazzo-1": "^2.
|
|
239
|
-
"@speclynx/apidom-ns-asyncapi-2": "^2.
|
|
240
|
-
"@speclynx/apidom-ns-json-schema-2020-12": "^2.
|
|
241
|
-
"@speclynx/apidom-ns-openapi-2": "^2.
|
|
242
|
-
"@speclynx/apidom-ns-openapi-3-0": "^2.
|
|
243
|
-
"@speclynx/apidom-ns-openapi-3-1": "^2.
|
|
244
|
-
"@speclynx/apidom-parser-adapter-arazzo-json-1": "^2.
|
|
245
|
-
"@speclynx/apidom-parser-adapter-arazzo-yaml-1": "^2.
|
|
246
|
-
"@speclynx/apidom-parser-adapter-asyncapi-json-2": "^2.
|
|
247
|
-
"@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "^2.
|
|
248
|
-
"@speclynx/apidom-parser-adapter-json": "^2.
|
|
249
|
-
"@speclynx/apidom-parser-adapter-openapi-json-2": "^2.
|
|
250
|
-
"@speclynx/apidom-parser-adapter-openapi-json-3-0": "^2.
|
|
251
|
-
"@speclynx/apidom-parser-adapter-openapi-json-3-1": "^2.
|
|
252
|
-
"@speclynx/apidom-parser-adapter-openapi-yaml-2": "^2.
|
|
253
|
-
"@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "^2.
|
|
254
|
-
"@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "^2.
|
|
255
|
-
"@speclynx/apidom-parser-adapter-yaml-1-2": "^2.
|
|
256
|
-
"@speclynx/apidom-traverse": "^2.
|
|
234
|
+
"@speclynx/apidom-core": "^2.6.1",
|
|
235
|
+
"@speclynx/apidom-datamodel": "^2.6.1",
|
|
236
|
+
"@speclynx/apidom-error": "^2.6.1",
|
|
237
|
+
"@speclynx/apidom-json-pointer": "^2.6.1",
|
|
238
|
+
"@speclynx/apidom-ns-arazzo-1": "^2.6.1",
|
|
239
|
+
"@speclynx/apidom-ns-asyncapi-2": "^2.6.1",
|
|
240
|
+
"@speclynx/apidom-ns-json-schema-2020-12": "^2.6.1",
|
|
241
|
+
"@speclynx/apidom-ns-openapi-2": "^2.6.1",
|
|
242
|
+
"@speclynx/apidom-ns-openapi-3-0": "^2.6.1",
|
|
243
|
+
"@speclynx/apidom-ns-openapi-3-1": "^2.6.1",
|
|
244
|
+
"@speclynx/apidom-parser-adapter-arazzo-json-1": "^2.6.1",
|
|
245
|
+
"@speclynx/apidom-parser-adapter-arazzo-yaml-1": "^2.6.1",
|
|
246
|
+
"@speclynx/apidom-parser-adapter-asyncapi-json-2": "^2.6.1",
|
|
247
|
+
"@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "^2.6.1",
|
|
248
|
+
"@speclynx/apidom-parser-adapter-json": "^2.6.1",
|
|
249
|
+
"@speclynx/apidom-parser-adapter-openapi-json-2": "^2.6.1",
|
|
250
|
+
"@speclynx/apidom-parser-adapter-openapi-json-3-0": "^2.6.1",
|
|
251
|
+
"@speclynx/apidom-parser-adapter-openapi-json-3-1": "^2.6.1",
|
|
252
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-2": "^2.6.1",
|
|
253
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "^2.6.1",
|
|
254
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "^2.6.1",
|
|
255
|
+
"@speclynx/apidom-parser-adapter-yaml-1-2": "^2.6.1",
|
|
256
|
+
"@speclynx/apidom-traverse": "^2.6.1",
|
|
257
257
|
"@swaggerexpert/arazzo-runtime-expression": "^2.0.2",
|
|
258
258
|
"axios": "^1.13.0",
|
|
259
259
|
"minimatch": "^7.4.6",
|
|
@@ -274,5 +274,5 @@
|
|
|
274
274
|
"README.md",
|
|
275
275
|
"CHANGELOG.md"
|
|
276
276
|
],
|
|
277
|
-
"gitHead": "
|
|
277
|
+
"gitHead": "bac6186b9bca75fd7deac283c3fb042559eea5fb"
|
|
278
278
|
}
|
package/src/bundle/index.cjs
CHANGED
|
@@ -45,7 +45,7 @@ const bundle = async (uri, options) => {
|
|
|
45
45
|
|
|
46
46
|
// we couldn't find any bundle strategy for this File
|
|
47
47
|
if ((0, _ramda.isEmpty)(bundleStrategies)) {
|
|
48
|
-
throw new _UnmatchedBundleStrategyError.default(file.uri);
|
|
48
|
+
throw new _UnmatchedBundleStrategyError.default(`Could not find a bundle strategy that can bundle the file "${file.uri}"`);
|
|
49
49
|
}
|
|
50
50
|
try {
|
|
51
51
|
const {
|
package/src/bundle/index.mjs
CHANGED
|
@@ -39,7 +39,7 @@ const bundle = async (uri, options) => {
|
|
|
39
39
|
|
|
40
40
|
// we couldn't find any bundle strategy for this File
|
|
41
41
|
if (isEmpty(bundleStrategies)) {
|
|
42
|
-
throw new UnmatchedBundleStrategyError(file.uri);
|
|
42
|
+
throw new UnmatchedBundleStrategyError(`Could not find a bundle strategy that can bundle the file "${file.uri}"`);
|
|
43
43
|
}
|
|
44
44
|
try {
|
|
45
45
|
const {
|
|
@@ -62,10 +62,12 @@ _index25.options.parse.parsers = [new _index7.default({
|
|
|
62
62
|
sourceMap: false
|
|
63
63
|
}), new _index13.default({
|
|
64
64
|
allowEmpty: true,
|
|
65
|
-
sourceMap: false
|
|
65
|
+
sourceMap: false,
|
|
66
|
+
parseFn: _index25.parse
|
|
66
67
|
}), new _index14.default({
|
|
67
68
|
allowEmpty: true,
|
|
68
|
-
sourceMap: false
|
|
69
|
+
sourceMap: false,
|
|
70
|
+
parseFn: _index25.parse
|
|
69
71
|
}), new _index15.default({
|
|
70
72
|
allowEmpty: true,
|
|
71
73
|
sourceMap: false
|
|
@@ -26,7 +26,7 @@ import OpenAPI3_1DereferenceStrategy from "../dereference/strategies/openapi-3-1
|
|
|
26
26
|
import AsyncAPI2DereferenceStrategy from "../dereference/strategies/asyncapi-2/index.mjs";
|
|
27
27
|
import Arazzo1DereferenceStrategy from "../dereference/strategies/arazzo-1/index.mjs";
|
|
28
28
|
import OpenAPI3_1BundleStrategy from "../bundle/strategies/openapi-3-1/index.mjs";
|
|
29
|
-
import { options } from "../index.mjs";
|
|
29
|
+
import { options, parse } from "../index.mjs";
|
|
30
30
|
options.parse.parsers = [new OpenAPIJSON2Parser({
|
|
31
31
|
allowEmpty: true,
|
|
32
32
|
sourceMap: false
|
|
@@ -53,10 +53,12 @@ options.parse.parsers = [new OpenAPIJSON2Parser({
|
|
|
53
53
|
sourceMap: false
|
|
54
54
|
}), new ArazzoJSON1Parser({
|
|
55
55
|
allowEmpty: true,
|
|
56
|
-
sourceMap: false
|
|
56
|
+
sourceMap: false,
|
|
57
|
+
parseFn: parse
|
|
57
58
|
}), new ArazzoYAML1Parser({
|
|
58
59
|
allowEmpty: true,
|
|
59
|
-
sourceMap: false
|
|
60
|
+
sourceMap: false,
|
|
61
|
+
parseFn: parse
|
|
60
62
|
}), new APIDOMJSONParser({
|
|
61
63
|
allowEmpty: true,
|
|
62
64
|
sourceMap: false
|
|
@@ -37,7 +37,7 @@ const dereferenceApiDOM = async (element, options) => {
|
|
|
37
37
|
|
|
38
38
|
// we couldn't find any dereference strategy for this File
|
|
39
39
|
if ((0, _ramda.isEmpty)(dereferenceStrategies)) {
|
|
40
|
-
throw new _UnmatchedDereferenceStrategyError.default(file.uri);
|
|
40
|
+
throw new _UnmatchedDereferenceStrategyError.default(`Could not find a dereference strategy that can dereference the file "${file.uri}"`);
|
|
41
41
|
}
|
|
42
42
|
try {
|
|
43
43
|
const {
|
|
@@ -31,7 +31,7 @@ export const dereferenceApiDOM = async (element, options) => {
|
|
|
31
31
|
|
|
32
32
|
// we couldn't find any dereference strategy for this File
|
|
33
33
|
if (isEmpty(dereferenceStrategies)) {
|
|
34
|
-
throw new UnmatchedDereferenceStrategyError(file.uri);
|
|
34
|
+
throw new UnmatchedDereferenceStrategyError(`Could not find a dereference strategy that can dereference the file "${file.uri}"`);
|
|
35
35
|
}
|
|
36
36
|
try {
|
|
37
37
|
const {
|
|
@@ -440,7 +440,7 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
440
440
|
operationElement = (0, _apidomTraverse.find)(reference.value.result, e => (0, _apidomNsOpenapi.isOperationElement)(e) && (0, _apidomDatamodel.isElement)(e.operationId) && e.operationId.equals(operationId));
|
|
441
441
|
// OperationElement not found by its operationId
|
|
442
442
|
if ((0, _ramdaAdjunct.isUndefined)(operationElement)) {
|
|
443
|
-
throw new _apidomError.ApiDOMError(`OperationElement(operationId=${operationId}) not found
|
|
443
|
+
throw new _apidomError.ApiDOMError(`OperationElement(operationId=${operationId}) not found`);
|
|
444
444
|
}
|
|
445
445
|
const linkElementCopy = (0, _apidomDatamodel.cloneShallow)(linkElement);
|
|
446
446
|
linkElementCopy.operationId?.meta.set('operation', operationElement);
|
|
@@ -434,7 +434,7 @@ class OpenAPI3_0DereferenceVisitor {
|
|
|
434
434
|
operationElement = find(reference.value.result, e => isOperationElement(e) && isElement(e.operationId) && e.operationId.equals(operationId));
|
|
435
435
|
// OperationElement not found by its operationId
|
|
436
436
|
if (isUndefined(operationElement)) {
|
|
437
|
-
throw new ApiDOMError(`OperationElement(operationId=${operationId}) not found
|
|
437
|
+
throw new ApiDOMError(`OperationElement(operationId=${operationId}) not found`);
|
|
438
438
|
}
|
|
439
439
|
const linkElementCopy = cloneShallow(linkElement);
|
|
440
440
|
linkElementCopy.operationId?.meta.set('operation', operationElement);
|
|
@@ -462,7 +462,7 @@ class OpenAPI3_1DereferenceVisitor {
|
|
|
462
462
|
operationElement = (0, _apidomTraverse.find)(reference.value.result, e => (0, _apidomNsOpenapi.isOperationElement)(e) && (0, _apidomDatamodel.isElement)(e.operationId) && e.operationId.equals(operationId));
|
|
463
463
|
// OperationElement not found by its operationId
|
|
464
464
|
if ((0, _ramdaAdjunct.isUndefined)(operationElement)) {
|
|
465
|
-
throw new _apidomError.ApiDOMError(`OperationElement(operationId=${operationId}) not found
|
|
465
|
+
throw new _apidomError.ApiDOMError(`OperationElement(operationId=${operationId}) not found`);
|
|
466
466
|
}
|
|
467
467
|
const linkElementCopy = (0, _apidomDatamodel.cloneShallow)(linkElement);
|
|
468
468
|
linkElementCopy.operationId?.meta.set('operation', operationElement);
|
|
@@ -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);
|
|
@@ -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;
|
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
|
*/
|
package/src/parse/index.cjs
CHANGED
|
@@ -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
|
|
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
|
|
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}"
|
|
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) {
|
package/src/parse/index.mjs
CHANGED
|
@@ -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
|
|
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
|
|
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}"
|
|
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) {
|
|
@@ -7,6 +7,7 @@ var _ramda = require("ramda");
|
|
|
7
7
|
var _apidomParserAdapterArazzoJson = require("@speclynx/apidom-parser-adapter-arazzo-json-1");
|
|
8
8
|
var _ParserError = _interopRequireDefault(require("../../../errors/ParserError.cjs"));
|
|
9
9
|
var _Parser = _interopRequireDefault(require("../Parser.cjs"));
|
|
10
|
+
var _sourceDescription = require("./source-description.cjs");
|
|
10
11
|
/**
|
|
11
12
|
* @public
|
|
12
13
|
*/
|
|
@@ -16,8 +17,10 @@ var _Parser = _interopRequireDefault(require("../Parser.cjs"));
|
|
|
16
17
|
*/
|
|
17
18
|
class ArazzoJSON1Parser extends _Parser.default {
|
|
18
19
|
refractorOpts;
|
|
20
|
+
parseFn;
|
|
19
21
|
constructor(options) {
|
|
20
22
|
const {
|
|
23
|
+
parseFn,
|
|
21
24
|
fileExtensions = [],
|
|
22
25
|
mediaTypes = _apidomParserAdapterArazzoJson.mediaTypes,
|
|
23
26
|
...rest
|
|
@@ -28,6 +31,7 @@ class ArazzoJSON1Parser extends _Parser.default {
|
|
|
28
31
|
fileExtensions,
|
|
29
32
|
mediaTypes
|
|
30
33
|
});
|
|
34
|
+
this.parseFn = parseFn;
|
|
31
35
|
}
|
|
32
36
|
async canParse(file) {
|
|
33
37
|
const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
|
|
@@ -39,11 +43,17 @@ class ArazzoJSON1Parser extends _Parser.default {
|
|
|
39
43
|
}
|
|
40
44
|
return false;
|
|
41
45
|
}
|
|
42
|
-
async parse(file) {
|
|
46
|
+
async parse(file, options) {
|
|
43
47
|
const source = file.toString();
|
|
44
48
|
try {
|
|
45
49
|
const parserOpts = (0, _ramda.pick)(['sourceMap', 'strict', 'refractorOpts'], this);
|
|
46
|
-
|
|
50
|
+
const parseResult = await (0, _apidomParserAdapterArazzoJson.parse)(source, parserOpts);
|
|
51
|
+
const shouldParseSourceDescriptions = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
|
|
52
|
+
if (shouldParseSourceDescriptions) {
|
|
53
|
+
const sourceDescriptions = await _sourceDescription.parseSourceDescriptions.call(this, parseResult.api, file, options);
|
|
54
|
+
parseResult.push(...sourceDescriptions);
|
|
55
|
+
}
|
|
56
|
+
return parseResult;
|
|
47
57
|
} catch (error) {
|
|
48
58
|
throw new _ParserError.default(`Error parsing "${file.uri}"`, {
|
|
49
59
|
cause: error
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { pick } from 'ramda';
|
|
2
|
-
import { parse, mediaTypes as
|
|
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
6
|
/**
|
|
6
7
|
* @public
|
|
7
8
|
*/
|
|
@@ -10,10 +11,12 @@ import Parser from "../Parser.mjs";
|
|
|
10
11
|
*/
|
|
11
12
|
class ArazzoJSON1Parser extends Parser {
|
|
12
13
|
refractorOpts;
|
|
14
|
+
parseFn;
|
|
13
15
|
constructor(options) {
|
|
14
16
|
const {
|
|
17
|
+
parseFn,
|
|
15
18
|
fileExtensions = [],
|
|
16
|
-
mediaTypes =
|
|
19
|
+
mediaTypes = ArazzoJSON1MediaTypes,
|
|
17
20
|
...rest
|
|
18
21
|
} = options ?? {};
|
|
19
22
|
super({
|
|
@@ -22,6 +25,7 @@ class ArazzoJSON1Parser extends Parser {
|
|
|
22
25
|
fileExtensions,
|
|
23
26
|
mediaTypes
|
|
24
27
|
});
|
|
28
|
+
this.parseFn = parseFn;
|
|
25
29
|
}
|
|
26
30
|
async canParse(file) {
|
|
27
31
|
const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension);
|
|
@@ -33,11 +37,17 @@ class ArazzoJSON1Parser extends Parser {
|
|
|
33
37
|
}
|
|
34
38
|
return false;
|
|
35
39
|
}
|
|
36
|
-
async parse(file) {
|
|
40
|
+
async parse(file, options) {
|
|
37
41
|
const source = file.toString();
|
|
38
42
|
try {
|
|
39
43
|
const parserOpts = pick(['sourceMap', 'strict', 'refractorOpts'], this);
|
|
40
|
-
|
|
44
|
+
const parseResult = await parse(source, parserOpts);
|
|
45
|
+
const shouldParseSourceDescriptions = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
|
|
46
|
+
if (shouldParseSourceDescriptions) {
|
|
47
|
+
const sourceDescriptions = await parseSourceDescriptions.call(this, parseResult.api, file, options);
|
|
48
|
+
parseResult.push(...sourceDescriptions);
|
|
49
|
+
}
|
|
50
|
+
return parseResult;
|
|
41
51
|
} catch (error) {
|
|
42
52
|
throw new ParserError(`Error parsing "${file.uri}"`, {
|
|
43
53
|
cause: error
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
|
|
4
|
+
exports.__esModule = true;
|
|
5
|
+
exports.parseSourceDescriptions = parseSourceDescriptions;
|
|
6
|
+
var _apidomDatamodel = require("@speclynx/apidom-datamodel");
|
|
7
|
+
var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
|
|
8
|
+
var _apidomNsOpenapi = require("@speclynx/apidom-ns-openapi-2");
|
|
9
|
+
var _apidomNsOpenapi2 = require("@speclynx/apidom-ns-openapi-3-0");
|
|
10
|
+
var _apidomNsOpenapi3 = require("@speclynx/apidom-ns-openapi-3-1");
|
|
11
|
+
var _apidomCore = require("@speclynx/apidom-core");
|
|
12
|
+
var url = _interopRequireWildcard(require("../../../util/url.cjs"));
|
|
13
|
+
var _util = require("../../../options/util.cjs");
|
|
14
|
+
// shared key for recursion state (works across JSON/YAML parsers)
|
|
15
|
+
const ARAZZO_RECURSION_KEY = 'arazzo-1';
|
|
16
|
+
/**
|
|
17
|
+
* Parses a single source description element.
|
|
18
|
+
* Returns ParseResultElement on success, or undefined if skipped.
|
|
19
|
+
*/
|
|
20
|
+
async function parseSourceDescription(sourceDescription, ctx) {
|
|
21
|
+
const parseResult = new _apidomDatamodel.ParseResultElement();
|
|
22
|
+
if (!(0, _apidomNsArazzo.isSourceDescriptionElement)(sourceDescription)) {
|
|
23
|
+
const annotation = new _apidomDatamodel.AnnotationElement('Element is not a valid SourceDescriptionElement. Skipping.');
|
|
24
|
+
annotation.classes.push('warning');
|
|
25
|
+
parseResult.push(annotation);
|
|
26
|
+
return parseResult;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// set class and metadata from source description element
|
|
30
|
+
parseResult.classes.push('source-description');
|
|
31
|
+
if ((0, _apidomDatamodel.isStringElement)(sourceDescription.name)) parseResult.setMetaProperty('name', (0, _apidomDatamodel.cloneDeep)(sourceDescription.name));
|
|
32
|
+
if ((0, _apidomDatamodel.isStringElement)(sourceDescription.type)) parseResult.setMetaProperty('type', (0, _apidomDatamodel.cloneDeep)(sourceDescription.type));
|
|
33
|
+
const sourceDescriptionURI = (0, _apidomCore.toValue)(sourceDescription.url);
|
|
34
|
+
if (typeof sourceDescriptionURI !== 'string') {
|
|
35
|
+
const annotation = new _apidomDatamodel.AnnotationElement('Source description URL is missing or not a string. Skipping.');
|
|
36
|
+
annotation.classes.push('warning');
|
|
37
|
+
parseResult.push(annotation);
|
|
38
|
+
return parseResult;
|
|
39
|
+
}
|
|
40
|
+
const retrievalURI = url.resolve(ctx.baseURI, sourceDescriptionURI);
|
|
41
|
+
|
|
42
|
+
// skip if already visited (cycle detection)
|
|
43
|
+
if (ctx.visitedUrls.has(retrievalURI)) {
|
|
44
|
+
const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" has already been visited. Skipping to prevent cycle.`);
|
|
45
|
+
annotation.classes.push('warning');
|
|
46
|
+
parseResult.push(annotation);
|
|
47
|
+
return parseResult;
|
|
48
|
+
}
|
|
49
|
+
ctx.visitedUrls.add(retrievalURI);
|
|
50
|
+
try {
|
|
51
|
+
const sdParseResult = await ctx.parseFn(retrievalURI, (0, _util.merge)(ctx.options, {
|
|
52
|
+
parse: {
|
|
53
|
+
mediaType: 'text/plain',
|
|
54
|
+
// allow parser plugin detection
|
|
55
|
+
parserOpts: {
|
|
56
|
+
[ARAZZO_RECURSION_KEY]: {
|
|
57
|
+
sourceDescriptionsDepth: ctx.currentDepth + 1,
|
|
58
|
+
sourceDescriptionsVisitedUrls: ctx.visitedUrls
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}));
|
|
63
|
+
// merge parsed result into our parse result
|
|
64
|
+
for (const item of sdParseResult) {
|
|
65
|
+
parseResult.push(item);
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
// create error annotation instead of failing entire parse
|
|
69
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
70
|
+
const annotation = new _apidomDatamodel.AnnotationElement(`Error parsing source description "${retrievalURI}": ${message}`);
|
|
71
|
+
annotation.classes.push('error');
|
|
72
|
+
parseResult.push(annotation);
|
|
73
|
+
return parseResult;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// only allow OpenAPI and Arazzo as source descriptions
|
|
77
|
+
const {
|
|
78
|
+
api: sourceDescriptionAPI
|
|
79
|
+
} = parseResult;
|
|
80
|
+
const isOpenApi = (0, _apidomNsOpenapi.isSwaggerElement)(sourceDescriptionAPI) || (0, _apidomNsOpenapi2.isOpenApi3_0Element)(sourceDescriptionAPI) || (0, _apidomNsOpenapi3.isOpenApi3_1Element)(sourceDescriptionAPI);
|
|
81
|
+
const isArazzo = (0, _apidomNsArazzo.isArazzoSpecification1Element)(sourceDescriptionAPI);
|
|
82
|
+
if (!isOpenApi && !isArazzo) {
|
|
83
|
+
const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" is not an OpenAPI or Arazzo document. Skipping.`);
|
|
84
|
+
annotation.classes.push('warning');
|
|
85
|
+
parseResult.push(annotation);
|
|
86
|
+
return parseResult;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// validate declared type matches actual parsed type
|
|
90
|
+
const declaredType = (0, _apidomCore.toValue)(sourceDescription.type);
|
|
91
|
+
if (typeof declaredType === 'string') {
|
|
92
|
+
if (declaredType === 'openapi' && !isOpenApi) {
|
|
93
|
+
const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "openapi" but parsed as Arazzo document.`);
|
|
94
|
+
annotation.classes.push('warning');
|
|
95
|
+
parseResult.push(annotation);
|
|
96
|
+
} else if (declaredType === 'arazzo' && !isArazzo) {
|
|
97
|
+
const annotation = new _apidomDatamodel.AnnotationElement(`Source description "${retrievalURI}" declared as "arazzo" but parsed as OpenAPI document.`);
|
|
98
|
+
annotation.classes.push('warning');
|
|
99
|
+
parseResult.push(annotation);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return parseResult;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Shared function for parsing source descriptions.
|
|
107
|
+
* Call with `.call(this, ...)` where `this` has `name` and `parseFn` properties.
|
|
108
|
+
* @public
|
|
109
|
+
*/
|
|
110
|
+
async function parseSourceDescriptions(api, file, options) {
|
|
111
|
+
const results = [];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Validate prerequisites for parsing source descriptions.
|
|
115
|
+
* Return warning annotations if validation fails.
|
|
116
|
+
*/
|
|
117
|
+
if (!(0, _apidomNsArazzo.isArazzoSpecification1Element)(api)) {
|
|
118
|
+
const annotation = new _apidomDatamodel.AnnotationElement('Cannot parse source descriptions: API is not an Arazzo specification.');
|
|
119
|
+
annotation.classes.push('warning');
|
|
120
|
+
return [new _apidomDatamodel.ParseResultElement([annotation])];
|
|
121
|
+
}
|
|
122
|
+
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
|
+
annotation.classes.push('warning');
|
|
125
|
+
return [new _apidomDatamodel.ParseResultElement([annotation])];
|
|
126
|
+
}
|
|
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
|
+
|
|
133
|
+
// user config: parser-specific options take precedence over global parserOpts
|
|
134
|
+
const maxDepth = options?.parse?.parserOpts?.[this.name]?.sourceDescriptionsMaxDepth ?? options?.parse?.parserOpts?.sourceDescriptionsMaxDepth ?? +Infinity;
|
|
135
|
+
|
|
136
|
+
// recursion state comes from shared key (works across JSON/YAML)
|
|
137
|
+
const sharedOpts = options?.parse?.parserOpts?.[ARAZZO_RECURSION_KEY] ?? {};
|
|
138
|
+
const currentDepth = sharedOpts.sourceDescriptionsDepth ?? 0;
|
|
139
|
+
const visitedUrls = sharedOpts.sourceDescriptionsVisitedUrls ?? new Set();
|
|
140
|
+
|
|
141
|
+
// add current file to visited URLs to prevent cycles
|
|
142
|
+
visitedUrls.add(file.uri);
|
|
143
|
+
if (currentDepth >= maxDepth) {
|
|
144
|
+
const annotation = new _apidomDatamodel.AnnotationElement(`Maximum parse depth of ${maxDepth} has been exceeded by file "${file.uri}"`);
|
|
145
|
+
annotation.classes.push('error');
|
|
146
|
+
const parseResult = new _apidomDatamodel.ParseResultElement([annotation]);
|
|
147
|
+
parseResult.classes.push('source-description');
|
|
148
|
+
return [parseResult];
|
|
149
|
+
}
|
|
150
|
+
const ctx = {
|
|
151
|
+
parseFn: this.parseFn,
|
|
152
|
+
baseURI: file.uri,
|
|
153
|
+
options,
|
|
154
|
+
currentDepth,
|
|
155
|
+
visitedUrls
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// determine which source descriptions to parse
|
|
159
|
+
const sourceDescriptionsOption = options?.parse?.parserOpts?.[this.name]?.sourceDescriptions ?? options?.parse?.parserOpts?.sourceDescriptions;
|
|
160
|
+
|
|
161
|
+
// handle false or other falsy values - no source descriptions should be parsed
|
|
162
|
+
if (!sourceDescriptionsOption) {
|
|
163
|
+
return results;
|
|
164
|
+
}
|
|
165
|
+
const sourceDescriptions = Array.isArray(sourceDescriptionsOption) ? api.sourceDescriptions.filter(sd => {
|
|
166
|
+
if (!(0, _apidomNsArazzo.isSourceDescriptionElement)(sd)) return false;
|
|
167
|
+
const name = (0, _apidomCore.toValue)(sd.name);
|
|
168
|
+
return typeof name === 'string' && sourceDescriptionsOption.includes(name);
|
|
169
|
+
}) : api.sourceDescriptions;
|
|
170
|
+
|
|
171
|
+
// process sequentially to ensure proper cycle detection with shared visitedUrls
|
|
172
|
+
for (const sourceDescription of sourceDescriptions) {
|
|
173
|
+
const sourceDescriptionParseResult = await parseSourceDescription(sourceDescription, ctx);
|
|
174
|
+
results.push(sourceDescriptionParseResult);
|
|
175
|
+
}
|
|
176
|
+
return results;
|
|
177
|
+
}
|