@usearazzo/runner 1.0.1-alpha.15 → 1.0.1-alpha.17
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/dist/arazzo-runner.browser.js +89 -33
- package/dist/arazzo-runner.browser.min.js +1 -1
- package/package.json +5 -5
- package/src/client/ParameterDelivery.cjs +28 -6
- package/src/client/ParameterDelivery.mjs +28 -6
- package/src/normalizer/ArazzoWorkflowNormalizer.cjs +49 -19
- package/src/normalizer/ArazzoWorkflowNormalizer.mjs +50 -20
- package/src/resolver/OpenAPIOperationParameterResolver.cjs +12 -8
- package/src/resolver/OpenAPIOperationParameterResolver.mjs +12 -8
- package/types/runner.d.ts +9 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usearazzo/runner",
|
|
3
|
-
"version": "1.0.1-alpha.
|
|
3
|
+
"version": "1.0.1-alpha.17",
|
|
4
4
|
"description": "Runner for Arazzo Workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"arazzo",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"author": "Vladimir Gorej <vladimir.gorej@gmail.com>",
|
|
57
57
|
"license": "Apache-2.0",
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@babel/runtime-corejs3": "^8.0.
|
|
59
|
+
"@babel/runtime-corejs3": "^8.0.8",
|
|
60
60
|
"@speclynx/apidom-core": "^6.1.0",
|
|
61
61
|
"@speclynx/apidom-datamodel": "^6.1.0",
|
|
62
62
|
"@speclynx/apidom-error": "^6.1.0",
|
|
@@ -73,8 +73,8 @@
|
|
|
73
73
|
"@swaggerexpert/json-pointer": "^3.0.2",
|
|
74
74
|
"@swaggerexpert/jsonpath": "^4.0.5",
|
|
75
75
|
"@swaggerexpert/media-types": "^1.0.1",
|
|
76
|
-
"@usearazzo/parser": "1.0.1-alpha.
|
|
77
|
-
"@usearazzo/resolver": "1.0.1-alpha.
|
|
76
|
+
"@usearazzo/parser": "1.0.1-alpha.17",
|
|
77
|
+
"@usearazzo/resolver": "1.0.1-alpha.17",
|
|
78
78
|
"@xmldom/xmldom": "^0.9.12",
|
|
79
79
|
"fontoxpath": "^3.34.0",
|
|
80
80
|
"ramda": "^0.32.0",
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"swagger-client": "^3.38.4"
|
|
96
96
|
},
|
|
97
|
-
"gitHead": "
|
|
97
|
+
"gitHead": "92ccbcd1dff00a1744e6c0543db9d17ee5a91ef2"
|
|
98
98
|
}
|
|
@@ -4,10 +4,19 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* A key starting with an `in` value the client builds qualified keys from —
|
|
9
|
+
* the OpenAPI locations, including OpenAPI 2.0's `formData` and `body`. The
|
|
10
|
+
* client qualifies whatever `in` an operation declares, so a non-standard one
|
|
11
|
+
* is not covered.
|
|
12
|
+
*/
|
|
13
|
+
const QUALIFIED_KEY = /^(?:path|query|header|cookie|formData|body)\./;
|
|
14
|
+
|
|
7
15
|
/**
|
|
8
16
|
* The outcome of claiming a delivery key: `claimed` for a first claim,
|
|
9
|
-
* `duplicate` when the same `(name, in)` parameter claims its key again,
|
|
10
|
-
* `collision` when a *different* parameter produces an already-claimed key
|
|
17
|
+
* `duplicate` when the same `(name, in)` parameter claims its key again,
|
|
18
|
+
* `collision` when a *different* parameter produces an already-claimed key,
|
|
19
|
+
* and `misaddressed` when a bare key has the shape of a qualified one.
|
|
11
20
|
* @internal
|
|
12
21
|
*/
|
|
13
22
|
|
|
@@ -47,8 +56,16 @@ exports.default = void 0;
|
|
|
47
56
|
* alone identifies the claimant. A bare key and a qualified key sharing one
|
|
48
57
|
* name are a collision too, even though the keys differ — the client consults
|
|
49
58
|
* the bare name first for every declared parameter bearing it, so the bare
|
|
50
|
-
* entry would silently capture the qualified one.
|
|
51
|
-
*
|
|
59
|
+
* entry would silently capture the qualified one.
|
|
60
|
+
*
|
|
61
|
+
* A bare key that starts with a location the client qualifies keys with
|
|
62
|
+
* (`querystring` named `header.X-Foo`) is misaddressed even when it claims
|
|
63
|
+
* alone: the client matches it as the qualified key of every declared
|
|
64
|
+
* parameter that location and the rest of the name identify, so the value
|
|
65
|
+
* would reach the header `X-Foo` — and `OpenAPIOperationExecutor` reads such
|
|
66
|
+
* a key the same way when it delivers undeclared parameters. What to do about
|
|
67
|
+
* a collision or a misaddressed key is the caller's policy — the map only
|
|
68
|
+
* reports it.
|
|
52
69
|
*
|
|
53
70
|
* Diff this against the vendored bundle's lookup when bumping swagger-client.
|
|
54
71
|
* @internal
|
|
@@ -71,10 +88,16 @@ class ParameterDelivery {
|
|
|
71
88
|
* Only a `claimed` outcome entitles the caller to {@link ParameterDelivery.set}
|
|
72
89
|
* the key; a `duplicate` means the same parameter already holds it, and a
|
|
73
90
|
* `collision` means a different parameter does — on the same key, or across
|
|
74
|
-
* a bare/qualified pair sharing the name (see the class doc).
|
|
91
|
+
* a bare/qualified pair sharing the name (see the class doc). A
|
|
92
|
+
* `misaddressed` bare key is never claimed.
|
|
75
93
|
*/
|
|
76
94
|
claim(location, name) {
|
|
77
95
|
const key = ParameterDelivery.keyFor(location, name);
|
|
96
|
+
const bare = key === name;
|
|
97
|
+
if (bare && QUALIFIED_KEY.test(name)) return {
|
|
98
|
+
key,
|
|
99
|
+
outcome: 'misaddressed'
|
|
100
|
+
};
|
|
78
101
|
const claimant = this.#claimedBy.get(key);
|
|
79
102
|
if (claimant !== undefined) {
|
|
80
103
|
return {
|
|
@@ -82,7 +105,6 @@ class ParameterDelivery {
|
|
|
82
105
|
outcome: claimant === location ? 'duplicate' : 'collision'
|
|
83
106
|
};
|
|
84
107
|
}
|
|
85
|
-
const bare = key === name;
|
|
86
108
|
if (bare ? this.#qualifiedNames.has(name) : this.#bareNames.has(name)) {
|
|
87
109
|
return {
|
|
88
110
|
key,
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A key starting with an `in` value the client builds qualified keys from —
|
|
3
|
+
* the OpenAPI locations, including OpenAPI 2.0's `formData` and `body`. The
|
|
4
|
+
* client qualifies whatever `in` an operation declares, so a non-standard one
|
|
5
|
+
* is not covered.
|
|
6
|
+
*/
|
|
7
|
+
const QUALIFIED_KEY = /^(?:path|query|header|cookie|formData|body)\./;
|
|
8
|
+
|
|
1
9
|
/**
|
|
2
10
|
* The outcome of claiming a delivery key: `claimed` for a first claim,
|
|
3
|
-
* `duplicate` when the same `(name, in)` parameter claims its key again,
|
|
4
|
-
* `collision` when a *different* parameter produces an already-claimed key
|
|
11
|
+
* `duplicate` when the same `(name, in)` parameter claims its key again,
|
|
12
|
+
* `collision` when a *different* parameter produces an already-claimed key,
|
|
13
|
+
* and `misaddressed` when a bare key has the shape of a qualified one.
|
|
5
14
|
* @internal
|
|
6
15
|
*/
|
|
7
16
|
|
|
@@ -41,8 +50,16 @@
|
|
|
41
50
|
* alone identifies the claimant. A bare key and a qualified key sharing one
|
|
42
51
|
* name are a collision too, even though the keys differ — the client consults
|
|
43
52
|
* the bare name first for every declared parameter bearing it, so the bare
|
|
44
|
-
* entry would silently capture the qualified one.
|
|
45
|
-
*
|
|
53
|
+
* entry would silently capture the qualified one.
|
|
54
|
+
*
|
|
55
|
+
* A bare key that starts with a location the client qualifies keys with
|
|
56
|
+
* (`querystring` named `header.X-Foo`) is misaddressed even when it claims
|
|
57
|
+
* alone: the client matches it as the qualified key of every declared
|
|
58
|
+
* parameter that location and the rest of the name identify, so the value
|
|
59
|
+
* would reach the header `X-Foo` — and `OpenAPIOperationExecutor` reads such
|
|
60
|
+
* a key the same way when it delivers undeclared parameters. What to do about
|
|
61
|
+
* a collision or a misaddressed key is the caller's policy — the map only
|
|
62
|
+
* reports it.
|
|
46
63
|
*
|
|
47
64
|
* Diff this against the vendored bundle's lookup when bumping swagger-client.
|
|
48
65
|
* @internal
|
|
@@ -65,10 +82,16 @@ class ParameterDelivery {
|
|
|
65
82
|
* Only a `claimed` outcome entitles the caller to {@link ParameterDelivery.set}
|
|
66
83
|
* the key; a `duplicate` means the same parameter already holds it, and a
|
|
67
84
|
* `collision` means a different parameter does — on the same key, or across
|
|
68
|
-
* a bare/qualified pair sharing the name (see the class doc).
|
|
85
|
+
* a bare/qualified pair sharing the name (see the class doc). A
|
|
86
|
+
* `misaddressed` bare key is never claimed.
|
|
69
87
|
*/
|
|
70
88
|
claim(location, name) {
|
|
71
89
|
const key = ParameterDelivery.keyFor(location, name);
|
|
90
|
+
const bare = key === name;
|
|
91
|
+
if (bare && QUALIFIED_KEY.test(name)) return {
|
|
92
|
+
key,
|
|
93
|
+
outcome: 'misaddressed'
|
|
94
|
+
};
|
|
72
95
|
const claimant = this.#claimedBy.get(key);
|
|
73
96
|
if (claimant !== undefined) {
|
|
74
97
|
return {
|
|
@@ -76,7 +99,6 @@ class ParameterDelivery {
|
|
|
76
99
|
outcome: claimant === location ? 'duplicate' : 'collision'
|
|
77
100
|
};
|
|
78
101
|
}
|
|
79
|
-
const bare = key === name;
|
|
80
102
|
if (bare ? this.#qualifiedNames.has(name) : this.#bareNames.has(name)) {
|
|
81
103
|
return {
|
|
82
104
|
key,
|
|
@@ -159,23 +159,32 @@ class ArazzoWorkflowNormalizer {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
162
|
+
* Merges the workflow's `successActions` / `failureActions` into each step's
|
|
163
|
+
* `onSuccess` / `onFailure`.
|
|
164
164
|
*
|
|
165
|
-
* Per Arazzo
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* the
|
|
165
|
+
* Per Arazzo both lists are "applicable for all steps described under this
|
|
166
|
+
* workflow" and "can be overridden at the step level but cannot be removed
|
|
167
|
+
* there". The required action `name` is what makes both halves hold: a
|
|
168
|
+
* step's action replaces the workflow action of the same `name`, and every
|
|
169
|
+
* workflow action the step does not name still applies. The effective list is
|
|
170
|
+
* the step's own actions in order, then the workflow actions it did not
|
|
171
|
+
* override, in theirs — order matters, as selection is first-match-wins on
|
|
172
|
+
* `criteria`. So a step with no list, or with `[]`, gets every workflow
|
|
173
|
+
* action. The step's own list is kept exactly as written, even a duplicate
|
|
174
|
+
* `name` in it, which the validator reports: inheritance only adds to it.
|
|
175
|
+
* Within the workflow's list the first action with a given `name` wins.
|
|
176
|
+
* Success and failure merge independently.
|
|
171
177
|
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* is present but not a list
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
178
|
+
* An entry without a readable `name` (an unresolved Reusable Object, a
|
|
179
|
+
* scalar someone put in the list) neither overrides nor is overridden: it
|
|
180
|
+
* keeps its place, and is added only if that same element is not already in
|
|
181
|
+
* the list. A step whose `onSuccess` is present but not a list is left
|
|
182
|
+
* alone, for the same reason the parameters pass leaves a malformed list
|
|
183
|
+
* alone — overwriting it would erase what makes the document invalid.
|
|
184
|
+
*
|
|
185
|
+
* The pass is idempotent, so a workflow reached again through the registry
|
|
186
|
+
* cache is merged into once: on a second pass every inherited action is
|
|
187
|
+
* already in the step's list, under its own `name` or as the same element.
|
|
179
188
|
*
|
|
180
189
|
* Unlike parameters there is no step-kind filter — an action names a
|
|
181
190
|
* transition within the workflow, which is as meaningful for a step targeting
|
|
@@ -202,13 +211,34 @@ class ArazzoWorkflowNormalizer {
|
|
|
202
211
|
if (!inheritSuccess && !inheritFailure) return;
|
|
203
212
|
for (const step of workflow.steps) {
|
|
204
213
|
if (!(0, _apidomNsArazzo.isStepElement)(step)) continue;
|
|
205
|
-
if (inheritSuccess && !step.hasKey('onSuccess')) {
|
|
206
|
-
step.onSuccess = new _apidomNsArazzo.StepOnSuccessElement([...successActions]);
|
|
214
|
+
if (inheritSuccess && (!step.hasKey('onSuccess') || (0, _apidomDatamodel.isArrayElement)(step.onSuccess))) {
|
|
215
|
+
step.onSuccess = new _apidomNsArazzo.StepOnSuccessElement(ArazzoWorkflowNormalizer.#mergeActions([...(step.onSuccess ?? [])], [...successActions]));
|
|
216
|
+
}
|
|
217
|
+
if (inheritFailure && (!step.hasKey('onFailure') || (0, _apidomDatamodel.isArrayElement)(step.onFailure))) {
|
|
218
|
+
step.onFailure = new _apidomNsArazzo.StepOnFailureElement(ArazzoWorkflowNormalizer.#mergeActions([...(step.onFailure ?? [])], [...failureActions]));
|
|
207
219
|
}
|
|
208
|
-
|
|
209
|
-
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* The step's actions as written, followed by each workflow action whose
|
|
225
|
+
* `name` neither the step nor an earlier workflow action carries; a nameless
|
|
226
|
+
* workflow entry is added unless that same element is already present.
|
|
227
|
+
*/
|
|
228
|
+
static #mergeActions(own, inherited) {
|
|
229
|
+
const nameOf = action => (0, _apidomDatamodel.isObjectElement)(action) ? (0, _apidomCore.toValue)(action.get('name')) : undefined;
|
|
230
|
+
const names = new Set(own.map(nameOf));
|
|
231
|
+
const merged = [...own];
|
|
232
|
+
for (const action of inherited) {
|
|
233
|
+
const name = nameOf(action);
|
|
234
|
+
if (typeof name !== 'string') {
|
|
235
|
+
if (!merged.includes(action)) merged.push(action);
|
|
236
|
+
} else if (!names.has(name)) {
|
|
237
|
+
names.add(name);
|
|
238
|
+
merged.push(action);
|
|
210
239
|
}
|
|
211
240
|
}
|
|
241
|
+
return merged;
|
|
212
242
|
}
|
|
213
243
|
}
|
|
214
244
|
var _default = exports.default = ArazzoWorkflowNormalizer;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { uniqWith } from 'ramda';
|
|
2
2
|
import { isParameterElement, isStepElement, StepParametersElement, StepOnSuccessElement, StepOnFailureElement } from '@speclynx/apidom-ns-arazzo-1';
|
|
3
3
|
import { toValue } from '@speclynx/apidom-core';
|
|
4
|
-
import { isArrayElement, isStringElement } from '@speclynx/apidom-datamodel';
|
|
4
|
+
import { isArrayElement, isObjectElement, isStringElement } from '@speclynx/apidom-datamodel';
|
|
5
5
|
import { dereferenceArazzoElement, defaultDereferenceArazzoOptions } from '@usearazzo/resolver';
|
|
6
6
|
import { mergeOptions } from '@speclynx/apidom-reference/configuration/empty';
|
|
7
7
|
import ParameterIdentity from "../document/ParameterIdentity.mjs";
|
|
@@ -151,23 +151,32 @@ class ArazzoWorkflowNormalizer {
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
154
|
+
* Merges the workflow's `successActions` / `failureActions` into each step's
|
|
155
|
+
* `onSuccess` / `onFailure`.
|
|
156
156
|
*
|
|
157
|
-
* Per Arazzo
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* the
|
|
157
|
+
* Per Arazzo both lists are "applicable for all steps described under this
|
|
158
|
+
* workflow" and "can be overridden at the step level but cannot be removed
|
|
159
|
+
* there". The required action `name` is what makes both halves hold: a
|
|
160
|
+
* step's action replaces the workflow action of the same `name`, and every
|
|
161
|
+
* workflow action the step does not name still applies. The effective list is
|
|
162
|
+
* the step's own actions in order, then the workflow actions it did not
|
|
163
|
+
* override, in theirs — order matters, as selection is first-match-wins on
|
|
164
|
+
* `criteria`. So a step with no list, or with `[]`, gets every workflow
|
|
165
|
+
* action. The step's own list is kept exactly as written, even a duplicate
|
|
166
|
+
* `name` in it, which the validator reports: inheritance only adds to it.
|
|
167
|
+
* Within the workflow's list the first action with a given `name` wins.
|
|
168
|
+
* Success and failure merge independently.
|
|
163
169
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* is present but not a list
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
170
|
+
* An entry without a readable `name` (an unresolved Reusable Object, a
|
|
171
|
+
* scalar someone put in the list) neither overrides nor is overridden: it
|
|
172
|
+
* keeps its place, and is added only if that same element is not already in
|
|
173
|
+
* the list. A step whose `onSuccess` is present but not a list is left
|
|
174
|
+
* alone, for the same reason the parameters pass leaves a malformed list
|
|
175
|
+
* alone — overwriting it would erase what makes the document invalid.
|
|
176
|
+
*
|
|
177
|
+
* The pass is idempotent, so a workflow reached again through the registry
|
|
178
|
+
* cache is merged into once: on a second pass every inherited action is
|
|
179
|
+
* already in the step's list, under its own `name` or as the same element.
|
|
171
180
|
*
|
|
172
181
|
* Unlike parameters there is no step-kind filter — an action names a
|
|
173
182
|
* transition within the workflow, which is as meaningful for a step targeting
|
|
@@ -194,13 +203,34 @@ class ArazzoWorkflowNormalizer {
|
|
|
194
203
|
if (!inheritSuccess && !inheritFailure) return;
|
|
195
204
|
for (const step of workflow.steps) {
|
|
196
205
|
if (!isStepElement(step)) continue;
|
|
197
|
-
if (inheritSuccess && !step.hasKey('onSuccess')) {
|
|
198
|
-
step.onSuccess = new StepOnSuccessElement([...successActions]);
|
|
206
|
+
if (inheritSuccess && (!step.hasKey('onSuccess') || isArrayElement(step.onSuccess))) {
|
|
207
|
+
step.onSuccess = new StepOnSuccessElement(ArazzoWorkflowNormalizer.#mergeActions([...(step.onSuccess ?? [])], [...successActions]));
|
|
208
|
+
}
|
|
209
|
+
if (inheritFailure && (!step.hasKey('onFailure') || isArrayElement(step.onFailure))) {
|
|
210
|
+
step.onFailure = new StepOnFailureElement(ArazzoWorkflowNormalizer.#mergeActions([...(step.onFailure ?? [])], [...failureActions]));
|
|
199
211
|
}
|
|
200
|
-
|
|
201
|
-
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* The step's actions as written, followed by each workflow action whose
|
|
217
|
+
* `name` neither the step nor an earlier workflow action carries; a nameless
|
|
218
|
+
* workflow entry is added unless that same element is already present.
|
|
219
|
+
*/
|
|
220
|
+
static #mergeActions(own, inherited) {
|
|
221
|
+
const nameOf = action => isObjectElement(action) ? toValue(action.get('name')) : undefined;
|
|
222
|
+
const names = new Set(own.map(nameOf));
|
|
223
|
+
const merged = [...own];
|
|
224
|
+
for (const action of inherited) {
|
|
225
|
+
const name = nameOf(action);
|
|
226
|
+
if (typeof name !== 'string') {
|
|
227
|
+
if (!merged.includes(action)) merged.push(action);
|
|
228
|
+
} else if (!names.has(name)) {
|
|
229
|
+
names.add(name);
|
|
230
|
+
merged.push(action);
|
|
202
231
|
}
|
|
203
232
|
}
|
|
233
|
+
return merged;
|
|
204
234
|
}
|
|
205
235
|
}
|
|
206
236
|
export default ArazzoWorkflowNormalizer;
|
|
@@ -41,12 +41,15 @@ var _StepParameterResolver = _interopRequireDefault(require("./StepParameterReso
|
|
|
41
41
|
* against an OpenAPI 2.0 operation, bypassing the step's `requestBody`, while
|
|
42
42
|
* an unknown location reaches nothing at all. And two *different* parameters the
|
|
43
43
|
* map reports as colliding cannot both be delivered, so a collision throws
|
|
44
|
-
* rather than silently dropping one —
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
44
|
+
* rather than silently dropping one — a bare/qualified pair sharing a name (a
|
|
45
|
+
* `querystring` `token` next to a header `token`), where the client would
|
|
46
|
+
* consult the bare name first and silently capture the qualified value. A
|
|
47
|
+
* `querystring` parameter whose name starts with a location the client
|
|
48
|
+
* qualifies keys with (`header.X-Foo`) throws even alone: the client would
|
|
49
|
+
* match its bare key as the qualified key of a declared header `X-Foo` and
|
|
50
|
+
* deliver it there. The same check rejects it, in either order, next to a
|
|
51
|
+
* header parameter `X-Foo` producing that very key — the scheme is not
|
|
52
|
+
* injective, so the two could otherwise collide on one key.
|
|
50
53
|
* @public
|
|
51
54
|
*/
|
|
52
55
|
class OpenAPIOperationParameterResolver extends _StepParameterResolver.default {
|
|
@@ -113,8 +116,9 @@ class OpenAPIOperationParameterResolver extends _StepParameterResolver.default {
|
|
|
113
116
|
} = delivery.claim(location, name);
|
|
114
117
|
// the same parameter declared again: the earlier, more specific one won
|
|
115
118
|
if (outcome === 'duplicate') continue;
|
|
116
|
-
if (outcome
|
|
117
|
-
|
|
119
|
+
if (outcome !== 'claimed') {
|
|
120
|
+
const why = outcome === 'collision' ? `collides with another parameter on the delivery key "${key}"` : 'has a name the client reads as the delivery key of another location';
|
|
121
|
+
throw new _ResolverError.default(`Parameter "${name}" (in: ${location}) ${why} and cannot be delivered unambiguously`, {
|
|
118
122
|
...scope,
|
|
119
123
|
target: name,
|
|
120
124
|
reason: 'ambiguous-delivery'
|
|
@@ -34,12 +34,15 @@ import StepParameterResolver from "./StepParameterResolver.mjs";
|
|
|
34
34
|
* against an OpenAPI 2.0 operation, bypassing the step's `requestBody`, while
|
|
35
35
|
* an unknown location reaches nothing at all. And two *different* parameters the
|
|
36
36
|
* map reports as colliding cannot both be delivered, so a collision throws
|
|
37
|
-
* rather than silently dropping one —
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
37
|
+
* rather than silently dropping one — a bare/qualified pair sharing a name (a
|
|
38
|
+
* `querystring` `token` next to a header `token`), where the client would
|
|
39
|
+
* consult the bare name first and silently capture the qualified value. A
|
|
40
|
+
* `querystring` parameter whose name starts with a location the client
|
|
41
|
+
* qualifies keys with (`header.X-Foo`) throws even alone: the client would
|
|
42
|
+
* match its bare key as the qualified key of a declared header `X-Foo` and
|
|
43
|
+
* deliver it there. The same check rejects it, in either order, next to a
|
|
44
|
+
* header parameter `X-Foo` producing that very key — the scheme is not
|
|
45
|
+
* injective, so the two could otherwise collide on one key.
|
|
43
46
|
* @public
|
|
44
47
|
*/
|
|
45
48
|
class OpenAPIOperationParameterResolver extends StepParameterResolver {
|
|
@@ -106,8 +109,9 @@ class OpenAPIOperationParameterResolver extends StepParameterResolver {
|
|
|
106
109
|
} = delivery.claim(location, name);
|
|
107
110
|
// the same parameter declared again: the earlier, more specific one won
|
|
108
111
|
if (outcome === 'duplicate') continue;
|
|
109
|
-
if (outcome
|
|
110
|
-
|
|
112
|
+
if (outcome !== 'claimed') {
|
|
113
|
+
const why = outcome === 'collision' ? `collides with another parameter on the delivery key "${key}"` : 'has a name the client reads as the delivery key of another location';
|
|
114
|
+
throw new ResolverError(`Parameter "${name}" (in: ${location}) ${why} and cannot be delivered unambiguously`, {
|
|
111
115
|
...scope,
|
|
112
116
|
target: name,
|
|
113
117
|
reason: 'ambiguous-delivery'
|
package/types/runner.d.ts
CHANGED
|
@@ -1202,12 +1202,15 @@ export declare interface OpenAPIOperationNormalizerOptions {
|
|
|
1202
1202
|
* against an OpenAPI 2.0 operation, bypassing the step's `requestBody`, while
|
|
1203
1203
|
* an unknown location reaches nothing at all. And two *different* parameters the
|
|
1204
1204
|
* map reports as colliding cannot both be delivered, so a collision throws
|
|
1205
|
-
* rather than silently dropping one —
|
|
1206
|
-
*
|
|
1207
|
-
*
|
|
1208
|
-
*
|
|
1209
|
-
*
|
|
1210
|
-
*
|
|
1205
|
+
* rather than silently dropping one — a bare/qualified pair sharing a name (a
|
|
1206
|
+
* `querystring` `token` next to a header `token`), where the client would
|
|
1207
|
+
* consult the bare name first and silently capture the qualified value. A
|
|
1208
|
+
* `querystring` parameter whose name starts with a location the client
|
|
1209
|
+
* qualifies keys with (`header.X-Foo`) throws even alone: the client would
|
|
1210
|
+
* match its bare key as the qualified key of a declared header `X-Foo` and
|
|
1211
|
+
* deliver it there. The same check rejects it, in either order, next to a
|
|
1212
|
+
* header parameter `X-Foo` producing that very key — the scheme is not
|
|
1213
|
+
* injective, so the two could otherwise collide on one key.
|
|
1211
1214
|
* @public
|
|
1212
1215
|
*/
|
|
1213
1216
|
export declare class OpenAPIOperationParameterResolver extends StepParameterResolver {
|