@usearazzo/runner 0.0.0-stage → 1.0.1-alpha.9

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.
Files changed (152) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +20 -0
  4. package/README.md +777 -2
  5. package/dist/arazzo-runner.browser.js +111247 -0
  6. package/dist/arazzo-runner.browser.min.js +1 -0
  7. package/package.json +90 -4
  8. package/src/action/ActionResolver.cjs +160 -0
  9. package/src/action/ActionResolver.mjs +150 -0
  10. package/src/assembler/OpenAPI2DocumentAssembler.cjs +111 -0
  11. package/src/assembler/OpenAPI2DocumentAssembler.mjs +104 -0
  12. package/src/assembler/OpenAPI30DocumentAssembler.cjs +110 -0
  13. package/src/assembler/OpenAPI30DocumentAssembler.mjs +103 -0
  14. package/src/assembler/OpenAPI31DocumentAssembler.cjs +111 -0
  15. package/src/assembler/OpenAPI31DocumentAssembler.mjs +104 -0
  16. package/src/assembler/OpenAPIDocumentAssembler.cjs +58 -0
  17. package/src/assembler/OpenAPIDocumentAssembler.mjs +50 -0
  18. package/src/client/HTTPClient.cjs +5 -0
  19. package/src/client/HTTPClient.mjs +1 -0
  20. package/src/client/HTTPClientFetch.cjs +16 -0
  21. package/src/client/HTTPClientFetch.mjs +10 -0
  22. package/src/client/OpenAPIOperationRequest.cjs +5 -0
  23. package/src/client/OpenAPIOperationRequest.mjs +1 -0
  24. package/src/client/OpenAPIOperationResponse.cjs +42 -0
  25. package/src/client/OpenAPIOperationResponse.mjs +36 -0
  26. package/src/client/OpenAPIOperationResponseNormalizer.cjs +48 -0
  27. package/src/client/OpenAPIOperationResponseNormalizer.mjs +40 -0
  28. package/src/client/ParameterDelivery.cjs +119 -0
  29. package/src/client/ParameterDelivery.mjs +113 -0
  30. package/src/constants.cjs +9 -0
  31. package/src/constants.mjs +3 -0
  32. package/src/criterion/CriterionEvaluator.cjs +205 -0
  33. package/src/criterion/CriterionEvaluator.mjs +196 -0
  34. package/src/criterion/JSONPathCriterionEvaluator.cjs +47 -0
  35. package/src/criterion/JSONPathCriterionEvaluator.mjs +40 -0
  36. package/src/criterion/RegexCriterionEvaluator.cjs +67 -0
  37. package/src/criterion/RegexCriterionEvaluator.mjs +60 -0
  38. package/src/criterion/SimpleCriterionEvaluator.cjs +50 -0
  39. package/src/criterion/SimpleCriterionEvaluator.mjs +43 -0
  40. package/src/criterion/XPathCriterionEvaluator.cjs +117 -0
  41. package/src/criterion/XPathCriterionEvaluator.mjs +109 -0
  42. package/src/document/APIDocument.cjs +35 -0
  43. package/src/document/APIDocument.mjs +30 -0
  44. package/src/document/ArazzoDocument.cjs +81 -0
  45. package/src/document/ArazzoDocument.mjs +74 -0
  46. package/src/document/ArazzoSourceDescriptionIndex.cjs +26 -0
  47. package/src/document/ArazzoSourceDescriptionIndex.mjs +20 -0
  48. package/src/document/ArazzoStepIndex.cjs +25 -0
  49. package/src/document/ArazzoStepIndex.mjs +19 -0
  50. package/src/document/ArazzoWorkflowIndex.cjs +17 -0
  51. package/src/document/ArazzoWorkflowIndex.mjs +11 -0
  52. package/src/document/OpenAPIDocument.cjs +28 -0
  53. package/src/document/OpenAPIDocument.mjs +21 -0
  54. package/src/document/OpenAPIOperationIndex.cjs +24 -0
  55. package/src/document/OpenAPIOperationIndex.mjs +18 -0
  56. package/src/document/ParameterIdentity.cjs +93 -0
  57. package/src/document/ParameterIdentity.mjs +88 -0
  58. package/src/document/openapi-types.cjs +5 -0
  59. package/src/document/openapi-types.mjs +1 -0
  60. package/src/errors/ArazzoRunnerError.cjs +10 -0
  61. package/src/errors/ArazzoRunnerError.mjs +5 -0
  62. package/src/errors/AssemblerError.cjs +11 -0
  63. package/src/errors/AssemblerError.mjs +4 -0
  64. package/src/errors/ClientError.cjs +11 -0
  65. package/src/errors/ClientError.mjs +4 -0
  66. package/src/errors/CriterionError.cjs +11 -0
  67. package/src/errors/CriterionError.mjs +4 -0
  68. package/src/errors/ExecutionError.cjs +11 -0
  69. package/src/errors/ExecutionError.mjs +4 -0
  70. package/src/errors/ExtractionError.cjs +11 -0
  71. package/src/errors/ExtractionError.mjs +4 -0
  72. package/src/errors/InvalidEntryDocumentError.cjs +11 -0
  73. package/src/errors/InvalidEntryDocumentError.mjs +4 -0
  74. package/src/errors/NormalizationError.cjs +11 -0
  75. package/src/errors/NormalizationError.mjs +4 -0
  76. package/src/errors/ResolverError.cjs +11 -0
  77. package/src/errors/ResolverError.mjs +4 -0
  78. package/src/errors/RuntimeExpressionError.cjs +11 -0
  79. package/src/errors/RuntimeExpressionError.mjs +4 -0
  80. package/src/errors/UnmatchedProviderError.cjs +11 -0
  81. package/src/errors/UnmatchedProviderError.mjs +4 -0
  82. package/src/executor/ArazzoWorkflowLocatorNormalizer.cjs +147 -0
  83. package/src/executor/ArazzoWorkflowLocatorNormalizer.mjs +137 -0
  84. package/src/executor/OpenAPIOperationExecutor.cjs +457 -0
  85. package/src/executor/OpenAPIOperationExecutor.mjs +446 -0
  86. package/src/executor/OpenAPIOperationLocatorNormalizer.cjs +197 -0
  87. package/src/executor/OpenAPIOperationLocatorNormalizer.mjs +189 -0
  88. package/src/executor/SourceDescriptionsLocatorNormalizer.cjs +44 -0
  89. package/src/executor/SourceDescriptionsLocatorNormalizer.mjs +38 -0
  90. package/src/executor/StepExecutor.cjs +333 -0
  91. package/src/executor/StepExecutor.mjs +326 -0
  92. package/src/executor/StepRetryRunner.cjs +226 -0
  93. package/src/executor/StepRetryRunner.mjs +215 -0
  94. package/src/executor/StepTransitionInterpreter.cjs +159 -0
  95. package/src/executor/StepTransitionInterpreter.mjs +151 -0
  96. package/src/executor/WorkflowCallStack.cjs +116 -0
  97. package/src/executor/WorkflowCallStack.mjs +106 -0
  98. package/src/executor/WorkflowExecutor.cjs +1091 -0
  99. package/src/executor/WorkflowExecutor.mjs +1077 -0
  100. package/src/executor/abort.cjs +70 -0
  101. package/src/executor/abort.mjs +60 -0
  102. package/src/expression/RuntimeExpressionContext.cjs +5 -0
  103. package/src/expression/RuntimeExpressionContext.mjs +1 -0
  104. package/src/expression/RuntimeExpressionEvaluator.cjs +337 -0
  105. package/src/expression/RuntimeExpressionEvaluator.mjs +328 -0
  106. package/src/extractor/ArazzoStepExtractor.cjs +48 -0
  107. package/src/extractor/ArazzoStepExtractor.mjs +41 -0
  108. package/src/extractor/ArazzoWorkflowExtractor.cjs +50 -0
  109. package/src/extractor/ArazzoWorkflowExtractor.mjs +43 -0
  110. package/src/extractor/OpenAPIOperationExtractor.cjs +84 -0
  111. package/src/extractor/OpenAPIOperationExtractor.mjs +77 -0
  112. package/src/index.cjs +419 -0
  113. package/src/index.mjs +73 -0
  114. package/src/normalizer/ArazzoStepNormalizer.cjs +23 -0
  115. package/src/normalizer/ArazzoStepNormalizer.mjs +17 -0
  116. package/src/normalizer/ArazzoWorkflowNormalizer.cjs +214 -0
  117. package/src/normalizer/ArazzoWorkflowNormalizer.mjs +206 -0
  118. package/src/normalizer/OpenAPI2OperationNormalizer.cjs +128 -0
  119. package/src/normalizer/OpenAPI2OperationNormalizer.mjs +120 -0
  120. package/src/normalizer/OpenAPI30OperationNormalizer.cjs +129 -0
  121. package/src/normalizer/OpenAPI30OperationNormalizer.mjs +121 -0
  122. package/src/normalizer/OpenAPI31OperationNormalizer.cjs +131 -0
  123. package/src/normalizer/OpenAPI31OperationNormalizer.mjs +123 -0
  124. package/src/normalizer/OpenAPIOperationNormalizer.cjs +58 -0
  125. package/src/normalizer/OpenAPIOperationNormalizer.mjs +50 -0
  126. package/src/registry/DocumentRegistry.cjs +160 -0
  127. package/src/registry/DocumentRegistry.mjs +151 -0
  128. package/src/registry/providers/ArazzoDocumentRegistryProvider.cjs +154 -0
  129. package/src/registry/providers/ArazzoDocumentRegistryProvider.mjs +146 -0
  130. package/src/registry/providers/DocumentRegistryProvider.cjs +31 -0
  131. package/src/registry/providers/DocumentRegistryProvider.mjs +25 -0
  132. package/src/registry/providers/OpenAPIDocumentRegistryProvider.cjs +122 -0
  133. package/src/registry/providers/OpenAPIDocumentRegistryProvider.mjs +114 -0
  134. package/src/resolver/ArazzoValueResolver.cjs +42 -0
  135. package/src/resolver/ArazzoValueResolver.mjs +37 -0
  136. package/src/resolver/OpenAPIOperationParameterResolver.cjs +117 -0
  137. package/src/resolver/OpenAPIOperationParameterResolver.mjs +110 -0
  138. package/src/resolver/OutputResolver.cjs +71 -0
  139. package/src/resolver/OutputResolver.mjs +64 -0
  140. package/src/resolver/RequestBodyResolver.cjs +227 -0
  141. package/src/resolver/RequestBodyResolver.mjs +220 -0
  142. package/src/resolver/ResolverScope.cjs +5 -0
  143. package/src/resolver/ResolverScope.mjs +1 -0
  144. package/src/resolver/StepParameterResolver.cjs +22 -0
  145. package/src/resolver/StepParameterResolver.mjs +15 -0
  146. package/src/resolver/WorkflowParameterResolver.cjs +73 -0
  147. package/src/resolver/WorkflowParameterResolver.mjs +66 -0
  148. package/src/state/WorkflowExecutionState.cjs +99 -0
  149. package/src/state/WorkflowExecutionState.mjs +93 -0
  150. package/src/vendor/swagger-client.cjs +1 -0
  151. package/src/vendor/swagger-client.mjs +1 -0
  152. package/types/runner.d.ts +2341 -0
