@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
package/package.json CHANGED
@@ -1,6 +1,92 @@
1
1
  {
2
2
  "name": "@usearazzo/runner",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.1-alpha.9",
4
+ "description": "Runner for Arazzo Workflows.",
5
+ "keywords": [
6
+ "arazzo",
7
+ "arazzo-specification",
8
+ "runner",
9
+ "workflow",
10
+ "workflows"
11
+ ],
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "registry": "https://registry.npmjs.org",
15
+ "provenance": true,
16
+ "tag": "latest",
17
+ "timeout": 60000
18
+ },
19
+ "type": "module",
20
+ "sideEffects": false,
21
+ "engines": {
22
+ "node": ">=20.10.0"
23
+ },
24
+ "unpkg": "./dist/arazzo-runner.browser.min.js",
25
+ "main": "./src/index.cjs",
26
+ "exports": {
27
+ "types": "./types/runner.d.ts",
28
+ "import": "./src/index.mjs",
29
+ "require": "./src/index.cjs"
30
+ },
31
+ "types": "./types/runner.d.ts",
32
+ "scripts": {
33
+ "build": "npm run clean && npm run build:es && run-p --max-parallel ${CPU_CORES:-2} typescript:declaration build:cjs build:umd:browser",
34
+ "build:es": "npm run build:swagger-client && cross-env BABEL_ENV=es babel src --out-dir src --extensions '.ts' --out-file-extension '.mjs' --root-mode 'upward'",
35
+ "build:cjs": "cross-env BABEL_ENV=cjs babel src --out-dir src --extensions '.ts' --out-file-extension '.cjs' --root-mode 'upward'",
36
+ "build:umd:browser": "cross-env BABEL_ENV=browser webpack --config config/webpack/browser.config.js --progress",
37
+ "build:swagger-client": "webpack --config config/webpack/swagger-client.config.js --progress",
38
+ "lint": "eslint ./",
39
+ "lint:fix": "eslint ./ --fix",
40
+ "clean": "rimraf --glob 'src/**/*.mjs' 'src/**/*.cjs' 'test/**/*.mjs' ./dist ./types",
41
+ "typescript:check-types": "tsc --noEmit",
42
+ "typescript:declaration": "tsc -p tsconfig.declaration.json && api-extractor run -l -c ./config/api-extractor/api-extractor.json",
43
+ "test": "npm run build:es && cross-env BABEL_ENV=es babel test --out-dir test --extensions '.ts' --out-file-extension '.mjs' --root-mode 'upward' && cross-env NODE_ENV=test mocha",
44
+ "test:e2e": "npm run build:es && cross-env BABEL_ENV=es babel test --out-dir test --extensions '.ts' --out-file-extension '.mjs' --root-mode 'upward' && cross-env NODE_ENV=test mocha --config .mocharc.e2e.json",
45
+ "prepack": "copyfiles -u 2 ../../LICENSE . && copyfiles -u 2 ../../NOTICE .",
46
+ "postpack": "rimraf NOTICE LICENSE"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/usearazzo/arazzo-toolkit.git"
51
+ },
52
+ "author": "Vladimir Gorej <vladimir.gorej@gmail.com>",
53
+ "license": "Apache-2.0",
54
+ "dependencies": {
55
+ "@babel/runtime-corejs3": "^8.0.7",
56
+ "@speclynx/apidom-core": "^6.1.0",
57
+ "@speclynx/apidom-datamodel": "^6.1.0",
58
+ "@speclynx/apidom-error": "^6.1.0",
59
+ "@speclynx/apidom-json-pointer": "^6.1.0",
60
+ "@speclynx/apidom-ns-arazzo-1": "^6.1.0",
61
+ "@speclynx/apidom-ns-openapi-2": "^6.1.0",
62
+ "@speclynx/apidom-ns-openapi-3-0": "^6.1.0",
63
+ "@speclynx/apidom-ns-openapi-3-1": "^6.1.0",
64
+ "@speclynx/apidom-reference": "^6.1.0",
65
+ "@speclynx/apidom-traverse": "^6.1.0",
66
+ "@swaggerexpert/arazzo-criterion": "^1.0.1",
67
+ "@swaggerexpert/arazzo-runtime-expression": "^3.3.0",
68
+ "@swaggerexpert/json-pointer": "^3.0.2",
69
+ "@swaggerexpert/jsonpath": "^4.0.5",
70
+ "@usearazzo/parser": "1.0.1-alpha.9",
71
+ "@usearazzo/resolver": "1.0.1-alpha.9",
72
+ "@xmldom/xmldom": "^0.9.12",
73
+ "fontoxpath": "^3.34.0",
74
+ "ramda": "^0.32.0",
75
+ "ramda-adjunct": "^6.1.0",
76
+ "type-fest": "^5.10.0"
77
+ },
78
+ "files": [
79
+ "src/**/*.mjs",
80
+ "src/**/*.cjs",
81
+ "dist/",
82
+ "types/runner.d.ts",
83
+ "LICENSE",
84
+ "NOTICE",
85
+ "README.md",
86
+ "CHANGELOG.md"
87
+ ],
88
+ "devDependencies": {
89
+ "swagger-client": "^3.38.4"
90
+ },
91
+ "gitHead": "1db5e1c4882c10ac907372f24725f8f08f0c61d9"
92
+ }
@@ -0,0 +1,160 @@
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 _apidomDatamodel = require("@speclynx/apidom-datamodel");
9
+ var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
10
+ var _ResolverError = _interopRequireDefault(require("../errors/ResolverError.cjs"));
11
+ /**
12
+ * Determines whether a single criterion is met.
13
+ *
14
+ * Bridged to a criterion evaluator
15
+ * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve)`); an
16
+ * unresolvable/failing criterion is `false`, not an error.
17
+ * @public
18
+ */
19
+
20
+ /**
21
+ * The action selected for a step outcome — a Success or Failure Action element.
22
+ * @public
23
+ */
24
+
25
+ /**
26
+ * Which of a step's two action lists is being resolved. See
27
+ * {@link ActionResolver.#resolveAll} for why it's needed and why it's baked
28
+ * in by the public method rather than taken from the caller. Internal: never
29
+ * leaks into the public API.
30
+ */
31
+
32
+ /**
33
+ * Selects the actions to take for a step outcome from its `onSuccess` /
34
+ * `onFailure` list.
35
+ *
36
+ * Actions are tried in order and every one whose `criteria` all pass is
37
+ * returned (an action with no criteria always matches). Action elements are
38
+ * returned as-is — interpreting them (branching on `type`, reading
39
+ * `stepId`/`workflowId`/`retryAfter`/`retryLimit`) is the caller's concern, and
40
+ * keeping them elements preserves the document provenance. The usual caller
41
+ * acts on the first and takes an empty result as "no action matched", applying
42
+ * the path default — the next sequential step on success, break-and-return on
43
+ * failure.
44
+ *
45
+ * A step's list is the only list there is: Reusable Object entries are already
46
+ * inlined by workflow normalization, and the workflow-level
47
+ * `successActions` / `failureActions` a step falls back to are inherited into
48
+ * `onSuccess` / `onFailure` by the same pass, so a well-formed document reaches
49
+ * this point as the step's own list of concrete action elements.
50
+ * @public
51
+ */
52
+ class ActionResolver {
53
+ /**
54
+ * Returns every `onSuccess` action whose criteria are all met, in list order.
55
+ *
56
+ * The whole matching chain rather than only the first, because the caller
57
+ * needs both: it acts on `[0]`, and the one honoring "retryLimit exhausted
58
+ * prior to subsequent failure actions" walks the rest, falling from an
59
+ * exhausted `retry` to the next matching action without re-evaluating
60
+ * criteria. Empty when the list is absent or nothing matches.
61
+ *
62
+ * `scope` names the step this list belongs to, for a thrown
63
+ * {@link ResolverError}.
64
+ *
65
+ * A well-formed list whose entry is not a Success/Failure Action Object
66
+ * throws rather than being skipped: an unrecognized entry is indistinguishable
67
+ * from a step that deliberately declared no action for it, and the `goto` /
68
+ * `end` its author was reaching for would otherwise never happen without a
69
+ * word said about why.
70
+ */
71
+ resolveOnSuccess(actions, isCriterionMet, scope) {
72
+ // safe: `#resolveAll` validates every entry as *a* Success/Failure Action
73
+ // Object, not one matching this list's own field, but a well-formed
74
+ // `StepOnSuccessElement` only ever refracts Success Action entries — the
75
+ // apidom refractor types list entries positionally at parse time.
76
+ return this.#resolveAll(actions, isCriterionMet, 'onSuccess', scope);
77
+ }
78
+
79
+ /**
80
+ * Returns every `onFailure` action whose criteria are all met, in list order.
81
+ *
82
+ * Same matching and error behavior as {@link ActionResolver.resolveOnSuccess} —
83
+ * see there for the full rationale — mirrored for the step's other list.
84
+ */
85
+ resolveOnFailure(actions, isCriterionMet, scope) {
86
+ // safe: see the same-named comment in `resolveOnSuccess` above.
87
+ return this.#resolveAll(actions, isCriterionMet, 'onFailure', scope);
88
+ }
89
+
90
+ /**
91
+ * Shared implementation behind {@link ActionResolver.resolveOnSuccess} and
92
+ * {@link ActionResolver.resolveOnFailure}.
93
+ *
94
+ * `field` names which of the step's two lists this is, for the same
95
+ * `ResolverError` reason `scope` names the step: the one case that needs it —
96
+ * a list that is present but not a list — is exactly the case where the
97
+ * element's own type no longer distinguishes them. Baked in by the public
98
+ * method rather than taken from the caller.
99
+ */
100
+ #resolveAll(actions, isCriterionMet, field, scope) {
101
+ if (actions === undefined) return [];
102
+ // present but scalar: walking it would fail as a bare
103
+ // `TypeError: actions is not iterable`.
104
+ if (!(0, _apidomDatamodel.isArrayElement)(actions)) {
105
+ throw new _ResolverError.default(`\`${field}\` is present but is not a list`, {
106
+ ...scope,
107
+ target: field,
108
+ reason: 'malformed-actions'
109
+ });
110
+ }
111
+ const matched = [];
112
+ for (const action of actions) {
113
+ if (!(0, _apidomNsArazzo.isSuccessActionElement)(action) && !(0, _apidomNsArazzo.isFailureActionElement)(action)) {
114
+ throw new _ResolverError.default(`\`${field}\` contains an entry that is not a Success/Failure Action Object`, {
115
+ ...scope,
116
+ target: field,
117
+ reason: 'malformed-action-entry'
118
+ });
119
+ }
120
+ if (this.#criteriaMet(action, isCriterionMet, scope)) {
121
+ matched.push(action);
122
+ }
123
+ }
124
+ return matched;
125
+ }
126
+
127
+ /**
128
+ * Whether every criterion of the action passes. An action with no criteria
129
+ * matches vacuously.
130
+ *
131
+ * A `criteria` that is present but not a list, or that contains an entry
132
+ * that is not a Criterion Object, throws either way: an entry the resolver
133
+ * cannot read and a container it cannot read are both a document that does
134
+ * not say what its author meant, the same as an unrecognized entry in the
135
+ * action list itself.
136
+ */
137
+ #criteriaMet(action, isCriterionMet, scope) {
138
+ const criteria = action.criteria;
139
+ if (criteria === undefined) return true;
140
+ if (!(0, _apidomDatamodel.isArrayElement)(criteria)) {
141
+ throw new _ResolverError.default("An action's `criteria` is present but is not a list", {
142
+ ...scope,
143
+ target: 'criteria',
144
+ reason: 'malformed-criteria'
145
+ });
146
+ }
147
+ for (const criterion of criteria) {
148
+ if (!(0, _apidomNsArazzo.isCriterionElement)(criterion)) {
149
+ throw new _ResolverError.default("An action's `criteria` contains an entry that is not a Criterion Object", {
150
+ ...scope,
151
+ target: 'criteria',
152
+ reason: 'malformed-criterion'
153
+ });
154
+ }
155
+ if (!isCriterionMet(criterion)) return false;
156
+ }
157
+ return true;
158
+ }
159
+ }
160
+ var _default = exports.default = ActionResolver;
@@ -0,0 +1,150 @@
1
+ import { isArrayElement } from '@speclynx/apidom-datamodel';
2
+ import { isSuccessActionElement, isFailureActionElement, isCriterionElement } from '@speclynx/apidom-ns-arazzo-1';
3
+ import ResolverError from "../errors/ResolverError.mjs";
4
+ /**
5
+ * Determines whether a single criterion is met.
6
+ *
7
+ * Bridged to a criterion evaluator
8
+ * (`(criterion) => criterionEvaluator.evaluate(criterion, resolve)`); an
9
+ * unresolvable/failing criterion is `false`, not an error.
10
+ * @public
11
+ */
12
+ /**
13
+ * The action selected for a step outcome — a Success or Failure Action element.
14
+ * @public
15
+ */
16
+ /**
17
+ * Which of a step's two action lists is being resolved. See
18
+ * {@link ActionResolver.#resolveAll} for why it's needed and why it's baked
19
+ * in by the public method rather than taken from the caller. Internal: never
20
+ * leaks into the public API.
21
+ */
22
+ /**
23
+ * Selects the actions to take for a step outcome from its `onSuccess` /
24
+ * `onFailure` list.
25
+ *
26
+ * Actions are tried in order and every one whose `criteria` all pass is
27
+ * returned (an action with no criteria always matches). Action elements are
28
+ * returned as-is — interpreting them (branching on `type`, reading
29
+ * `stepId`/`workflowId`/`retryAfter`/`retryLimit`) is the caller's concern, and
30
+ * keeping them elements preserves the document provenance. The usual caller
31
+ * acts on the first and takes an empty result as "no action matched", applying
32
+ * the path default — the next sequential step on success, break-and-return on
33
+ * failure.
34
+ *
35
+ * A step's list is the only list there is: Reusable Object entries are already
36
+ * inlined by workflow normalization, and the workflow-level
37
+ * `successActions` / `failureActions` a step falls back to are inherited into
38
+ * `onSuccess` / `onFailure` by the same pass, so a well-formed document reaches
39
+ * this point as the step's own list of concrete action elements.
40
+ * @public
41
+ */
42
+ class ActionResolver {
43
+ /**
44
+ * Returns every `onSuccess` action whose criteria are all met, in list order.
45
+ *
46
+ * The whole matching chain rather than only the first, because the caller
47
+ * needs both: it acts on `[0]`, and the one honoring "retryLimit exhausted
48
+ * prior to subsequent failure actions" walks the rest, falling from an
49
+ * exhausted `retry` to the next matching action without re-evaluating
50
+ * criteria. Empty when the list is absent or nothing matches.
51
+ *
52
+ * `scope` names the step this list belongs to, for a thrown
53
+ * {@link ResolverError}.
54
+ *
55
+ * A well-formed list whose entry is not a Success/Failure Action Object
56
+ * throws rather than being skipped: an unrecognized entry is indistinguishable
57
+ * from a step that deliberately declared no action for it, and the `goto` /
58
+ * `end` its author was reaching for would otherwise never happen without a
59
+ * word said about why.
60
+ */
61
+ resolveOnSuccess(actions, isCriterionMet, scope) {
62
+ // safe: `#resolveAll` validates every entry as *a* Success/Failure Action
63
+ // Object, not one matching this list's own field, but a well-formed
64
+ // `StepOnSuccessElement` only ever refracts Success Action entries — the
65
+ // apidom refractor types list entries positionally at parse time.
66
+ return this.#resolveAll(actions, isCriterionMet, 'onSuccess', scope);
67
+ }
68
+
69
+ /**
70
+ * Returns every `onFailure` action whose criteria are all met, in list order.
71
+ *
72
+ * Same matching and error behavior as {@link ActionResolver.resolveOnSuccess} —
73
+ * see there for the full rationale — mirrored for the step's other list.
74
+ */
75
+ resolveOnFailure(actions, isCriterionMet, scope) {
76
+ // safe: see the same-named comment in `resolveOnSuccess` above.
77
+ return this.#resolveAll(actions, isCriterionMet, 'onFailure', scope);
78
+ }
79
+
80
+ /**
81
+ * Shared implementation behind {@link ActionResolver.resolveOnSuccess} and
82
+ * {@link ActionResolver.resolveOnFailure}.
83
+ *
84
+ * `field` names which of the step's two lists this is, for the same
85
+ * `ResolverError` reason `scope` names the step: the one case that needs it —
86
+ * a list that is present but not a list — is exactly the case where the
87
+ * element's own type no longer distinguishes them. Baked in by the public
88
+ * method rather than taken from the caller.
89
+ */
90
+ #resolveAll(actions, isCriterionMet, field, scope) {
91
+ if (actions === undefined) return [];
92
+ // present but scalar: walking it would fail as a bare
93
+ // `TypeError: actions is not iterable`.
94
+ if (!isArrayElement(actions)) {
95
+ throw new ResolverError(`\`${field}\` is present but is not a list`, {
96
+ ...scope,
97
+ target: field,
98
+ reason: 'malformed-actions'
99
+ });
100
+ }
101
+ const matched = [];
102
+ for (const action of actions) {
103
+ if (!isSuccessActionElement(action) && !isFailureActionElement(action)) {
104
+ throw new ResolverError(`\`${field}\` contains an entry that is not a Success/Failure Action Object`, {
105
+ ...scope,
106
+ target: field,
107
+ reason: 'malformed-action-entry'
108
+ });
109
+ }
110
+ if (this.#criteriaMet(action, isCriterionMet, scope)) {
111
+ matched.push(action);
112
+ }
113
+ }
114
+ return matched;
115
+ }
116
+
117
+ /**
118
+ * Whether every criterion of the action passes. An action with no criteria
119
+ * matches vacuously.
120
+ *
121
+ * A `criteria` that is present but not a list, or that contains an entry
122
+ * that is not a Criterion Object, throws either way: an entry the resolver
123
+ * cannot read and a container it cannot read are both a document that does
124
+ * not say what its author meant, the same as an unrecognized entry in the
125
+ * action list itself.
126
+ */
127
+ #criteriaMet(action, isCriterionMet, scope) {
128
+ const criteria = action.criteria;
129
+ if (criteria === undefined) return true;
130
+ if (!isArrayElement(criteria)) {
131
+ throw new ResolverError("An action's `criteria` is present but is not a list", {
132
+ ...scope,
133
+ target: 'criteria',
134
+ reason: 'malformed-criteria'
135
+ });
136
+ }
137
+ for (const criterion of criteria) {
138
+ if (!isCriterionElement(criterion)) {
139
+ throw new ResolverError("An action's `criteria` contains an entry that is not a Criterion Object", {
140
+ ...scope,
141
+ target: 'criteria',
142
+ reason: 'malformed-criterion'
143
+ });
144
+ }
145
+ if (!isCriterionMet(criterion)) return false;
146
+ }
147
+ return true;
148
+ }
149
+ }
150
+ export default ActionResolver;
@@ -0,0 +1,111 @@
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 _apidomJsonPointer = require("@speclynx/apidom-json-pointer");
11
+ var _apidomNsOpenapi = require("@speclynx/apidom-ns-openapi-2");
12
+ var _OpenAPIDocument = _interopRequireDefault(require("../document/OpenAPIDocument.cjs"));
13
+ var _OpenAPIOperationIndex = _interopRequireDefault(require("../document/OpenAPIOperationIndex.cjs"));
14
+ var _AssemblerError = _interopRequireDefault(require("../errors/AssemblerError.cjs"));
15
+ /**
16
+ * Assembles a standalone OpenAPI 2.0 (Swagger) document from a
17
+ * normalized operation element.
18
+ *
19
+ * The assembled document is a valid Swagger 2.0 specification containing
20
+ * only the single operation with its host, basePath, schemes, and
21
+ * referenced security definitions from the source document.
22
+ * @public
23
+ */
24
+ class OpenAPI2DocumentAssembler {
25
+ /**
26
+ * Assembles a standalone Swagger 2.0 document from a normalized operation.
27
+ */
28
+ assemble(operation, document) {
29
+ const entry = document.parseResult.api;
30
+ const method = (0, _apidomCore.toValue)(operation.meta.get('http-method'));
31
+ const path = (0, _apidomCore.toValue)(operation.meta.get('path'));
32
+ if (typeof method !== 'string' || typeof path !== 'string') {
33
+ throw new _AssemblerError.default(`Operation is missing valid "http-method" or "path" metadata. Was it produced by OpenAPIOperationExtractor?`, {
34
+ uri: document.uri,
35
+ operationId: (0, _apidomCore.toValue)(operation.operationId)
36
+ });
37
+ }
38
+ if (!(0, _apidomNsOpenapi.isSwaggerElement)(entry)) {
39
+ throw new _AssemblerError.default(`Expected OpenAPI 2.0 document at "${document.uri}"`, {
40
+ uri: document.uri
41
+ });
42
+ }
43
+
44
+ // build Swagger 2.0 document
45
+ const swagger = new _apidomNsOpenapi.SwaggerElement({
46
+ swagger: entry.swagger
47
+ }, {
48
+ classes: ['api']
49
+ });
50
+ // prettier-ignore
51
+ {
52
+ if ((0, _apidomDatamodel.isElement)(entry.info)) swagger.info = entry.info;
53
+ if ((0, _apidomDatamodel.isElement)(entry.host)) swagger.host = entry.host;
54
+ if ((0, _apidomDatamodel.isElement)(entry.basePath)) swagger.basePath = entry.basePath;
55
+ if ((0, _apidomDatamodel.isElement)(entry.schemes)) swagger.schemes = entry.schemes;
56
+ if ((0, _apidomDatamodel.isElement)(entry.consumes)) swagger.consumes = entry.consumes;
57
+ if ((0, _apidomDatamodel.isElement)(entry.produces)) swagger.produces = entry.produces;
58
+ if ((0, _apidomDatamodel.isElement)(entry.tags)) swagger.tags = entry.tags;
59
+ if ((0, _apidomDatamodel.isElement)(entry.externalDocs)) swagger.externalDocs = entry.externalDocs;
60
+ }
61
+
62
+ // build paths with single operation
63
+ const pathItem = new _apidomNsOpenapi.PathItemElement();
64
+ const paths = new _apidomNsOpenapi.PathsElement();
65
+ pathItem.set(method, operation);
66
+ paths.set(path, pathItem);
67
+ swagger.paths = paths;
68
+
69
+ // include only referenced security definitions
70
+ const securityDefinitions = this.#extractReferencedSecurityDefinitions(operation, entry);
71
+ if (securityDefinitions.length > 0) {
72
+ swagger.securityDefinitions = securityDefinitions;
73
+ }
74
+
75
+ // wrap in ParseResultElement and return as OpenAPIDocument
76
+ const parseResult = new _apidomDatamodel.ParseResultElement([swagger]);
77
+ const operationIndex = new _OpenAPIOperationIndex.default();
78
+ const operationId = (0, _apidomCore.toValue)(operation.operationId);
79
+ if (typeof operationId === 'string' && operationId.length > 0) {
80
+ operationIndex.set(operationId, (0, _apidomJsonPointer.compile)(['paths', path, method]));
81
+ }
82
+ return new _OpenAPIDocument.default(document.uri, parseResult, operationIndex);
83
+ }
84
+
85
+ /**
86
+ * Extracts only the security definitions referenced by the operation's
87
+ * security requirements.
88
+ */
89
+ #extractReferencedSecurityDefinitions(operation, entry) {
90
+ const securityDefinitions = new _apidomNsOpenapi.SecurityDefinitionsElement();
91
+ if (!(0, _apidomDatamodel.isArrayElement)(operation.security)) return securityDefinitions;
92
+ if (!(0, _apidomNsOpenapi.isSecurityDefinitionsElement)(entry.securityDefinitions)) return securityDefinitions;
93
+
94
+ // collect referenced names of Security Definitions
95
+ const referencedNames = new Set();
96
+ for (const securityRequirement of operation.security) {
97
+ if (!(0, _apidomNsOpenapi.isSecurityRequirementElement)(securityRequirement)) continue;
98
+ securityRequirement.forEach((_value, keyElement) => {
99
+ referencedNames.add((0, _apidomCore.toValue)(keyElement));
100
+ });
101
+ }
102
+ if (referencedNames.size === 0) return securityDefinitions;
103
+ for (const name of referencedNames) {
104
+ const securityScheme = entry.securityDefinitions.get(name);
105
+ if (!(0, _apidomNsOpenapi.isSecuritySchemeElement)(securityScheme)) continue;
106
+ securityDefinitions.set(name, securityScheme);
107
+ }
108
+ return securityDefinitions;
109
+ }
110
+ }
111
+ var _default = exports.default = OpenAPI2DocumentAssembler;
@@ -0,0 +1,104 @@
1
+ import { toValue } from '@speclynx/apidom-core';
2
+ import { isArrayElement, isElement, ParseResultElement } from '@speclynx/apidom-datamodel';
3
+ import { compile } from '@speclynx/apidom-json-pointer';
4
+ import { SwaggerElement, PathsElement, PathItemElement, SecurityDefinitionsElement, isSwaggerElement, isSecurityRequirementElement, isSecurityDefinitionsElement, isSecuritySchemeElement } from '@speclynx/apidom-ns-openapi-2';
5
+ import OpenAPIDocument from "../document/OpenAPIDocument.mjs";
6
+ import OpenAPIOperationIndex from "../document/OpenAPIOperationIndex.mjs";
7
+ import AssemblerError from "../errors/AssemblerError.mjs";
8
+ /**
9
+ * Assembles a standalone OpenAPI 2.0 (Swagger) document from a
10
+ * normalized operation element.
11
+ *
12
+ * The assembled document is a valid Swagger 2.0 specification containing
13
+ * only the single operation with its host, basePath, schemes, and
14
+ * referenced security definitions from the source document.
15
+ * @public
16
+ */
17
+ class OpenAPI2DocumentAssembler {
18
+ /**
19
+ * Assembles a standalone Swagger 2.0 document from a normalized operation.
20
+ */
21
+ assemble(operation, document) {
22
+ const entry = document.parseResult.api;
23
+ const method = toValue(operation.meta.get('http-method'));
24
+ const path = toValue(operation.meta.get('path'));
25
+ if (typeof method !== 'string' || typeof path !== 'string') {
26
+ throw new AssemblerError(`Operation is missing valid "http-method" or "path" metadata. Was it produced by OpenAPIOperationExtractor?`, {
27
+ uri: document.uri,
28
+ operationId: toValue(operation.operationId)
29
+ });
30
+ }
31
+ if (!isSwaggerElement(entry)) {
32
+ throw new AssemblerError(`Expected OpenAPI 2.0 document at "${document.uri}"`, {
33
+ uri: document.uri
34
+ });
35
+ }
36
+
37
+ // build Swagger 2.0 document
38
+ const swagger = new SwaggerElement({
39
+ swagger: entry.swagger
40
+ }, {
41
+ classes: ['api']
42
+ });
43
+ // prettier-ignore
44
+ {
45
+ if (isElement(entry.info)) swagger.info = entry.info;
46
+ if (isElement(entry.host)) swagger.host = entry.host;
47
+ if (isElement(entry.basePath)) swagger.basePath = entry.basePath;
48
+ if (isElement(entry.schemes)) swagger.schemes = entry.schemes;
49
+ if (isElement(entry.consumes)) swagger.consumes = entry.consumes;
50
+ if (isElement(entry.produces)) swagger.produces = entry.produces;
51
+ if (isElement(entry.tags)) swagger.tags = entry.tags;
52
+ if (isElement(entry.externalDocs)) swagger.externalDocs = entry.externalDocs;
53
+ }
54
+
55
+ // build paths with single operation
56
+ const pathItem = new PathItemElement();
57
+ const paths = new PathsElement();
58
+ pathItem.set(method, operation);
59
+ paths.set(path, pathItem);
60
+ swagger.paths = paths;
61
+
62
+ // include only referenced security definitions
63
+ const securityDefinitions = this.#extractReferencedSecurityDefinitions(operation, entry);
64
+ if (securityDefinitions.length > 0) {
65
+ swagger.securityDefinitions = securityDefinitions;
66
+ }
67
+
68
+ // wrap in ParseResultElement and return as OpenAPIDocument
69
+ const parseResult = new ParseResultElement([swagger]);
70
+ const operationIndex = new OpenAPIOperationIndex();
71
+ const operationId = toValue(operation.operationId);
72
+ if (typeof operationId === 'string' && operationId.length > 0) {
73
+ operationIndex.set(operationId, compile(['paths', path, method]));
74
+ }
75
+ return new OpenAPIDocument(document.uri, parseResult, operationIndex);
76
+ }
77
+
78
+ /**
79
+ * Extracts only the security definitions referenced by the operation's
80
+ * security requirements.
81
+ */
82
+ #extractReferencedSecurityDefinitions(operation, entry) {
83
+ const securityDefinitions = new SecurityDefinitionsElement();
84
+ if (!isArrayElement(operation.security)) return securityDefinitions;
85
+ if (!isSecurityDefinitionsElement(entry.securityDefinitions)) return securityDefinitions;
86
+
87
+ // collect referenced names of Security Definitions
88
+ const referencedNames = new Set();
89
+ for (const securityRequirement of operation.security) {
90
+ if (!isSecurityRequirementElement(securityRequirement)) continue;
91
+ securityRequirement.forEach((_value, keyElement) => {
92
+ referencedNames.add(toValue(keyElement));
93
+ });
94
+ }
95
+ if (referencedNames.size === 0) return securityDefinitions;
96
+ for (const name of referencedNames) {
97
+ const securityScheme = entry.securityDefinitions.get(name);
98
+ if (!isSecuritySchemeElement(securityScheme)) continue;
99
+ securityDefinitions.set(name, securityScheme);
100
+ }
101
+ return securityDefinitions;
102
+ }
103
+ }
104
+ export default OpenAPI2DocumentAssembler;