@usearazzo/parser 1.0.1-alpha.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/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +716 -0
- package/dist/arazzo-parser.browser.js +83807 -0
- package/dist/arazzo-parser.browser.min.js +1 -0
- package/package.json +86 -0
- package/src/errors/ParseError.cjs +18 -0
- package/src/errors/ParseError.mjs +13 -0
- package/src/index.cjs +77 -0
- package/src/index.mjs +5 -0
- package/src/options/util.cjs +30 -0
- package/src/options/util.mjs +23 -0
- package/src/parse-arazzo.cjs +209 -0
- package/src/parse-arazzo.mjs +200 -0
- package/src/parse-criterion-condition.cjs +82 -0
- package/src/parse-criterion-condition.mjs +71 -0
- package/src/parse-openapi.cjs +210 -0
- package/src/parse-openapi.mjs +201 -0
- package/src/parse-runtime-expression.cjs +84 -0
- package/src/parse-runtime-expression.mjs +73 -0
- package/src/resolve/resolvers/memory/index.cjs +52 -0
- package/src/resolve/resolvers/memory/index.mjs +47 -0
- package/types/parser.d.ts +260 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "ArazzoCriterionParseError", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _arazzoCriterion.ArazzoCriterionParseError;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
exports.defaultOptions = void 0;
|
|
13
|
+
exports.parse = parse;
|
|
14
|
+
var _arazzoCriterion = require("@swaggerexpert/arazzo-criterion");
|
|
15
|
+
/**
|
|
16
|
+
* Options for parsing Arazzo "simple" criterion conditions.
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Result of parsing an Arazzo "simple" criterion condition: the foundation
|
|
22
|
+
* ParseResult bound to the AST node type this parser produces.
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Default options for parsing Arazzo "simple" criterion conditions. Empty on
|
|
28
|
+
* purpose: the underlying grammar package supplies its own defaults, including
|
|
29
|
+
* a fresh ASTTranslator per call.
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
const defaultOptions = exports.defaultOptions = {};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Parses an Arazzo "simple" criterion condition (e.g. `$statusCode == 200`,
|
|
36
|
+
* `$response.body#/status == 'available' && $response.header.X-Rate-Limit-Remaining > 0`)
|
|
37
|
+
* into its AST.
|
|
38
|
+
*
|
|
39
|
+
* A pure, context-free syntax parser: the condition string in, an AST plus
|
|
40
|
+
* position-carrying diagnostics (`result.matched` / `result.maxMatched`) out.
|
|
41
|
+
* No evaluation is performed and no context is required; evaluating the
|
|
42
|
+
* parsed condition against runtime state is the runner's responsibility.
|
|
43
|
+
* Embedded runtime expression operands are parsed too: each `RuntimeExpression`
|
|
44
|
+
* node in the resulting AST carries its own sub-AST, produced by
|
|
45
|
+
* `@swaggerexpert/arazzo-runtime-expression` (see {@link parseRuntimeExpression}).
|
|
46
|
+
*
|
|
47
|
+
* @param condition - The "simple" criterion condition source string
|
|
48
|
+
* @param options - Parse options (uses defaultOptions when not provided)
|
|
49
|
+
* @returns The parse result: `{ result, tree, stats, trace }`. On success,
|
|
50
|
+
* `result.success` is `true` and `tree` holds the AST. On failure,
|
|
51
|
+
* `result.success` is `false`, `tree` is `undefined`, and `result.maxMatched`
|
|
52
|
+
* gives the offset into `condition` up to which parsing succeeded.
|
|
53
|
+
* @throws TypeError - When `condition` is not a string.
|
|
54
|
+
* @throws ArazzoCriterionParseError - When parsing fails for a reason other
|
|
55
|
+
* than invalid syntax (an unexpected internal error). Invalid syntax is never
|
|
56
|
+
* thrown; it is reported through the returned `result`.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* Valid condition
|
|
60
|
+
* ```typescript
|
|
61
|
+
* import { parseCriterionCondition } from '@usearazzo/parser';
|
|
62
|
+
*
|
|
63
|
+
* const { result, tree } = parseCriterionCondition('$statusCode == 200');
|
|
64
|
+
* // result.success === true
|
|
65
|
+
* // tree.type === 'BinaryExpression'
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* Invalid condition
|
|
70
|
+
* ```typescript
|
|
71
|
+
* import { parseCriterionCondition } from '@usearazzo/parser';
|
|
72
|
+
*
|
|
73
|
+
* const { result, tree } = parseCriterionCondition('$statusCode ===');
|
|
74
|
+
* // result.success === false
|
|
75
|
+
* // tree === undefined
|
|
76
|
+
* // result.maxMatched - the offset parsing failed at
|
|
77
|
+
* ```
|
|
78
|
+
* @public
|
|
79
|
+
*/
|
|
80
|
+
function parse(condition, options = defaultOptions) {
|
|
81
|
+
return (0, _arazzoCriterion.parse)(condition, options);
|
|
82
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { parse as parseCriterionCondition, ArazzoCriterionParseError } from '@swaggerexpert/arazzo-criterion';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options for parsing Arazzo "simple" criterion conditions.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Result of parsing an Arazzo "simple" criterion condition: the foundation
|
|
10
|
+
* ParseResult bound to the AST node type this parser produces.
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Default options for parsing Arazzo "simple" criterion conditions. Empty on
|
|
16
|
+
* purpose: the underlying grammar package supplies its own defaults, including
|
|
17
|
+
* a fresh ASTTranslator per call.
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export const defaultOptions = {};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Parses an Arazzo "simple" criterion condition (e.g. `$statusCode == 200`,
|
|
24
|
+
* `$response.body#/status == 'available' && $response.header.X-Rate-Limit-Remaining > 0`)
|
|
25
|
+
* into its AST.
|
|
26
|
+
*
|
|
27
|
+
* A pure, context-free syntax parser: the condition string in, an AST plus
|
|
28
|
+
* position-carrying diagnostics (`result.matched` / `result.maxMatched`) out.
|
|
29
|
+
* No evaluation is performed and no context is required; evaluating the
|
|
30
|
+
* parsed condition against runtime state is the runner's responsibility.
|
|
31
|
+
* Embedded runtime expression operands are parsed too: each `RuntimeExpression`
|
|
32
|
+
* node in the resulting AST carries its own sub-AST, produced by
|
|
33
|
+
* `@swaggerexpert/arazzo-runtime-expression` (see {@link parseRuntimeExpression}).
|
|
34
|
+
*
|
|
35
|
+
* @param condition - The "simple" criterion condition source string
|
|
36
|
+
* @param options - Parse options (uses defaultOptions when not provided)
|
|
37
|
+
* @returns The parse result: `{ result, tree, stats, trace }`. On success,
|
|
38
|
+
* `result.success` is `true` and `tree` holds the AST. On failure,
|
|
39
|
+
* `result.success` is `false`, `tree` is `undefined`, and `result.maxMatched`
|
|
40
|
+
* gives the offset into `condition` up to which parsing succeeded.
|
|
41
|
+
* @throws TypeError - When `condition` is not a string.
|
|
42
|
+
* @throws ArazzoCriterionParseError - When parsing fails for a reason other
|
|
43
|
+
* than invalid syntax (an unexpected internal error). Invalid syntax is never
|
|
44
|
+
* thrown; it is reported through the returned `result`.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* Valid condition
|
|
48
|
+
* ```typescript
|
|
49
|
+
* import { parseCriterionCondition } from '@usearazzo/parser';
|
|
50
|
+
*
|
|
51
|
+
* const { result, tree } = parseCriterionCondition('$statusCode == 200');
|
|
52
|
+
* // result.success === true
|
|
53
|
+
* // tree.type === 'BinaryExpression'
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* Invalid condition
|
|
58
|
+
* ```typescript
|
|
59
|
+
* import { parseCriterionCondition } from '@usearazzo/parser';
|
|
60
|
+
*
|
|
61
|
+
* const { result, tree } = parseCriterionCondition('$statusCode ===');
|
|
62
|
+
* // result.success === false
|
|
63
|
+
* // tree === undefined
|
|
64
|
+
* // result.maxMatched - the offset parsing failed at
|
|
65
|
+
* ```
|
|
66
|
+
* @public
|
|
67
|
+
*/
|
|
68
|
+
export function parse(condition, options = defaultOptions) {
|
|
69
|
+
return parseCriterionCondition(condition, options);
|
|
70
|
+
}
|
|
71
|
+
export { ArazzoCriterionParseError };
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.defaultOptions = void 0;
|
|
8
|
+
exports.parse = parse;
|
|
9
|
+
var _empty = require("@speclynx/apidom-reference/configuration/empty");
|
|
10
|
+
var _openapiJson = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-json-2"));
|
|
11
|
+
var _openapiYaml = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-yaml-2"));
|
|
12
|
+
var _openapiJson2 = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-json-3-0"));
|
|
13
|
+
var _openapiYaml2 = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-yaml-3-0"));
|
|
14
|
+
var _openapiJson3 = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-json-3-1"));
|
|
15
|
+
var _openapiYaml3 = _interopRequireDefault(require("@speclynx/apidom-reference/parse/parsers/openapi-yaml-3-1"));
|
|
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 _util = require("./options/util.cjs");
|
|
25
|
+
var _index = _interopRequireDefault(require("./resolve/resolvers/memory/index.cjs"));
|
|
26
|
+
var _parseArazzo = require("./parse-arazzo.cjs");
|
|
27
|
+
/**
|
|
28
|
+
* Options for parsing OpenAPI Documents.
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Default reference options for parsing OpenAPI Documents.
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
const defaultOptions = exports.defaultOptions = {
|
|
37
|
+
parse: {
|
|
38
|
+
parsers: [new _openapiJson.default({
|
|
39
|
+
allowEmpty: false
|
|
40
|
+
}), new _openapiYaml.default({
|
|
41
|
+
allowEmpty: false
|
|
42
|
+
}), new _openapiJson2.default({
|
|
43
|
+
allowEmpty: false
|
|
44
|
+
}), new _openapiYaml2.default({
|
|
45
|
+
allowEmpty: false
|
|
46
|
+
}), new _openapiJson3.default({
|
|
47
|
+
allowEmpty: false
|
|
48
|
+
}), new _openapiYaml3.default({
|
|
49
|
+
allowEmpty: false
|
|
50
|
+
})],
|
|
51
|
+
parserOpts: {
|
|
52
|
+
..._parseArazzo.defaultOptions.parse.parserOpts
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
resolve: {
|
|
56
|
+
resolvers: [..._parseArazzo.defaultOptions.resolve.resolvers],
|
|
57
|
+
resolverOpts: {}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Parses an OpenAPI Document from an object.
|
|
63
|
+
* @param source - The OpenAPI Document as a plain object
|
|
64
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
65
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
66
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Parses an OpenAPI Document from a string or URI.
|
|
72
|
+
* @param source - The OpenAPI Document as string content, or a file system path / HTTP(S) URL
|
|
73
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
74
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
75
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
76
|
+
* @public
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Parses an OpenAPI Document from a string, object, or URI.
|
|
81
|
+
* @param source - The OpenAPI Document as a plain object, string content, or URI
|
|
82
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
83
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
84
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Parses an OpenAPI Document from a string, object, or URI.
|
|
90
|
+
*
|
|
91
|
+
* The function handles three types of input:
|
|
92
|
+
* 1. Object - converts to JSON string and parses (source maps supported with `strict: false`)
|
|
93
|
+
* 2. String content - uses OpenAPI detection to identify and parse inline JSON or YAML content
|
|
94
|
+
* 3. URI string - if not detected as OpenAPI content, treats as file system path or HTTP(S) URL
|
|
95
|
+
*
|
|
96
|
+
* @param source - The OpenAPI Document as an object, string content, or a file system path / HTTP(S) URL
|
|
97
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
98
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
99
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* Parse from object
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const result = await parseOpenAPI({ openapi: '3.1.0', info: {...} });
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* Parse inline JSON
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const result = await parseOpenAPI('{"openapi": "3.1.0", "info": {...}}');
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* Parse from file
|
|
115
|
+
* ```typescript
|
|
116
|
+
* const result = await parseOpenAPI('/path/to/openapi.json');
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* Parse from URL
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const result = await parseOpenAPI('https://example.com/openapi.yaml');
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* Parse with custom options
|
|
127
|
+
* ```typescript
|
|
128
|
+
* const result = await parseOpenAPI('/path/to/openapi.json', customOptions);
|
|
129
|
+
* ```
|
|
130
|
+
* @public
|
|
131
|
+
*/
|
|
132
|
+
async function parse(source, options = {}) {
|
|
133
|
+
let mergedOptions = (0, _util.mergeOptions)(defaultOptions, options);
|
|
134
|
+
const strict = mergedOptions.parse?.parserOpts?.strict ?? true;
|
|
135
|
+
let sourceProvenance;
|
|
136
|
+
let document;
|
|
137
|
+
if ((0, _ramdaAdjunct.isPlainObject)(source)) {
|
|
138
|
+
document = JSON.stringify(source, null, 2);
|
|
139
|
+
source = 'memory://openapi.json';
|
|
140
|
+
sourceProvenance = '[object]';
|
|
141
|
+
} else if (await (0, _apidomParserAdapterOpenapiJson3.detect)(source, {
|
|
142
|
+
strict
|
|
143
|
+
})) {
|
|
144
|
+
document = source;
|
|
145
|
+
source = 'memory://openapi.json';
|
|
146
|
+
sourceProvenance = '[inline JSON]';
|
|
147
|
+
} else if (await (0, _apidomParserAdapterOpenapiYaml3.detect)(source, {
|
|
148
|
+
strict
|
|
149
|
+
})) {
|
|
150
|
+
document = source;
|
|
151
|
+
source = 'memory://openapi.yaml';
|
|
152
|
+
sourceProvenance = '[inline YAML]';
|
|
153
|
+
} else if (await (0, _apidomParserAdapterOpenapiJson2.detect)(source, {
|
|
154
|
+
strict
|
|
155
|
+
})) {
|
|
156
|
+
document = source;
|
|
157
|
+
source = 'memory://openapi.json';
|
|
158
|
+
sourceProvenance = '[inline JSON]';
|
|
159
|
+
} else if (await (0, _apidomParserAdapterOpenapiYaml2.detect)(source, {
|
|
160
|
+
strict
|
|
161
|
+
})) {
|
|
162
|
+
document = source;
|
|
163
|
+
source = 'memory://openapi.yaml';
|
|
164
|
+
sourceProvenance = '[inline YAML]';
|
|
165
|
+
} else if (await (0, _apidomParserAdapterOpenapiJson.detect)(source, {
|
|
166
|
+
strict
|
|
167
|
+
})) {
|
|
168
|
+
document = source;
|
|
169
|
+
source = 'memory://openapi.json';
|
|
170
|
+
sourceProvenance = '[inline JSON]';
|
|
171
|
+
} else if (await (0, _apidomParserAdapterOpenapiYaml.detect)(source, {
|
|
172
|
+
strict
|
|
173
|
+
})) {
|
|
174
|
+
document = source;
|
|
175
|
+
source = 'memory://openapi.yaml';
|
|
176
|
+
sourceProvenance = '[inline YAML]';
|
|
177
|
+
} else {
|
|
178
|
+
sourceProvenance = source;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// in-memory documents are served under their synthetic memory:// URI, or under the
|
|
182
|
+
// caller-supplied base URI so that relative references resolve against a real location
|
|
183
|
+
if (document !== undefined) {
|
|
184
|
+
// raw options, not merged: mergeOptions defaults baseURI to the current working directory
|
|
185
|
+
source = options.resolve?.baseURI || source;
|
|
186
|
+
mergedOptions = (0, _util.mergeOptions)(mergedOptions, {
|
|
187
|
+
resolve: {
|
|
188
|
+
resolvers: [...mergedOptions.resolve.resolvers, new _index.default({
|
|
189
|
+
document,
|
|
190
|
+
uri: source
|
|
191
|
+
})]
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// next we assume that source is either file system URI or HTTP(S) URL
|
|
197
|
+
try {
|
|
198
|
+
const parseResult = await (0, _empty.parse)(source, mergedOptions);
|
|
199
|
+
|
|
200
|
+
// set retrievalURI metadata for file/URL sources (not for inline content)
|
|
201
|
+
if (!source.startsWith('memory://')) {
|
|
202
|
+
parseResult.meta.set('retrievalURI', source);
|
|
203
|
+
}
|
|
204
|
+
return parseResult;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
throw new _ParseError.default(`Failed to parse OpenAPI Document from "${sourceProvenance}"`, {
|
|
207
|
+
cause: error
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { parse as parseURI } 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 { detect as detectOpenApiJSON3_1 } from '@speclynx/apidom-parser-adapter-openapi-json-3-1';
|
|
9
|
+
import { detect as detectOpenApiYAML3_1 } from '@speclynx/apidom-parser-adapter-openapi-yaml-3-1';
|
|
10
|
+
import { detect as detectOpenApiJSON3_0 } from '@speclynx/apidom-parser-adapter-openapi-json-3-0';
|
|
11
|
+
import { detect as detectOpenApiYAML3_0 } from '@speclynx/apidom-parser-adapter-openapi-yaml-3-0';
|
|
12
|
+
import { detect as detectOpenApiJSON2 } from '@speclynx/apidom-parser-adapter-openapi-json-2';
|
|
13
|
+
import { detect as detectOpenApiYAML2 } from '@speclynx/apidom-parser-adapter-openapi-yaml-2';
|
|
14
|
+
import { isPlainObject } from 'ramda-adjunct';
|
|
15
|
+
import ParseError from "./errors/ParseError.mjs";
|
|
16
|
+
import { mergeOptions } from "./options/util.mjs";
|
|
17
|
+
import MemoryResolver from "./resolve/resolvers/memory/index.mjs";
|
|
18
|
+
import { defaultOptions as arazzoDefaultOptions } from "./parse-arazzo.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
|
+
}), new OpenApiYAML2Parser({
|
|
32
|
+
allowEmpty: false
|
|
33
|
+
}), new OpenApiJSON3_0Parser({
|
|
34
|
+
allowEmpty: false
|
|
35
|
+
}), new OpenApiYAML3_0Parser({
|
|
36
|
+
allowEmpty: false
|
|
37
|
+
}), new OpenApiJSON3_1Parser({
|
|
38
|
+
allowEmpty: false
|
|
39
|
+
}), new OpenApiYAML3_1Parser({
|
|
40
|
+
allowEmpty: false
|
|
41
|
+
})],
|
|
42
|
+
parserOpts: {
|
|
43
|
+
...arazzoDefaultOptions.parse.parserOpts
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
resolve: {
|
|
47
|
+
resolvers: [...arazzoDefaultOptions.resolve.resolvers],
|
|
48
|
+
resolverOpts: {}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Parses an OpenAPI Document from an object.
|
|
54
|
+
* @param source - The OpenAPI Document as a plain object
|
|
55
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
56
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
57
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Parses an OpenAPI Document from a string or URI.
|
|
63
|
+
* @param source - The OpenAPI Document as string content, or a file system path / HTTP(S) URL
|
|
64
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
65
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
66
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Parses an OpenAPI Document from a string, object, or URI.
|
|
72
|
+
* @param source - The OpenAPI Document as a plain object, string content, or URI
|
|
73
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
74
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
75
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
76
|
+
* @public
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Parses an OpenAPI Document from a string, object, or URI.
|
|
81
|
+
*
|
|
82
|
+
* The function handles three types of input:
|
|
83
|
+
* 1. Object - converts to JSON string and parses (source maps supported with `strict: false`)
|
|
84
|
+
* 2. String content - uses OpenAPI detection to identify and parse inline JSON or YAML content
|
|
85
|
+
* 3. URI string - if not detected as OpenAPI content, treats as file system path or HTTP(S) URL
|
|
86
|
+
*
|
|
87
|
+
* @param source - The OpenAPI Document as an object, string content, or a file system path / HTTP(S) URL
|
|
88
|
+
* @param options - Reference options (uses defaultOptions when not provided)
|
|
89
|
+
* @returns A promise that resolves to the parsed OpenAPI Document as ApiDOM data model
|
|
90
|
+
* @throws ParseError - When parsing fails for any reason. The original error is available via the `cause` property.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* Parse from object
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const result = await parseOpenAPI({ openapi: '3.1.0', info: {...} });
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* Parse inline JSON
|
|
100
|
+
* ```typescript
|
|
101
|
+
* const result = await parseOpenAPI('{"openapi": "3.1.0", "info": {...}}');
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* Parse from file
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const result = await parseOpenAPI('/path/to/openapi.json');
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* Parse from URL
|
|
112
|
+
* ```typescript
|
|
113
|
+
* const result = await parseOpenAPI('https://example.com/openapi.yaml');
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* Parse with custom options
|
|
118
|
+
* ```typescript
|
|
119
|
+
* const result = await parseOpenAPI('/path/to/openapi.json', customOptions);
|
|
120
|
+
* ```
|
|
121
|
+
* @public
|
|
122
|
+
*/
|
|
123
|
+
export async function parse(source, options = {}) {
|
|
124
|
+
let mergedOptions = mergeOptions(defaultOptions, options);
|
|
125
|
+
const strict = mergedOptions.parse?.parserOpts?.strict ?? true;
|
|
126
|
+
let sourceProvenance;
|
|
127
|
+
let document;
|
|
128
|
+
if (isPlainObject(source)) {
|
|
129
|
+
document = JSON.stringify(source, null, 2);
|
|
130
|
+
source = 'memory://openapi.json';
|
|
131
|
+
sourceProvenance = '[object]';
|
|
132
|
+
} else if (await detectOpenApiJSON2(source, {
|
|
133
|
+
strict
|
|
134
|
+
})) {
|
|
135
|
+
document = source;
|
|
136
|
+
source = 'memory://openapi.json';
|
|
137
|
+
sourceProvenance = '[inline JSON]';
|
|
138
|
+
} else if (await detectOpenApiYAML2(source, {
|
|
139
|
+
strict
|
|
140
|
+
})) {
|
|
141
|
+
document = source;
|
|
142
|
+
source = 'memory://openapi.yaml';
|
|
143
|
+
sourceProvenance = '[inline YAML]';
|
|
144
|
+
} else if (await detectOpenApiJSON3_0(source, {
|
|
145
|
+
strict
|
|
146
|
+
})) {
|
|
147
|
+
document = source;
|
|
148
|
+
source = 'memory://openapi.json';
|
|
149
|
+
sourceProvenance = '[inline JSON]';
|
|
150
|
+
} else if (await detectOpenApiYAML3_0(source, {
|
|
151
|
+
strict
|
|
152
|
+
})) {
|
|
153
|
+
document = source;
|
|
154
|
+
source = 'memory://openapi.yaml';
|
|
155
|
+
sourceProvenance = '[inline YAML]';
|
|
156
|
+
} else if (await detectOpenApiJSON3_1(source, {
|
|
157
|
+
strict
|
|
158
|
+
})) {
|
|
159
|
+
document = source;
|
|
160
|
+
source = 'memory://openapi.json';
|
|
161
|
+
sourceProvenance = '[inline JSON]';
|
|
162
|
+
} else if (await detectOpenApiYAML3_1(source, {
|
|
163
|
+
strict
|
|
164
|
+
})) {
|
|
165
|
+
document = source;
|
|
166
|
+
source = 'memory://openapi.yaml';
|
|
167
|
+
sourceProvenance = '[inline YAML]';
|
|
168
|
+
} else {
|
|
169
|
+
sourceProvenance = source;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// in-memory documents are served under their synthetic memory:// URI, or under the
|
|
173
|
+
// caller-supplied base URI so that relative references resolve against a real location
|
|
174
|
+
if (document !== undefined) {
|
|
175
|
+
// raw options, not merged: mergeOptions defaults baseURI to the current working directory
|
|
176
|
+
source = options.resolve?.baseURI || source;
|
|
177
|
+
mergedOptions = mergeOptions(mergedOptions, {
|
|
178
|
+
resolve: {
|
|
179
|
+
resolvers: [...mergedOptions.resolve.resolvers, new MemoryResolver({
|
|
180
|
+
document,
|
|
181
|
+
uri: source
|
|
182
|
+
})]
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// next we assume that source is either file system URI or HTTP(S) URL
|
|
188
|
+
try {
|
|
189
|
+
const parseResult = await parseURI(source, mergedOptions);
|
|
190
|
+
|
|
191
|
+
// set retrievalURI metadata for file/URL sources (not for inline content)
|
|
192
|
+
if (!source.startsWith('memory://')) {
|
|
193
|
+
parseResult.meta.set('retrievalURI', source);
|
|
194
|
+
}
|
|
195
|
+
return parseResult;
|
|
196
|
+
} catch (error) {
|
|
197
|
+
throw new ParseError(`Failed to parse OpenAPI Document from "${sourceProvenance}"`, {
|
|
198
|
+
cause: error
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "ArazzoRuntimeExpressionParseError", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _arazzoRuntimeExpression.ArazzoRuntimeExpressionParseError;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
exports.defaultOptions = void 0;
|
|
13
|
+
exports.parse = parse;
|
|
14
|
+
var _arazzoRuntimeExpression = require("@swaggerexpert/arazzo-runtime-expression");
|
|
15
|
+
/**
|
|
16
|
+
* Options for parsing Arazzo Runtime Expressions.
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Result of parsing an Arazzo Runtime Expression: the foundation ParseResult
|
|
22
|
+
* bound to the AST node type this parser produces.
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Default options for parsing Arazzo Runtime Expressions. Empty on purpose:
|
|
28
|
+
* the underlying grammar package supplies its own defaults, including a fresh
|
|
29
|
+
* ASTTranslator per call.
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
const defaultOptions = exports.defaultOptions = {};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Parses an Arazzo Runtime Expression (e.g. `$inputs.username`,
|
|
36
|
+
* `$steps.myStep.outputs.result`, `$response.body#/pets/0/id`) into its AST.
|
|
37
|
+
*
|
|
38
|
+
* A pure, context-free syntax parser: the expression string in, an AST plus
|
|
39
|
+
* position-carrying diagnostics (`result.matched` / `result.maxMatched`) out.
|
|
40
|
+
* No evaluation is performed and no document is required; evaluating the
|
|
41
|
+
* parsed expression against runtime state is the runner's responsibility.
|
|
42
|
+
*
|
|
43
|
+
* The expression must be the bare form without surrounding braces. Splitting a
|
|
44
|
+
* `{expression}` template into literal and expression spans is left to
|
|
45
|
+
* `@swaggerexpert/arazzo-runtime-expression`'s own `extract`/`interpolate`
|
|
46
|
+
* functions, which remain a foundation dependency rather than being wrapped
|
|
47
|
+
* here.
|
|
48
|
+
*
|
|
49
|
+
* @param expression - The runtime expression source string
|
|
50
|
+
* @param options - Parse options (uses defaultOptions when not provided)
|
|
51
|
+
* @returns The parse result: `{ result, tree, stats, trace }`. On success,
|
|
52
|
+
* `result.success` is `true` and `tree` holds the AST. On failure,
|
|
53
|
+
* `result.success` is `false`, `tree` is `undefined`, and `result.maxMatched`
|
|
54
|
+
* gives the offset into `expression` up to which parsing succeeded.
|
|
55
|
+
* @throws TypeError - When `expression` is not a string.
|
|
56
|
+
* @throws ArazzoRuntimeExpressionParseError - When parsing fails for a reason
|
|
57
|
+
* other than invalid syntax (an unexpected internal error). Invalid syntax is
|
|
58
|
+
* never thrown; it is reported through the returned `result`.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* Valid expression
|
|
62
|
+
* ```typescript
|
|
63
|
+
* import { parseRuntimeExpression } from '@usearazzo/parser';
|
|
64
|
+
*
|
|
65
|
+
* const { result, tree } = parseRuntimeExpression('$steps.myStep.outputs.result');
|
|
66
|
+
* // result.success === true
|
|
67
|
+
* // tree === { type: 'StepsExpression', stepId: 'myStep', field: 'outputs', outputName: 'result' }
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* Invalid expression
|
|
72
|
+
* ```typescript
|
|
73
|
+
* import { parseRuntimeExpression } from '@usearazzo/parser';
|
|
74
|
+
*
|
|
75
|
+
* const { result, tree } = parseRuntimeExpression('$unknown.thing');
|
|
76
|
+
* // result.success === false
|
|
77
|
+
* // tree === undefined
|
|
78
|
+
* // result.maxMatched === 0 - the offset parsing failed at
|
|
79
|
+
* ```
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
function parse(expression, options = defaultOptions) {
|
|
83
|
+
return (0, _arazzoRuntimeExpression.parse)(expression, options);
|
|
84
|
+
}
|