@jentic/arazzo-parser 1.0.0-alpha.6 → 1.0.0-alpha.7
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 +6 -0
- package/README.md +42 -29
- package/dist/jentic-arazzo-parser.browser.js +348 -68
- package/dist/jentic-arazzo-parser.browser.min.js +1 -1
- package/package.json +15 -9
- package/src/index.cjs +5 -2
- package/src/index.mjs +2 -1
- package/src/parse-arazzo.cjs +5 -14
- package/src/parse-arazzo.mjs +6 -15
- package/src/parse-openapi.cjs +239 -0
- package/src/parse-openapi.mjs +232 -0
- package/src/resolve/resolvers/memory/index.cjs +2 -2
- package/src/resolve/resolvers/memory/index.mjs +2 -2
- package/types/arazzo-parser.d.ts +37 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jentic/arazzo-parser",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.7",
|
|
4
4
|
"description": "Parser for Arazzo Documents producing SpecLynx ApiDOM data model.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"arazzo",
|
|
@@ -48,13 +48,19 @@
|
|
|
48
48
|
"license": "Apache-2.0",
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@babel/runtime-corejs3": "^7.28.4",
|
|
51
|
-
"@speclynx/apidom-core": "2.6.
|
|
52
|
-
"@speclynx/apidom-datamodel": "2.6.
|
|
53
|
-
"@speclynx/apidom-error": "2.6.
|
|
54
|
-
"@speclynx/apidom-ns-arazzo-1": "2.6.
|
|
55
|
-
"@speclynx/apidom-parser-adapter-arazzo-json-1": "2.6.
|
|
56
|
-
"@speclynx/apidom-parser-adapter-arazzo-yaml-1": "2.6.
|
|
57
|
-
"@speclynx/apidom-
|
|
51
|
+
"@speclynx/apidom-core": "2.6.1",
|
|
52
|
+
"@speclynx/apidom-datamodel": "2.6.1",
|
|
53
|
+
"@speclynx/apidom-error": "2.6.1",
|
|
54
|
+
"@speclynx/apidom-ns-arazzo-1": "2.6.1",
|
|
55
|
+
"@speclynx/apidom-parser-adapter-arazzo-json-1": "2.6.1",
|
|
56
|
+
"@speclynx/apidom-parser-adapter-arazzo-yaml-1": "2.6.1",
|
|
57
|
+
"@speclynx/apidom-parser-adapter-openapi-json-2": "2.6.1",
|
|
58
|
+
"@speclynx/apidom-parser-adapter-openapi-json-3-0": "2.6.1",
|
|
59
|
+
"@speclynx/apidom-parser-adapter-openapi-json-3-1": "2.6.1",
|
|
60
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-2": "2.6.1",
|
|
61
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "2.6.1",
|
|
62
|
+
"@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "2.6.1",
|
|
63
|
+
"@speclynx/apidom-reference": "2.6.1",
|
|
58
64
|
"ramda-adjunct": "^6.0.0",
|
|
59
65
|
"type-fest": "^5.4.3"
|
|
60
66
|
},
|
|
@@ -68,5 +74,5 @@
|
|
|
68
74
|
"README.md",
|
|
69
75
|
"CHANGELOG.md"
|
|
70
76
|
],
|
|
71
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "683d99b8d14208c655b8367c298282087be79e69"
|
|
72
78
|
}
|
package/src/index.cjs
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.parseArazzo = exports.
|
|
4
|
+
exports.parseOpenAPI = exports.parseArazzo = exports.defaultOpenAPIOptions = exports.defaultArazzoOptions = void 0;
|
|
5
5
|
var _parseArazzo = require("./parse-arazzo.cjs");
|
|
6
6
|
exports.parseArazzo = _parseArazzo.parse;
|
|
7
|
-
exports.
|
|
7
|
+
exports.defaultArazzoOptions = _parseArazzo.defaultOptions;
|
|
8
|
+
var _parseOpenapi = require("./parse-openapi.cjs");
|
|
9
|
+
exports.parseOpenAPI = _parseOpenapi.parse;
|
|
10
|
+
exports.defaultOpenAPIOptions = _parseOpenapi.defaultOptions;
|
package/src/index.mjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { parse as parseArazzo, defaultOptions } from "./parse-arazzo.mjs";
|
|
1
|
+
export { parse as parseArazzo, defaultOptions as defaultArazzoOptions } from "./parse-arazzo.mjs";
|
|
2
|
+
export { parse as parseOpenAPI, defaultOptions as defaultOpenAPIOptions } from "./parse-openapi.mjs";
|
package/src/parse-arazzo.cjs
CHANGED
|
@@ -4,8 +4,6 @@ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequ
|
|
|
4
4
|
exports.__esModule = true;
|
|
5
5
|
exports.defaultOptions = void 0;
|
|
6
6
|
exports.parse = parse;
|
|
7
|
-
var _apidomCore = require("@speclynx/apidom-core");
|
|
8
|
-
var _apidomDatamodel = require("@speclynx/apidom-datamodel");
|
|
9
7
|
var _empty = require("@speclynx/apidom-reference/configuration/empty");
|
|
10
8
|
var _arazzoJson = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/arazzo-json-1"));
|
|
11
9
|
var _arazzoYaml = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/arazzo-yaml-1"));
|
|
@@ -146,11 +144,11 @@ async function parse(source, options = {}) {
|
|
|
146
144
|
const strict = mergedOptions.parse?.parserOpts?.strict ?? true;
|
|
147
145
|
let sourceProvenance;
|
|
148
146
|
if ((0, _ramdaAdjunct.isPlainObject)(source)) {
|
|
149
|
-
const
|
|
147
|
+
const document = JSON.stringify(source, null, 2);
|
|
150
148
|
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
151
149
|
resolve: {
|
|
152
150
|
resolverOpts: {
|
|
153
|
-
|
|
151
|
+
document
|
|
154
152
|
}
|
|
155
153
|
}
|
|
156
154
|
});
|
|
@@ -162,7 +160,7 @@ async function parse(source, options = {}) {
|
|
|
162
160
|
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
163
161
|
resolve: {
|
|
164
162
|
resolverOpts: {
|
|
165
|
-
|
|
163
|
+
document: source
|
|
166
164
|
}
|
|
167
165
|
}
|
|
168
166
|
});
|
|
@@ -174,7 +172,7 @@ async function parse(source, options = {}) {
|
|
|
174
172
|
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
175
173
|
resolve: {
|
|
176
174
|
resolverOpts: {
|
|
177
|
-
|
|
175
|
+
document: source
|
|
178
176
|
}
|
|
179
177
|
}
|
|
180
178
|
});
|
|
@@ -195,14 +193,7 @@ async function parse(source, options = {}) {
|
|
|
195
193
|
|
|
196
194
|
// validate that the parsed document is an Arazzo specification
|
|
197
195
|
if (!(0, _apidomNsArazzo.isArazzoSpecification1Element)(parseResult.api)) {
|
|
198
|
-
|
|
199
|
-
classes: ['error']
|
|
200
|
-
});
|
|
201
|
-
// remove 'api' class so .api returns undefined, but keep parsed result available
|
|
202
|
-
if (parseResult.api) {
|
|
203
|
-
parseResult.api.classes = parseResult.api.classes.filter(cls => (0, _apidomCore.toValue)(cls) !== 'api');
|
|
204
|
-
}
|
|
205
|
-
parseResult.push(annotation);
|
|
196
|
+
throw new _empty.UnmatchedParserError(`Could not find a parser that can parse "${sourceProvenance}" as an Arazzo specification`);
|
|
206
197
|
}
|
|
207
198
|
return parseResult;
|
|
208
199
|
} catch (error) {
|
package/src/parse-arazzo.mjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AnnotationElement } from '@speclynx/apidom-datamodel';
|
|
3
|
-
import { parse as parseURI, mergeOptions } from '@speclynx/apidom-reference/configuration/empty';
|
|
1
|
+
import { parse as parseURI, mergeOptions, UnmatchedParserError } from '@speclynx/apidom-reference/configuration/empty';
|
|
4
2
|
import ArazzoJSON1Parser from '@speclynx/apidom-reference/parse/parsers/arazzo-json-1';
|
|
5
3
|
import ArazzoYAML1Parser from '@speclynx/apidom-reference/parse/parsers/arazzo-yaml-1';
|
|
6
4
|
import OpenApiJSON2Parser from '@speclynx/apidom-reference/parse/parsers/openapi-json-2';
|
|
@@ -139,11 +137,11 @@ export async function parse(source, options = {}) {
|
|
|
139
137
|
const strict = mergedOptions.parse?.parserOpts?.strict ?? true;
|
|
140
138
|
let sourceProvenance;
|
|
141
139
|
if (isPlainObject(source)) {
|
|
142
|
-
const
|
|
140
|
+
const document = JSON.stringify(source, null, 2);
|
|
143
141
|
mergedOptions = mergeOptions(mergedOptions, {
|
|
144
142
|
resolve: {
|
|
145
143
|
resolverOpts: {
|
|
146
|
-
|
|
144
|
+
document
|
|
147
145
|
}
|
|
148
146
|
}
|
|
149
147
|
});
|
|
@@ -155,7 +153,7 @@ export async function parse(source, options = {}) {
|
|
|
155
153
|
mergedOptions = mergeOptions(mergedOptions, {
|
|
156
154
|
resolve: {
|
|
157
155
|
resolverOpts: {
|
|
158
|
-
|
|
156
|
+
document: source
|
|
159
157
|
}
|
|
160
158
|
}
|
|
161
159
|
});
|
|
@@ -167,7 +165,7 @@ export async function parse(source, options = {}) {
|
|
|
167
165
|
mergedOptions = mergeOptions(mergedOptions, {
|
|
168
166
|
resolve: {
|
|
169
167
|
resolverOpts: {
|
|
170
|
-
|
|
168
|
+
document: source
|
|
171
169
|
}
|
|
172
170
|
}
|
|
173
171
|
});
|
|
@@ -188,14 +186,7 @@ export async function parse(source, options = {}) {
|
|
|
188
186
|
|
|
189
187
|
// validate that the parsed document is an Arazzo specification
|
|
190
188
|
if (!isArazzoSpecification1Element(parseResult.api)) {
|
|
191
|
-
|
|
192
|
-
classes: ['error']
|
|
193
|
-
});
|
|
194
|
-
// remove 'api' class so .api returns undefined, but keep parsed result available
|
|
195
|
-
if (parseResult.api) {
|
|
196
|
-
parseResult.api.classes = parseResult.api.classes.filter(cls => toValue(cls) !== 'api');
|
|
197
|
-
}
|
|
198
|
-
parseResult.push(annotation);
|
|
189
|
+
throw new UnmatchedParserError(`Could not find a parser that can parse "${sourceProvenance}" as an Arazzo specification`);
|
|
199
190
|
}
|
|
200
191
|
return parseResult;
|
|
201
192
|
} catch (error) {
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
|
|
4
|
+
exports.__esModule = true;
|
|
5
|
+
exports.defaultOptions = void 0;
|
|
6
|
+
exports.parse = parse;
|
|
7
|
+
var _empty = require("@speclynx/apidom-reference/configuration/empty");
|
|
8
|
+
var _openapiJson = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-json-2"));
|
|
9
|
+
var _openapiYaml = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-yaml-2"));
|
|
10
|
+
var _openapiJson2 = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-json-3-0"));
|
|
11
|
+
var _openapiYaml2 = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-yaml-3-0"));
|
|
12
|
+
var _openapiJson3 = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-json-3-1"));
|
|
13
|
+
var _openapiYaml3 = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-yaml-3-1"));
|
|
14
|
+
var _file = _interopRequireDefault(require("@speclynx/apidom-reference/resolve/resolvers/file"));
|
|
15
|
+
var _httpAxios = _interopRequireDefault(require("@speclynx/apidom-reference/resolve/resolvers/http-axios"));
|
|
16
|
+
var _apidomParserAdapterOpenapiJson = require("@speclynx/apidom-parser-adapter-openapi-json-3-1");
|
|
17
|
+
var _apidomParserAdapterOpenapiYaml = require("@speclynx/apidom-parser-adapter-openapi-yaml-3-1");
|
|
18
|
+
var _apidomParserAdapterOpenapiJson2 = require("@speclynx/apidom-parser-adapter-openapi-json-3-0");
|
|
19
|
+
var _apidomParserAdapterOpenapiYaml2 = require("@speclynx/apidom-parser-adapter-openapi-yaml-3-0");
|
|
20
|
+
var _apidomParserAdapterOpenapiJson3 = require("@speclynx/apidom-parser-adapter-openapi-json-2");
|
|
21
|
+
var _apidomParserAdapterOpenapiYaml3 = require("@speclynx/apidom-parser-adapter-openapi-yaml-2");
|
|
22
|
+
var _ramdaAdjunct = require("ramda-adjunct");
|
|
23
|
+
var _ParseError = _interopRequireDefault(require("./errors/ParseError.cjs"));
|
|
24
|
+
var _index = _interopRequireDefault(require("./resolve/resolvers/memory/index.cjs"));
|
|
25
|
+
/**
|
|
26
|
+
* Options for parsing OpenAPI Documents.
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Default reference options for parsing OpenAPI Documents.
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
const defaultOptions = exports.defaultOptions = {
|
|
35
|
+
parse: {
|
|
36
|
+
parsers: [new _openapiJson.default({
|
|
37
|
+
allowEmpty: false,
|
|
38
|
+
fileExtensions: ['.json']
|
|
39
|
+
}), new _openapiYaml.default({
|
|
40
|
+
allowEmpty: false,
|
|
41
|
+
fileExtensions: ['.yaml', '.yml']
|
|
42
|
+
}), new _openapiJson2.default({
|
|
43
|
+
allowEmpty: false,
|
|
44
|
+
fileExtensions: ['.json']
|
|
45
|
+
}), new _openapiYaml2.default({
|
|
46
|
+
allowEmpty: false,
|
|
47
|
+
fileExtensions: ['.yaml', '.yml']
|
|
48
|
+
}), new _openapiJson3.default({
|
|
49
|
+
allowEmpty: false,
|
|
50
|
+
fileExtensions: ['.json']
|
|
51
|
+
}), new _openapiYaml3.default({
|
|
52
|
+
allowEmpty: false,
|
|
53
|
+
fileExtensions: ['.yaml', '.yml']
|
|
54
|
+
})],
|
|
55
|
+
parserOpts: {
|
|
56
|
+
sourceMap: false,
|
|
57
|
+
strict: true
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
resolve: {
|
|
61
|
+
resolvers: [new _index.default(), new _file.default({
|
|
62
|
+
fileAllowList: ['*.json', '*.yaml', '*.yml']
|
|
63
|
+
}), new _httpAxios.default({
|
|
64
|
+
timeout: 5000,
|
|
65
|
+
redirects: 5,
|
|
66
|
+
withCredentials: false
|
|
67
|
+
})],
|
|
68
|
+
resolverOpts: {}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Parses an OpenAPI Document from an object.
|
|
74
|
+
* @param source - The OpenAPI Document as a plain object
|
|
75
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
76
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
77
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
78
|
+
* @public
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Parses an OpenAPI Document from a string or URI.
|
|
83
|
+
* @param source - The OpenAPI Document as string content, or a file system path / HTTP(S) URL
|
|
84
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
85
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
86
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Parses an OpenAPI Document from a string, object, or URI.
|
|
92
|
+
*
|
|
93
|
+
* The function handles three types of input:
|
|
94
|
+
* 1. Object - converts to JSON string and parses (source maps supported with `strict: false`)
|
|
95
|
+
* 2. String content - uses OpenAPI detection to identify and parse inline JSON or YAML content
|
|
96
|
+
* 3. URI string - if not detected as OpenAPI content, treats as file system path or HTTP(S) URL
|
|
97
|
+
*
|
|
98
|
+
* @param source - The OpenAPI Document as an object, string content, or a file system path / HTTP(S) URL
|
|
99
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
100
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
101
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* Parse from object
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const result = await parseOpenAPI({ openapi: '3.1.0', info: {...} });
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* Parse inline JSON
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const result = await parseOpenAPI('{"openapi": "3.1.0", "info": {...}}');
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* Parse from file
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const result = await parseOpenAPI('/path/to/openapi.json');
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* Parse from URL
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const result = await parseOpenAPI('https://example.com/openapi.yaml');
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* Parse with custom options
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const result = await parseOpenAPI('/path/to/openapi.json', customOptions);
|
|
131
|
+
* ```
|
|
132
|
+
* @public
|
|
133
|
+
*/
|
|
134
|
+
async function parse(source, options = {}) {
|
|
135
|
+
let mergedOptions = (0, _empty.mergeOptions)(defaultOptions, options);
|
|
136
|
+
const strict = mergedOptions.parse?.parserOpts?.strict ?? true;
|
|
137
|
+
let sourceProvenance;
|
|
138
|
+
if ((0, _ramdaAdjunct.isPlainObject)(source)) {
|
|
139
|
+
const document = JSON.stringify(source, null, 2);
|
|
140
|
+
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
141
|
+
resolve: {
|
|
142
|
+
resolverOpts: {
|
|
143
|
+
document
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
source = 'memory://openapi.json';
|
|
148
|
+
sourceProvenance = '[object]';
|
|
149
|
+
} else if (await (0, _apidomParserAdapterOpenapiJson3.detect)(source, {
|
|
150
|
+
strict
|
|
151
|
+
})) {
|
|
152
|
+
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
153
|
+
resolve: {
|
|
154
|
+
resolverOpts: {
|
|
155
|
+
document: source
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
source = 'memory://openapi.json';
|
|
160
|
+
sourceProvenance = '[inline JSON]';
|
|
161
|
+
} else if (await (0, _apidomParserAdapterOpenapiYaml3.detect)(source, {
|
|
162
|
+
strict
|
|
163
|
+
})) {
|
|
164
|
+
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
165
|
+
resolve: {
|
|
166
|
+
resolverOpts: {
|
|
167
|
+
document: source
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
source = 'memory://openapi.yaml';
|
|
172
|
+
sourceProvenance = '[inline YAML]';
|
|
173
|
+
} else if (await (0, _apidomParserAdapterOpenapiJson2.detect)(source, {
|
|
174
|
+
strict
|
|
175
|
+
})) {
|
|
176
|
+
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
177
|
+
resolve: {
|
|
178
|
+
resolverOpts: {
|
|
179
|
+
document: source
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
source = 'memory://openapi.json';
|
|
184
|
+
sourceProvenance = '[inline JSON]';
|
|
185
|
+
} else if (await (0, _apidomParserAdapterOpenapiYaml2.detect)(source, {
|
|
186
|
+
strict
|
|
187
|
+
})) {
|
|
188
|
+
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
189
|
+
resolve: {
|
|
190
|
+
resolverOpts: {
|
|
191
|
+
document: source
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
source = 'memory://openapi.yaml';
|
|
196
|
+
sourceProvenance = '[inline YAML]';
|
|
197
|
+
} else if (await (0, _apidomParserAdapterOpenapiJson.detect)(source, {
|
|
198
|
+
strict
|
|
199
|
+
})) {
|
|
200
|
+
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
201
|
+
resolve: {
|
|
202
|
+
resolverOpts: {
|
|
203
|
+
document: source
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
source = 'memory://openapi.json';
|
|
208
|
+
sourceProvenance = '[inline JSON]';
|
|
209
|
+
} else if (await (0, _apidomParserAdapterOpenapiYaml.detect)(source, {
|
|
210
|
+
strict
|
|
211
|
+
})) {
|
|
212
|
+
mergedOptions = (0, _empty.mergeOptions)(mergedOptions, {
|
|
213
|
+
resolve: {
|
|
214
|
+
resolverOpts: {
|
|
215
|
+
document: source
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
source = 'memory://openapi.yaml';
|
|
220
|
+
sourceProvenance = '[inline YAML]';
|
|
221
|
+
} else {
|
|
222
|
+
sourceProvenance = source;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// next we assume that source is either file system URI or HTTP(S) URL
|
|
226
|
+
try {
|
|
227
|
+
const parseResult = await (0, _empty.parse)(source, mergedOptions);
|
|
228
|
+
|
|
229
|
+
// set retrievalURI metadata for file/URL sources (not for inline content)
|
|
230
|
+
if (!source.startsWith('memory://')) {
|
|
231
|
+
parseResult.meta.set('retrievalURI', source);
|
|
232
|
+
}
|
|
233
|
+
return parseResult;
|
|
234
|
+
} catch (error) {
|
|
235
|
+
throw new _ParseError.default(`Failed to parse OpenAPI Document from "${sourceProvenance}"`, {
|
|
236
|
+
cause: error
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { parse as parseURI, mergeOptions } from '@speclynx/apidom-reference/configuration/empty';
|
|
2
|
+
import OpenApiJSON2Parser from '@speclynx/apidom-reference/parse/parsers/openapi-json-2';
|
|
3
|
+
import OpenApiYAML2Parser from '@speclynx/apidom-reference/parse/parsers/openapi-yaml-2';
|
|
4
|
+
import OpenApiJSON3_0Parser from '@speclynx/apidom-reference/parse/parsers/openapi-json-3-0';
|
|
5
|
+
import OpenApiYAML3_0Parser from '@speclynx/apidom-reference/parse/parsers/openapi-yaml-3-0';
|
|
6
|
+
import OpenApiJSON3_1Parser from '@speclynx/apidom-reference/parse/parsers/openapi-json-3-1';
|
|
7
|
+
import OpenApiYAML3_1Parser from '@speclynx/apidom-reference/parse/parsers/openapi-yaml-3-1';
|
|
8
|
+
import FileResolver from '@speclynx/apidom-reference/resolve/resolvers/file';
|
|
9
|
+
import HTTPResolverAxios from '@speclynx/apidom-reference/resolve/resolvers/http-axios';
|
|
10
|
+
import { detect as detectOpenApiJSON3_1 } from '@speclynx/apidom-parser-adapter-openapi-json-3-1';
|
|
11
|
+
import { detect as detectOpenApiYAML3_1 } from '@speclynx/apidom-parser-adapter-openapi-yaml-3-1';
|
|
12
|
+
import { detect as detectOpenApiJSON3_0 } from '@speclynx/apidom-parser-adapter-openapi-json-3-0';
|
|
13
|
+
import { detect as detectOpenApiYAML3_0 } from '@speclynx/apidom-parser-adapter-openapi-yaml-3-0';
|
|
14
|
+
import { detect as detectOpenApiJSON2 } from '@speclynx/apidom-parser-adapter-openapi-json-2';
|
|
15
|
+
import { detect as detectOpenApiYAML2 } from '@speclynx/apidom-parser-adapter-openapi-yaml-2';
|
|
16
|
+
import { isPlainObject } from 'ramda-adjunct';
|
|
17
|
+
import ParseError from "./errors/ParseError.mjs";
|
|
18
|
+
import MemoryResolver from "./resolve/resolvers/memory/index.mjs";
|
|
19
|
+
/**
|
|
20
|
+
* Options for parsing OpenAPI Documents.
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Default reference options for parsing OpenAPI Documents.
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export const defaultOptions = {
|
|
28
|
+
parse: {
|
|
29
|
+
parsers: [new OpenApiJSON2Parser({
|
|
30
|
+
allowEmpty: false,
|
|
31
|
+
fileExtensions: ['.json']
|
|
32
|
+
}), new OpenApiYAML2Parser({
|
|
33
|
+
allowEmpty: false,
|
|
34
|
+
fileExtensions: ['.yaml', '.yml']
|
|
35
|
+
}), new OpenApiJSON3_0Parser({
|
|
36
|
+
allowEmpty: false,
|
|
37
|
+
fileExtensions: ['.json']
|
|
38
|
+
}), new OpenApiYAML3_0Parser({
|
|
39
|
+
allowEmpty: false,
|
|
40
|
+
fileExtensions: ['.yaml', '.yml']
|
|
41
|
+
}), new OpenApiJSON3_1Parser({
|
|
42
|
+
allowEmpty: false,
|
|
43
|
+
fileExtensions: ['.json']
|
|
44
|
+
}), new OpenApiYAML3_1Parser({
|
|
45
|
+
allowEmpty: false,
|
|
46
|
+
fileExtensions: ['.yaml', '.yml']
|
|
47
|
+
})],
|
|
48
|
+
parserOpts: {
|
|
49
|
+
sourceMap: false,
|
|
50
|
+
strict: true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
resolve: {
|
|
54
|
+
resolvers: [new MemoryResolver(), new FileResolver({
|
|
55
|
+
fileAllowList: ['*.json', '*.yaml', '*.yml']
|
|
56
|
+
}), new HTTPResolverAxios({
|
|
57
|
+
timeout: 5000,
|
|
58
|
+
redirects: 5,
|
|
59
|
+
withCredentials: false
|
|
60
|
+
})],
|
|
61
|
+
resolverOpts: {}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Parses an OpenAPI Document from an object.
|
|
67
|
+
* @param source - The OpenAPI Document as a plain object
|
|
68
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
69
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
70
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
71
|
+
* @public
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Parses an OpenAPI Document from a string or URI.
|
|
76
|
+
* @param source - The OpenAPI Document as string content, or a file system path / HTTP(S) URL
|
|
77
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
78
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
79
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Parses an OpenAPI Document from a string, object, or URI.
|
|
85
|
+
*
|
|
86
|
+
* The function handles three types of input:
|
|
87
|
+
* 1. Object - converts to JSON string and parses (source maps supported with `strict: false`)
|
|
88
|
+
* 2. String content - uses OpenAPI detection to identify and parse inline JSON or YAML content
|
|
89
|
+
* 3. URI string - if not detected as OpenAPI content, treats as file system path or HTTP(S) URL
|
|
90
|
+
*
|
|
91
|
+
* @param source - The OpenAPI Document as an object, string content, or a file system path / HTTP(S) URL
|
|
92
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
93
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
94
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* Parse from object
|
|
98
|
+
* ```typescript
|
|
99
|
+
* const result = await parseOpenAPI({ openapi: '3.1.0', info: {...} });
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* Parse inline JSON
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const result = await parseOpenAPI('{"openapi": "3.1.0", "info": {...}}');
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* Parse from file
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const result = await parseOpenAPI('/path/to/openapi.json');
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* Parse from URL
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const result = await parseOpenAPI('https://example.com/openapi.yaml');
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* Parse with custom options
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const result = await parseOpenAPI('/path/to/openapi.json', customOptions);
|
|
124
|
+
* ```
|
|
125
|
+
* @public
|
|
126
|
+
*/
|
|
127
|
+
export async function parse(source, options = {}) {
|
|
128
|
+
let mergedOptions = mergeOptions(defaultOptions, options);
|
|
129
|
+
const strict = mergedOptions.parse?.parserOpts?.strict ?? true;
|
|
130
|
+
let sourceProvenance;
|
|
131
|
+
if (isPlainObject(source)) {
|
|
132
|
+
const document = JSON.stringify(source, null, 2);
|
|
133
|
+
mergedOptions = mergeOptions(mergedOptions, {
|
|
134
|
+
resolve: {
|
|
135
|
+
resolverOpts: {
|
|
136
|
+
document
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
source = 'memory://openapi.json';
|
|
141
|
+
sourceProvenance = '[object]';
|
|
142
|
+
} else if (await detectOpenApiJSON2(source, {
|
|
143
|
+
strict
|
|
144
|
+
})) {
|
|
145
|
+
mergedOptions = mergeOptions(mergedOptions, {
|
|
146
|
+
resolve: {
|
|
147
|
+
resolverOpts: {
|
|
148
|
+
document: source
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
source = 'memory://openapi.json';
|
|
153
|
+
sourceProvenance = '[inline JSON]';
|
|
154
|
+
} else if (await detectOpenApiYAML2(source, {
|
|
155
|
+
strict
|
|
156
|
+
})) {
|
|
157
|
+
mergedOptions = mergeOptions(mergedOptions, {
|
|
158
|
+
resolve: {
|
|
159
|
+
resolverOpts: {
|
|
160
|
+
document: source
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
source = 'memory://openapi.yaml';
|
|
165
|
+
sourceProvenance = '[inline YAML]';
|
|
166
|
+
} else if (await detectOpenApiJSON3_0(source, {
|
|
167
|
+
strict
|
|
168
|
+
})) {
|
|
169
|
+
mergedOptions = mergeOptions(mergedOptions, {
|
|
170
|
+
resolve: {
|
|
171
|
+
resolverOpts: {
|
|
172
|
+
document: source
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
source = 'memory://openapi.json';
|
|
177
|
+
sourceProvenance = '[inline JSON]';
|
|
178
|
+
} else if (await detectOpenApiYAML3_0(source, {
|
|
179
|
+
strict
|
|
180
|
+
})) {
|
|
181
|
+
mergedOptions = mergeOptions(mergedOptions, {
|
|
182
|
+
resolve: {
|
|
183
|
+
resolverOpts: {
|
|
184
|
+
document: source
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
source = 'memory://openapi.yaml';
|
|
189
|
+
sourceProvenance = '[inline YAML]';
|
|
190
|
+
} else if (await detectOpenApiJSON3_1(source, {
|
|
191
|
+
strict
|
|
192
|
+
})) {
|
|
193
|
+
mergedOptions = mergeOptions(mergedOptions, {
|
|
194
|
+
resolve: {
|
|
195
|
+
resolverOpts: {
|
|
196
|
+
document: source
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
source = 'memory://openapi.json';
|
|
201
|
+
sourceProvenance = '[inline JSON]';
|
|
202
|
+
} else if (await detectOpenApiYAML3_1(source, {
|
|
203
|
+
strict
|
|
204
|
+
})) {
|
|
205
|
+
mergedOptions = mergeOptions(mergedOptions, {
|
|
206
|
+
resolve: {
|
|
207
|
+
resolverOpts: {
|
|
208
|
+
document: source
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
source = 'memory://openapi.yaml';
|
|
213
|
+
sourceProvenance = '[inline YAML]';
|
|
214
|
+
} else {
|
|
215
|
+
sourceProvenance = source;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// next we assume that source is either file system URI or HTTP(S) URL
|
|
219
|
+
try {
|
|
220
|
+
const parseResult = await parseURI(source, mergedOptions);
|
|
221
|
+
|
|
222
|
+
// set retrievalURI metadata for file/URL sources (not for inline content)
|
|
223
|
+
if (!source.startsWith('memory://')) {
|
|
224
|
+
parseResult.meta.set('retrievalURI', source);
|
|
225
|
+
}
|
|
226
|
+
return parseResult;
|
|
227
|
+
} catch (error) {
|
|
228
|
+
throw new ParseError(`Failed to parse OpenAPI Document from "${sourceProvenance}"`, {
|
|
229
|
+
cause: error
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
@@ -13,12 +13,12 @@ class MemoryResolver extends _empty.Resolver {
|
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
15
|
canRead(file) {
|
|
16
|
-
return file.uri.startsWith('memory://') &&
|
|
16
|
+
return file.uri.startsWith('memory://') && this.document !== undefined;
|
|
17
17
|
}
|
|
18
18
|
async read(file) {
|
|
19
19
|
try {
|
|
20
20
|
const encoder = new TextEncoder();
|
|
21
|
-
return encoder.encode(this.
|
|
21
|
+
return encoder.encode(this.document);
|
|
22
22
|
} catch (error) {
|
|
23
23
|
throw new _empty.ResolverError(`Error opening file "${file.uri}"`, {
|
|
24
24
|
cause: error
|
|
@@ -9,12 +9,12 @@ class MemoryResolver extends Resolver {
|
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
canRead(file) {
|
|
12
|
-
return file.uri.startsWith('memory://') &&
|
|
12
|
+
return file.uri.startsWith('memory://') && this.document !== undefined;
|
|
13
13
|
}
|
|
14
14
|
async read(file) {
|
|
15
15
|
try {
|
|
16
16
|
const encoder = new TextEncoder();
|
|
17
|
-
return encoder.encode(this.
|
|
17
|
+
return encoder.encode(this.document);
|
|
18
18
|
} catch (error) {
|
|
19
19
|
throw new ResolverError(`Error opening file "${file.uri}"`, {
|
|
20
20
|
cause: error
|