@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,214 @@
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 _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
10
+ var _apidomCore = require("@speclynx/apidom-core");
11
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
12
+ var _resolver = require("@usearazzo/resolver");
13
+ var _empty = require("@speclynx/apidom-reference/configuration/empty");
14
+ var _ParameterIdentity = _interopRequireDefault(require("../document/ParameterIdentity.cjs"));
15
+ var _NormalizationError = _interopRequireDefault(require("../errors/NormalizationError.cjs"));
16
+ var _ArazzoDocumentRegistryProvider = require("../registry/providers/ArazzoDocumentRegistryProvider.cjs");
17
+ /**
18
+ * Options for normalizing an Arazzo workflow.
19
+ * @public
20
+ */
21
+
22
+ /**
23
+ * Default options for normalizing an Arazzo workflow.
24
+ */
25
+ // shallow copy to avoid mutating the provider's shared options
26
+ const normalizerOptionsOverride = (0, _empty.mergeOptions)(_ArazzoDocumentRegistryProvider.providerOptionsOverride, {});
27
+
28
+ /**
29
+ * Normalizes an extracted Arazzo workflow.
30
+ *
31
+ * Dereferences the workflow subtree ($components.* references),
32
+ * producing a self-contained workflow element, then inherits the workflow's
33
+ * "applicable for all steps" defaults — its `parameters`, and its
34
+ * `successActions` / `failureActions` — into each of its steps.
35
+ *
36
+ * All passes mutate, and what they mutate is the document itself: the extractor
37
+ * hands over the live workflow node out of `document.parseResult`, and
38
+ * dereferencing runs `immutable: false`, returning that same instance. Writing
39
+ * through to the document is what lets the registry act as a natural cache —
40
+ * a workflow reached a second time is already dereferenced and already
41
+ * inherited into, so no pass repeats. The inheritance is idempotent for
42
+ * exactly that reason.
43
+ *
44
+ * The writes differ in kind, which is worth knowing before sharing a
45
+ * registry. Dereferencing only *resolves* what the document already says — a
46
+ * `$ref` replaced by its target means the same thing. Inheritance *synthesizes*:
47
+ * afterwards a step carries `parameters` or an `onSuccess` its source never
48
+ * declared, so a consumer that reads the document back (`APIDocument.toJSON()`)
49
+ * sees one that no longer matches the file it was parsed from. The OpenAPI
50
+ * normalizers write inherited servers, parameters and security requirements into
51
+ * their documents the same way, so this is the layer's established contract
52
+ * rather than a property of Arazzo.
53
+ * @public
54
+ */
55
+ class ArazzoWorkflowNormalizer {
56
+ #options;
57
+ constructor(options = {}) {
58
+ this.#options = (0, _empty.mergeOptions)(normalizerOptionsOverride, options);
59
+ }
60
+
61
+ /**
62
+ * Dereferences the workflow subtree against its parent document, then inherits
63
+ * the workflow's `parameters` and default actions into its steps.
64
+ */
65
+ async normalize(workflow, document) {
66
+ let dereferenced;
67
+ try {
68
+ dereferenced = await (0, _resolver.dereferenceArazzoElement)(workflow, (0, _empty.mergeOptions)(_resolver.defaultDereferenceArazzoOptions, (0, _empty.mergeOptions)(this.#options, {
69
+ resolve: {
70
+ baseURI: document.uri
71
+ },
72
+ dereference: {
73
+ strategyOpts: {
74
+ parseResult: document.parseResult
75
+ }
76
+ }
77
+ })));
78
+ } catch (error) {
79
+ throw new _NormalizationError.default(`Failed to normalize workflow "${(0, _apidomCore.toValue)(workflow.workflowId)}" in Arazzo document at "${document.uri}"`, {
80
+ cause: error,
81
+ workflowId: (0, _apidomCore.toValue)(workflow.workflowId),
82
+ uri: document.uri
83
+ });
84
+ }
85
+
86
+ // normalization (mutable) — after dereferencing, so a `parameters` or
87
+ // action list reaching the steps through a $components reference is
88
+ // inherited as a resolved Parameter / Success Action Object rather than as
89
+ // the Reusable Object it was written as.
90
+ this.#inheritParametersToSteps(dereferenced);
91
+ this.#inheritActionsToSteps(dereferenced);
92
+ return dereferenced;
93
+ }
94
+
95
+ /**
96
+ * Inherits the workflow's `parameters` into each of its steps.
97
+ *
98
+ * Per Arazzo 1.0.1 a workflow's `parameters` are "applicable for all steps
99
+ * described under this workflow" and a step's own definition "will override it
100
+ * but can never remove it" — so each step ends up with the union, its own
101
+ * declaration winning wherever the two are the same parameter by
102
+ * {@link ParameterIdentity}. `uniqWith` keeps the first of each equal pair,
103
+ * so the step's own list leads, exactly as `inheritParametersToOperation`
104
+ * orders an Operation's ahead of the Path Item's it inherits.
105
+ *
106
+ * That leading position is what makes the override effective and not merely
107
+ * present: the parameter resolvers key resolved values first-wins — by the
108
+ * same `(name, in)` identity for an operation step
109
+ * ({@link OpenAPIOperationParameterResolver}), and by bare name for a
110
+ * `workflowId` step's inputs ({@link WorkflowParameterResolver}) — so
111
+ * wherever the two collapse to one key, the earlier survives, which must be
112
+ * the step's.
113
+ *
114
+ * Inheriting the elements here rather than the resolved values is what lets a
115
+ * workflow-level `value` that is a runtime expression still be evaluated once
116
+ * per step, against the state that step is entered with.
117
+ *
118
+ * Not every workflow parameter is applicable to every kind of step: one
119
+ * without a location is a workflow-input mapping (see
120
+ * {@link ParameterIdentity}), so it is inherited only into steps targeting a
121
+ * `workflowId` — on an operation step it names no place in a request, and
122
+ * the resolver reports a location-less parameter there as the step's *own*
123
+ * authoring error, which not synthesizing one is what keeps true. The
124
+ * workflow's own `parameters` list is left intact; only the synthesized
125
+ * per-step copies are filtered.
126
+ *
127
+ * A malformed `steps` or `parameters` is left for the executor to report as
128
+ * the authoring error it is; there is nothing to inherit through it here, and
129
+ * a step whose own `parameters` is present but not a list is skipped rather
130
+ * than handed a synthesized one — overwriting it would erase the very thing
131
+ * that makes the document invalid and leave nothing to report. An entry
132
+ * *within* either list that is not a Parameter Object is carried across
133
+ * untouched rather than filtered out, for the same reason: rebuilding a step's
134
+ * list is no licence to drop what its author wrote, and the parameter
135
+ * resolvers ignore it anyway. A parameter whose location is malformed (`in: 1`) is
136
+ * likewise carried, for the resolver to report loudly.
137
+ */
138
+ #inheritParametersToSteps(workflow) {
139
+ const inherited = workflow.parameters;
140
+ if (!(0, _apidomDatamodel.isArrayElement)(inherited) || inherited.isEmpty) return;
141
+ if (!(0, _apidomDatamodel.isArrayElement)(workflow.steps)) return;
142
+ const inheritedParameters = [...inherited];
143
+ // what an operation step may inherit — the input-shaped entries filtered
144
+ // out once, ahead of the per-step loop
145
+ const requestShaped = inheritedParameters.filter(parameter => !(0, _apidomNsArazzo.isParameterElement)(parameter) || _ParameterIdentity.default.locationOf(parameter) !== undefined);
146
+ for (const step of workflow.steps) {
147
+ if (!(0, _apidomNsArazzo.isStepElement)(step)) continue;
148
+ if (step.parameters !== undefined && !(0, _apidomDatamodel.isArrayElement)(step.parameters)) continue;
149
+
150
+ // when nothing applicable remains AND the step declares no list of its
151
+ // own, there is nothing to synthesize. A step with its own list is still
152
+ // rebuilt, so its duplicates collapse the same way whichever kind of
153
+ // step it is — not depending on what the workflow happened to contribute
154
+ const applicable = (0, _apidomDatamodel.isStringElement)(step.workflowId) ? inheritedParameters : requestShaped;
155
+ if (applicable.length === 0 && step.parameters === undefined) continue;
156
+ const own = (0, _apidomDatamodel.isArrayElement)(step.parameters) ? [...step.parameters] : [];
157
+ step.parameters = new _apidomNsArazzo.StepParametersElement((0, _ramda.uniqWith)(_ParameterIdentity.default.equal, [...own, ...applicable]));
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Inherits the workflow's `successActions` / `failureActions` into each step
163
+ * that declares no `onSuccess` / `onFailure` of its own.
164
+ *
165
+ * Per Arazzo 1.0.1 both lists are "applicable for all steps described under
166
+ * this workflow", and a step's own list **overrides** the corresponding
167
+ * workflow one — wholesale, with no per-action merge, which is where this
168
+ * differs from the parameters above. Success and failure fall back
169
+ * independently: a step may override only its `onFailure` and still inherit
170
+ * the workflow's `successActions`.
171
+ *
172
+ * Presence is tested with `hasKey`, not truthiness: a step declaring an empty
173
+ * list (`onSuccess: []`) has *overridden* the default with an empty set of
174
+ * actions, not asked for one — it is skipped, as is a step whose `onSuccess`
175
+ * is present but not a list, for the same reason the parameters pass leaves a
176
+ * malformed list alone. Testing the key is also what makes the pass
177
+ * idempotent: after the first run the step has it, so a workflow reached again
178
+ * through the registry cache is skipped.
179
+ *
180
+ * Unlike parameters there is no step-kind filter — an action names a
181
+ * transition within the workflow, which is as meaningful for a step targeting
182
+ * a `workflowId` as for one invoking an operation, so both kinds take the
183
+ * defaults.
184
+ *
185
+ * The workflow's own action *elements* are shared into the steps rather than
186
+ * copied, matching what falling back to one shared list did before: retry
187
+ * budgets are keyed by action element identity ({@link StepRetryRunner}) and
188
+ * held per `run()` call, so steps sharing an inherited `retry` share nothing
189
+ * that outlives the attempt loop.
190
+ */
191
+ #inheritActionsToSteps(workflow) {
192
+ if (!(0, _apidomDatamodel.isArrayElement)(workflow.steps)) return;
193
+ const {
194
+ successActions,
195
+ failureActions
196
+ } = workflow;
197
+ // an empty list defaults to nothing, which is what declaring no list
198
+ // already means — synthesizing one would only move the document further
199
+ // from its source for no change in behavior.
200
+ const inheritSuccess = (0, _apidomDatamodel.isArrayElement)(successActions) && !successActions.isEmpty;
201
+ const inheritFailure = (0, _apidomDatamodel.isArrayElement)(failureActions) && !failureActions.isEmpty;
202
+ if (!inheritSuccess && !inheritFailure) return;
203
+ for (const step of workflow.steps) {
204
+ if (!(0, _apidomNsArazzo.isStepElement)(step)) continue;
205
+ if (inheritSuccess && !step.hasKey('onSuccess')) {
206
+ step.onSuccess = new _apidomNsArazzo.StepOnSuccessElement([...successActions]);
207
+ }
208
+ if (inheritFailure && !step.hasKey('onFailure')) {
209
+ step.onFailure = new _apidomNsArazzo.StepOnFailureElement([...failureActions]);
210
+ }
211
+ }
212
+ }
213
+ }
214
+ var _default = exports.default = ArazzoWorkflowNormalizer;
@@ -0,0 +1,206 @@
1
+ import { uniqWith } from 'ramda';
2
+ import { isParameterElement, isStepElement, StepParametersElement, StepOnSuccessElement, StepOnFailureElement } from '@speclynx/apidom-ns-arazzo-1';
3
+ import { toValue } from '@speclynx/apidom-core';
4
+ import { isArrayElement, isStringElement } from '@speclynx/apidom-datamodel';
5
+ import { dereferenceArazzoElement, defaultDereferenceArazzoOptions } from '@usearazzo/resolver';
6
+ import { mergeOptions } from '@speclynx/apidom-reference/configuration/empty';
7
+ import ParameterIdentity from "../document/ParameterIdentity.mjs";
8
+ import NormalizationError from "../errors/NormalizationError.mjs";
9
+ import { providerOptionsOverride as arazzoProviderOptions } from "../registry/providers/ArazzoDocumentRegistryProvider.mjs";
10
+ /**
11
+ * Options for normalizing an Arazzo workflow.
12
+ * @public
13
+ */
14
+ /**
15
+ * Default options for normalizing an Arazzo workflow.
16
+ */
17
+ // shallow copy to avoid mutating the provider's shared options
18
+ const normalizerOptionsOverride = mergeOptions(arazzoProviderOptions, {});
19
+
20
+ /**
21
+ * Normalizes an extracted Arazzo workflow.
22
+ *
23
+ * Dereferences the workflow subtree ($components.* references),
24
+ * producing a self-contained workflow element, then inherits the workflow's
25
+ * "applicable for all steps" defaults — its `parameters`, and its
26
+ * `successActions` / `failureActions` — into each of its steps.
27
+ *
28
+ * All passes mutate, and what they mutate is the document itself: the extractor
29
+ * hands over the live workflow node out of `document.parseResult`, and
30
+ * dereferencing runs `immutable: false`, returning that same instance. Writing
31
+ * through to the document is what lets the registry act as a natural cache —
32
+ * a workflow reached a second time is already dereferenced and already
33
+ * inherited into, so no pass repeats. The inheritance is idempotent for
34
+ * exactly that reason.
35
+ *
36
+ * The writes differ in kind, which is worth knowing before sharing a
37
+ * registry. Dereferencing only *resolves* what the document already says — a
38
+ * `$ref` replaced by its target means the same thing. Inheritance *synthesizes*:
39
+ * afterwards a step carries `parameters` or an `onSuccess` its source never
40
+ * declared, so a consumer that reads the document back (`APIDocument.toJSON()`)
41
+ * sees one that no longer matches the file it was parsed from. The OpenAPI
42
+ * normalizers write inherited servers, parameters and security requirements into
43
+ * their documents the same way, so this is the layer's established contract
44
+ * rather than a property of Arazzo.
45
+ * @public
46
+ */
47
+ class ArazzoWorkflowNormalizer {
48
+ #options;
49
+ constructor(options = {}) {
50
+ this.#options = mergeOptions(normalizerOptionsOverride, options);
51
+ }
52
+
53
+ /**
54
+ * Dereferences the workflow subtree against its parent document, then inherits
55
+ * the workflow's `parameters` and default actions into its steps.
56
+ */
57
+ async normalize(workflow, document) {
58
+ let dereferenced;
59
+ try {
60
+ dereferenced = await dereferenceArazzoElement(workflow, mergeOptions(defaultDereferenceArazzoOptions, mergeOptions(this.#options, {
61
+ resolve: {
62
+ baseURI: document.uri
63
+ },
64
+ dereference: {
65
+ strategyOpts: {
66
+ parseResult: document.parseResult
67
+ }
68
+ }
69
+ })));
70
+ } catch (error) {
71
+ throw new NormalizationError(`Failed to normalize workflow "${toValue(workflow.workflowId)}" in Arazzo document at "${document.uri}"`, {
72
+ cause: error,
73
+ workflowId: toValue(workflow.workflowId),
74
+ uri: document.uri
75
+ });
76
+ }
77
+
78
+ // normalization (mutable) — after dereferencing, so a `parameters` or
79
+ // action list reaching the steps through a $components reference is
80
+ // inherited as a resolved Parameter / Success Action Object rather than as
81
+ // the Reusable Object it was written as.
82
+ this.#inheritParametersToSteps(dereferenced);
83
+ this.#inheritActionsToSteps(dereferenced);
84
+ return dereferenced;
85
+ }
86
+
87
+ /**
88
+ * Inherits the workflow's `parameters` into each of its steps.
89
+ *
90
+ * Per Arazzo 1.0.1 a workflow's `parameters` are "applicable for all steps
91
+ * described under this workflow" and a step's own definition "will override it
92
+ * but can never remove it" — so each step ends up with the union, its own
93
+ * declaration winning wherever the two are the same parameter by
94
+ * {@link ParameterIdentity}. `uniqWith` keeps the first of each equal pair,
95
+ * so the step's own list leads, exactly as `inheritParametersToOperation`
96
+ * orders an Operation's ahead of the Path Item's it inherits.
97
+ *
98
+ * That leading position is what makes the override effective and not merely
99
+ * present: the parameter resolvers key resolved values first-wins — by the
100
+ * same `(name, in)` identity for an operation step
101
+ * ({@link OpenAPIOperationParameterResolver}), and by bare name for a
102
+ * `workflowId` step's inputs ({@link WorkflowParameterResolver}) — so
103
+ * wherever the two collapse to one key, the earlier survives, which must be
104
+ * the step's.
105
+ *
106
+ * Inheriting the elements here rather than the resolved values is what lets a
107
+ * workflow-level `value` that is a runtime expression still be evaluated once
108
+ * per step, against the state that step is entered with.
109
+ *
110
+ * Not every workflow parameter is applicable to every kind of step: one
111
+ * without a location is a workflow-input mapping (see
112
+ * {@link ParameterIdentity}), so it is inherited only into steps targeting a
113
+ * `workflowId` — on an operation step it names no place in a request, and
114
+ * the resolver reports a location-less parameter there as the step's *own*
115
+ * authoring error, which not synthesizing one is what keeps true. The
116
+ * workflow's own `parameters` list is left intact; only the synthesized
117
+ * per-step copies are filtered.
118
+ *
119
+ * A malformed `steps` or `parameters` is left for the executor to report as
120
+ * the authoring error it is; there is nothing to inherit through it here, and
121
+ * a step whose own `parameters` is present but not a list is skipped rather
122
+ * than handed a synthesized one — overwriting it would erase the very thing
123
+ * that makes the document invalid and leave nothing to report. An entry
124
+ * *within* either list that is not a Parameter Object is carried across
125
+ * untouched rather than filtered out, for the same reason: rebuilding a step's
126
+ * list is no licence to drop what its author wrote, and the parameter
127
+ * resolvers ignore it anyway. A parameter whose location is malformed (`in: 1`) is
128
+ * likewise carried, for the resolver to report loudly.
129
+ */
130
+ #inheritParametersToSteps(workflow) {
131
+ const inherited = workflow.parameters;
132
+ if (!isArrayElement(inherited) || inherited.isEmpty) return;
133
+ if (!isArrayElement(workflow.steps)) return;
134
+ const inheritedParameters = [...inherited];
135
+ // what an operation step may inherit — the input-shaped entries filtered
136
+ // out once, ahead of the per-step loop
137
+ const requestShaped = inheritedParameters.filter(parameter => !isParameterElement(parameter) || ParameterIdentity.locationOf(parameter) !== undefined);
138
+ for (const step of workflow.steps) {
139
+ if (!isStepElement(step)) continue;
140
+ if (step.parameters !== undefined && !isArrayElement(step.parameters)) continue;
141
+
142
+ // when nothing applicable remains AND the step declares no list of its
143
+ // own, there is nothing to synthesize. A step with its own list is still
144
+ // rebuilt, so its duplicates collapse the same way whichever kind of
145
+ // step it is — not depending on what the workflow happened to contribute
146
+ const applicable = isStringElement(step.workflowId) ? inheritedParameters : requestShaped;
147
+ if (applicable.length === 0 && step.parameters === undefined) continue;
148
+ const own = isArrayElement(step.parameters) ? [...step.parameters] : [];
149
+ step.parameters = new StepParametersElement(uniqWith(ParameterIdentity.equal, [...own, ...applicable]));
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Inherits the workflow's `successActions` / `failureActions` into each step
155
+ * that declares no `onSuccess` / `onFailure` of its own.
156
+ *
157
+ * Per Arazzo 1.0.1 both lists are "applicable for all steps described under
158
+ * this workflow", and a step's own list **overrides** the corresponding
159
+ * workflow one — wholesale, with no per-action merge, which is where this
160
+ * differs from the parameters above. Success and failure fall back
161
+ * independently: a step may override only its `onFailure` and still inherit
162
+ * the workflow's `successActions`.
163
+ *
164
+ * Presence is tested with `hasKey`, not truthiness: a step declaring an empty
165
+ * list (`onSuccess: []`) has *overridden* the default with an empty set of
166
+ * actions, not asked for one — it is skipped, as is a step whose `onSuccess`
167
+ * is present but not a list, for the same reason the parameters pass leaves a
168
+ * malformed list alone. Testing the key is also what makes the pass
169
+ * idempotent: after the first run the step has it, so a workflow reached again
170
+ * through the registry cache is skipped.
171
+ *
172
+ * Unlike parameters there is no step-kind filter — an action names a
173
+ * transition within the workflow, which is as meaningful for a step targeting
174
+ * a `workflowId` as for one invoking an operation, so both kinds take the
175
+ * defaults.
176
+ *
177
+ * The workflow's own action *elements* are shared into the steps rather than
178
+ * copied, matching what falling back to one shared list did before: retry
179
+ * budgets are keyed by action element identity ({@link StepRetryRunner}) and
180
+ * held per `run()` call, so steps sharing an inherited `retry` share nothing
181
+ * that outlives the attempt loop.
182
+ */
183
+ #inheritActionsToSteps(workflow) {
184
+ if (!isArrayElement(workflow.steps)) return;
185
+ const {
186
+ successActions,
187
+ failureActions
188
+ } = workflow;
189
+ // an empty list defaults to nothing, which is what declaring no list
190
+ // already means — synthesizing one would only move the document further
191
+ // from its source for no change in behavior.
192
+ const inheritSuccess = isArrayElement(successActions) && !successActions.isEmpty;
193
+ const inheritFailure = isArrayElement(failureActions) && !failureActions.isEmpty;
194
+ if (!inheritSuccess && !inheritFailure) return;
195
+ for (const step of workflow.steps) {
196
+ if (!isStepElement(step)) continue;
197
+ if (inheritSuccess && !step.hasKey('onSuccess')) {
198
+ step.onSuccess = new StepOnSuccessElement([...successActions]);
199
+ }
200
+ if (inheritFailure && !step.hasKey('onFailure')) {
201
+ step.onFailure = new StepOnFailureElement([...failureActions]);
202
+ }
203
+ }
204
+ }
205
+ }
206
+ export default ArazzoWorkflowNormalizer;
@@ -0,0 +1,128 @@
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 _resolver = require("@usearazzo/resolver");
11
+ var _empty = require("@speclynx/apidom-reference/configuration/empty");
12
+ var _apidomJsonPointer = require("@speclynx/apidom-json-pointer");
13
+ var _openapi = _interopRequireDefault(require("@speclynx/apidom-reference/dereference/strategies/openapi-2"));
14
+ var _apidomNsOpenapi = require("@speclynx/apidom-ns-openapi-2");
15
+ var _NormalizationError = _interopRequireDefault(require("../errors/NormalizationError.cjs"));
16
+ var _OpenAPIDocumentRegistryProvider = require("../registry/providers/OpenAPIDocumentRegistryProvider.cjs");
17
+ /**
18
+ * Options for normalizing an OpenAPI 2.0 operation.
19
+ * @public
20
+ */
21
+
22
+ const normalizerOptionsOverride = (0, _empty.mergeOptions)(_OpenAPIDocumentRegistryProvider.providerOptionsOverride, {
23
+ dereference: {
24
+ strategies: [new _openapi.default()]
25
+ }
26
+ });
27
+
28
+ /**
29
+ * Version-specific normalization for OpenAPI 2.0 (Swagger) operations.
30
+ *
31
+ * Dereferences the operation subtree and handles merging of
32
+ * parameters and security from path item and root levels.
33
+ * OpenAPI 2.0 does not support servers at path item or operation level;
34
+ * host/basePath/schemes are root-level only and handled at execution time.
35
+ * @public
36
+ */
37
+ class OpenAPI2OperationNormalizer {
38
+ #options;
39
+ constructor(options = {}) {
40
+ this.#options = (0, _empty.mergeOptions)(normalizerOptionsOverride, options);
41
+ }
42
+ async normalize(operation, document) {
43
+ const operationPointer = (0, _apidomCore.toValue)(operation.meta.get('pointer'));
44
+ if (!(0, _apidomJsonPointer.testJSONPointer)(operationPointer)) {
45
+ throw new _NormalizationError.default(`Operation is missing valid "pointer" metadata. Was it produced by OpenAPIOperationExtractor?`, {
46
+ operationId: (0, _apidomCore.toValue)(operation.operationId),
47
+ uri: document.uri,
48
+ operationPointer
49
+ });
50
+ }
51
+ const tokens = (0, _apidomJsonPointer.parse)(operationPointer).tree;
52
+ const pathItemPointer = (0, _apidomJsonPointer.compile)(tokens.slice(0, -1));
53
+ let pathItem;
54
+ try {
55
+ pathItem = (0, _apidomJsonPointer.evaluate)(document.parseResult.api, pathItemPointer);
56
+ } catch (error) {
57
+ throw new _NormalizationError.default(`Failed to evaluate path item pointer "${pathItemPointer}" in OpenAPI 2.0 document at "${document.uri}"`, {
58
+ cause: error,
59
+ operationId: (0, _apidomCore.toValue)(operation.operationId),
60
+ uri: document.uri,
61
+ operationPointer,
62
+ pathItemPointer
63
+ });
64
+ }
65
+ if (!(0, _apidomNsOpenapi.isPathItemElement)(pathItem)) {
66
+ throw new _NormalizationError.default(`Pointer "${pathItemPointer}" does not reference a path item in OpenAPI 2.0 document at "${document.uri}"`, {
67
+ operationId: (0, _apidomCore.toValue)(operation.operationId),
68
+ uri: document.uri,
69
+ operationPointer,
70
+ pathItemPointer
71
+ });
72
+ }
73
+
74
+ // preparing data for normalization by lazy dereferencing
75
+ const entry = document.parseResult.api;
76
+ const operationDeref = await this.#dereferenceOperation(operation, document);
77
+
78
+ // dereferencing Path Item Parameter Object references
79
+ if ((0, _apidomDatamodel.isArrayElement)(pathItem.parameters)) {
80
+ pathItem.parameters = await this.#dereferencePathItemParameters(pathItem, document);
81
+ }
82
+
83
+ // normalization (mutable) — no servers in OpenAPI 2.0
84
+ _apidomNsOpenapi.refractorPluginNormalizeParameters.inheritParametersToOperation(operationDeref, pathItem);
85
+ _apidomNsOpenapi.refractorPluginNormalizeSecurityRequirements.inheritSecurityToOperation(operationDeref, entry);
86
+ return operationDeref;
87
+ }
88
+ async #dereferenceOperation(operation, document) {
89
+ try {
90
+ return await (0, _resolver.dereferenceOpenAPIElement)(operation, (0, _empty.mergeOptions)(_resolver.defaultDereferenceOpenAPIOptions, (0, _empty.mergeOptions)(this.#options, {
91
+ resolve: {
92
+ baseURI: document.uri
93
+ },
94
+ dereference: {
95
+ strategyOpts: {
96
+ parseResult: document.parseResult
97
+ }
98
+ }
99
+ })));
100
+ } catch (error) {
101
+ throw new _NormalizationError.default(`Failed to dereference Operation("${(0, _apidomCore.toValue)(operation.operationId)}") in OpenAPI 2.0 document at "${document.uri}"`, {
102
+ cause: error,
103
+ operationId: (0, _apidomCore.toValue)(operation.operationId),
104
+ uri: document.uri
105
+ });
106
+ }
107
+ }
108
+ async #dereferencePathItemParameters(pathItem, document) {
109
+ try {
110
+ return await (0, _resolver.dereferenceOpenAPIElement)(pathItem.parameters, (0, _empty.mergeOptions)(_resolver.defaultDereferenceOpenAPIOptions, (0, _empty.mergeOptions)(this.#options, {
111
+ resolve: {
112
+ baseURI: document.uri
113
+ },
114
+ dereference: {
115
+ strategyOpts: {
116
+ parseResult: document.parseResult
117
+ }
118
+ }
119
+ })));
120
+ } catch (error) {
121
+ throw new _NormalizationError.default(`Failed to dereference Path Item parameters in OpenAPI 2.0 document at "${document.uri}"`, {
122
+ cause: error,
123
+ uri: document.uri
124
+ });
125
+ }
126
+ }
127
+ }
128
+ var _default = exports.default = OpenAPI2OperationNormalizer;
@@ -0,0 +1,120 @@
1
+ import { toValue } from '@speclynx/apidom-core';
2
+ import { isArrayElement } from '@speclynx/apidom-datamodel';
3
+ import { dereferenceOpenAPIElement, defaultDereferenceOpenAPIOptions } from '@usearazzo/resolver';
4
+ import { mergeOptions } from '@speclynx/apidom-reference/configuration/empty';
5
+ import { evaluate, parse, compile, testJSONPointer } from '@speclynx/apidom-json-pointer';
6
+ import OpenAPI2DereferenceStrategy from '@speclynx/apidom-reference/dereference/strategies/openapi-2';
7
+ import { isPathItemElement, refractorPluginNormalizeParameters, refractorPluginNormalizeSecurityRequirements } from '@speclynx/apidom-ns-openapi-2';
8
+ import NormalizationError from "../errors/NormalizationError.mjs";
9
+ import { providerOptionsOverride as openAPIProviderOptions } from "../registry/providers/OpenAPIDocumentRegistryProvider.mjs";
10
+ /**
11
+ * Options for normalizing an OpenAPI 2.0 operation.
12
+ * @public
13
+ */
14
+ const normalizerOptionsOverride = mergeOptions(openAPIProviderOptions, {
15
+ dereference: {
16
+ strategies: [new OpenAPI2DereferenceStrategy()]
17
+ }
18
+ });
19
+
20
+ /**
21
+ * Version-specific normalization for OpenAPI 2.0 (Swagger) operations.
22
+ *
23
+ * Dereferences the operation subtree and handles merging of
24
+ * parameters and security from path item and root levels.
25
+ * OpenAPI 2.0 does not support servers at path item or operation level;
26
+ * host/basePath/schemes are root-level only and handled at execution time.
27
+ * @public
28
+ */
29
+ class OpenAPI2OperationNormalizer {
30
+ #options;
31
+ constructor(options = {}) {
32
+ this.#options = mergeOptions(normalizerOptionsOverride, options);
33
+ }
34
+ async normalize(operation, document) {
35
+ const operationPointer = toValue(operation.meta.get('pointer'));
36
+ if (!testJSONPointer(operationPointer)) {
37
+ throw new NormalizationError(`Operation is missing valid "pointer" metadata. Was it produced by OpenAPIOperationExtractor?`, {
38
+ operationId: toValue(operation.operationId),
39
+ uri: document.uri,
40
+ operationPointer
41
+ });
42
+ }
43
+ const tokens = parse(operationPointer).tree;
44
+ const pathItemPointer = compile(tokens.slice(0, -1));
45
+ let pathItem;
46
+ try {
47
+ pathItem = evaluate(document.parseResult.api, pathItemPointer);
48
+ } catch (error) {
49
+ throw new NormalizationError(`Failed to evaluate path item pointer "${pathItemPointer}" in OpenAPI 2.0 document at "${document.uri}"`, {
50
+ cause: error,
51
+ operationId: toValue(operation.operationId),
52
+ uri: document.uri,
53
+ operationPointer,
54
+ pathItemPointer
55
+ });
56
+ }
57
+ if (!isPathItemElement(pathItem)) {
58
+ throw new NormalizationError(`Pointer "${pathItemPointer}" does not reference a path item in OpenAPI 2.0 document at "${document.uri}"`, {
59
+ operationId: toValue(operation.operationId),
60
+ uri: document.uri,
61
+ operationPointer,
62
+ pathItemPointer
63
+ });
64
+ }
65
+
66
+ // preparing data for normalization by lazy dereferencing
67
+ const entry = document.parseResult.api;
68
+ const operationDeref = await this.#dereferenceOperation(operation, document);
69
+
70
+ // dereferencing Path Item Parameter Object references
71
+ if (isArrayElement(pathItem.parameters)) {
72
+ pathItem.parameters = await this.#dereferencePathItemParameters(pathItem, document);
73
+ }
74
+
75
+ // normalization (mutable) — no servers in OpenAPI 2.0
76
+ refractorPluginNormalizeParameters.inheritParametersToOperation(operationDeref, pathItem);
77
+ refractorPluginNormalizeSecurityRequirements.inheritSecurityToOperation(operationDeref, entry);
78
+ return operationDeref;
79
+ }
80
+ async #dereferenceOperation(operation, document) {
81
+ try {
82
+ return await dereferenceOpenAPIElement(operation, mergeOptions(defaultDereferenceOpenAPIOptions, mergeOptions(this.#options, {
83
+ resolve: {
84
+ baseURI: document.uri
85
+ },
86
+ dereference: {
87
+ strategyOpts: {
88
+ parseResult: document.parseResult
89
+ }
90
+ }
91
+ })));
92
+ } catch (error) {
93
+ throw new NormalizationError(`Failed to dereference Operation("${toValue(operation.operationId)}") in OpenAPI 2.0 document at "${document.uri}"`, {
94
+ cause: error,
95
+ operationId: toValue(operation.operationId),
96
+ uri: document.uri
97
+ });
98
+ }
99
+ }
100
+ async #dereferencePathItemParameters(pathItem, document) {
101
+ try {
102
+ return await dereferenceOpenAPIElement(pathItem.parameters, mergeOptions(defaultDereferenceOpenAPIOptions, mergeOptions(this.#options, {
103
+ resolve: {
104
+ baseURI: document.uri
105
+ },
106
+ dereference: {
107
+ strategyOpts: {
108
+ parseResult: document.parseResult
109
+ }
110
+ }
111
+ })));
112
+ } catch (error) {
113
+ throw new NormalizationError(`Failed to dereference Path Item parameters in OpenAPI 2.0 document at "${document.uri}"`, {
114
+ cause: error,
115
+ uri: document.uri
116
+ });
117
+ }
118
+ }
119
+ }
120
+ export default OpenAPI2OperationNormalizer;