@usearazzo/runner 1.0.1-alpha.20 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usearazzo/runner",
3
- "version": "1.0.1-alpha.20",
3
+ "version": "1.0.1-alpha.21",
4
4
  "description": "Runner for Arazzo Workflows.",
5
5
  "keywords": [
6
6
  "arazzo",
@@ -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.2",
76
- "@usearazzo/parser": "1.0.1-alpha.20",
77
- "@usearazzo/resolver": "1.0.1-alpha.20",
76
+ "@usearazzo/parser": "1.0.1-alpha.21",
77
+ "@usearazzo/resolver": "1.0.1-alpha.21",
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": "5af237fe28ae20de4d56e5c0ba6d2e17fcf90f73"
97
+ "gitHead": "d342b02adbd11f5362aa4850b2417521e59448ce"
98
98
  }
@@ -9,10 +9,11 @@ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
9
9
  var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
10
10
  var _ResolverError = _interopRequireDefault(require("../errors/ResolverError.cjs"));
11
11
  /**
12
- * Determines whether a single criterion is met.
12
+ * Determines whether a single criterion of an action is met. Receives the
13
+ * action declaring the criterion, so a caller can attribute the outcome to it.
13
14
  *
14
15
  * Bridged to a criterion evaluator
15
- * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve)`); an
16
+ * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve).met`); an
16
17
  * unresolvable/failing criterion is `false`, not an error.
17
18
  * @public
18
19
  */
@@ -144,6 +145,7 @@ class ActionResolver {
144
145
  reason: 'malformed-criteria'
145
146
  });
146
147
  }
148
+ let met = true;
147
149
  for (const criterion of criteria) {
148
150
  if (!(0, _apidomNsArazzo.isCriterionElement)(criterion)) {
149
151
  throw new _ResolverError.default("An action's `criteria` contains an entry that is not a Criterion Object", {
@@ -152,9 +154,11 @@ class ActionResolver {
152
154
  reason: 'malformed-criterion'
153
155
  });
154
156
  }
155
- if (!isCriterionMet(criterion)) return false;
157
+ // every criterion is evaluated, not only up to the first unmet one, so
158
+ // a predicate that records outcomes sees the whole list.
159
+ if (!isCriterionMet(criterion, action)) met = false;
156
160
  }
157
- return true;
161
+ return met;
158
162
  }
159
163
  }
160
164
  var _default = exports.default = ActionResolver;
@@ -2,10 +2,11 @@ import { isArrayElement } from '@speclynx/apidom-datamodel';
2
2
  import { isSuccessActionElement, isFailureActionElement, isCriterionElement } from '@speclynx/apidom-ns-arazzo-1';
3
3
  import ResolverError from "../errors/ResolverError.mjs";
4
4
  /**
5
- * Determines whether a single criterion is met.
5
+ * Determines whether a single criterion of an action is met. Receives the
6
+ * action declaring the criterion, so a caller can attribute the outcome to it.
6
7
  *
7
8
  * Bridged to a criterion evaluator
8
- * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve)`); an
9
+ * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve).met`); an
9
10
  * unresolvable/failing criterion is `false`, not an error.
10
11
  * @public
11
12
  */
@@ -134,6 +135,7 @@ class ActionResolver {
134
135
  reason: 'malformed-criteria'
135
136
  });
136
137
  }
138
+ let met = true;
137
139
  for (const criterion of criteria) {
138
140
  if (!isCriterionElement(criterion)) {
139
141
  throw new ResolverError("An action's `criteria` contains an entry that is not a Criterion Object", {
@@ -142,9 +144,11 @@ class ActionResolver {
142
144
  reason: 'malformed-criterion'
143
145
  });
144
146
  }
145
- if (!isCriterionMet(criterion)) return false;
147
+ // every criterion is evaluated, not only up to the first unmet one, so
148
+ // a predicate that records outcomes sees the whole list.
149
+ if (!isCriterionMet(criterion, action)) met = false;
146
150
  }
147
- return true;
151
+ return met;
148
152
  }
149
153
  }
150
154
  export default ActionResolver;
