@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.
- package/CHANGELOG.md +12 -0
- package/README.md +60 -33
- package/dist/apidom-reference.browser.js +349 -99
- package/dist/apidom-reference.browser.min.js +1 -1
- package/package.json +25 -25
- package/src/configuration/saturated.cjs +2 -4
- package/src/configuration/saturated.mjs +3 -5
- package/src/dereference/strategies/arazzo-1/index.cjs +10 -0
- package/src/dereference/strategies/arazzo-1/index.mjs +10 -0
- package/src/dereference/strategies/arazzo-1/source-description.cjs +179 -0
- package/src/dereference/strategies/arazzo-1/source-description.mjs +172 -0
- package/src/dereference/strategies/openapi-3-0/visitor.cjs +2 -2
- package/src/dereference/strategies/openapi-3-0/visitor.mjs +2 -2
- package/src/dereference/strategies/openapi-3-1/visitor.cjs +2 -2
- package/src/dereference/strategies/openapi-3-1/visitor.mjs +2 -2
- package/src/parse/parsers/arazzo-json-1/index.cjs +3 -5
- package/src/parse/parsers/arazzo-json-1/index.mjs +3 -5
- package/src/parse/parsers/arazzo-json-1/{source-description.cjs → source-descriptions.cjs} +47 -21
- package/src/parse/parsers/arazzo-json-1/{source-description.mjs → source-descriptions.mjs} +47 -22
- package/src/parse/parsers/arazzo-yaml-1/index.cjs +3 -5
- package/src/parse/parsers/arazzo-yaml-1/index.mjs +3 -5
- package/src/parse/parsers/arazzo-yaml-1/source-descriptions.cjs +12 -0
- package/src/parse/parsers/arazzo-yaml-1/source-descriptions.mjs +7 -0
- package/src/resolve/resolvers/file/index-browser.cjs +1 -1
- package/src/resolve/resolvers/file/index-browser.mjs +1 -1
- package/types/dereference/strategies/arazzo-1/source-description.d.ts +8 -0
- package/types/parse/parsers/arazzo-json-1/index.d.ts +1 -3
- package/types/parse/parsers/arazzo-json-1/source-descriptions.d.ts +31 -0
- package/types/parse/parsers/arazzo-yaml-1/index.d.ts +1 -3
- package/types/parse/parsers/arazzo-yaml-1/source-descriptions.d.ts +6 -0
- 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-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
107
|
-
*
|
|
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(
|
|
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?.[
|
|
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?.[
|
|
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";
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
101
|
-
*
|
|
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(
|
|
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?.[
|
|
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?.[
|
|
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
|
|
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
|
|
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 "
|
|
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
|
|
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[]>;
|