@jentic/arazzo-parser 1.0.0-alpha.32 → 1.0.0-alpha.33
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 +15 -0
- package/dist/jentic-arazzo-parser.browser.js +1282 -224
- package/dist/jentic-arazzo-parser.browser.min.js +1 -1
- package/package.json +7 -5
- package/src/index.cjs +13 -0
- package/src/index.mjs +1 -0
- package/src/step-operations.cjs +156 -0
- package/src/step-operations.mjs +150 -0
- package/types/arazzo-parser.d.ts +60 -0
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.33",
|
|
4
4
|
"description": "Parser for Arazzo Documents producing SpecLynx ApiDOM data model.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"arazzo",
|
|
@@ -48,9 +48,14 @@
|
|
|
48
48
|
"license": "Apache-2.0",
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@babel/runtime-corejs3": "^8.0.0",
|
|
51
|
+
"@speclynx/apidom-core": "^5.0.1",
|
|
51
52
|
"@speclynx/apidom-datamodel": "^5.0.1",
|
|
52
53
|
"@speclynx/apidom-error": "^5.0.1",
|
|
54
|
+
"@speclynx/apidom-json-pointer": "^5.0.1",
|
|
53
55
|
"@speclynx/apidom-ns-arazzo-1": "^5.0.1",
|
|
56
|
+
"@speclynx/apidom-ns-openapi-2": "^5.0.1",
|
|
57
|
+
"@speclynx/apidom-ns-openapi-3-0": "^5.0.1",
|
|
58
|
+
"@speclynx/apidom-ns-openapi-3-1": "^5.0.1",
|
|
54
59
|
"@speclynx/apidom-parser-adapter-arazzo-json-1": "^5.0.1",
|
|
55
60
|
"@speclynx/apidom-parser-adapter-arazzo-yaml-1": "^5.0.1",
|
|
56
61
|
"@speclynx/apidom-parser-adapter-openapi-json-2": "^5.0.1",
|
|
@@ -63,9 +68,6 @@
|
|
|
63
68
|
"ramda-adjunct": "^6.0.0",
|
|
64
69
|
"type-fest": "^5.4.4"
|
|
65
70
|
},
|
|
66
|
-
"devDependencies": {
|
|
67
|
-
"@speclynx/apidom-core": "^5.0.1"
|
|
68
|
-
},
|
|
69
71
|
"files": [
|
|
70
72
|
"src/**/*.mjs",
|
|
71
73
|
"src/**/*.cjs",
|
|
@@ -76,5 +78,5 @@
|
|
|
76
78
|
"README.md",
|
|
77
79
|
"CHANGELOG.md"
|
|
78
80
|
],
|
|
79
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "a17270442ac27615af0348fad9c71817d818151f"
|
|
80
82
|
}
|
package/src/index.cjs
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "attachStepOperations", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _stepOperations.attachStepOperations;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "defaultParseArazzoOptions", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function () {
|
|
@@ -15,6 +21,12 @@ Object.defineProperty(exports, "defaultParseOpenAPIOptions", {
|
|
|
15
21
|
return _parseOpenapi.defaultOptions;
|
|
16
22
|
}
|
|
17
23
|
});
|
|
24
|
+
Object.defineProperty(exports, "findStepOperation", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _stepOperations.findStepOperation;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
18
30
|
Object.defineProperty(exports, "parseArazzo", {
|
|
19
31
|
enumerable: true,
|
|
20
32
|
get: function () {
|
|
@@ -28,4 +40,5 @@ Object.defineProperty(exports, "parseOpenAPI", {
|
|
|
28
40
|
}
|
|
29
41
|
});
|
|
30
42
|
var _parseArazzo = require("./parse-arazzo.cjs");
|
|
43
|
+
var _stepOperations = require("./step-operations.cjs");
|
|
31
44
|
var _parseOpenapi = require("./parse-openapi.cjs");
|
package/src/index.mjs
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { parse as parseArazzo, defaultOptions as defaultParseArazzoOptions } from "./parse-arazzo.mjs";
|
|
2
|
+
export { findStepOperation, attachStepOperations } from "./step-operations.mjs";
|
|
2
3
|
export { parse as parseOpenAPI, defaultOptions as defaultParseOpenAPIOptions } from "./parse-openapi.mjs";
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.attachStepOperations = attachStepOperations;
|
|
7
|
+
exports.findStepOperation = findStepOperation;
|
|
8
|
+
var _apidomCore = require("@speclynx/apidom-core");
|
|
9
|
+
var _apidomJsonPointer = require("@speclynx/apidom-json-pointer");
|
|
10
|
+
var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
|
|
11
|
+
var _apidomNsOpenapi = require("@speclynx/apidom-ns-openapi-2");
|
|
12
|
+
var _apidomNsOpenapi2 = require("@speclynx/apidom-ns-openapi-3-0");
|
|
13
|
+
var _apidomNsOpenapi3 = require("@speclynx/apidom-ns-openapi-3-1");
|
|
14
|
+
/**
|
|
15
|
+
* HTTP method and path of the OpenAPI operation targeted by an Arazzo step.
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Minimal shape of a plain Arazzo Document needed to attach step operations.
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A plain Arazzo Document whose steps may carry the `_operation` they target. Every other field
|
|
26
|
+
* of the document type, and of its workflows and steps, is preserved as is.
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// OpenAPI 3.1 path items extend the OpenAPI 3.0 ones, so isPathItem3Element covers both
|
|
31
|
+
const pathItemOperations = pathItem => ({
|
|
32
|
+
get: pathItem.getField,
|
|
33
|
+
put: pathItem.put,
|
|
34
|
+
post: pathItem.post,
|
|
35
|
+
delete: pathItem.deleteField,
|
|
36
|
+
options: pathItem.options,
|
|
37
|
+
head: pathItem.head,
|
|
38
|
+
patch: pathItem.patch,
|
|
39
|
+
trace: (0, _apidomNsOpenapi2.isPathItemElement)(pathItem) ? pathItem.trace : undefined
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// resolves a (possibly relative) URI against the document it appears in, as far as possible
|
|
43
|
+
const resolveURI = (uri, baseURI) => {
|
|
44
|
+
try {
|
|
45
|
+
return new URL(uri, baseURI).href;
|
|
46
|
+
} catch {
|
|
47
|
+
return uri;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// whether a literal URL targets the document of the source description, as declared or as retrieved
|
|
52
|
+
const targetsSource = (sourceDescription, documentURI, baseURI) => {
|
|
53
|
+
const target = resolveURI(documentURI, baseURI);
|
|
54
|
+
const url = sourceDescription.url?.toValue();
|
|
55
|
+
const retrievalURI = sourceDescription.meta.get('parseResult')?.meta.get('retrievalURI');
|
|
56
|
+
return [url, retrievalURI].some(uri => uri !== undefined && (uri === documentURI || resolveURI(uri, baseURI) === target));
|
|
57
|
+
};
|
|
58
|
+
const pointerTokens = pointer => pointer.split('/').slice(1).map(token => token.replace(/~1/g, '/').replace(/~0/g, '~'));
|
|
59
|
+
|
|
60
|
+
// resolves a JSON Pointer against a source document, so it can target operations of both
|
|
61
|
+
// `paths` entries and reusable Path Items (`#/components/pathItems/...`)
|
|
62
|
+
const operationAtPointer = (api, pointer) => {
|
|
63
|
+
const tokens = pointerTokens(pointer);
|
|
64
|
+
const withPath = method => ({
|
|
65
|
+
method: method.toUpperCase(),
|
|
66
|
+
...(tokens[0] === 'paths' && {
|
|
67
|
+
path: tokens[1]
|
|
68
|
+
})
|
|
69
|
+
});
|
|
70
|
+
const evaluateAt = parts => {
|
|
71
|
+
try {
|
|
72
|
+
return (0, _apidomJsonPointer.evaluate)(api, (0, _apidomJsonPointer.compile)(parts));
|
|
73
|
+
} catch {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const target = evaluateAt(tokens);
|
|
78
|
+
// a pointer to a path item (no method) is unambiguous only when it has a single operation
|
|
79
|
+
if ((0, _apidomNsOpenapi.isPathItemElement)(target) || (0, _apidomNsOpenapi2.isPathItemElement)(target)) {
|
|
80
|
+
const defined = Object.entries(pathItemOperations(target)).filter(([, operation]) => operation);
|
|
81
|
+
return defined.length === 1 ? withPath(defined[0][0]) : undefined;
|
|
82
|
+
}
|
|
83
|
+
const method = tokens[tokens.length - 1];
|
|
84
|
+
const parent = evaluateAt(tokens.slice(0, -1));
|
|
85
|
+
if (!target || !((0, _apidomNsOpenapi.isPathItemElement)(parent) || (0, _apidomNsOpenapi2.isPathItemElement)(parent))) return undefined;
|
|
86
|
+
return Object.keys(pathItemOperations(parent)).includes(method) ? withPath(method) : undefined;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Finds the OpenAPI operation targeted by an Arazzo step in the `openapi` source descriptions
|
|
91
|
+
* parsed along with the Arazzo Document (see the `sourceDescriptions` parser option).
|
|
92
|
+
* @param parseResult - The result of parsing an Arazzo Document with source descriptions
|
|
93
|
+
* @param step - The step's `operationId` or `operationPath`
|
|
94
|
+
* @returns The operation's HTTP method and path, or undefined when it can't be located
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
function findStepOperation(parseResult, {
|
|
98
|
+
operationId,
|
|
99
|
+
operationPath
|
|
100
|
+
}) {
|
|
101
|
+
const reference = operationPath ?? operationId;
|
|
102
|
+
if (!reference || !(0, _apidomNsArazzo.isArazzoSpecification1Element)(parseResult.api)) return undefined;
|
|
103
|
+
// `$sourceDescriptions.{name}.{operationId}` and `{$sourceDescriptions.{name}.url}#{pointer}` name their source
|
|
104
|
+
const [, sourceName, qualifiedId] = /^\{?\$sourceDescriptions\.([^.]+)\.(.+)$/.exec(reference) ?? [];
|
|
105
|
+
const pointer = operationPath && _apidomJsonPointer.URIFragmentIdentifier.fromURIReference(operationPath);
|
|
106
|
+
// a literal URL (no `$sourceDescriptions` expression) names its source by the document it targets
|
|
107
|
+
const documentURI = operationPath && !sourceName ? operationPath.split('#')[0].replace(/^\{|\}$/g, '') : '';
|
|
108
|
+
const baseURI = parseResult.meta.get('retrievalURI');
|
|
109
|
+
let found;
|
|
110
|
+
parseResult.api.sourceDescriptions?.forEach(sourceDescription => {
|
|
111
|
+
if (found || !(0, _apidomNsArazzo.isSourceDescriptionElement)(sourceDescription)) return;
|
|
112
|
+
if (sourceDescription.type && sourceDescription.type.toValue() !== 'openapi') return;
|
|
113
|
+
if (sourceName && sourceDescription.name?.toValue() !== sourceName) return;
|
|
114
|
+
// the source must be the one the URL targets, and it is not searched when it failed to load
|
|
115
|
+
if (documentURI && !targetsSource(sourceDescription, documentURI, baseURI)) return;
|
|
116
|
+
const api = sourceDescription.meta.get('parseResult')?.api;
|
|
117
|
+
if (!(0, _apidomNsOpenapi.isSwaggerElement)(api) && !(0, _apidomNsOpenapi2.isOpenApi3_0Element)(api) && !(0, _apidomNsOpenapi3.isOpenApi3_1Element)(api)) return;
|
|
118
|
+
if (pointer) {
|
|
119
|
+
found = operationAtPointer(api, pointer);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
api.paths?.forEach((pathItem, key) => {
|
|
123
|
+
if (found || !(0, _apidomNsOpenapi.isPathItemElement)(pathItem) && !(0, _apidomNsOpenapi2.isPathItemElement)(pathItem)) return;
|
|
124
|
+
const path = String(key.toValue());
|
|
125
|
+
for (const [method, operation] of Object.entries(pathItemOperations(pathItem))) {
|
|
126
|
+
if (operation?.operationId?.toValue() === (qualifiedId ?? operationId)) {
|
|
127
|
+
found = {
|
|
128
|
+
method: method.toUpperCase(),
|
|
129
|
+
path
|
|
130
|
+
};
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
return found;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Converts an Arazzo Document element to a plain object and sets `_operation` on every step that
|
|
141
|
+
* targets an operation of the `openapi` source descriptions parsed along with it.
|
|
142
|
+
* @param element - The Arazzo Document element, e.g. the (dereferenced) result of the parse result
|
|
143
|
+
* @param parseResult - The result of parsing the Arazzo Document with source descriptions
|
|
144
|
+
* @returns The plain Arazzo Document, typed with `_operation` on its steps and set on the resolved ones
|
|
145
|
+
* @public
|
|
146
|
+
*/
|
|
147
|
+
function attachStepOperations(element, parseResult) {
|
|
148
|
+
const doc = (0, _apidomCore.toValue)(element);
|
|
149
|
+
doc?.workflows?.forEach(workflow => workflow.steps?.forEach(step => {
|
|
150
|
+
const operation = findStepOperation(parseResult, step);
|
|
151
|
+
if (operation) Object.assign(step, {
|
|
152
|
+
_operation: operation
|
|
153
|
+
});
|
|
154
|
+
}));
|
|
155
|
+
return doc;
|
|
156
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
2
|
+
import { compile, evaluate, URIFragmentIdentifier } from '@speclynx/apidom-json-pointer';
|
|
3
|
+
import { isArazzoSpecification1Element, isSourceDescriptionElement } from '@speclynx/apidom-ns-arazzo-1';
|
|
4
|
+
import { isSwaggerElement, isPathItemElement as isPathItem2Element } from '@speclynx/apidom-ns-openapi-2';
|
|
5
|
+
import { isOpenApi3_0Element, isPathItemElement as isPathItem3Element } from '@speclynx/apidom-ns-openapi-3-0';
|
|
6
|
+
import { isOpenApi3_1Element } from '@speclynx/apidom-ns-openapi-3-1';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* HTTP method and path of the OpenAPI operation targeted by an Arazzo step.
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Minimal shape of a plain Arazzo Document needed to attach step operations.
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A plain Arazzo Document whose steps may carry the `_operation` they target. Every other field
|
|
20
|
+
* of the document type, and of its workflows and steps, is preserved as is.
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// OpenAPI 3.1 path items extend the OpenAPI 3.0 ones, so isPathItem3Element covers both
|
|
25
|
+
const pathItemOperations = pathItem => ({
|
|
26
|
+
get: pathItem.getField,
|
|
27
|
+
put: pathItem.put,
|
|
28
|
+
post: pathItem.post,
|
|
29
|
+
delete: pathItem.deleteField,
|
|
30
|
+
options: pathItem.options,
|
|
31
|
+
head: pathItem.head,
|
|
32
|
+
patch: pathItem.patch,
|
|
33
|
+
trace: isPathItem3Element(pathItem) ? pathItem.trace : undefined
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// resolves a (possibly relative) URI against the document it appears in, as far as possible
|
|
37
|
+
const resolveURI = (uri, baseURI) => {
|
|
38
|
+
try {
|
|
39
|
+
return new URL(uri, baseURI).href;
|
|
40
|
+
} catch {
|
|
41
|
+
return uri;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// whether a literal URL targets the document of the source description, as declared or as retrieved
|
|
46
|
+
const targetsSource = (sourceDescription, documentURI, baseURI) => {
|
|
47
|
+
const target = resolveURI(documentURI, baseURI);
|
|
48
|
+
const url = sourceDescription.url?.toValue();
|
|
49
|
+
const retrievalURI = sourceDescription.meta.get('parseResult')?.meta.get('retrievalURI');
|
|
50
|
+
return [url, retrievalURI].some(uri => uri !== undefined && (uri === documentURI || resolveURI(uri, baseURI) === target));
|
|
51
|
+
};
|
|
52
|
+
const pointerTokens = pointer => pointer.split('/').slice(1).map(token => token.replace(/~1/g, '/').replace(/~0/g, '~'));
|
|
53
|
+
|
|
54
|
+
// resolves a JSON Pointer against a source document, so it can target operations of both
|
|
55
|
+
// `paths` entries and reusable Path Items (`#/components/pathItems/...`)
|
|
56
|
+
const operationAtPointer = (api, pointer) => {
|
|
57
|
+
const tokens = pointerTokens(pointer);
|
|
58
|
+
const withPath = method => ({
|
|
59
|
+
method: method.toUpperCase(),
|
|
60
|
+
...(tokens[0] === 'paths' && {
|
|
61
|
+
path: tokens[1]
|
|
62
|
+
})
|
|
63
|
+
});
|
|
64
|
+
const evaluateAt = parts => {
|
|
65
|
+
try {
|
|
66
|
+
return evaluate(api, compile(parts));
|
|
67
|
+
} catch {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const target = evaluateAt(tokens);
|
|
72
|
+
// a pointer to a path item (no method) is unambiguous only when it has a single operation
|
|
73
|
+
if (isPathItem2Element(target) || isPathItem3Element(target)) {
|
|
74
|
+
const defined = Object.entries(pathItemOperations(target)).filter(([, operation]) => operation);
|
|
75
|
+
return defined.length === 1 ? withPath(defined[0][0]) : undefined;
|
|
76
|
+
}
|
|
77
|
+
const method = tokens[tokens.length - 1];
|
|
78
|
+
const parent = evaluateAt(tokens.slice(0, -1));
|
|
79
|
+
if (!target || !(isPathItem2Element(parent) || isPathItem3Element(parent))) return undefined;
|
|
80
|
+
return Object.keys(pathItemOperations(parent)).includes(method) ? withPath(method) : undefined;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Finds the OpenAPI operation targeted by an Arazzo step in the `openapi` source descriptions
|
|
85
|
+
* parsed along with the Arazzo Document (see the `sourceDescriptions` parser option).
|
|
86
|
+
* @param parseResult - The result of parsing an Arazzo Document with source descriptions
|
|
87
|
+
* @param step - The step's `operationId` or `operationPath`
|
|
88
|
+
* @returns The operation's HTTP method and path, or undefined when it can't be located
|
|
89
|
+
* @public
|
|
90
|
+
*/
|
|
91
|
+
export function findStepOperation(parseResult, {
|
|
92
|
+
operationId,
|
|
93
|
+
operationPath
|
|
94
|
+
}) {
|
|
95
|
+
const reference = operationPath ?? operationId;
|
|
96
|
+
if (!reference || !isArazzoSpecification1Element(parseResult.api)) return undefined;
|
|
97
|
+
// `$sourceDescriptions.{name}.{operationId}` and `{$sourceDescriptions.{name}.url}#{pointer}` name their source
|
|
98
|
+
const [, sourceName, qualifiedId] = /^\{?\$sourceDescriptions\.([^.]+)\.(.+)$/.exec(reference) ?? [];
|
|
99
|
+
const pointer = operationPath && URIFragmentIdentifier.fromURIReference(operationPath);
|
|
100
|
+
// a literal URL (no `$sourceDescriptions` expression) names its source by the document it targets
|
|
101
|
+
const documentURI = operationPath && !sourceName ? operationPath.split('#')[0].replace(/^\{|\}$/g, '') : '';
|
|
102
|
+
const baseURI = parseResult.meta.get('retrievalURI');
|
|
103
|
+
let found;
|
|
104
|
+
parseResult.api.sourceDescriptions?.forEach(sourceDescription => {
|
|
105
|
+
if (found || !isSourceDescriptionElement(sourceDescription)) return;
|
|
106
|
+
if (sourceDescription.type && sourceDescription.type.toValue() !== 'openapi') return;
|
|
107
|
+
if (sourceName && sourceDescription.name?.toValue() !== sourceName) return;
|
|
108
|
+
// the source must be the one the URL targets, and it is not searched when it failed to load
|
|
109
|
+
if (documentURI && !targetsSource(sourceDescription, documentURI, baseURI)) return;
|
|
110
|
+
const api = sourceDescription.meta.get('parseResult')?.api;
|
|
111
|
+
if (!isSwaggerElement(api) && !isOpenApi3_0Element(api) && !isOpenApi3_1Element(api)) return;
|
|
112
|
+
if (pointer) {
|
|
113
|
+
found = operationAtPointer(api, pointer);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
api.paths?.forEach((pathItem, key) => {
|
|
117
|
+
if (found || !isPathItem2Element(pathItem) && !isPathItem3Element(pathItem)) return;
|
|
118
|
+
const path = String(key.toValue());
|
|
119
|
+
for (const [method, operation] of Object.entries(pathItemOperations(pathItem))) {
|
|
120
|
+
if (operation?.operationId?.toValue() === (qualifiedId ?? operationId)) {
|
|
121
|
+
found = {
|
|
122
|
+
method: method.toUpperCase(),
|
|
123
|
+
path
|
|
124
|
+
};
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
return found;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Converts an Arazzo Document element to a plain object and sets `_operation` on every step that
|
|
135
|
+
* targets an operation of the `openapi` source descriptions parsed along with it.
|
|
136
|
+
* @param element - The Arazzo Document element, e.g. the (dereferenced) result of the parse result
|
|
137
|
+
* @param parseResult - The result of parsing the Arazzo Document with source descriptions
|
|
138
|
+
* @returns The plain Arazzo Document, typed with `_operation` on its steps and set on the resolved ones
|
|
139
|
+
* @public
|
|
140
|
+
*/
|
|
141
|
+
export function attachStepOperations(element, parseResult) {
|
|
142
|
+
const doc = toValue(element);
|
|
143
|
+
doc?.workflows?.forEach(workflow => workflow.steps?.forEach(step => {
|
|
144
|
+
const operation = findStepOperation(parseResult, step);
|
|
145
|
+
if (operation) Object.assign(step, {
|
|
146
|
+
_operation: operation
|
|
147
|
+
});
|
|
148
|
+
}));
|
|
149
|
+
return doc;
|
|
150
|
+
}
|
package/types/arazzo-parser.d.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import type { ApiDOMReferenceOptions } from '@speclynx/apidom-reference/configuration/empty';
|
|
2
|
+
import type { Element as Element_2 } from '@speclynx/apidom-datamodel';
|
|
2
3
|
import { ParseResultElement } from '@speclynx/apidom-datamodel';
|
|
3
4
|
import type { PartialDeep } from 'type-fest';
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Converts an Arazzo Document element to a plain object and sets `_operation` on every step that
|
|
8
|
+
* targets an operation of the `openapi` source descriptions parsed along with it.
|
|
9
|
+
* @param element - The Arazzo Document element, e.g. the (dereferenced) result of the parse result
|
|
10
|
+
* @param parseResult - The result of parsing the Arazzo Document with source descriptions
|
|
11
|
+
* @returns The plain Arazzo Document, typed with `_operation` on its steps and set on the resolved ones
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export declare function attachStepOperations<T extends StepOperationsDocument = StepOperationsDocument>(element: Element_2 | undefined, parseResult: ParseResultElement): StepOperationsResult<T>;
|
|
15
|
+
|
|
5
16
|
/**
|
|
6
17
|
* Default reference options for parsing Arazzo Documents.
|
|
7
18
|
* @public
|
|
@@ -14,6 +25,19 @@ export declare const defaultParseArazzoOptions: ParseArazzoOptions;
|
|
|
14
25
|
*/
|
|
15
26
|
export declare const defaultParseOpenAPIOptions: ParseOpenAPIOptions;
|
|
16
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Finds the OpenAPI operation targeted by an Arazzo step in the `openapi` source descriptions
|
|
30
|
+
* parsed along with the Arazzo Document (see the `sourceDescriptions` parser option).
|
|
31
|
+
* @param parseResult - The result of parsing an Arazzo Document with source descriptions
|
|
32
|
+
* @param step - The step's `operationId` or `operationPath`
|
|
33
|
+
* @returns The operation's HTTP method and path, or undefined when it can't be located
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export declare function findStepOperation(parseResult: ParseResultElement, { operationId, operationPath }: {
|
|
37
|
+
operationId?: string;
|
|
38
|
+
operationPath?: string;
|
|
39
|
+
}): StepOperation | undefined;
|
|
40
|
+
|
|
17
41
|
/**
|
|
18
42
|
* Parses an Arazzo Document from an object.
|
|
19
43
|
* @param source - The Arazzo Document as a plain object
|
|
@@ -88,4 +112,40 @@ export declare type ParseOpenAPIOptions = PartialDeep<ApiDOMReferenceOptions>;
|
|
|
88
112
|
|
|
89
113
|
export { ParseResultElement }
|
|
90
114
|
|
|
115
|
+
/**
|
|
116
|
+
* HTTP method and path of the OpenAPI operation targeted by an Arazzo step.
|
|
117
|
+
* @public
|
|
118
|
+
*/
|
|
119
|
+
export declare interface StepOperation {
|
|
120
|
+
/** upper-case HTTP method, e.g. `GET` */
|
|
121
|
+
method: string;
|
|
122
|
+
path?: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Minimal shape of a plain Arazzo Document needed to attach step operations.
|
|
127
|
+
* @public
|
|
128
|
+
*/
|
|
129
|
+
export declare interface StepOperationsDocument {
|
|
130
|
+
workflows?: {
|
|
131
|
+
steps?: {
|
|
132
|
+
operationId?: string;
|
|
133
|
+
operationPath?: string;
|
|
134
|
+
}[];
|
|
135
|
+
}[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* A plain Arazzo Document whose steps may carry the `_operation` they target. Every other field
|
|
140
|
+
* of the document type, and of its workflows and steps, is preserved as is.
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
export declare type StepOperationsResult<T extends StepOperationsDocument = StepOperationsDocument> = {
|
|
144
|
+
[K in keyof T]: K extends 'workflows' ? NonNullable<T[K]> extends readonly (infer Workflow)[] ? {
|
|
145
|
+
[W in keyof Workflow]: W extends 'steps' ? NonNullable<Workflow[W]> extends readonly (infer Step)[] ? (Step & {
|
|
146
|
+
_operation?: StepOperation;
|
|
147
|
+
})[] : Workflow[W] : Workflow[W];
|
|
148
|
+
}[] : T[K] : T[K];
|
|
149
|
+
};
|
|
150
|
+
|
|
91
151
|
export { }
|