@@ -28,6 +28,11 @@ var _XPathCriterionEvaluator = _interopRequireDefault(require("./XPathCriterionE
28
28
  * @public
29
29
  */
30
30
 
31
+ /**
32
+ * The outcome of evaluating one criterion.
33
+ * @public
34
+ */
35
+
31
36
  /**
32
37
  * Options for the CriterionEvaluator.
33
38
  *
@@ -38,7 +43,7 @@ var _XPathCriterionEvaluator = _interopRequireDefault(require("./XPathCriterionE
38
43
  */
39
44
 
40
45
  /**
41
- * Evaluates an Arazzo Criterion Object to a boolean.
46
+ * Evaluates an Arazzo Criterion Object to a {@link CriterionOutcome}.
42
47
  *
43
48
  * Dispatches on the criterion's `type` (defaulting to `simple` when omitted):
44
49
  * - `simple` — evaluates the condition directly, resolving the runtime
@@ -58,12 +63,13 @@ var _XPathCriterionEvaluator = _interopRequireDefault(require("./XPathCriterionE
58
63
  * the 1.1.0 rule to every document, which accepts more but never evaluates a
59
64
  * query under the wrong dialect.
60
65
  *
61
- * A condition that cannot be evaluated fails the criterion (`false`), as
66
+ * A condition that cannot be evaluated fails the criterion (`met: false`), as
62
67
  * Arazzo 1.1.0 requires: a syntax error in the condition, a context the
63
68
  * condition cannot apply to (non-XML data for `xpath`), or an XPath evaluation
64
69
  * error. The type-specific evaluators report these as a
65
- * {@link CriterionEvaluationError}, which this facade absorbs; any other error
66
- * they raise propagates. A criterion that is malformed as written still throws: a
70
+ * {@link CriterionEvaluationError}, which this facade returns as the
71
+ * outcome's `error` so the caller can report it; any other error they raise
72
+ * propagates. A criterion that is malformed as written still throws: a
67
73
  * missing `condition`, an unknown or unreadable `type`, an unsupported
68
74
  * expression `version`, or a `context` that is missing or not a runtime
69
75
  * expression.
@@ -87,7 +93,8 @@ class CriterionEvaluator {
87
93
  }
88
94
 
89
95
  /**
90
- * Evaluates a criterion element, returning whether the condition is met.
96
+ * Evaluates a criterion element, returning whether the condition is met and,
97
+ * when it cannot be evaluated, why.
91
98
  *
92
99
  * `resolve` turns a runtime expression into a value: for `simple` it resolves
93
100
  * the expressions embedded in the condition; for the other types it resolves
@@ -109,23 +116,28 @@ class CriterionEvaluator {
109
116
  }
110
117
  const type = this.#resolveType(criterion);
111
118
  this.#requireValidContext(criterion, type);
119
+ let met;
112
120
  try {
113
121
  switch (type) {
114
122
  case 'simple':
115
- return this.#simple.evaluate(condition, resolve);
123
+ met = this.#simple.evaluate(condition, resolve);
124
+ break;
116
125
  case 'regex':
117
- return this.#regex.evaluate(condition, this.#resolveContext(criterion, type, resolve));
126
+ met = this.#regex.evaluate(condition, this.#resolveContext(criterion, type, resolve));
127
+ break;
118
128
  case 'jsonpath':
119
129
  // only rfc9535 is supported, Arazzo 1.1.0's default, so an omitted
120
130
  // version is accepted. draft-goessner has different semantics and is
121
131
  // rejected rather than mis-evaluated.
122
132
  this.#requireVersion(criterion, type, condition, 'rfc9535');
123
- return this.#jsonpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
133
+ met = this.#jsonpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
134
+ break;
124
135
  case 'xpath':
125
136
  // only XPath 3.1 is supported; xpath-31 is Arazzo 1.1.0's default, so
126
137
  // an omitted version is accepted. Older versions are rejected.
127
138
  this.#requireVersion(criterion, type, condition, 'xpath-31');
128
- return this.#xpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
139
+ met = this.#xpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
140
+ break;
129
141
  default:
130
142
  throw new _CriterionError.default(`Unknown criterion type "${type}"`, {
131
143
  condition,
@@ -136,9 +148,15 @@ class CriterionEvaluator {
136
148
  } catch (error) {
137
149
  // Arazzo 1.1.0: a condition that cannot be evaluated MUST evaluate to fail.
138
150
  // The structural checks throw a plain CriterionError and still propagate.
139
- if (error instanceof _CriterionEvaluationError.default) return false;
151
+ if (error instanceof _CriterionEvaluationError.default) return {
152
+ met: false,
153
+ error
154
+ };
140
155
  throw error;
141
156
  }
157
+ return {
158
+ met
159
+ };
142
160
  }
143
161
 
144
162
  /**
@@ -20,6 +20,10 @@ import XPathCriterionEvaluator from "./XPathCriterionEvaluator.mjs";
20
20
  * lenient evaluator).
21
21
  * @public
22
22
  */
23
+ /**
24
+ * The outcome of evaluating one criterion.
25
+ * @public
26
+ */
23
27
  /**
24
28
  * Options for the CriterionEvaluator.
25
29
  *
@@ -29,7 +33,7 @@ import XPathCriterionEvaluator from "./XPathCriterionEvaluator.mjs";
29
33
  * @public
30
34
  */
31
35
  /**
32
- * Evaluates an Arazzo Criterion Object to a boolean.
36
+ * Evaluates an Arazzo Criterion Object to a {@link CriterionOutcome}.
33
37
  *
34
38
  * Dispatches on the criterion's `type` (defaulting to `simple` when omitted):
35
39
  * - `simple` — evaluates the condition directly, resolving the runtime
@@ -49,12 +53,13 @@ import XPathCriterionEvaluator from "./XPathCriterionEvaluator.mjs";
49
53
  * the 1.1.0 rule to every document, which accepts more but never evaluates a
50
54
  * query under the wrong dialect.
51
55
  *
52
- * A condition that cannot be evaluated fails the criterion (`false`), as
56
+ * A condition that cannot be evaluated fails the criterion (`met: false`), as
53
57
  * Arazzo 1.1.0 requires: a syntax error in the condition, a context the
54
58
  * condition cannot apply to (non-XML data for `xpath`), or an XPath evaluation
55
59
  * error. The type-specific evaluators report these as a
56
- * {@link CriterionEvaluationError}, which this facade absorbs; any other error
57
- * they raise propagates. A criterion that is malformed as written still throws: a
60
+ * {@link CriterionEvaluationError}, which this facade returns as the
61
+ * outcome's `error` so the caller can report it; any other error they raise
62
+ * propagates. A criterion that is malformed as written still throws: a
58
63
  * missing `condition`, an unknown or unreadable `type`, an unsupported
59
64
  * expression `version`, or a `context` that is missing or not a runtime
60
65
  * expression.
@@ -78,7 +83,8 @@ class CriterionEvaluator {
78
83
  }
79
84
 
80
85
  /**
81
- * Evaluates a criterion element, returning whether the condition is met.
86
+ * Evaluates a criterion element, returning whether the condition is met and,
87
+ * when it cannot be evaluated, why.
82
88
  *
83
89
  * `resolve` turns a runtime expression into a value: for `simple` it resolves
84
90
  * the expressions embedded in the condition; for the other types it resolves
@@ -100,23 +106,28 @@ class CriterionEvaluator {
100
106
  }
101
107
  const type = this.#resolveType(criterion);
102
108
  this.#requireValidContext(criterion, type);
109
+ let met;
103
110
  try {
104
111
  switch (type) {
105
112
  case 'simple':
106
- return this.#simple.evaluate(condition, resolve);
113
+ met = this.#simple.evaluate(condition, resolve);
114
+ break;
107
115
  case 'regex':
108
- return this.#regex.evaluate(condition, this.#resolveContext(criterion, type, resolve));
116
+ met = this.#regex.evaluate(condition, this.#resolveContext(criterion, type, resolve));
117
+ break;
109
118
  case 'jsonpath':
110
119
  // only rfc9535 is supported, Arazzo 1.1.0's default, so an omitted
111
120
  // version is accepted. draft-goessner has different semantics and is
112
121
  // rejected rather than mis-evaluated.
113
122
  this.#requireVersion(criterion, type, condition, 'rfc9535');
114
- return this.#jsonpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
123
+ met = this.#jsonpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
124
+ break;
115
125
  case 'xpath':
116
126
  // only XPath 3.1 is supported; xpath-31 is Arazzo 1.1.0's default, so
117
127
  // an omitted version is accepted. Older versions are rejected.
118
128
  this.#requireVersion(criterion, type, condition, 'xpath-31');
119
- return this.#xpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
129
+ met = this.#xpath.evaluate(condition, this.#resolveContext(criterion, type, resolve));
130
+ break;
120
131
  default:
121
132
  throw new CriterionError(`Unknown criterion type "${type}"`, {
122
133
  condition,
@@ -127,9 +138,15 @@ class CriterionEvaluator {
127
138
  } catch (error) {
128
139
  // Arazzo 1.1.0: a condition that cannot be evaluated MUST evaluate to fail.
129
140
  // The structural checks throw a plain CriterionError and still propagate.
130
- if (error instanceof CriterionEvaluationError) return false;
141
+ if (error instanceof CriterionEvaluationError) return {
142
+ met: false,
143
+ error
144
+ };
131
145
  throw error;
132
146
  }
147
+ return {
148
+ met
149
+ };
133
150
  }
134
151
 
135
152
  /**
@@ -34,7 +34,10 @@ class JSONPathCriterionEvaluator {
34
34
  return (0, _jsonpath.evaluate)(context, condition).length > 0;
35
35
  } catch (error) {
36
36
  if (error instanceof _jsonpath.JSONPathError) {
37
- throw new _CriterionEvaluationError.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}`, {
38
41
  cause: error,
39
42
  condition,
40
43
  type: 'jsonpath',
@@ -1,4 +1,4 @@
1
- import { evaluate as evaluateJSONPath, JSONPathError } from '@swaggerexpert/jsonpath';
1
+ import { evaluate as evaluateJSONPath, JSONPathError, JSONPathParseError } from '@swaggerexpert/jsonpath';
2
2
  import CriterionEvaluationError from "../errors/CriterionEvaluationError.mjs";
3
3
  import CriterionErrorReason from "./CriterionErrorReason.mjs";
4
4
  /**
@@ -27,7 +27,10 @@ class JSONPathCriterionEvaluator {
27
27
  return evaluateJSONPath(context, condition).length > 0;
28
28
  } catch (error) {
29
29
  if (error instanceof JSONPathError) {
30
- throw new CriterionEvaluationError(`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}`, {
31
34
  cause: error,
32
35
  condition,
33
36
  type: 'jsonpath',
@@ -43,7 +43,9 @@ class RegexCriterionEvaluator {
43
43
  try {
44
44
  regExp = new RegExp(condition);
45
45
  } catch (error) {
46
- throw new _CriterionEvaluationError.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}`, {
47
49
  cause: error,
48
50
  condition,
49
51
  type: 'regex',
@@ -36,7 +36,9 @@ class RegexCriterionEvaluator {
36
36
  try {
37
37
  regExp = new RegExp(condition);
38
38
  } catch (error) {
39
- throw new CriterionEvaluationError(`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}`, {
40
42
  cause: error,
41
43
  condition,
42
44
  type: 'regex',
@@ -48,6 +48,9 @@ class XPathCriterionEvaluator {
48
48
  language: evaluateXPath.XPATH_3_1_LANGUAGE
49
49
  });
50
50
  } catch (error) {
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).
51
54
  throw new _CriterionEvaluationError.default(`Invalid xpath criterion condition "${condition}"`, {
52
55
  cause: error,
53
56
  condition,
@@ -40,6 +40,9 @@ class XPathCriterionEvaluator {
40
40
  language: evaluateXPath.XPATH_3_1_LANGUAGE
41
41
  });
42
42
  } catch (error) {
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).
43
46
  throw new CriterionEvaluationError(`Invalid xpath criterion condition "${condition}"`, {
44
47
  cause: error,
45
48
  condition,
@@ -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
  /**