@usearazzo/runner 1.0.1-alpha.19 → 1.0.1-alpha.21

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.
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.default = void 0;
8
8
  var _jsonpath = require("@swaggerexpert/jsonpath");
9
- var _CriterionError = _interopRequireDefault(require("../errors/CriterionError.cjs"));
9
+ var _CriterionEvaluationError = _interopRequireDefault(require("../errors/CriterionEvaluationError.cjs"));
10
+ var _CriterionErrorReason = _interopRequireDefault(require("./CriterionErrorReason.cjs"));
10
11
  /**
11
12
  * Evaluates a `jsonpath` Arazzo criterion condition against a resolved context value.
12
13
  *
@@ -25,7 +26,7 @@ class JSONPathCriterionEvaluator {
25
26
  * whether it matched anything.
26
27
  *
27
28
  * Returns `false` when the context is `null` or `undefined`. Throws
28
- * {@link CriterionError} when the condition is not a valid JSONPath query.
29
+ * {@link CriterionEvaluationError} when the condition is not a valid JSONPath query.
29
30
  */
30
31
  evaluate(condition, context) {
31
32
  if (context === null || context === undefined) return false;
@@ -33,11 +34,14 @@ class JSONPathCriterionEvaluator {
33
34
  return (0, _jsonpath.evaluate)(context, condition).length > 0;
34
35
  } catch (error) {
35
36
  if (error instanceof _jsonpath.JSONPathError) {
36
- throw new _CriterionError.default(`Invalid jsonpath criterion condition "${condition}"`, {
37
+ // a parse error describes the query only; an evaluation error ran
38
+ // against the context, so its message is not surfaced.
39
+ const detail = error instanceof _jsonpath.JSONPathParseError ? `: ${error.message}` : '';
40
+ throw new _CriterionEvaluationError.default(`Invalid jsonpath criterion condition "${condition}"${detail}`, {
37
41
  cause: error,
38
42
  condition,
39
43
  type: 'jsonpath',
40
- reason: 'invalid-jsonpath'
44
+ reason: _CriterionErrorReason.default.InvalidJSONPath
41
45
  });
42
46
  }
43
47
  throw error;
@@ -1,5 +1,6 @@
1
- import { evaluate as evaluateJSONPath, JSONPathError } from '@swaggerexpert/jsonpath';
2
- import CriterionError from "../errors/CriterionError.mjs";
1
+ import { evaluate as evaluateJSONPath, JSONPathError, JSONPathParseError } from '@swaggerexpert/jsonpath';
2
+ import CriterionEvaluationError from "../errors/CriterionEvaluationError.mjs";
3
+ import CriterionErrorReason from "./CriterionErrorReason.mjs";
3
4
  /**
4
5
  * Evaluates a `jsonpath` Arazzo criterion condition against a resolved context value.
5
6
  *
@@ -18,7 +19,7 @@ class JSONPathCriterionEvaluator {
18
19
  * whether it matched anything.
19
20
  *
20
21
  * Returns `false` when the context is `null` or `undefined`. Throws
21
- * {@link CriterionError} when the condition is not a valid JSONPath query.
22
+ * {@link CriterionEvaluationError} when the condition is not a valid JSONPath query.
22
23
  */
23
24
  evaluate(condition, context) {
24
25
  if (context === null || context === undefined) return false;
@@ -26,11 +27,14 @@ class JSONPathCriterionEvaluator {
26
27
  return evaluateJSONPath(context, condition).length > 0;
27
28
  } catch (error) {
28
29
  if (error instanceof JSONPathError) {
29
- throw new CriterionError(`Invalid jsonpath criterion condition "${condition}"`, {
30
+ // a parse error describes the query only; an evaluation error ran
31
+ // against the context, so its message is not surfaced.
32
+ const detail = error instanceof JSONPathParseError ? `: ${error.message}` : '';
33
+ throw new CriterionEvaluationError(`Invalid jsonpath criterion condition "${condition}"${detail}`, {
30
34
  cause: error,
31
35
  condition,
32
36
  type: 'jsonpath',
33
- reason: 'invalid-jsonpath'
37
+ reason: CriterionErrorReason.InvalidJSONPath
34
38
  });
35
39
  }
36
40
  throw error;
@@ -5,7 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.default = void 0;
8
- var _CriterionError = _interopRequireDefault(require("../errors/CriterionError.cjs"));
8
+ var _CriterionEvaluationError = _interopRequireDefault(require("../errors/CriterionEvaluationError.cjs"));
9
+ var _CriterionErrorReason = _interopRequireDefault(require("./CriterionErrorReason.cjs"));
9
10
  /**
10
11
  * Evaluates a `regex` Arazzo criterion condition against a resolved context value.
11
12
  *
@@ -33,7 +34,7 @@ class RegexCriterionEvaluator {
33
34
  * Tests the resolved context value against the regular expression `condition`.
34
35
  *
35
36
  * The context is coerced to a string before matching. Returns `false` when the
36
- * context is `null` or `undefined`. Throws {@link CriterionError} when the
37
+ * context is `null` or `undefined`. Throws {@link CriterionEvaluationError} when the
37
38
  * condition is not a valid regular expression.
38
39
  */
39
40
  evaluate(condition, context) {
@@ -42,11 +43,13 @@ class RegexCriterionEvaluator {
42
43
  try {
43
44
  regExp = new RegExp(condition);
44
45
  } catch (error) {
45
- throw new _CriterionError.default(`Invalid regex criterion condition "${condition}"`, {
46
+ // the engine has seen only the pattern, never the context, so its
47
+ // message is safe to surface.
48
+ throw new _CriterionEvaluationError.default(`Invalid regex criterion condition "${condition}": ${error.message}`, {
46
49
  cause: error,
47
50
  condition,
48
51
  type: 'regex',
49
- reason: 'invalid-regex'
52
+ reason: _CriterionErrorReason.default.InvalidRegex
50
53
  });
51
54
  }
52
55
  return regExp.test(this.#stringify(context));
@@ -1,4 +1,5 @@
1
- import CriterionError from "../errors/CriterionError.mjs";
1
+ import CriterionEvaluationError from "../errors/CriterionEvaluationError.mjs";
2
+ import CriterionErrorReason from "./CriterionErrorReason.mjs";
2
3
  /**
3
4
  * Evaluates a `regex` Arazzo criterion condition against a resolved context value.
4
5
  *
@@ -26,7 +27,7 @@ class RegexCriterionEvaluator {
26
27
  * Tests the resolved context value against the regular expression `condition`.
27
28
  *
28
29
  * The context is coerced to a string before matching. Returns `false` when the
29
- * context is `null` or `undefined`. Throws {@link CriterionError} when the
30
+ * context is `null` or `undefined`. Throws {@link CriterionEvaluationError} when the
30
31
  * condition is not a valid regular expression.
31
32
  */
32
33
  evaluate(condition, context) {
@@ -35,11 +36,13 @@ class RegexCriterionEvaluator {
35
36
  try {
36
37
  regExp = new RegExp(condition);
37
38
  } catch (error) {
38
- throw new CriterionError(`Invalid regex criterion condition "${condition}"`, {
39
+ // the engine has seen only the pattern, never the context, so its
40
+ // message is safe to surface.
41
+ throw new CriterionEvaluationError(`Invalid regex criterion condition "${condition}": ${error.message}`, {
39
42
  cause: error,
40
43
  condition,
41
44
  type: 'regex',
42
- reason: 'invalid-regex'
45
+ reason: CriterionErrorReason.InvalidRegex
43
46
  });
44
47
  }
45
48
  return regExp.test(this.#stringify(context));
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.default = void 0;
8
8
  var _arazzoCriterion = require("@swaggerexpert/arazzo-criterion");
9
- var _CriterionError = _interopRequireDefault(require("../errors/CriterionError.cjs"));
9
+ var _CriterionEvaluationError = _interopRequireDefault(require("../errors/CriterionEvaluationError.cjs"));
10
+ var _CriterionErrorReason = _interopRequireDefault(require("./CriterionErrorReason.cjs"));
10
11
  /**
11
12
  * Evaluates a `simple` Arazzo criterion condition.
12
13
  *
@@ -21,7 +22,7 @@ var _CriterionError = _interopRequireDefault(require("../errors/CriterionError.c
21
22
  * compared per the library's rules (e.g. `undefined == x` and relational
22
23
  * comparisons are false, matching the spec's "null equals only null"), so a
23
24
  * negated or disjunctive condition may still pass. A malformed condition throws
24
- * {@link CriterionError}.
25
+ * {@link CriterionEvaluationError}.
25
26
  * @public
26
27
  */
27
28
  class SimpleCriterionEvaluator {
@@ -36,11 +37,11 @@ class SimpleCriterionEvaluator {
36
37
  });
37
38
  } catch (error) {
38
39
  if (error instanceof _arazzoCriterion.ArazzoCriterionError) {
39
- throw new _CriterionError.default(`Invalid simple criterion condition "${condition}"`, {
40
+ throw new _CriterionEvaluationError.default(`Invalid simple criterion condition "${condition}"`, {
40
41
  cause: error,
41
42
  condition,
42
43
  type: 'simple',
43
- reason: 'invalid-simple'
44
+ reason: _CriterionErrorReason.default.InvalidSimple
44
45
  });
45
46
  }
46
47
  throw error;
@@ -1,5 +1,6 @@
1
1
  import { evaluate as evaluateSimpleCriterion, ArazzoCriterionError } from '@swaggerexpert/arazzo-criterion';
2
- import CriterionError from "../errors/CriterionError.mjs";
2
+ import CriterionEvaluationError from "../errors/CriterionEvaluationError.mjs";
3
+ import CriterionErrorReason from "./CriterionErrorReason.mjs";
3
4
  /**
4
5
  * Evaluates a `simple` Arazzo criterion condition.
5
6
  *
@@ -14,7 +15,7 @@ import CriterionError from "../errors/CriterionError.mjs";
14
15
  * compared per the library's rules (e.g. `undefined == x` and relational
15
16
  * comparisons are false, matching the spec's "null equals only null"), so a
16
17
  * negated or disjunctive condition may still pass. A malformed condition throws
17
- * {@link CriterionError}.
18
+ * {@link CriterionEvaluationError}.
18
19
  * @public
19
20
  */
20
21
  class SimpleCriterionEvaluator {
@@ -29,11 +30,11 @@ class SimpleCriterionEvaluator {
29
30
  });
30
31
  } catch (error) {
31
32
  if (error instanceof ArazzoCriterionError) {
32
- throw new CriterionError(`Invalid simple criterion condition "${condition}"`, {
33
+ throw new CriterionEvaluationError(`Invalid simple criterion condition "${condition}"`, {
33
34
  cause: error,
34
35
  condition,
35
36
  type: 'simple',
36
- reason: 'invalid-simple'
37
+ reason: CriterionErrorReason.InvalidSimple
37
38
  });
38
39
  }
39
40
  throw error;
@@ -7,7 +7,8 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.default = void 0;
8
8
  var _fontoxpath = _interopRequireDefault(require("fontoxpath"));
9
9
  var _xmldom = require("@xmldom/xmldom");
10
- var _CriterionError = _interopRequireDefault(require("../errors/CriterionError.cjs"));
10
+ var _CriterionEvaluationError = _interopRequireDefault(require("../errors/CriterionEvaluationError.cjs"));
11
+ var _CriterionErrorReason = _interopRequireDefault(require("./CriterionErrorReason.cjs"));
11
12
  // fontoxpath is CommonJS and its named exports are not statically resolvable
12
13
  // under ESM, so import the default and destructure.
13
14
 
@@ -28,7 +29,7 @@ const {
28
29
  *
29
30
  * Only XPath 3.1 is supported (`fontoxpath`'s engine); version gating happens in
30
31
  * the facade. Per Arazzo 1.1.0, a `null` or `undefined` context fails the
31
- * condition. An invalid query throws {@link CriterionError}.
32
+ * condition. An invalid query throws {@link CriterionEvaluationError}.
32
33
  * @public
33
34
  */
34
35
  class XPathCriterionEvaluator {
@@ -37,7 +38,7 @@ class XPathCriterionEvaluator {
37
38
  * its Effective Boolean Value.
38
39
  *
39
40
  * Returns `false` when the context is `null` or `undefined`. Throws
40
- * {@link CriterionError} when the context is not XML or the query is invalid.
41
+ * {@link CriterionEvaluationError} when the context is not XML or the query is invalid.
41
42
  */
42
43
  evaluate(condition, context) {
43
44
  if (context === null || context === undefined) return false;
@@ -47,11 +48,14 @@ class XPathCriterionEvaluator {
47
48
  language: evaluateXPath.XPATH_3_1_LANGUAGE
48
49
  });
49
50
  } catch (error) {
50
- throw new _CriterionError.default(`Invalid xpath criterion condition "${condition}"`, {
51
+ // no engine detail: the query has run against the context, and it can
52
+ // put context values into its own error (a dynamic error, or fn:error
53
+ // with a code and description of the query's choosing).
54
+ throw new _CriterionEvaluationError.default(`Invalid xpath criterion condition "${condition}"`, {
51
55
  cause: error,
52
56
  condition,
53
57
  type: 'xpath',
54
- reason: 'invalid-xpath'
58
+ reason: _CriterionErrorReason.default.InvalidXPath
55
59
  });
56
60
  }
57
61
  }
@@ -64,10 +68,10 @@ class XPathCriterionEvaluator {
64
68
  #toNode(condition, context) {
65
69
  if (this.#isNode(context)) return context;
66
70
  if (typeof context !== 'string') {
67
- throw new _CriterionError.default('xpath criterion context is not XML', {
71
+ throw new _CriterionEvaluationError.default('xpath criterion context is not XML', {
68
72
  condition,
69
73
  type: 'xpath',
70
- reason: 'invalid-context'
74
+ reason: _CriterionErrorReason.default.InvalidXPathContext
71
75
  });
72
76
  }
73
77
 
@@ -83,21 +87,21 @@ class XPathCriterionEvaluator {
83
87
  }
84
88
  }).parseFromString(context, 'text/xml');
85
89
  if (parseError !== undefined) {
86
- throw new _CriterionError.default('xpath criterion context is not valid XML', {
90
+ throw new _CriterionEvaluationError.default('xpath criterion context is not valid XML', {
87
91
  cause: parseError,
88
92
  condition,
89
93
  type: 'xpath',
90
- reason: 'invalid-context'
94
+ reason: _CriterionErrorReason.default.InvalidXPathContext
91
95
  });
92
96
  }
93
97
  return document;
94
98
  } catch (error) {
95
- if (error instanceof _CriterionError.default) throw error;
96
- throw new _CriterionError.default('xpath criterion context is not valid XML', {
99
+ if (error instanceof _CriterionEvaluationError.default) throw error;
100
+ throw new _CriterionEvaluationError.default('xpath criterion context is not valid XML', {
97
101
  cause: error,
98
102
  condition,
99
103
  type: 'xpath',
100
- reason: 'invalid-context'
104
+ reason: _CriterionErrorReason.default.InvalidXPathContext
101
105
  });
102
106
  }
103
107
  }
@@ -2,7 +2,8 @@
2
2
  // under ESM, so import the default and destructure.
3
3
  import fontoxpath from 'fontoxpath';
4
4
  import { DOMParser } from '@xmldom/xmldom';
5
- import CriterionError from "../errors/CriterionError.mjs";
5
+ import CriterionEvaluationError from "../errors/CriterionEvaluationError.mjs";
6
+ import CriterionErrorReason from "./CriterionErrorReason.mjs";
6
7
  const {
7
8
  evaluateXPathToBoolean,
8
9
  evaluateXPath
@@ -20,7 +21,7 @@ const {
20
21
  *
21
22
  * Only XPath 3.1 is supported (`fontoxpath`'s engine); version gating happens in
22
23
  * the facade. Per Arazzo 1.1.0, a `null` or `undefined` context fails the
23
- * condition. An invalid query throws {@link CriterionError}.
24
+ * condition. An invalid query throws {@link CriterionEvaluationError}.
24
25
  * @public
25
26
  */
26
27
  class XPathCriterionEvaluator {
@@ -29,7 +30,7 @@ class XPathCriterionEvaluator {
29
30
  * its Effective Boolean Value.
30
31
  *
31
32
  * Returns `false` when the context is `null` or `undefined`. Throws
32
- * {@link CriterionError} when the context is not XML or the query is invalid.
33
+ * {@link CriterionEvaluationError} when the context is not XML or the query is invalid.
33
34
  */
34
35
  evaluate(condition, context) {
35
36
  if (context === null || context === undefined) return false;
@@ -39,11 +40,14 @@ class XPathCriterionEvaluator {
39
40
  language: evaluateXPath.XPATH_3_1_LANGUAGE
40
41
  });
41
42
  } catch (error) {
42
- throw new CriterionError(`Invalid xpath criterion condition "${condition}"`, {
43
+ // no engine detail: the query has run against the context, and it can
44
+ // put context values into its own error (a dynamic error, or fn:error
45
+ // with a code and description of the query's choosing).
46
+ throw new CriterionEvaluationError(`Invalid xpath criterion condition "${condition}"`, {
43
47
  cause: error,
44
48
  condition,
45
49
  type: 'xpath',
46
- reason: 'invalid-xpath'
50
+ reason: CriterionErrorReason.InvalidXPath
47
51
  });
48
52
  }
49
53
  }
@@ -56,10 +60,10 @@ class XPathCriterionEvaluator {
56
60
  #toNode(condition, context) {
57
61
  if (this.#isNode(context)) return context;
58
62
  if (typeof context !== 'string') {
59
- throw new CriterionError('xpath criterion context is not XML', {
63
+ throw new CriterionEvaluationError('xpath criterion context is not XML', {
60
64
  condition,
61
65
  type: 'xpath',
62
- reason: 'invalid-context'
66
+ reason: CriterionErrorReason.InvalidXPathContext
63
67
  });
64
68
  }
65
69
 
@@ -75,21 +79,21 @@ class XPathCriterionEvaluator {
75
79
  }
76
80
  }).parseFromString(context, 'text/xml');
77
81
  if (parseError !== undefined) {
78
- throw new CriterionError('xpath criterion context is not valid XML', {
82
+ throw new CriterionEvaluationError('xpath criterion context is not valid XML', {
79
83
  cause: parseError,
80
84
  condition,
81
85
  type: 'xpath',
82
- reason: 'invalid-context'
86
+ reason: CriterionErrorReason.InvalidXPathContext
83
87
  });
84
88
  }
85
89
  return document;
86
90
  } catch (error) {
87
- if (error instanceof CriterionError) throw error;
88
- throw new CriterionError('xpath criterion context is not valid XML', {
91
+ if (error instanceof CriterionEvaluationError) throw error;
92
+ throw new CriterionEvaluationError('xpath criterion context is not valid XML', {
89
93
  cause: error,
90
94
  condition,
91
95
  type: 'xpath',
92
- reason: 'invalid-context'
96
+ reason: CriterionErrorReason.InvalidXPathContext
93
97
  });
94
98
  }
95
99
  }
@@ -0,0 +1,18 @@
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.default = void 0;
8
+ var _CriterionError = _interopRequireDefault(require("./CriterionError.cjs"));
9
+ /**
10
+ * A criterion condition that cannot be evaluated: a syntax error in the
11
+ * condition, a context the condition cannot apply to, or an error raised while
12
+ * evaluating it. The type-specific criterion evaluators throw it;
13
+ * `CriterionEvaluator` turns it into an unmet criterion, as Arazzo 1.1.0
14
+ * requires.
15
+ * @public
16
+ */
17
+ class CriterionEvaluationError extends _CriterionError.default {}
18
+ var _default = exports.default = CriterionEvaluationError;
@@ -0,0 +1,11 @@
1
+ import CriterionError from "./CriterionError.mjs";
2
+ /**
3
+ * A criterion condition that cannot be evaluated: a syntax error in the
4
+ * condition, a context the condition cannot apply to, or an error raised while
5
+ * evaluating it. The type-specific criterion evaluators throw it;
6
+ * `CriterionEvaluator` turns it into an unmet criterion, as Arazzo 1.1.0
7
+ * requires.
8
+ * @public
9
+ */
10
+ class CriterionEvaluationError extends CriterionError {}
11
+ export default CriterionEvaluationError;
@@ -44,6 +44,12 @@ const STEP_TARGET_FIELDS = exports.STEP_TARGET_FIELDS = ['operationId', 'operati
44
44
  * @public
45
45
  */
46
46
 
47
+ /**
48
+ * The outcome of one criterion a step evaluated: one of its `successCriteria`,
49
+ * or one of the `criteria` of an action it considered.
50
+ * @public
51
+ */
52
+
47
53
  /**
48
54
  * The outcome of executing a single step.
49
55
  * @public
@@ -190,16 +196,22 @@ class StepExecutor {
190
196
  // evaluate criteria, outputs, and the next action against the post-request
191
197
  // context (with $request / $url / $method and $response / $statusCode).
192
198
  const postContext = state.toContext(this.#requestContext(response), this.#responseContext(response));
193
- const successful = this.evaluateCriteria(step, postContext);
199
+ const successCriteria = this.evaluateCriteria(step, postContext);
200
+ const successful = successCriteria.every(criterion => criterion.met);
194
201
  const outputs = this.#outputResolver.resolve(step.outputs, expression => this.#evaluate(postContext, expression), scope);
195
- const matchedActions = this.selectActions(step, successful, postContext);
202
+ const {
203
+ matchedActions,
204
+ actionCriteria
205
+ } = this.selectActions(step, successful, postContext);
196
206
  return {
197
207
  stepId,
198
208
  response,
199
209
  successful,
200
210
  outputs,
201
211
  action: matchedActions[0],
202
- matchedActions
212
+ matchedActions,
213
+ successCriteria,
214
+ actionCriteria
203
215
  };
204
216
  }
205
217
 
@@ -272,9 +284,12 @@ class StepExecutor {
272
284
  }
273
285
 
274
286
  /**
275
- * Evaluates the step's `successCriteria`; all criteria must pass. A step with
276
- * no criteria succeeds on a received response. An unreadable
277
- * `successCriteria` throws, see {@link StepExecutor.assertSuccessCriteria}.
287
+ * Evaluates the step's `successCriteria`, returning one record per criterion
288
+ * in list order; the step succeeds when every record is met. Every criterion
289
+ * is evaluated, so the records explain each unmet one, not only the first. A
290
+ * step with no criteria returns no records and succeeds on a received
291
+ * response. An unreadable `successCriteria` throws, see
292
+ * {@link StepExecutor.assertSuccessCriteria}.
278
293
  *
279
294
  * Public for the same reason as {@link StepExecutor.selectActions}: a step
280
295
  * targeting a `workflowId` is run by the workflow executor and never reaches
@@ -284,15 +299,16 @@ class StepExecutor {
284
299
  evaluateCriteria(step, context) {
285
300
  this.assertSuccessCriteria(step);
286
301
  const criteria = step.successCriteria;
287
- if (criteria === undefined) return true;
302
+ if (criteria === undefined) return [];
288
303
 
289
304
  // assertSuccessCriteria above guarantees every entry is a Criterion Object
290
- return [...criteria].every(criterion => this.#criterionEvaluator.evaluate(criterion, expression => this.#evaluate(context, expression)));
305
+ return [...criteria].map(criterion => this.#evaluateCriterion(criterion, context));
291
306
  }
292
307
 
293
308
  /**
294
309
  * Selects every matching `onSuccess` / `onFailure` action for the outcome, in
295
- * list order, gating each action's criteria against the context.
310
+ * list order, gating each action's criteria against the context, and records
311
+ * the outcome of every action criterion evaluated.
296
312
  *
297
313
  * The step's own list is the whole story here: a step that declares none of
298
314
  * its own already carries the workflow-level defaults, inherited by
@@ -311,25 +327,65 @@ class StepExecutor {
311
327
  * the expression context through this one method rather than wiring their own.
312
328
  */
313
329
  selectActions(step, successful, context) {
314
- const isCriterionMet = criterion => {
315
- try {
316
- return this.#criterionEvaluator.evaluate(criterion, expression => this.#evaluate(context, expression));
317
- } catch (error) {
318
- // an action's criteria decide whether it applies to this outcome, and
319
- // actions are shared — inherited from the workflow, reused from
320
- // components. A condition on an HTTP exchange cannot apply to a step
321
- // that calls a workflow, so the action does not match; the run does not
322
- // abort over a default written for the operation steps.
323
- if (error instanceof _RuntimeExpressionError.default && error.reason === 'unavailable-expression') {
324
- return false;
325
- }
326
- throw error;
327
- }
330
+ const actionCriteria = [];
331
+ const isCriterionMet = (criterion, action) => {
332
+ const record = {
333
+ ...this.#evaluateCriterion(criterion, context),
334
+ actionName: (0, _apidomCore.toValue)(action.name)
335
+ };
336
+ actionCriteria.push(record);
337
+ return record.met;
328
338
  };
329
339
  const scope = {
330
340
  stepId: (0, _apidomCore.toValue)(step.stepId)
331
341
  };
332
- return successful ? this.#actionResolver.resolveOnSuccess(step.onSuccess, isCriterionMet, scope) : this.#actionResolver.resolveOnFailure(step.onFailure, isCriterionMet, scope);
342
+ const matchedActions = successful ? this.#actionResolver.resolveOnSuccess(step.onSuccess, isCriterionMet, scope) : this.#actionResolver.resolveOnFailure(step.onFailure, isCriterionMet, scope);
343
+ return {
344
+ matchedActions,
345
+ actionCriteria
346
+ };
347
+ }
348
+
349
+ /**
350
+ * Evaluates one criterion into a {@link CriterionEvaluationRecord}. A
351
+ * condition that cannot be evaluated is unmet and records why; any other
352
+ * error propagates.
353
+ */
354
+ #evaluateCriterion(criterion, context) {
355
+ const condition = (0, _apidomCore.toValue)(criterion.condition);
356
+ try {
357
+ const {
358
+ met,
359
+ error
360
+ } = this.#criterionEvaluator.evaluate(criterion, expression => this.#evaluate(context, expression));
361
+ if (error === undefined) return {
362
+ condition,
363
+ met
364
+ };
365
+ return {
366
+ condition,
367
+ met,
368
+ diagnostic: {
369
+ code: error.reason,
370
+ message: error.message
371
+ }
372
+ };
373
+ } catch (error) {
374
+ // a step that calls a workflow made no HTTP call, so a condition on one
375
+ // fails like any unevaluable condition; the diagnostic keeps the
376
+ // authoring mistake visible.
377
+ if (error instanceof _RuntimeExpressionError.default && error.reason === 'unavailable-expression') {
378
+ return {
379
+ condition,
380
+ met: false,
381
+ diagnostic: {
382
+ code: error.reason,
383
+ message: error.message
384
+ }
385
+ };
386
+ }
387
+ throw error;
388
+ }
333
389
  }
334
390
 
335
391
  /**