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

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 +31 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +20 -0
  4. package/README.md +777 -2
  5. package/dist/arazzo-runner.browser.js +113254 -0
  6. package/dist/arazzo-runner.browser.min.js +1 -0
  7. package/package.json +91 -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 +458 -0
  85. package/src/executor/OpenAPIOperationExecutor.mjs +447 -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,227 @@
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 _ramda = require("ramda");
9
+ var _apidomCore = require("@speclynx/apidom-core");
10
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
11
+ var _jsonPointer = require("@swaggerexpert/json-pointer");
12
+ var _arazzoRuntimeExpression = require("@swaggerexpert/arazzo-runtime-expression");
13
+ var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
14
+ var _ResolverError = _interopRequireDefault(require("../errors/ResolverError.cjs"));
15
+ var _ArazzoValueResolver = _interopRequireDefault(require("./ArazzoValueResolver.cjs"));
16
+ /**
17
+ * Matches a canonical non-negative integer (RFC 6901 array index): no leading
18
+ * zeros other than `0` itself.
19
+ */
20
+ const ARRAY_INDEX = /^(0|[1-9][0-9]*)$/;
21
+
22
+ /**
23
+ * Marks a bare-expression payload value that did not resolve. Its container
24
+ * decides what "not provided" means there: an object member is omitted, while
25
+ * an array element or the whole payload throws.
26
+ */
27
+ const UNRESOLVED = Symbol('unresolved');
28
+
29
+ /**
30
+ * A resolved request body: the payload with all replacements applied, plus the
31
+ * declared content type when present.
32
+ * @public
33
+ */
34
+
35
+ /**
36
+ * Resolves a step's `requestBody` to a concrete payload.
37
+ *
38
+ * The `payload` is resolved first. Per the specification it "can contain"
39
+ * runtime expressions, so it is walked: every string in it — the payload
40
+ * itself, or any value nested in its objects and arrays — that is a whole
41
+ * runtime expression resolves to its typed value, and every other string has
42
+ * its embedded `{expression}` occurrences interpolated (tolerantly, so literal
43
+ * braces such as a JSON template's own are kept). Object keys and resolved
44
+ * values are never evaluated.
45
+ *
46
+ * An unresolved expression reads as "not provided": an object member is
47
+ * omitted, while a whole-expression payload, an array element or an embedded
48
+ * expression — none of which can be omitted — throws {@link ResolverError}
49
+ * (`unresolved-expression`), as does an invalid embedded expression
50
+ * (`invalid-expression`).
51
+ *
52
+ * Then each `replacements` entry is applied — its `value` is resolved by the
53
+ * family-wide literal-vs-expression rule of {@link ArazzoValueResolver} and set
54
+ * into the payload at the replacement's `target` JSON Pointer. A replacement
55
+ * whose value does not resolve is skipped, leaving the payload as authored.
56
+ *
57
+ * `target` may be a JSON Pointer or an XPath per the specification; only JSON
58
+ * Pointer targets are supported — an XPath target throws {@link ResolverError}.
59
+ * @public
60
+ */
61
+ class RequestBodyResolver extends _ArazzoValueResolver.default {
62
+ /**
63
+ * Resolves the request body, returning its payload and content type. Returns
64
+ * `undefined` when there is no request body.
65
+ *
66
+ * `scope` names the step in a thrown {@link ResolverError}.
67
+ */
68
+ resolve(requestBody, resolve, scope) {
69
+ if (requestBody === undefined) return undefined;
70
+
71
+ // present but scalar: `.payload`, `.replacements` and `.contentType` are
72
+ // all plain `undefined` on a non-map element, so the step would silently
73
+ // send no body and report success.
74
+ if (!(0, _apidomDatamodel.isObjectElement)(requestBody)) {
75
+ throw new _ResolverError.default('`requestBody` is present but is not a map', {
76
+ ...scope,
77
+ target: 'requestBody',
78
+ reason: 'malformed-request-body'
79
+ });
80
+ }
81
+ const authoredPayload = (0, _apidomCore.toValue)(requestBody.payload);
82
+ let payload = this.#requireResolved(authoredPayload, this.#resolvePayloadValue(authoredPayload, [], resolve, scope), [], scope);
83
+ if (requestBody.replacements !== undefined) {
84
+ // present but scalar: walking it would fail as a bare
85
+ // `TypeError: requestBody.replacements is not iterable`.
86
+ if (!(0, _apidomDatamodel.isArrayElement)(requestBody.replacements)) {
87
+ throw new _ResolverError.default('`requestBody.replacements` is present but is not a list', {
88
+ ...scope,
89
+ target: 'requestBody.replacements',
90
+ reason: 'malformed-replacements'
91
+ });
92
+ }
93
+ for (const replacement of requestBody.replacements) {
94
+ if (!(0, _apidomNsArazzo.isPayloadReplacementElement)(replacement)) continue;
95
+ const target = (0, _apidomCore.toValue)(replacement.target);
96
+ if (typeof target !== 'string') continue;
97
+ const value = this.resolveValue(replacement.value, resolve);
98
+ if (value === undefined) continue;
99
+ payload = this.#applyReplacement(payload, target, value, scope);
100
+ }
101
+ }
102
+ const contentType = (0, _apidomDatamodel.isStringElement)(requestBody.contentType) ? (0, _apidomCore.toValue)(requestBody.contentType) : undefined;
103
+ return contentType === undefined ? {
104
+ payload
105
+ } : {
106
+ payload,
107
+ contentType
108
+ };
109
+ }
110
+
111
+ /**
112
+ * Resolves one authored payload value at the `tokens` path, recursing into
113
+ * objects and arrays. Returns {@link UNRESOLVED} for a bare expression that
114
+ * did not resolve, for its container to handle.
115
+ */
116
+ #resolvePayloadValue(value, tokens, resolve, scope) {
117
+ if (typeof value === 'string') return this.#resolvePayloadString(value, tokens, resolve, scope);
118
+ if (Array.isArray(value)) {
119
+ return value.map((item, index) => {
120
+ const itemTokens = [...tokens, String(index)];
121
+ const resolved = this.#resolvePayloadValue(item, itemTokens, resolve, scope);
122
+ return this.#requireResolved(item, resolved, itemTokens, scope);
123
+ });
124
+ }
125
+ if (value !== null && typeof value === 'object') {
126
+ // `fromEntries` defines own properties, so an authored `__proto__` key
127
+ // stays a plain member instead of replacing the prototype.
128
+ return Object.fromEntries(Object.entries(value).map(([key, member]) => [key, this.#resolvePayloadValue(member, [...tokens, key], resolve, scope)]).filter(([, resolved]) => resolved !== UNRESOLVED));
129
+ }
130
+ return value;
131
+ }
132
+
133
+ /**
134
+ * Resolves one authored payload string: a whole runtime expression to its
135
+ * typed value (or {@link UNRESOLVED}), anything else by tolerant
136
+ * interpolation of its embedded `{expression}` occurrences.
137
+ */
138
+ #resolvePayloadString(value, tokens, resolve, scope) {
139
+ if ((0, _arazzoRuntimeExpression.test)(value)) {
140
+ const resolved = resolve(value);
141
+ return resolved === undefined ? UNRESOLVED : resolved;
142
+ }
143
+ return (0, _arazzoRuntimeExpression.interpolate)(value, expression => {
144
+ const resolved = resolve(expression);
145
+ if (resolved === undefined) throw this.#unresolvedError(expression, tokens, scope);
146
+ return resolved;
147
+ }, {
148
+ strict: false,
149
+ onError: ({
150
+ text
151
+ }) => {
152
+ throw new _ResolverError.default(`Invalid runtime expression "${text}" in ${this.#payloadTarget(tokens)}`, {
153
+ ...scope,
154
+ target: this.#payloadTarget(tokens),
155
+ reason: 'invalid-expression'
156
+ });
157
+ }
158
+ });
159
+ }
160
+
161
+ /**
162
+ * Throws for an unresolved bare expression where omission is not possible —
163
+ * the whole payload or an array element; passes every other value through.
164
+ */
165
+ #requireResolved(authored, resolved, tokens, scope) {
166
+ if (resolved === UNRESOLVED) throw this.#unresolvedError(authored, tokens, scope);
167
+ return resolved;
168
+ }
169
+ #unresolvedError(expression, tokens, scope) {
170
+ const target = this.#payloadTarget(tokens);
171
+ return new _ResolverError.default(`Runtime expression "${expression}" in ${target} did not resolve`, {
172
+ ...scope,
173
+ target,
174
+ reason: 'unresolved-expression'
175
+ });
176
+ }
177
+
178
+ /**
179
+ * Names a payload location for errors: `requestBody.payload` itself, or a
180
+ * member as a JSON Pointer fragment (e.g. `requestBody.payload#/order/petId`).
181
+ */
182
+ #payloadTarget(tokens) {
183
+ return tokens.length === 0 ? 'requestBody.payload' : `requestBody.payload#${(0, _jsonPointer.compile)(tokens)}`;
184
+ }
185
+
186
+ /**
187
+ * Immutably sets `value` into `payload` at the `target` JSON Pointer,
188
+ * returning a new payload (the input is never mutated, so a payload aliased
189
+ * from a runtime expression's resolved value — e.g. `$inputs.order` — is not
190
+ * corrupted). Throws {@link ResolverError} for a non-JSON-Pointer target
191
+ * (e.g. XPath) or a target that does not resolve within the payload.
192
+ */
193
+ #applyReplacement(payload, target, value, scope) {
194
+ if (!(0, _jsonPointer.testJSONPointer)(target)) {
195
+ throw new _ResolverError.default(`Unsupported requestBody replacement target "${target}" (expected JSON Pointer)`, {
196
+ ...scope,
197
+ target,
198
+ reason: 'unsupported-target'
199
+ });
200
+ }
201
+
202
+ // an empty pointer targets the payload root — replace the whole payload.
203
+ const tokens = this.#pathTokens(target);
204
+ if (tokens.length === 0) return value;
205
+
206
+ // the target must resolve against the payload; `hasPath` also rejects
207
+ // prototype-chain tokens (e.g. `__proto__`) since they are not own paths.
208
+ if (!(0, _ramda.hasPath)(tokens, payload)) {
209
+ throw new _ResolverError.default(`requestBody replacement target "${target}" does not resolve in the payload`, {
210
+ ...scope,
211
+ target,
212
+ reason: 'unresolved-target'
213
+ });
214
+ }
215
+ return (0, _ramda.assocPath)(tokens, value, payload);
216
+ }
217
+
218
+ /**
219
+ * Parses a JSON Pointer into path tokens, coercing an array-index token to a
220
+ * number so it indexes an array rather than converting it to an object key
221
+ * (Ramda's `assocPath` distinguishes numeric from string keys).
222
+ */
223
+ #pathTokens(target) {
224
+ return (0, _jsonPointer.parse)(target).tree.map(token => ARRAY_INDEX.test(token) ? Number(token) : token);
225
+ }
226
+ }
227
+ var _default = exports.default = RequestBodyResolver;
@@ -0,0 +1,220 @@
1
+ import { assocPath, hasPath } from 'ramda';
2
+ import { toValue } from '@speclynx/apidom-core';
3
+ import { isArrayElement, isObjectElement, isStringElement } from '@speclynx/apidom-datamodel';
4
+ import { compile as compileJSONPointer, parse as parseJSONPointer, testJSONPointer } from '@swaggerexpert/json-pointer';
5
+ import { interpolate, test as isRuntimeExpression } from '@swaggerexpert/arazzo-runtime-expression';
6
+ import { isPayloadReplacementElement } from '@speclynx/apidom-ns-arazzo-1';
7
+ import ResolverError from "../errors/ResolverError.mjs";
8
+ import ArazzoValueResolver from "./ArazzoValueResolver.mjs";
9
+ /**
10
+ * Matches a canonical non-negative integer (RFC 6901 array index): no leading
11
+ * zeros other than `0` itself.
12
+ */
13
+ const ARRAY_INDEX = /^(0|[1-9][0-9]*)$/;
14
+
15
+ /**
16
+ * Marks a bare-expression payload value that did not resolve. Its container
17
+ * decides what "not provided" means there: an object member is omitted, while
18
+ * an array element or the whole payload throws.
19
+ */
20
+ const UNRESOLVED = Symbol('unresolved');
21
+
22
+ /**
23
+ * A resolved request body: the payload with all replacements applied, plus the
24
+ * declared content type when present.
25
+ * @public
26
+ */
27
+
28
+ /**
29
+ * Resolves a step's `requestBody` to a concrete payload.
30
+ *
31
+ * The `payload` is resolved first. Per the specification it "can contain"
32
+ * runtime expressions, so it is walked: every string in it — the payload
33
+ * itself, or any value nested in its objects and arrays — that is a whole
34
+ * runtime expression resolves to its typed value, and every other string has
35
+ * its embedded `{expression}` occurrences interpolated (tolerantly, so literal
36
+ * braces such as a JSON template's own are kept). Object keys and resolved
37
+ * values are never evaluated.
38
+ *
39
+ * An unresolved expression reads as "not provided": an object member is
40
+ * omitted, while a whole-expression payload, an array element or an embedded
41
+ * expression — none of which can be omitted — throws {@link ResolverError}
42
+ * (`unresolved-expression`), as does an invalid embedded expression
43
+ * (`invalid-expression`).
44
+ *
45
+ * Then each `replacements` entry is applied — its `value` is resolved by the
46
+ * family-wide literal-vs-expression rule of {@link ArazzoValueResolver} and set
47
+ * into the payload at the replacement's `target` JSON Pointer. A replacement
48
+ * whose value does not resolve is skipped, leaving the payload as authored.
49
+ *
50
+ * `target` may be a JSON Pointer or an XPath per the specification; only JSON
51
+ * Pointer targets are supported — an XPath target throws {@link ResolverError}.
52
+ * @public
53
+ */
54
+ class RequestBodyResolver extends ArazzoValueResolver {
55
+ /**
56
+ * Resolves the request body, returning its payload and content type. Returns
57
+ * `undefined` when there is no request body.
58
+ *
59
+ * `scope` names the step in a thrown {@link ResolverError}.
60
+ */
61
+ resolve(requestBody, resolve, scope) {
62
+ if (requestBody === undefined) return undefined;
63
+
64
+ // present but scalar: `.payload`, `.replacements` and `.contentType` are
65
+ // all plain `undefined` on a non-map element, so the step would silently
66
+ // send no body and report success.
67
+ if (!isObjectElement(requestBody)) {
68
+ throw new ResolverError('`requestBody` is present but is not a map', {
69
+ ...scope,
70
+ target: 'requestBody',
71
+ reason: 'malformed-request-body'
72
+ });
73
+ }
74
+ const authoredPayload = toValue(requestBody.payload);
75
+ let payload = this.#requireResolved(authoredPayload, this.#resolvePayloadValue(authoredPayload, [], resolve, scope), [], scope);
76
+ if (requestBody.replacements !== undefined) {
77
+ // present but scalar: walking it would fail as a bare
78
+ // `TypeError: requestBody.replacements is not iterable`.
79
+ if (!isArrayElement(requestBody.replacements)) {
80
+ throw new ResolverError('`requestBody.replacements` is present but is not a list', {
81
+ ...scope,
82
+ target: 'requestBody.replacements',
83
+ reason: 'malformed-replacements'
84
+ });
85
+ }
86
+ for (const replacement of requestBody.replacements) {
87
+ if (!isPayloadReplacementElement(replacement)) continue;
88
+ const target = toValue(replacement.target);
89
+ if (typeof target !== 'string') continue;
90
+ const value = this.resolveValue(replacement.value, resolve);
91
+ if (value === undefined) continue;
92
+ payload = this.#applyReplacement(payload, target, value, scope);
93
+ }
94
+ }
95
+ const contentType = isStringElement(requestBody.contentType) ? toValue(requestBody.contentType) : undefined;
96
+ return contentType === undefined ? {
97
+ payload
98
+ } : {
99
+ payload,
100
+ contentType
101
+ };
102
+ }
103
+
104
+ /**
105
+ * Resolves one authored payload value at the `tokens` path, recursing into
106
+ * objects and arrays. Returns {@link UNRESOLVED} for a bare expression that
107
+ * did not resolve, for its container to handle.
108
+ */
109
+ #resolvePayloadValue(value, tokens, resolve, scope) {
110
+ if (typeof value === 'string') return this.#resolvePayloadString(value, tokens, resolve, scope);
111
+ if (Array.isArray(value)) {
112
+ return value.map((item, index) => {
113
+ const itemTokens = [...tokens, String(index)];
114
+ const resolved = this.#resolvePayloadValue(item, itemTokens, resolve, scope);
115
+ return this.#requireResolved(item, resolved, itemTokens, scope);
116
+ });
117
+ }
118
+ if (value !== null && typeof value === 'object') {
119
+ // `fromEntries` defines own properties, so an authored `__proto__` key
120
+ // stays a plain member instead of replacing the prototype.
121
+ return Object.fromEntries(Object.entries(value).map(([key, member]) => [key, this.#resolvePayloadValue(member, [...tokens, key], resolve, scope)]).filter(([, resolved]) => resolved !== UNRESOLVED));
122
+ }
123
+ return value;
124
+ }
125
+
126
+ /**
127
+ * Resolves one authored payload string: a whole runtime expression to its
128
+ * typed value (or {@link UNRESOLVED}), anything else by tolerant
129
+ * interpolation of its embedded `{expression}` occurrences.
130
+ */
131
+ #resolvePayloadString(value, tokens, resolve, scope) {
132
+ if (isRuntimeExpression(value)) {
133
+ const resolved = resolve(value);
134
+ return resolved === undefined ? UNRESOLVED : resolved;
135
+ }
136
+ return interpolate(value, expression => {
137
+ const resolved = resolve(expression);
138
+ if (resolved === undefined) throw this.#unresolvedError(expression, tokens, scope);
139
+ return resolved;
140
+ }, {
141
+ strict: false,
142
+ onError: ({
143
+ text
144
+ }) => {
145
+ throw new ResolverError(`Invalid runtime expression "${text}" in ${this.#payloadTarget(tokens)}`, {
146
+ ...scope,
147
+ target: this.#payloadTarget(tokens),
148
+ reason: 'invalid-expression'
149
+ });
150
+ }
151
+ });
152
+ }
153
+
154
+ /**
155
+ * Throws for an unresolved bare expression where omission is not possible —
156
+ * the whole payload or an array element; passes every other value through.
157
+ */
158
+ #requireResolved(authored, resolved, tokens, scope) {
159
+ if (resolved === UNRESOLVED) throw this.#unresolvedError(authored, tokens, scope);
160
+ return resolved;
161
+ }
162
+ #unresolvedError(expression, tokens, scope) {
163
+ const target = this.#payloadTarget(tokens);
164
+ return new ResolverError(`Runtime expression "${expression}" in ${target} did not resolve`, {
165
+ ...scope,
166
+ target,
167
+ reason: 'unresolved-expression'
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Names a payload location for errors: `requestBody.payload` itself, or a
173
+ * member as a JSON Pointer fragment (e.g. `requestBody.payload#/order/petId`).
174
+ */
175
+ #payloadTarget(tokens) {
176
+ return tokens.length === 0 ? 'requestBody.payload' : `requestBody.payload#${compileJSONPointer(tokens)}`;
177
+ }
178
+
179
+ /**
180
+ * Immutably sets `value` into `payload` at the `target` JSON Pointer,
181
+ * returning a new payload (the input is never mutated, so a payload aliased
182
+ * from a runtime expression's resolved value — e.g. `$inputs.order` — is not
183
+ * corrupted). Throws {@link ResolverError} for a non-JSON-Pointer target
184
+ * (e.g. XPath) or a target that does not resolve within the payload.
185
+ */
186
+ #applyReplacement(payload, target, value, scope) {
187
+ if (!testJSONPointer(target)) {
188
+ throw new ResolverError(`Unsupported requestBody replacement target "${target}" (expected JSON Pointer)`, {
189
+ ...scope,
190
+ target,
191
+ reason: 'unsupported-target'
192
+ });
193
+ }
194
+
195
+ // an empty pointer targets the payload root — replace the whole payload.
196
+ const tokens = this.#pathTokens(target);
197
+ if (tokens.length === 0) return value;
198
+
199
+ // the target must resolve against the payload; `hasPath` also rejects
200
+ // prototype-chain tokens (e.g. `__proto__`) since they are not own paths.
201
+ if (!hasPath(tokens, payload)) {
202
+ throw new ResolverError(`requestBody replacement target "${target}" does not resolve in the payload`, {
203
+ ...scope,
204
+ target,
205
+ reason: 'unresolved-target'
206
+ });
207
+ }
208
+ return assocPath(tokens, value, payload);
209
+ }
210
+
211
+ /**
212
+ * Parses a JSON Pointer into path tokens, coercing an array-index token to a
213
+ * number so it indexes an array rather than converting it to an object key
214
+ * (Ramda's `assocPath` distinguishes numeric from string keys).
215
+ */
216
+ #pathTokens(target) {
217
+ return parseJSONPointer(target).tree.map(token => ARRAY_INDEX.test(token) ? Number(token) : token);
218
+ }
219
+ }
220
+ export default RequestBodyResolver;
@@ -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,22 @@
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 _ArazzoValueResolver = _interopRequireDefault(require("./ArazzoValueResolver.cjs"));
9
+ /**
10
+ * Resolves a step's `parameters` to a plain map of resolved values.
11
+ *
12
+ * What a parameter's `value` means is the family-wide rule of
13
+ * {@link ArazzoValueResolver}; how the resolved values are *keyed* is the subclass's
14
+ * policy, one per step target — {@link OpenAPIOperationParameterResolver} keys
15
+ * request delivery for a step targeting an operation,
16
+ * {@link WorkflowParameterResolver} keys a sub-workflow's inputs for a step
17
+ * targeting a `workflowId`. Each executor constructs the one resolver its kind
18
+ * of step calls for.
19
+ * @public
20
+ */
21
+ class StepParameterResolver extends _ArazzoValueResolver.default {}
22
+ var _default = exports.default = StepParameterResolver;
@@ -0,0 +1,15 @@
1
+ import ArazzoValueResolver from "./ArazzoValueResolver.mjs";
2
+ /**
3
+ * Resolves a step's `parameters` to a plain map of resolved values.
4
+ *
5
+ * What a parameter's `value` means is the family-wide rule of
6
+ * {@link ArazzoValueResolver}; how the resolved values are *keyed* is the subclass's
7
+ * policy, one per step target — {@link OpenAPIOperationParameterResolver} keys
8
+ * request delivery for a step targeting an operation,
9
+ * {@link WorkflowParameterResolver} keys a sub-workflow's inputs for a step
10
+ * targeting a `workflowId`. Each executor constructs the one resolver its kind
11
+ * of step calls for.
12
+ * @public
13
+ */
14
+ class StepParameterResolver extends ArazzoValueResolver {}
15
+ export default StepParameterResolver;
@@ -0,0 +1,73 @@
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 _apidomCore = require("@speclynx/apidom-core");
9
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
10
+ var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
11
+ var _ResolverError = _interopRequireDefault(require("../errors/ResolverError.cjs"));
12
+ var _StepParameterResolver = _interopRequireDefault(require("./StepParameterResolver.cjs"));
13
+ /**
14
+ * Resolves the `parameters` of a step targeting a `workflowId` into the
15
+ * sub-workflow's inputs.
16
+ *
17
+ * Values follow the family-wide literal-vs-expression rule of
18
+ * {@link ArazzoValueResolver}. Keys are bare parameter names: per the
19
+ * specification, "when the step in context specifies a `workflowId`, then all
20
+ * parameters map to workflow inputs" — which are keyed by name alone, even
21
+ * for an inherited parameter that carries an `in`. Locations are not
22
+ * consulted, so two parameters differing only in `in` collapse by name here,
23
+ * which for inputs is the override mechanism, not a loss.
24
+ *
25
+ * The first parameter to claim a name wins: the list is ordered by
26
+ * precedence, most specific first, as `ArazzoWorkflowNormalizer` leaves it
27
+ * once a step's own parameters have been merged with the ones it inherits —
28
+ * the override order the specification requires.
29
+ * @public
30
+ */
31
+ class WorkflowParameterResolver extends _StepParameterResolver.default {
32
+ /**
33
+ * Resolves each parameter's `value`, returning a `name` → value map.
34
+ * Returns an empty object when there are no parameters.
35
+ *
36
+ * `scope` names the step in a thrown {@link ResolverError}.
37
+ */
38
+ resolve(parameters, resolve, scope) {
39
+ const result = {};
40
+ if (parameters === undefined) return result;
41
+ // present but scalar: walking it would fail as a bare
42
+ // `TypeError: parameters is not iterable`.
43
+ if (!(0, _apidomDatamodel.isArrayElement)(parameters)) {
44
+ throw new _ResolverError.default('`parameters` is present but is not a list', {
45
+ ...scope,
46
+ target: 'parameters',
47
+ reason: 'malformed-parameters'
48
+ });
49
+ }
50
+ for (const parameter of parameters) {
51
+ if (!(0, _apidomNsArazzo.isParameterElement)(parameter)) continue;
52
+ const name = (0, _apidomCore.toValue)(parameter.name);
53
+ if (typeof name !== 'string') continue;
54
+ // first entry wins — see the precedence note above. `Object.hasOwn` rather
55
+ // than `name in result`, so a parameter named `toString` is not mistaken
56
+ // for one already resolved.
57
+ if (Object.hasOwn(result, name)) continue;
58
+
59
+ // defined rather than assigned: a name like `__proto__` hits the
60
+ // Object.prototype accessor on bracket assignment, so no own property is
61
+ // ever created and the input is silently lost — and an object value
62
+ // additionally rewrites the record's prototype
63
+ Object.defineProperty(result, name, {
64
+ value: this.resolveValue(parameter.value, resolve),
65
+ enumerable: true,
66
+ writable: true,
67
+ configurable: true
68
+ });
69
+ }
70
+ return result;
71
+ }
72
+ }
73
+ var _default = exports.default = WorkflowParameterResolver;
@@ -0,0 +1,66 @@
1
+ import { toValue } from '@speclynx/apidom-core';
2
+ import { isArrayElement } from '@speclynx/apidom-datamodel';
3
+ import { isParameterElement } from '@speclynx/apidom-ns-arazzo-1';
4
+ import ResolverError from "../errors/ResolverError.mjs";
5
+ import StepParameterResolver from "./StepParameterResolver.mjs";
6
+ /**
7
+ * Resolves the `parameters` of a step targeting a `workflowId` into the
8
+ * sub-workflow's inputs.
9
+ *
10
+ * Values follow the family-wide literal-vs-expression rule of
11
+ * {@link ArazzoValueResolver}. Keys are bare parameter names: per the
12
+ * specification, "when the step in context specifies a `workflowId`, then all
13
+ * parameters map to workflow inputs" — which are keyed by name alone, even
14
+ * for an inherited parameter that carries an `in`. Locations are not
15
+ * consulted, so two parameters differing only in `in` collapse by name here,
16
+ * which for inputs is the override mechanism, not a loss.
17
+ *
18
+ * The first parameter to claim a name wins: the list is ordered by
19
+ * precedence, most specific first, as `ArazzoWorkflowNormalizer` leaves it
20
+ * once a step's own parameters have been merged with the ones it inherits —
21
+ * the override order the specification requires.
22
+ * @public
23
+ */
24
+ class WorkflowParameterResolver extends StepParameterResolver {
25
+ /**
26
+ * Resolves each parameter's `value`, returning a `name` → value map.
27
+ * Returns an empty object when there are no parameters.
28
+ *
29
+ * `scope` names the step in a thrown {@link ResolverError}.
30
+ */
31
+ resolve(parameters, resolve, scope) {
32
+ const result = {};
33
+ if (parameters === undefined) return result;
34
+ // present but scalar: walking it would fail as a bare
35
+ // `TypeError: parameters is not iterable`.
36
+ if (!isArrayElement(parameters)) {
37
+ throw new ResolverError('`parameters` is present but is not a list', {
38
+ ...scope,
39
+ target: 'parameters',
40
+ reason: 'malformed-parameters'
41
+ });
42
+ }
43
+ for (const parameter of parameters) {
44
+ if (!isParameterElement(parameter)) continue;
45
+ const name = toValue(parameter.name);
46
+ if (typeof name !== 'string') continue;
47
+ // first entry wins — see the precedence note above. `Object.hasOwn` rather
48
+ // than `name in result`, so a parameter named `toString` is not mistaken
49
+ // for one already resolved.
50
+ if (Object.hasOwn(result, name)) continue;
51
+
52
+ // defined rather than assigned: a name like `__proto__` hits the
53
+ // Object.prototype accessor on bracket assignment, so no own property is
54
+ // ever created and the input is silently lost — and an object value
55
+ // additionally rewrites the record's prototype
56
+ Object.defineProperty(result, name, {
57
+ value: this.resolveValue(parameter.value, resolve),
58
+ enumerable: true,
59
+ writable: true,
60
+ configurable: true
61
+ });
62
+ }
63
+ return result;
64
+ }
65
+ }
66
+ export default WorkflowParameterResolver;