@@ -0,0 +1,70 @@
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.throwIfAborted = exports.readAbortSignal = void 0;
8
+ var _ExecutionError = _interopRequireDefault(require("../errors/ExecutionError.cjs"));
9
+ /**
10
+ * Where a run was when it observed the caller's abort — carried into the error
11
+ * so both the message and its structured fields name the boundary the run
12
+ * stopped at. Both names are optional because the observers sit at different
13
+ * depths: the workflow executor knows the workflow and (between attempts) the
14
+ * step, while a {@link StepExecutor} used on its own knows only the step.
15
+ * @internal
16
+ */
17
+
18
+ /**
19
+ * Reads the `AbortSignal` a caller put in the opaque execute options bag, or
20
+ * `undefined` when there is none.
21
+ *
22
+ * Duck-typed rather than `instanceof AbortSignal`: the bag is the caller's, and
23
+ * a signal made in another realm (a worker, a test harness, a polyfill) must
24
+ * still cancel the run.
25
+ *
26
+ * The whole surface the runner uses is required, not just `aborted`: what comes
27
+ * back is subscribed to as well as read (the abortable retry wait), so admitting
28
+ * a bare `{ aborted: false }` would trade a wrong-but-working run for a
29
+ * `TypeError` thrown from inside a `retryAfter` delay. Anything short of that
30
+ * surface is treated as no signal at all — the bag is open, and a value the
31
+ * runner cannot drive is not a cancellation.
32
+ * @internal
33
+ */
34
+ const readAbortSignal = options => {
35
+ const signal = options.signal;
36
+ if (typeof signal !== 'object' || signal === null) return undefined;
37
+ const usable = typeof signal.aborted === 'boolean' && typeof signal.addEventListener === 'function' && typeof signal.removeEventListener === 'function';
38
+ return usable ? signal : undefined;
39
+ };
40
+
41
+ /**
42
+ * Throws `reason: 'aborted'` when the caller has cancelled the run, and does
43
+ * nothing otherwise.
44
+ *
45
+ * Cancellation throws rather than resolving as a `failed` result because it is
46
+ * not a workflow outcome: nothing was judged by `successCriteria`, no failure
47
+ * action was consulted, and the steps that did not run were not *decided*
48
+ * against. A result would be indistinguishable from the API having answered.
49
+ * The signal's own `reason` travels as the error's `cause`, so a caller that
50
+ * aborted with a meaningful value keeps it.
51
+ * @internal
52
+ */
53
+ exports.readAbortSignal = readAbortSignal;
54
+ const throwIfAborted = (signal, context) => {
55
+ if (signal?.aborted !== true) return;
56
+ const {
57
+ workflowId,
58
+ stepId,
59
+ callStack
60
+ } = context;
61
+ const where = [stepId === undefined ? undefined : `step "${stepId}"`, workflowId === undefined ? undefined : `workflow "${workflowId}"`].filter(part => part !== undefined).join(' in ');
62
+ throw new _ExecutionError.default(`run aborted before ${where}`, {
63
+ workflowId,
64
+ stepId,
65
+ reason: 'aborted',
66
+ path: callStack?.path,
67
+ cause: signal.reason
68
+ });
69
+ };
70
+ exports.throwIfAborted = throwIfAborted;
@@ -0,0 +1,60 @@
1
+ import ExecutionError from "../errors/ExecutionError.mjs";
2
+ /**
3
+ * Where a run was when it observed the caller's abort — carried into the error
4
+ * so both the message and its structured fields name the boundary the run
5
+ * stopped at. Both names are optional because the observers sit at different
6
+ * depths: the workflow executor knows the workflow and (between attempts) the
7
+ * step, while a {@link StepExecutor} used on its own knows only the step.
8
+ * @internal
9
+ */
10
+ /**
11
+ * Reads the `AbortSignal` a caller put in the opaque execute options bag, or
12
+ * `undefined` when there is none.
13
+ *
14
+ * Duck-typed rather than `instanceof AbortSignal`: the bag is the caller's, and
15
+ * a signal made in another realm (a worker, a test harness, a polyfill) must
16
+ * still cancel the run.
17
+ *
18
+ * The whole surface the runner uses is required, not just `aborted`: what comes
19
+ * back is subscribed to as well as read (the abortable retry wait), so admitting
20
+ * a bare `{ aborted: false }` would trade a wrong-but-working run for a
21
+ * `TypeError` thrown from inside a `retryAfter` delay. Anything short of that
22
+ * surface is treated as no signal at all — the bag is open, and a value the
23
+ * runner cannot drive is not a cancellation.
24
+ * @internal
25
+ */
26
+ export const readAbortSignal = options => {
27
+ const signal = options.signal;
28
+ if (typeof signal !== 'object' || signal === null) return undefined;
29
+ const usable = typeof signal.aborted === 'boolean' && typeof signal.addEventListener === 'function' && typeof signal.removeEventListener === 'function';
30
+ return usable ? signal : undefined;
31
+ };
32
+
33
+ /**
34
+ * Throws `reason: 'aborted'` when the caller has cancelled the run, and does
35
+ * nothing otherwise.
36
+ *
37
+ * Cancellation throws rather than resolving as a `failed` result because it is
38
+ * not a workflow outcome: nothing was judged by `successCriteria`, no failure
39
+ * action was consulted, and the steps that did not run were not *decided*
40
+ * against. A result would be indistinguishable from the API having answered.
41
+ * The signal's own `reason` travels as the error's `cause`, so a caller that
42
+ * aborted with a meaningful value keeps it.
43
+ * @internal
44
+ */
45
+ export const throwIfAborted = (signal, context) => {
46
+ if (signal?.aborted !== true) return;
47
+ const {
48
+ workflowId,
49
+ stepId,
50
+ callStack
51
+ } = context;
52
+ const where = [stepId === undefined ? undefined : `step "${stepId}"`, workflowId === undefined ? undefined : `workflow "${workflowId}"`].filter(part => part !== undefined).join(' in ');
53
+ throw new ExecutionError(`run aborted before ${where}`, {
54
+ workflowId,
55
+ stepId,
56
+ reason: 'aborted',
57
+ path: callStack?.path,
58
+ cause: signal.reason
59
+ });
60
+ };
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,337 @@
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 _parser = require("@usearazzo/parser");
9
+ var _arazzoRuntimeExpression = require("@swaggerexpert/arazzo-runtime-expression");
10
+ var _jsonPointer = require("@swaggerexpert/json-pointer");
11
+ var _json = _interopRequireDefault(require("@swaggerexpert/json-pointer/evaluate/realms/json"));
12
+ var _apidomJsonPointer = require("@speclynx/apidom-json-pointer");
13
+ var _apidomCore = require("@speclynx/apidom-core");
14
+ var _RuntimeExpressionError = _interopRequireDefault(require("../errors/RuntimeExpressionError.cjs"));
15
+ var _ArazzoDocument = _interopRequireDefault(require("../document/ArazzoDocument.cjs"));
16
+ var _OpenAPIDocument = _interopRequireDefault(require("../document/OpenAPIDocument.cjs"));
17
+ /**
18
+ * Options for the RuntimeExpressionEvaluator.
19
+ * @public
20
+ */
21
+
22
+ /**
23
+ * The request/response side of the context a `$request`/`$response` source is
24
+ * evaluated against. Both request and response contexts are assignable to this
25
+ * shape; sources absent from a side (e.g. `$response.query`) resolve to
26
+ * `undefined` naturally.
27
+ */
28
+
29
+ /**
30
+ * Realm for drilling JSON Pointers into payload values. Composing the ApiDOM
31
+ * realm ahead of the JSON realm lets a single `evaluate` call handle plain JS
32
+ * values, ApiDOM elements, and mixed trees: the ApiDOM realm claims elements
33
+ * and falls through to the JSON realm for plain values. Order matters — the
34
+ * JSON realm would otherwise greedily claim ApiDOM elements and fail.
35
+ */
36
+ const pointerRealm = (0, _jsonPointer.composeRealms)(new _apidomJsonPointer.ApiDOMEvaluationRealm(), new _json.default());
37
+
38
+ /**
39
+ * The expression roots that describe one HTTP exchange — unavailable in a step
40
+ * that calls a workflow, which makes none.
41
+ */
42
+ const HTTP_EXCHANGE_NODES = new Set(['UrlExpression', 'MethodExpression', 'StatusCodeExpression', 'RequestExpression', 'ResponseExpression']);
43
+
44
+ /**
45
+ * Evaluates Arazzo runtime expressions against a context.
46
+ *
47
+ * A single evaluator is bound to one context and can evaluate many expressions
48
+ * against it — matching how a step executor resolves a step's parameters,
49
+ * success criteria, and outputs from the same state.
50
+ *
51
+ * The context holds only runtime state (`$inputs`, `$steps`, `$request`,
52
+ * `$response`, …). Static, document-sourced expressions are resolved on demand:
53
+ * `$components` and `$workflows.{workflowId}.steps.{stepId}` from the
54
+ * evaluator's document, and `$sourceDescriptions` from the external document
55
+ * (via the registry) the source name points at. A step reference resolves to
56
+ * the Step Object as authored — a locator, not the step's execution result.
57
+ *
58
+ * A reference resolves to `undefined` when it is absent. Runtime values
59
+ * originate from JSON (or ApiDOM), which cannot represent `undefined` — an
60
+ * absent value is a missing property and an explicit null is `null` — so
61
+ * `undefined` unambiguously marks "unresolved".
62
+ *
63
+ * Three modes are supported:
64
+ * - {@link RuntimeExpressionEvaluator.evaluate} resolves a pure expression
65
+ * (e.g. `$response.body#/id`) to its typed value.
66
+ * - {@link RuntimeExpressionEvaluator.interpolate} renders a template with
67
+ * embedded `{expression}` occurrences to a string.
68
+ * - {@link RuntimeExpressionEvaluator.resolve} applies Arazzo "value" semantics:
69
+ * a value that is itself a complete expression resolves to a typed value,
70
+ * otherwise the value is interpolated to a string.
71
+ * @public
72
+ */
73
+ class RuntimeExpressionEvaluator {
74
+ #context;
75
+ #strict;
76
+ #document;
77
+ #registry;
78
+ constructor(context, options = {}) {
79
+ this.#context = context;
80
+ this.#strict = options.strict ?? true;
81
+ this.#document = options.document;
82
+ this.#registry = options.registry;
83
+ }
84
+
85
+ /**
86
+ * Evaluates a pure runtime expression to its typed value.
87
+ *
88
+ * The expression must be the bare form without surrounding braces
89
+ * (e.g. `$inputs.username`, `$response.body#/pets/0/id`). In strict mode an
90
+ * unresolvable reference throws; otherwise it returns `undefined`.
91
+ */
92
+ evaluate(expression) {
93
+ const node = this.#parse(expression);
94
+ this.#assertAvailable(node, expression);
95
+ const value = this.#evaluateNode(node, expression);
96
+ if (value === undefined && this.#strict) {
97
+ throw new _RuntimeExpressionError.default(`Runtime expression "${expression}" could not be resolved against the context`, {
98
+ expression,
99
+ reason: 'unresolved-reference'
100
+ });
101
+ }
102
+ return value;
103
+ }
104
+
105
+ /**
106
+ * Renders a template string, replacing each embedded `{expression}` with the
107
+ * string form of its evaluated value. Returns a string.
108
+ *
109
+ * Object and array values are serialized with `JSON.stringify`. In non-strict
110
+ * mode, unresolvable references render as an empty string. A `{…}` that is not
111
+ * a valid embedded expression (e.g. a literal JSON payload) is left unchanged.
112
+ */
113
+ interpolate(template) {
114
+ return (0, _arazzoRuntimeExpression.interpolate)(template, expression => this.evaluate(expression));
115
+ }
116
+
117
+ /**
118
+ * Resolves an Arazzo "value" string.
119
+ *
120
+ * A value that is itself a complete runtime expression (the unbraced form,
121
+ * e.g. `$inputs.userId`) resolves to its typed value — "runtime expressions
122
+ * preserve the type of the referenced value". Any other string is an
123
+ * expression-string template: embedded `{expression}` occurrences are
124
+ * interpolated and a string is returned, so a whole-string `{expression}`
125
+ * yields the string representation of its value, not the typed value. A
126
+ * string containing no expressions is returned unchanged.
127
+ */
128
+ resolve(value) {
129
+ // `test` returns true only when the entire string is a valid runtime
130
+ // expression, so a braced or mixed string falls through to interpolation.
131
+ return (0, _arazzoRuntimeExpression.test)(value) ? this.evaluate(value) : this.interpolate(value);
132
+ }
133
+
134
+ /**
135
+ * Parses an expression to its AST, throwing on failure regardless of strict mode.
136
+ */
137
+ #parse(expression) {
138
+ let result;
139
+ try {
140
+ result = (0, _parser.parseRuntimeExpression)(expression);
141
+ } catch (error) {
142
+ throw new _RuntimeExpressionError.default(`Failed to parse runtime expression "${expression}"`, {
143
+ cause: error,
144
+ expression,
145
+ reason: 'parse-error'
146
+ });
147
+ }
148
+ if (!result.result.success || result.tree === undefined) {
149
+ throw new _RuntimeExpressionError.default(`Invalid runtime expression "${expression}"`, {
150
+ expression,
151
+ reason: 'invalid-expression'
152
+ });
153
+ }
154
+ return result.tree;
155
+ }
156
+
157
+ /**
158
+ * Rejects an HTTP-exchange expression in a step that calls a workflow. Such a
159
+ * step made no HTTP call, so the expression is an authoring error there — not
160
+ * a reference that merely did not resolve — and throws regardless of `strict`.
161
+ */
162
+ #assertAvailable(node, expression) {
163
+ const {
164
+ calledWorkflow
165
+ } = this.#context;
166
+ if (calledWorkflow === undefined || !HTTP_EXCHANGE_NODES.has(node.type)) return;
167
+ throw new _RuntimeExpressionError.default(`Runtime expression "${expression}" is not available: step "${calledWorkflow.stepId}" calls workflow "${calledWorkflow.workflowId}", not an operation, so it has no HTTP request or response`, {
168
+ expression,
169
+ reason: 'unavailable-expression'
170
+ });
171
+ }
172
+
173
+ /**
174
+ * Walks an AST node against the context, returning the referenced value or
175
+ * `undefined` when the reference does not resolve.
176
+ */
177
+ #evaluateNode(node, expression) {
178
+ switch (node.type) {
179
+ case 'UrlExpression':
180
+ return this.#context.request?.url;
181
+ case 'MethodExpression':
182
+ return this.#context.request?.method;
183
+ case 'StatusCodeExpression':
184
+ return this.#context.response?.statusCode;
185
+ case 'RequestExpression':
186
+ return this.#source(node.source, this.#context.request);
187
+ case 'ResponseExpression':
188
+ return this.#source(node.source, this.#context.response);
189
+ case 'InputsExpression':
190
+ return this.#drill(this.#get(this.#context.inputs, node.name));
191
+ case 'OutputsExpression':
192
+ return this.#drill(this.#get(this.#context.outputs, node.name));
193
+ case 'StepsExpression':
194
+ return this.#drill(this.#get(this.#context.steps?.[node.stepId]?.outputs, node.outputName), node.jsonPointer?.value);
195
+ case 'WorkflowsExpression':
196
+ return this.#drill(this.#get(this.#context.workflows?.[node.workflowId]?.[node.field], node.fieldName), node.jsonPointer?.value);
197
+ case 'WorkflowsStepsExpression':
198
+ return this.#step(this.#document, node.workflowId, node.stepId);
199
+ case 'SourceDescriptionsExpression':
200
+ return this.#sourceDescription(node);
201
+ case 'ComponentsExpression':
202
+ return this.#component(node.componentType, node.componentName);
203
+ default:
204
+ throw new _RuntimeExpressionError.default(`Unsupported runtime expression node "${node.type}"`, {
205
+ expression,
206
+ reason: 'unsupported-node'
207
+ });
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Evaluates a `$request`/`$response` source reference against the request or
213
+ * response side of the context.
214
+ */
215
+ #source(source, message) {
216
+ const {
217
+ reference
218
+ } = source;
219
+ switch (reference.type) {
220
+ case 'HeaderReference':
221
+ return this.#header(message?.header, reference.token);
222
+ case 'QueryReference':
223
+ return this.#get(message?.query, reference.name);
224
+ case 'PathReference':
225
+ return this.#get(message?.path, reference.name);
226
+ case 'BodyReference':
227
+ return this.#drill(message?.body, reference.jsonPointer?.value);
228
+ default:
229
+ return undefined;
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Resolves `$components.{field}.{name}` by drilling into the evaluator's
235
+ * document. Returns `undefined` when no document is configured or the
236
+ * component is absent.
237
+ */
238
+ #component(field, name) {
239
+ return this.#drillDocument(this.#document, (0, _jsonPointer.compile)(['components', field, name]));
240
+ }
241
+
242
+ /**
243
+ * Resolves `{workflowId}.steps.{stepId}` to the Step Object in an Arazzo
244
+ * document. Returns `undefined` when the document is absent or not Arazzo, or
245
+ * the workflow or step is unknown.
246
+ */
247
+ #step(document, workflowId, stepId) {
248
+ if (document === undefined || !_ArazzoDocument.default.is(document)) return undefined;
249
+ const pointer = document.stepIndex.getStep(workflowId, stepId);
250
+ return pointer === undefined ? undefined : this.#drillDocument(document, pointer);
251
+ }
252
+
253
+ /**
254
+ * Resolves `$sourceDescriptions.{name}.{reference}` with the resolution
255
+ * priority defined by the Arazzo Specification:
256
+ *
257
+ * 1. `{reference}` is matched as an operationId (OpenAPI source) or workflowId
258
+ * (Arazzo source) in the referenced document, resolving to that operation
259
+ * or workflow. A `{workflowId}.steps.{stepId}` reference resolves to that
260
+ * step of the referenced Arazzo document.
261
+ * 2. failing that, `{reference}` is matched as a field of the Source
262
+ * Description Object itself (e.g. `url`, `type`) — so
263
+ * `$sourceDescriptions.{name}.url` yields the source's URL. An operationId
264
+ * that collides with a field name takes precedence (tier 1 wins).
265
+ *
266
+ * Returns `undefined` when nothing matches.
267
+ */
268
+ #sourceDescription({
269
+ sourceName,
270
+ reference,
271
+ stepsReference
272
+ }) {
273
+ const uri = this.#document?.resolveSourceDescriptionURI(sourceName);
274
+
275
+ // tier 1: operationId / workflowId / workflow step in the referenced document.
276
+ const apiDocument = uri === undefined ? undefined : this.#registry?.get(uri);
277
+ if (apiDocument !== undefined) {
278
+ if (stepsReference !== undefined) {
279
+ return this.#step(apiDocument, stepsReference.workflowId, stepsReference.stepId);
280
+ }
281
+ const pointer = _OpenAPIDocument.default.is(apiDocument) ? apiDocument.operationIndex.get(reference) : _ArazzoDocument.default.is(apiDocument) ? apiDocument.workflowIndex.get(reference) : undefined;
282
+ if (pointer !== undefined) return this.#drillDocument(apiDocument, pointer);
283
+ }
284
+
285
+ // tier 2: a field of the Source Description Object (url, type, ...).
286
+ return this.#document?.resolveSourceDescriptionField(sourceName, reference);
287
+ }
288
+
289
+ /**
290
+ * Reads a property from a context slot, or `undefined` when the slot is not
291
+ * an object or lacks the key. Own properties only, so prototype members
292
+ * (`constructor`, `toString`) never leak into a resolution.
293
+ */
294
+ #get(slot, key) {
295
+ if (typeof slot !== 'object' || slot === null) return undefined;
296
+ if (!Object.hasOwn(slot, key)) return undefined;
297
+ return slot[key];
298
+ }
299
+
300
+ /**
301
+ * Reads a header case-insensitively. The parser already lowercases the header
302
+ * token, so only the context keys (populated from an HTTP response with
303
+ * arbitrary casing) need normalizing to match.
304
+ */
305
+ #header(headers, token) {
306
+ if (headers === undefined) return undefined;
307
+ const key = Object.keys(headers).find(k => k.toLowerCase() === token);
308
+ return key === undefined ? undefined : headers[key];
309
+ }
310
+
311
+ /**
312
+ * Drills a JSON Pointer into a document's API element. Returns `undefined`
313
+ * when the document is absent or the pointer does not resolve.
314
+ */
315
+ #drillDocument(document, pointer) {
316
+ return document === undefined ? undefined : this.#drill(document.parseResult.api, pointer);
317
+ }
318
+
319
+ /**
320
+ * Drills an optional JSON Pointer into a payload value, returning the plain
321
+ * runtime value. `toValue` is idempotent on plain values, so the leaf is plain
322
+ * whether the payload was JSON or an ApiDOM element (see `pointerRealm`).
323
+ */
324
+ #drill(value, pointer) {
325
+ if (value === undefined) return undefined;
326
+ if (pointer === undefined) return (0, _apidomCore.toValue)(value);
327
+ try {
328
+ return (0, _apidomCore.toValue)((0, _jsonPointer.evaluate)(value, pointer, {
329
+ realm: pointerRealm
330
+ }));
331
+ } catch (error) {
332
+ if (error instanceof _jsonPointer.JSONPointerEvaluateError) return undefined;
333
+ throw error;
334
+ }
335
+ }
336
+ }
337
+ var _default = exports.default = RuntimeExpressionEvaluator;