@usearazzo/runner 1.0.1-alpha.21 → 1.0.1-alpha.23
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 +2733 -446
- package/dist/arazzo-runner.browser.min.js +1 -1
- package/package.json +5 -5
- package/src/executor/ArazzoWorkflowLocatorNormalizer.cjs +18 -7
- package/src/executor/ArazzoWorkflowLocatorNormalizer.mjs +18 -7
- package/src/executor/OpenAPIOperationLocatorNormalizer.cjs +79 -47
- package/src/executor/OpenAPIOperationLocatorNormalizer.mjs +80 -48
- package/src/executor/StepExecutor.cjs +45 -25
- package/src/executor/StepExecutor.mjs +45 -25
- package/src/executor/StepRetryRunner.cjs +0 -10
- package/src/executor/StepRetryRunner.mjs +0 -9
- package/src/executor/WorkflowExecutor.cjs +11 -22
- package/src/executor/WorkflowExecutor.mjs +11 -22
- package/src/vendor/swagger-client.cjs +1 -1
- package/src/vendor/swagger-client.mjs +1 -1
- package/types/runner.d.ts +49 -21
|
@@ -55,6 +55,16 @@ const STEP_TARGET_FIELDS = exports.STEP_TARGET_FIELDS = ['operationId', 'operati
|
|
|
55
55
|
* @public
|
|
56
56
|
*/
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* What one attempt at a step produced.
|
|
60
|
+
*
|
|
61
|
+
* Both kinds of step reduce to this — an operation step (whose richer
|
|
62
|
+
* {@link StepExecutionResult} satisfies this shape) and a sub-workflow step
|
|
63
|
+
* (synthesized from the sub-run's outcome) — so the retry loop drives them
|
|
64
|
+
* identically and knows nothing about either.
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
|
|
58
68
|
/**
|
|
59
69
|
* Executes a single Arazzo step that invokes an OpenAPI operation.
|
|
60
70
|
*
|
|
@@ -124,38 +134,45 @@ class StepExecutor {
|
|
|
124
134
|
* request nobody is waiting for, whose wire-level cancellation would surface
|
|
125
135
|
* as a transport {@link ClientError} — a request that failed on its own terms
|
|
126
136
|
* — rather than as the withdrawal it is.
|
|
137
|
+
*
|
|
138
|
+
* `workflowId` names the workflow the step belongs to; every error raised
|
|
139
|
+
* here then carries it alongside the `stepId`, since step ids are only
|
|
140
|
+
* unique within a workflow. The workflow executor always passes it.
|
|
127
141
|
*/
|
|
128
|
-
async execute(step, state, executeOptions = {}) {
|
|
142
|
+
async execute(step, state, executeOptions = {}, workflowId) {
|
|
129
143
|
const stepId = (0, _apidomCore.toValue)(step.stepId);
|
|
144
|
+
const scope = {
|
|
145
|
+
...(workflowId === undefined ? {} : {
|
|
146
|
+
workflowId
|
|
147
|
+
}),
|
|
148
|
+
stepId
|
|
149
|
+
};
|
|
130
150
|
|
|
131
151
|
// a step's target fields are mutually exclusive; declaring more than one is
|
|
132
152
|
// malformed and has no defined resolution.
|
|
133
153
|
const declaredTargets = STEP_TARGET_FIELDS.filter(field => (0, _apidomDatamodel.isStringElement)(step[field]));
|
|
134
154
|
if (declaredTargets.length > 1) {
|
|
135
155
|
throw new _ExecutionError.default(`Step "${stepId}" declares more than one of ${STEP_TARGET_FIELDS.join(', ')} (mutually exclusive)`, {
|
|
136
|
-
|
|
156
|
+
...scope,
|
|
137
157
|
reason: 'ambiguous-target'
|
|
138
158
|
});
|
|
139
159
|
}
|
|
140
160
|
if ((0, _apidomDatamodel.isStringElement)(step.workflowId)) {
|
|
141
161
|
throw new _ExecutionError.default(`Step "${stepId}" targets a workflowId; use the workflow executor`, {
|
|
142
|
-
|
|
162
|
+
...scope,
|
|
143
163
|
reason: 'workflow-step'
|
|
144
164
|
});
|
|
145
165
|
}
|
|
146
|
-
this.assertSuccessCriteria(step);
|
|
166
|
+
this.assertSuccessCriteria(step, workflowId);
|
|
147
167
|
|
|
148
168
|
// locate which operation the step invokes — reduced to a (document, JSON
|
|
149
169
|
// Pointer) locator that the operation executor extracts, normalizes,
|
|
150
170
|
// assembles into a standalone doc, and runs.
|
|
151
|
-
const locator = await this.#locateOperation(step,
|
|
171
|
+
const locator = await this.#locateOperation(step, scope);
|
|
152
172
|
|
|
153
173
|
// resolve parameters and request body against the pre-request context.
|
|
154
174
|
// keyed by '{in}.{name}' rather than bare name, so two parameters that
|
|
155
175
|
// legally differ only in their location each reach their own place.
|
|
156
|
-
const scope = {
|
|
157
|
-
stepId
|
|
158
|
-
};
|
|
159
176
|
const preContext = state.toContext();
|
|
160
177
|
const parameters = this.#parameterResolver.resolve(step.parameters, expression => this.#evaluate(preContext, expression), scope);
|
|
161
178
|
const requestBody = this.#requestBodyResolver.resolve(step.requestBody, expression => this.#evaluate(preContext, expression), scope);
|
|
@@ -166,9 +183,7 @@ class StepExecutor {
|
|
|
166
183
|
// live side effect. The signal stays in the bag, so a request already in
|
|
167
184
|
// flight is aborted by the transport as before.
|
|
168
185
|
const signal = (0, _abort.readAbortSignal)(executeOptions);
|
|
169
|
-
(0, _abort.throwIfAborted)(signal,
|
|
170
|
-
stepId
|
|
171
|
-
});
|
|
186
|
+
(0, _abort.throwIfAborted)(signal, scope);
|
|
172
187
|
|
|
173
188
|
// the Arazzo-derived parameters and request body are spread after the opaque
|
|
174
189
|
// executeOptions bag so they take precedence over it. the operation executor
|
|
@@ -187,22 +202,20 @@ class StepExecutor {
|
|
|
187
202
|
// cancelled, it did not: reporting it as the abort keeps one error shape
|
|
188
203
|
// whether the run was withdrawn between two steps or mid-flight, and keeps
|
|
189
204
|
// the whole feature from reading differently per transport.
|
|
190
|
-
(0, _abort.throwIfAborted)(signal,
|
|
191
|
-
stepId
|
|
192
|
-
});
|
|
205
|
+
(0, _abort.throwIfAborted)(signal, scope);
|
|
193
206
|
throw error;
|
|
194
207
|
}
|
|
195
208
|
|
|
196
209
|
// evaluate criteria, outputs, and the next action against the post-request
|
|
197
210
|
// context (with $request / $url / $method and $response / $statusCode).
|
|
198
211
|
const postContext = state.toContext(this.#requestContext(response), this.#responseContext(response));
|
|
199
|
-
const successCriteria = this.evaluateCriteria(step, postContext);
|
|
212
|
+
const successCriteria = this.evaluateCriteria(step, postContext, workflowId);
|
|
200
213
|
const successful = successCriteria.every(criterion => criterion.met);
|
|
201
214
|
const outputs = this.#outputResolver.resolve(step.outputs, expression => this.#evaluate(postContext, expression), scope);
|
|
202
215
|
const {
|
|
203
216
|
matchedActions,
|
|
204
217
|
actionCriteria
|
|
205
|
-
} = this.selectActions(step, successful, postContext);
|
|
218
|
+
} = this.selectActions(step, successful, postContext, workflowId);
|
|
206
219
|
return {
|
|
207
220
|
stepId,
|
|
208
221
|
response,
|
|
@@ -232,15 +245,15 @@ class StepExecutor {
|
|
|
232
245
|
requestContentType: requestBody.contentType
|
|
233
246
|
};
|
|
234
247
|
}
|
|
235
|
-
async #locateOperation(step,
|
|
248
|
+
async #locateOperation(step, scope) {
|
|
236
249
|
if ((0, _apidomDatamodel.isStringElement)(step.operationId)) {
|
|
237
|
-
return this.#locatorNormalizer.normalizeOperationId((0, _apidomCore.toValue)(step.operationId), this.#document);
|
|
250
|
+
return this.#locatorNormalizer.normalizeOperationId((0, _apidomCore.toValue)(step.operationId), this.#document, scope);
|
|
238
251
|
}
|
|
239
252
|
if ((0, _apidomDatamodel.isStringElement)(step.operationPath)) {
|
|
240
|
-
return this.#locatorNormalizer.normalizeOperationPath((0, _apidomCore.toValue)(step.operationPath), this.#document);
|
|
253
|
+
return this.#locatorNormalizer.normalizeOperationPath((0, _apidomCore.toValue)(step.operationPath), this.#document, scope);
|
|
241
254
|
}
|
|
242
|
-
throw new _ExecutionError.default(`Step "${stepId}" has no operationId or operationPath`, {
|
|
243
|
-
|
|
255
|
+
throw new _ExecutionError.default(`Step "${scope.stepId}" has no operationId or operationPath`, {
|
|
256
|
+
...scope,
|
|
244
257
|
reason: 'missing-operation'
|
|
245
258
|
});
|
|
246
259
|
}
|
|
@@ -294,10 +307,12 @@ class StepExecutor {
|
|
|
294
307
|
* Public for the same reason as {@link StepExecutor.selectActions}: a step
|
|
295
308
|
* targeting a `workflowId` is run by the workflow executor and never reaches
|
|
296
309
|
* {@link StepExecutor.execute}, but its criteria are still the author's
|
|
297
|
-
* assertion about the step and must be evaluated somewhere.
|
|
310
|
+
* assertion about the step and must be evaluated somewhere. `workflowId`
|
|
311
|
+
* names the step's workflow on a thrown error, as for
|
|
312
|
+
* {@link StepExecutor.execute}.
|
|
298
313
|
*/
|
|
299
|
-
evaluateCriteria(step, context) {
|
|
300
|
-
this.assertSuccessCriteria(step);
|
|
314
|
+
evaluateCriteria(step, context, workflowId) {
|
|
315
|
+
this.assertSuccessCriteria(step, workflowId);
|
|
301
316
|
const criteria = step.successCriteria;
|
|
302
317
|
if (criteria === undefined) return [];
|
|
303
318
|
|
|
@@ -325,8 +340,10 @@ class StepExecutor {
|
|
|
325
340
|
* it runs itself and which therefore never reaches
|
|
326
341
|
* {@link StepExecutor.execute}. Both callers reach the criteria evaluator and
|
|
327
342
|
* the expression context through this one method rather than wiring their own.
|
|
343
|
+
* `workflowId` names the step's workflow on a thrown error, as for
|
|
344
|
+
* {@link StepExecutor.execute}.
|
|
328
345
|
*/
|
|
329
|
-
selectActions(step, successful, context) {
|
|
346
|
+
selectActions(step, successful, context, workflowId) {
|
|
330
347
|
const actionCriteria = [];
|
|
331
348
|
const isCriterionMet = (criterion, action) => {
|
|
332
349
|
const record = {
|
|
@@ -337,6 +354,9 @@ class StepExecutor {
|
|
|
337
354
|
return record.met;
|
|
338
355
|
};
|
|
339
356
|
const scope = {
|
|
357
|
+
...(workflowId === undefined ? {} : {
|
|
358
|
+
workflowId
|
|
359
|
+
}),
|
|
340
360
|
stepId: (0, _apidomCore.toValue)(step.stepId)
|
|
341
361
|
};
|
|
342
362
|
const matchedActions = successful ? this.#actionResolver.resolveOnSuccess(step.onSuccess, isCriterionMet, scope) : this.#actionResolver.resolveOnFailure(step.onFailure, isCriterionMet, scope);
|
|
@@ -48,6 +48,16 @@ export const STEP_TARGET_FIELDS = ['operationId', 'operationPath', 'workflowId']
|
|
|
48
48
|
* @public
|
|
49
49
|
*/
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* What one attempt at a step produced.
|
|
53
|
+
*
|
|
54
|
+
* Both kinds of step reduce to this — an operation step (whose richer
|
|
55
|
+
* {@link StepExecutionResult} satisfies this shape) and a sub-workflow step
|
|
56
|
+
* (synthesized from the sub-run's outcome) — so the retry loop drives them
|
|
57
|
+
* identically and knows nothing about either.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
|
|
51
61
|
/**
|
|
52
62
|
* Executes a single Arazzo step that invokes an OpenAPI operation.
|
|
53
63
|
*
|
|
@@ -117,38 +127,45 @@ class StepExecutor {
|
|
|
117
127
|
* request nobody is waiting for, whose wire-level cancellation would surface
|
|
118
128
|
* as a transport {@link ClientError} — a request that failed on its own terms
|
|
119
129
|
* — rather than as the withdrawal it is.
|
|
130
|
+
*
|
|
131
|
+
* `workflowId` names the workflow the step belongs to; every error raised
|
|
132
|
+
* here then carries it alongside the `stepId`, since step ids are only
|
|
133
|
+
* unique within a workflow. The workflow executor always passes it.
|
|
120
134
|
*/
|
|
121
|
-
async execute(step, state, executeOptions = {}) {
|
|
135
|
+
async execute(step, state, executeOptions = {}, workflowId) {
|
|
122
136
|
const stepId = toValue(step.stepId);
|
|
137
|
+
const scope = {
|
|
138
|
+
...(workflowId === undefined ? {} : {
|
|
139
|
+
workflowId
|
|
140
|
+
}),
|
|
141
|
+
stepId
|
|
142
|
+
};
|
|
123
143
|
|
|
124
144
|
// a step's target fields are mutually exclusive; declaring more than one is
|
|
125
145
|
// malformed and has no defined resolution.
|
|
126
146
|
const declaredTargets = STEP_TARGET_FIELDS.filter(field => isStringElement(step[field]));
|
|
127
147
|
if (declaredTargets.length > 1) {
|
|
128
148
|
throw new ExecutionError(`Step "${stepId}" declares more than one of ${STEP_TARGET_FIELDS.join(', ')} (mutually exclusive)`, {
|
|
129
|
-
|
|
149
|
+
...scope,
|
|
130
150
|
reason: 'ambiguous-target'
|
|
131
151
|
});
|
|
132
152
|
}
|
|
133
153
|
if (isStringElement(step.workflowId)) {
|
|
134
154
|
throw new ExecutionError(`Step "${stepId}" targets a workflowId; use the workflow executor`, {
|
|
135
|
-
|
|
155
|
+
...scope,
|
|
136
156
|
reason: 'workflow-step'
|
|
137
157
|
});
|
|
138
158
|
}
|
|
139
|
-
this.assertSuccessCriteria(step);
|
|
159
|
+
this.assertSuccessCriteria(step, workflowId);
|
|
140
160
|
|
|
141
161
|
// locate which operation the step invokes — reduced to a (document, JSON
|
|
142
162
|
// Pointer) locator that the operation executor extracts, normalizes,
|
|
143
163
|
// assembles into a standalone doc, and runs.
|
|
144
|
-
const locator = await this.#locateOperation(step,
|
|
164
|
+
const locator = await this.#locateOperation(step, scope);
|
|
145
165
|
|
|
146
166
|
// resolve parameters and request body against the pre-request context.
|
|
147
167
|
// keyed by '{in}.{name}' rather than bare name, so two parameters that
|
|
148
168
|
// legally differ only in their location each reach their own place.
|
|
149
|
-
const scope = {
|
|
150
|
-
stepId
|
|
151
|
-
};
|
|
152
169
|
const preContext = state.toContext();
|
|
153
170
|
const parameters = this.#parameterResolver.resolve(step.parameters, expression => this.#evaluate(preContext, expression), scope);
|
|
154
171
|
const requestBody = this.#requestBodyResolver.resolve(step.requestBody, expression => this.#evaluate(preContext, expression), scope);
|
|
@@ -159,9 +176,7 @@ class StepExecutor {
|
|
|
159
176
|
// live side effect. The signal stays in the bag, so a request already in
|
|
160
177
|
// flight is aborted by the transport as before.
|
|
161
178
|
const signal = readAbortSignal(executeOptions);
|
|
162
|
-
throwIfAborted(signal,
|
|
163
|
-
stepId
|
|
164
|
-
});
|
|
179
|
+
throwIfAborted(signal, scope);
|
|
165
180
|
|
|
166
181
|
// the Arazzo-derived parameters and request body are spread after the opaque
|
|
167
182
|
// executeOptions bag so they take precedence over it. the operation executor
|
|
@@ -180,22 +195,20 @@ class StepExecutor {
|
|
|
180
195
|
// cancelled, it did not: reporting it as the abort keeps one error shape
|
|
181
196
|
// whether the run was withdrawn between two steps or mid-flight, and keeps
|
|
182
197
|
// the whole feature from reading differently per transport.
|
|
183
|
-
throwIfAborted(signal,
|
|
184
|
-
stepId
|
|
185
|
-
});
|
|
198
|
+
throwIfAborted(signal, scope);
|
|
186
199
|
throw error;
|
|
187
200
|
}
|
|
188
201
|
|
|
189
202
|
// evaluate criteria, outputs, and the next action against the post-request
|
|
190
203
|
// context (with $request / $url / $method and $response / $statusCode).
|
|
191
204
|
const postContext = state.toContext(this.#requestContext(response), this.#responseContext(response));
|
|
192
|
-
const successCriteria = this.evaluateCriteria(step, postContext);
|
|
205
|
+
const successCriteria = this.evaluateCriteria(step, postContext, workflowId);
|
|
193
206
|
const successful = successCriteria.every(criterion => criterion.met);
|
|
194
207
|
const outputs = this.#outputResolver.resolve(step.outputs, expression => this.#evaluate(postContext, expression), scope);
|
|
195
208
|
const {
|
|
196
209
|
matchedActions,
|
|
197
210
|
actionCriteria
|
|
198
|
-
} = this.selectActions(step, successful, postContext);
|
|
211
|
+
} = this.selectActions(step, successful, postContext, workflowId);
|
|
199
212
|
return {
|
|
200
213
|
stepId,
|
|
201
214
|
response,
|
|
@@ -225,15 +238,15 @@ class StepExecutor {
|
|
|
225
238
|
requestContentType: requestBody.contentType
|
|
226
239
|
};
|
|
227
240
|
}
|
|
228
|
-
async #locateOperation(step,
|
|
241
|
+
async #locateOperation(step, scope) {
|
|
229
242
|
if (isStringElement(step.operationId)) {
|
|
230
|
-
return this.#locatorNormalizer.normalizeOperationId(toValue(step.operationId), this.#document);
|
|
243
|
+
return this.#locatorNormalizer.normalizeOperationId(toValue(step.operationId), this.#document, scope);
|
|
231
244
|
}
|
|
232
245
|
if (isStringElement(step.operationPath)) {
|
|
233
|
-
return this.#locatorNormalizer.normalizeOperationPath(toValue(step.operationPath), this.#document);
|
|
246
|
+
return this.#locatorNormalizer.normalizeOperationPath(toValue(step.operationPath), this.#document, scope);
|
|
234
247
|
}
|
|
235
|
-
throw new ExecutionError(`Step "${stepId}" has no operationId or operationPath`, {
|
|
236
|
-
|
|
248
|
+
throw new ExecutionError(`Step "${scope.stepId}" has no operationId or operationPath`, {
|
|
249
|
+
...scope,
|
|
237
250
|
reason: 'missing-operation'
|
|
238
251
|
});
|
|
239
252
|
}
|
|
@@ -287,10 +300,12 @@ class StepExecutor {
|
|
|
287
300
|
* Public for the same reason as {@link StepExecutor.selectActions}: a step
|
|
288
301
|
* targeting a `workflowId` is run by the workflow executor and never reaches
|
|
289
302
|
* {@link StepExecutor.execute}, but its criteria are still the author's
|
|
290
|
-
* assertion about the step and must be evaluated somewhere.
|
|
303
|
+
* assertion about the step and must be evaluated somewhere. `workflowId`
|
|
304
|
+
* names the step's workflow on a thrown error, as for
|
|
305
|
+
* {@link StepExecutor.execute}.
|
|
291
306
|
*/
|
|
292
|
-
evaluateCriteria(step, context) {
|
|
293
|
-
this.assertSuccessCriteria(step);
|
|
307
|
+
evaluateCriteria(step, context, workflowId) {
|
|
308
|
+
this.assertSuccessCriteria(step, workflowId);
|
|
294
309
|
const criteria = step.successCriteria;
|
|
295
310
|
if (criteria === undefined) return [];
|
|
296
311
|
|
|
@@ -318,8 +333,10 @@ class StepExecutor {
|
|
|
318
333
|
* it runs itself and which therefore never reaches
|
|
319
334
|
* {@link StepExecutor.execute}. Both callers reach the criteria evaluator and
|
|
320
335
|
* the expression context through this one method rather than wiring their own.
|
|
336
|
+
* `workflowId` names the step's workflow on a thrown error, as for
|
|
337
|
+
* {@link StepExecutor.execute}.
|
|
321
338
|
*/
|
|
322
|
-
selectActions(step, successful, context) {
|
|
339
|
+
selectActions(step, successful, context, workflowId) {
|
|
323
340
|
const actionCriteria = [];
|
|
324
341
|
const isCriterionMet = (criterion, action) => {
|
|
325
342
|
const record = {
|
|
@@ -330,6 +347,9 @@ class StepExecutor {
|
|
|
330
347
|
return record.met;
|
|
331
348
|
};
|
|
332
349
|
const scope = {
|
|
350
|
+
...(workflowId === undefined ? {} : {
|
|
351
|
+
workflowId
|
|
352
|
+
}),
|
|
333
353
|
stepId: toValue(step.stepId)
|
|
334
354
|
};
|
|
335
355
|
const matchedActions = successful ? this.#actionResolver.resolveOnSuccess(step.onSuccess, isCriterionMet, scope) : this.#actionResolver.resolveOnFailure(step.onFailure, isCriterionMet, scope);
|
|
@@ -9,16 +9,6 @@ var _apidomCore = require("@speclynx/apidom-core");
|
|
|
9
9
|
var _apidomDatamodel = require("@speclynx/apidom-datamodel");
|
|
10
10
|
var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
|
|
11
11
|
var _ExecutionError = _interopRequireDefault(require("../errors/ExecutionError.cjs"));
|
|
12
|
-
/**
|
|
13
|
-
* What one attempt at a step produced.
|
|
14
|
-
*
|
|
15
|
-
* Both kinds of step reduce to this — an operation step (whose richer
|
|
16
|
-
* `StepExecutionResult` satisfies this shape) and a sub-workflow step
|
|
17
|
-
* (synthesized from the sub-run's outcome) — so the retry loop drives them
|
|
18
|
-
* identically and knows nothing about either.
|
|
19
|
-
* @internal
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
12
|
/**
|
|
23
13
|
* The terminal outcome of a step once its retries are settled.
|
|
24
14
|
* @internal
|
|
@@ -2,15 +2,6 @@ import { toValue } from '@speclynx/apidom-core';
|
|
|
2
2
|
import { isNumberElement, isStringElement } from '@speclynx/apidom-datamodel';
|
|
3
3
|
import { isFailureActionElement } from '@speclynx/apidom-ns-arazzo-1';
|
|
4
4
|
import ExecutionError from "../errors/ExecutionError.mjs";
|
|
5
|
-
/**
|
|
6
|
-
* What one attempt at a step produced.
|
|
7
|
-
*
|
|
8
|
-
* Both kinds of step reduce to this — an operation step (whose richer
|
|
9
|
-
* `StepExecutionResult` satisfies this shape) and a sub-workflow step
|
|
10
|
-
* (synthesized from the sub-run's outcome) — so the retry loop drives them
|
|
11
|
-
* identically and knows nothing about either.
|
|
12
|
-
* @internal
|
|
13
|
-
*/
|
|
14
5
|
/**
|
|
15
6
|
* The terminal outcome of a step once its retries are settled.
|
|
16
7
|
* @internal
|
|
@@ -778,12 +778,6 @@ class WorkflowExecutor {
|
|
|
778
778
|
const locator = await this.#workflowLocatorNormalizer.normalize(reference, document, {
|
|
779
779
|
workflowId
|
|
780
780
|
});
|
|
781
|
-
if (!locator.document.workflowIndex.has(locator.workflowId)) {
|
|
782
|
-
throw new _ExecutionError.default(`workflow "${workflowId}" depends on "${reference}", which the Arazzo document at "${locator.document.uri}" does not define`, {
|
|
783
|
-
workflowId,
|
|
784
|
-
reason: 'workflow-not-found'
|
|
785
|
-
});
|
|
786
|
-
}
|
|
787
781
|
refs.push({
|
|
788
782
|
locator,
|
|
789
783
|
inputsKey: reference
|
|
@@ -816,10 +810,11 @@ class WorkflowExecutor {
|
|
|
816
810
|
callStack
|
|
817
811
|
} = invocation;
|
|
818
812
|
if (!(0, _apidomDatamodel.isStringElement)(step.workflowId)) {
|
|
819
|
-
return () => this.#stepExecutor.forDocument(document).execute(step, state, scope.executeOptions);
|
|
813
|
+
return () => this.#stepExecutor.forDocument(document).execute(step, state, scope.executeOptions, workflowId);
|
|
820
814
|
}
|
|
821
815
|
const reference = this.#subWorkflowReference(step, stepId, workflowId);
|
|
822
816
|
const stepScope = {
|
|
817
|
+
workflowId,
|
|
823
818
|
stepId
|
|
824
819
|
};
|
|
825
820
|
// the reference resolves to the same locator on every attempt, so it is
|
|
@@ -897,12 +892,12 @@ class WorkflowExecutor {
|
|
|
897
892
|
// evaluated by the parent document's step executor — only the sub-run
|
|
898
893
|
// itself switched documents.
|
|
899
894
|
const stepExecutor = this.#stepExecutor.forDocument(document);
|
|
900
|
-
const successCriteria = stepExecutor.evaluateCriteria(step, context);
|
|
895
|
+
const successCriteria = stepExecutor.evaluateCriteria(step, context, workflowId);
|
|
901
896
|
const successful = !this.#settledFailed(result) && successCriteria.every(criterion => criterion.met);
|
|
902
897
|
const {
|
|
903
898
|
matchedActions,
|
|
904
899
|
actionCriteria
|
|
905
|
-
} = stepExecutor.selectActions(step, successful, context);
|
|
900
|
+
} = stepExecutor.selectActions(step, successful, context, workflowId);
|
|
906
901
|
return {
|
|
907
902
|
stepId,
|
|
908
903
|
successful,
|
|
@@ -972,24 +967,14 @@ class WorkflowExecutor {
|
|
|
972
967
|
*
|
|
973
968
|
* Shared rather than duplicated by its two callers, which otherwise repeat
|
|
974
969
|
* the identical "resolve the reference, then run with no inputs" sequence.
|
|
975
|
-
*
|
|
976
|
-
*
|
|
977
|
-
* `workflow-not-found` (reached only once `#run` itself resolves the
|
|
978
|
-
* target) — which carries no caller context at all, since it is reached
|
|
979
|
-
* generically from every kind of nested call.
|
|
970
|
+
* A target its document does not define is rejected by the normalizer,
|
|
971
|
+
* attributed to the calling workflow and `stepId`.
|
|
980
972
|
*/
|
|
981
973
|
async #runReferencedWorkflow(reference, stepId, invocation, scope, via) {
|
|
982
974
|
const locator = await this.#workflowLocatorNormalizer.normalize(reference, invocation.document, {
|
|
983
975
|
workflowId: invocation.workflowId,
|
|
984
976
|
stepId
|
|
985
977
|
});
|
|
986
|
-
if (!locator.document.workflowIndex.has(locator.workflowId)) {
|
|
987
|
-
throw new _ExecutionError.default(`workflow "${locator.workflowId}" not found in Arazzo document at "${locator.document.uri}"`, {
|
|
988
|
-
workflowId: locator.workflowId,
|
|
989
|
-
stepId,
|
|
990
|
-
reason: 'workflow-not-found'
|
|
991
|
-
});
|
|
992
|
-
}
|
|
993
978
|
return this.#run(locator, {}, scope, invocation.callStack, via);
|
|
994
979
|
}
|
|
995
980
|
|
|
@@ -997,7 +982,11 @@ class WorkflowExecutor {
|
|
|
997
982
|
* Extracts and normalizes the workflow a locator names. A workflow its
|
|
998
983
|
* document does not define is the executor-level `workflow-not-found`
|
|
999
984
|
* authoring error, raised here rather than leaking the extractor's
|
|
1000
|
-
* `ExtractionError`.
|
|
985
|
+
* `ExtractionError`. Only the root {@link WorkflowExecutor.execute} id
|
|
986
|
+
* reaches this check unvalidated — every reference position goes through
|
|
987
|
+
* the locator normalizer, which already rejects a missing workflow with
|
|
988
|
+
* the referencing context attached — so the error's `workflowId` is the
|
|
989
|
+
* missing id itself.
|
|
1001
990
|
*/
|
|
1002
991
|
async #resolveWorkflow(locator, scope) {
|
|
1003
992
|
const {
|
|
@@ -764,12 +764,6 @@ class WorkflowExecutor {
|
|
|
764
764
|
const locator = await this.#workflowLocatorNormalizer.normalize(reference, document, {
|
|
765
765
|
workflowId
|
|
766
766
|
});
|
|
767
|
-
if (!locator.document.workflowIndex.has(locator.workflowId)) {
|
|
768
|
-
throw new ExecutionError(`workflow "${workflowId}" depends on "${reference}", which the Arazzo document at "${locator.document.uri}" does not define`, {
|
|
769
|
-
workflowId,
|
|
770
|
-
reason: 'workflow-not-found'
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
767
|
refs.push({
|
|
774
768
|
locator,
|
|
775
769
|
inputsKey: reference
|
|
@@ -802,10 +796,11 @@ class WorkflowExecutor {
|
|
|
802
796
|
callStack
|
|
803
797
|
} = invocation;
|
|
804
798
|
if (!isStringElement(step.workflowId)) {
|
|
805
|
-
return () => this.#stepExecutor.forDocument(document).execute(step, state, scope.executeOptions);
|
|
799
|
+
return () => this.#stepExecutor.forDocument(document).execute(step, state, scope.executeOptions, workflowId);
|
|
806
800
|
}
|
|
807
801
|
const reference = this.#subWorkflowReference(step, stepId, workflowId);
|
|
808
802
|
const stepScope = {
|
|
803
|
+
workflowId,
|
|
809
804
|
stepId
|
|
810
805
|
};
|
|
811
806
|
// the reference resolves to the same locator on every attempt, so it is
|
|
@@ -883,12 +878,12 @@ class WorkflowExecutor {
|
|
|
883
878
|
// evaluated by the parent document's step executor — only the sub-run
|
|
884
879
|
// itself switched documents.
|
|
885
880
|
const stepExecutor = this.#stepExecutor.forDocument(document);
|
|
886
|
-
const successCriteria = stepExecutor.evaluateCriteria(step, context);
|
|
881
|
+
const successCriteria = stepExecutor.evaluateCriteria(step, context, workflowId);
|
|
887
882
|
const successful = !this.#settledFailed(result) && successCriteria.every(criterion => criterion.met);
|
|
888
883
|
const {
|
|
889
884
|
matchedActions,
|
|
890
885
|
actionCriteria
|
|
891
|
-
} = stepExecutor.selectActions(step, successful, context);
|
|
886
|
+
} = stepExecutor.selectActions(step, successful, context, workflowId);
|
|
892
887
|
return {
|
|
893
888
|
stepId,
|
|
894
889
|
successful,
|
|
@@ -958,24 +953,14 @@ class WorkflowExecutor {
|
|
|
958
953
|
*
|
|
959
954
|
* Shared rather than duplicated by its two callers, which otherwise repeat
|
|
960
955
|
* the identical "resolve the reference, then run with no inputs" sequence.
|
|
961
|
-
*
|
|
962
|
-
*
|
|
963
|
-
* `workflow-not-found` (reached only once `#run` itself resolves the
|
|
964
|
-
* target) — which carries no caller context at all, since it is reached
|
|
965
|
-
* generically from every kind of nested call.
|
|
956
|
+
* A target its document does not define is rejected by the normalizer,
|
|
957
|
+
* attributed to the calling workflow and `stepId`.
|
|
966
958
|
*/
|
|
967
959
|
async #runReferencedWorkflow(reference, stepId, invocation, scope, via) {
|
|
968
960
|
const locator = await this.#workflowLocatorNormalizer.normalize(reference, invocation.document, {
|
|
969
961
|
workflowId: invocation.workflowId,
|
|
970
962
|
stepId
|
|
971
963
|
});
|
|
972
|
-
if (!locator.document.workflowIndex.has(locator.workflowId)) {
|
|
973
|
-
throw new ExecutionError(`workflow "${locator.workflowId}" not found in Arazzo document at "${locator.document.uri}"`, {
|
|
974
|
-
workflowId: locator.workflowId,
|
|
975
|
-
stepId,
|
|
976
|
-
reason: 'workflow-not-found'
|
|
977
|
-
});
|
|
978
|
-
}
|
|
979
964
|
return this.#run(locator, {}, scope, invocation.callStack, via);
|
|
980
965
|
}
|
|
981
966
|
|
|
@@ -983,7 +968,11 @@ class WorkflowExecutor {
|
|
|
983
968
|
* Extracts and normalizes the workflow a locator names. A workflow its
|
|
984
969
|
* document does not define is the executor-level `workflow-not-found`
|
|
985
970
|
* authoring error, raised here rather than leaking the extractor's
|
|
986
|
-
* `ExtractionError`.
|
|
971
|
+
* `ExtractionError`. Only the root {@link WorkflowExecutor.execute} id
|
|
972
|
+
* reaches this check unvalidated — every reference position goes through
|
|
973
|
+
* the locator normalizer, which already rejects a missing workflow with
|
|
974
|
+
* the referencing context attached — so the error's `workflowId` is the
|
|
975
|
+
* missing id itself.
|
|
987
976
|
*/
|
|
988
977
|
async #resolveWorkflow(locator, scope) {
|
|
989
978
|
const {
|