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

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 (154) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +20 -0
  4. package/README.md +163 -2
  5. package/dist/arazzo-runner.browser.js +113245 -0
  6. package/dist/arazzo-runner.browser.min.js +1 -0
  7. package/package.json +95 -4
  8. package/src/ArazzoRunner.cjs +122 -0
  9. package/src/ArazzoRunner.mjs +113 -0
  10. package/src/action/ActionResolver.cjs +160 -0
  11. package/src/action/ActionResolver.mjs +150 -0
  12. package/src/assembler/OpenAPI2DocumentAssembler.cjs +111 -0
  13. package/src/assembler/OpenAPI2DocumentAssembler.mjs +104 -0
  14. package/src/assembler/OpenAPI30DocumentAssembler.cjs +110 -0
  15. package/src/assembler/OpenAPI30DocumentAssembler.mjs +103 -0
  16. package/src/assembler/OpenAPI31DocumentAssembler.cjs +111 -0
  17. package/src/assembler/OpenAPI31DocumentAssembler.mjs +104 -0
  18. package/src/assembler/OpenAPIDocumentAssembler.cjs +58 -0
  19. package/src/assembler/OpenAPIDocumentAssembler.mjs +50 -0
  20. package/src/client/HTTPClient.cjs +5 -0
  21. package/src/client/HTTPClient.mjs +1 -0
  22. package/src/client/HTTPClientFetch.cjs +16 -0
  23. package/src/client/HTTPClientFetch.mjs +10 -0
  24. package/src/client/OpenAPIOperationRequest.cjs +5 -0
  25. package/src/client/OpenAPIOperationRequest.mjs +1 -0
  26. package/src/client/OpenAPIOperationResponse.cjs +42 -0
  27. package/src/client/OpenAPIOperationResponse.mjs +36 -0
  28. package/src/client/OpenAPIOperationResponseNormalizer.cjs +48 -0
  29. package/src/client/OpenAPIOperationResponseNormalizer.mjs +40 -0
  30. package/src/client/ParameterDelivery.cjs +119 -0
  31. package/src/client/ParameterDelivery.mjs +113 -0
  32. package/src/constants.cjs +9 -0
  33. package/src/constants.mjs +3 -0
  34. package/src/criterion/CriterionEvaluator.cjs +205 -0
  35. package/src/criterion/CriterionEvaluator.mjs +196 -0
  36. package/src/criterion/JSONPathCriterionEvaluator.cjs +47 -0
  37. package/src/criterion/JSONPathCriterionEvaluator.mjs +40 -0
  38. package/src/criterion/RegexCriterionEvaluator.cjs +67 -0
  39. package/src/criterion/RegexCriterionEvaluator.mjs +60 -0
  40. package/src/criterion/SimpleCriterionEvaluator.cjs +50 -0
  41. package/src/criterion/SimpleCriterionEvaluator.mjs +43 -0
  42. package/src/criterion/XPathCriterionEvaluator.cjs +117 -0
  43. package/src/criterion/XPathCriterionEvaluator.mjs +109 -0
  44. package/src/document/APIDocument.cjs +35 -0
  45. package/src/document/APIDocument.mjs +30 -0
  46. package/src/document/ArazzoDocument.cjs +81 -0
  47. package/src/document/ArazzoDocument.mjs +74 -0
  48. package/src/document/ArazzoSourceDescriptionIndex.cjs +26 -0
  49. package/src/document/ArazzoSourceDescriptionIndex.mjs +20 -0
  50. package/src/document/ArazzoStepIndex.cjs +25 -0
  51. package/src/document/ArazzoStepIndex.mjs +19 -0
  52. package/src/document/ArazzoWorkflowIndex.cjs +17 -0
  53. package/src/document/ArazzoWorkflowIndex.mjs +11 -0
  54. package/src/document/OpenAPIDocument.cjs +28 -0
  55. package/src/document/OpenAPIDocument.mjs +21 -0
  56. package/src/document/OpenAPIOperationIndex.cjs +24 -0
  57. package/src/document/OpenAPIOperationIndex.mjs +18 -0
  58. package/src/document/ParameterIdentity.cjs +93 -0
  59. package/src/document/ParameterIdentity.mjs +88 -0
  60. package/src/document/openapi-types.cjs +5 -0
  61. package/src/document/openapi-types.mjs +1 -0
  62. package/src/errors/ArazzoRunnerError.cjs +10 -0
  63. package/src/errors/ArazzoRunnerError.mjs +5 -0
  64. package/src/errors/AssemblerError.cjs +11 -0
  65. package/src/errors/AssemblerError.mjs +4 -0
  66. package/src/errors/ClientError.cjs +11 -0
  67. package/src/errors/ClientError.mjs +4 -0
  68. package/src/errors/CriterionError.cjs +11 -0
  69. package/src/errors/CriterionError.mjs +4 -0
  70. package/src/errors/ExecutionError.cjs +11 -0
  71. package/src/errors/ExecutionError.mjs +4 -0
  72. package/src/errors/ExtractionError.cjs +11 -0
  73. package/src/errors/ExtractionError.mjs +4 -0
  74. package/src/errors/InvalidEntryDocumentError.cjs +11 -0
  75. package/src/errors/InvalidEntryDocumentError.mjs +4 -0
  76. package/src/errors/NormalizationError.cjs +11 -0
  77. package/src/errors/NormalizationError.mjs +4 -0
  78. package/src/errors/ResolverError.cjs +11 -0
  79. package/src/errors/ResolverError.mjs +4 -0
  80. package/src/errors/RuntimeExpressionError.cjs +11 -0
  81. package/src/errors/RuntimeExpressionError.mjs +4 -0
  82. package/src/errors/UnmatchedProviderError.cjs +11 -0
  83. package/src/errors/UnmatchedProviderError.mjs +4 -0
  84. package/src/executor/ArazzoWorkflowLocatorNormalizer.cjs +147 -0
  85. package/src/executor/ArazzoWorkflowLocatorNormalizer.mjs +137 -0
  86. package/src/executor/OpenAPIOperationExecutor.cjs +458 -0
  87. package/src/executor/OpenAPIOperationExecutor.mjs +447 -0
  88. package/src/executor/OpenAPIOperationLocatorNormalizer.cjs +197 -0
  89. package/src/executor/OpenAPIOperationLocatorNormalizer.mjs +189 -0
  90. package/src/executor/SourceDescriptionsLocatorNormalizer.cjs +44 -0
  91. package/src/executor/SourceDescriptionsLocatorNormalizer.mjs +38 -0
  92. package/src/executor/StepExecutor.cjs +333 -0
  93. package/src/executor/StepExecutor.mjs +326 -0
  94. package/src/executor/StepRetryRunner.cjs +226 -0
  95. package/src/executor/StepRetryRunner.mjs +215 -0
  96. package/src/executor/StepTransitionInterpreter.cjs +159 -0
  97. package/src/executor/StepTransitionInterpreter.mjs +151 -0
  98. package/src/executor/WorkflowCallStack.cjs +116 -0
  99. package/src/executor/WorkflowCallStack.mjs +106 -0
  100. package/src/executor/WorkflowExecutor.cjs +1091 -0
  101. package/src/executor/WorkflowExecutor.mjs +1077 -0
  102. package/src/executor/abort.cjs +70 -0
  103. package/src/executor/abort.mjs +60 -0
  104. package/src/expression/RuntimeExpressionContext.cjs +5 -0
  105. package/src/expression/RuntimeExpressionContext.mjs +1 -0
  106. package/src/expression/RuntimeExpressionEvaluator.cjs +337 -0
  107. package/src/expression/RuntimeExpressionEvaluator.mjs +328 -0
  108. package/src/extractor/ArazzoStepExtractor.cjs +48 -0
  109. package/src/extractor/ArazzoStepExtractor.mjs +41 -0
  110. package/src/extractor/ArazzoWorkflowExtractor.cjs +50 -0
  111. package/src/extractor/ArazzoWorkflowExtractor.mjs +43 -0
  112. package/src/extractor/OpenAPIOperationExtractor.cjs +84 -0
  113. package/src/extractor/OpenAPIOperationExtractor.mjs +77 -0
  114. package/src/index.cjs +426 -0
  115. package/src/index.mjs +75 -0
  116. package/src/normalizer/ArazzoStepNormalizer.cjs +23 -0
  117. package/src/normalizer/ArazzoStepNormalizer.mjs +17 -0
  118. package/src/normalizer/ArazzoWorkflowNormalizer.cjs +214 -0
  119. package/src/normalizer/ArazzoWorkflowNormalizer.mjs +206 -0
  120. package/src/normalizer/OpenAPI2OperationNormalizer.cjs +128 -0
  121. package/src/normalizer/OpenAPI2OperationNormalizer.mjs +120 -0
  122. package/src/normalizer/OpenAPI30OperationNormalizer.cjs +129 -0
  123. package/src/normalizer/OpenAPI30OperationNormalizer.mjs +121 -0
  124. package/src/normalizer/OpenAPI31OperationNormalizer.cjs +131 -0
  125. package/src/normalizer/OpenAPI31OperationNormalizer.mjs +123 -0
  126. package/src/normalizer/OpenAPIOperationNormalizer.cjs +58 -0
  127. package/src/normalizer/OpenAPIOperationNormalizer.mjs +50 -0
  128. package/src/registry/DocumentRegistry.cjs +160 -0
  129. package/src/registry/DocumentRegistry.mjs +151 -0
  130. package/src/registry/providers/ArazzoDocumentRegistryProvider.cjs +154 -0
  131. package/src/registry/providers/ArazzoDocumentRegistryProvider.mjs +146 -0
  132. package/src/registry/providers/DocumentRegistryProvider.cjs +31 -0
  133. package/src/registry/providers/DocumentRegistryProvider.mjs +25 -0
  134. package/src/registry/providers/OpenAPIDocumentRegistryProvider.cjs +122 -0
  135. package/src/registry/providers/OpenAPIDocumentRegistryProvider.mjs +114 -0
  136. package/src/resolver/ArazzoValueResolver.cjs +42 -0
  137. package/src/resolver/ArazzoValueResolver.mjs +37 -0
  138. package/src/resolver/OpenAPIOperationParameterResolver.cjs +117 -0
  139. package/src/resolver/OpenAPIOperationParameterResolver.mjs +110 -0
  140. package/src/resolver/OutputResolver.cjs +71 -0
  141. package/src/resolver/OutputResolver.mjs +64 -0
  142. package/src/resolver/RequestBodyResolver.cjs +227 -0
  143. package/src/resolver/RequestBodyResolver.mjs +220 -0
  144. package/src/resolver/ResolverScope.cjs +5 -0
  145. package/src/resolver/ResolverScope.mjs +1 -0
  146. package/src/resolver/StepParameterResolver.cjs +22 -0
  147. package/src/resolver/StepParameterResolver.mjs +15 -0
  148. package/src/resolver/WorkflowParameterResolver.cjs +73 -0
  149. package/src/resolver/WorkflowParameterResolver.mjs +66 -0
  150. package/src/state/WorkflowExecutionState.cjs +99 -0
  151. package/src/state/WorkflowExecutionState.mjs +93 -0
  152. package/src/vendor/swagger-client.cjs +1 -0
  153. package/src/vendor/swagger-client.mjs +1 -0
  154. package/types/runner.d.ts +2410 -0
package/package.json CHANGED
@@ -1,6 +1,97 @@
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.11",
4
+ "description": "Runner for Arazzo Workflows.",
5
+ "keywords": [
6
+ "arazzo",
7
+ "arazzo-specification",
8
+ "runner",
9
+ "execute",
10
+ "executor",
11
+ "workflow",
12
+ "workflows",
13
+ "api",
14
+ "api-workflow"
15
+ ],
16
+ "publishConfig": {
17
+ "access": "public",
18
+ "registry": "https://registry.npmjs.org",
19
+ "provenance": true,
20
+ "tag": "latest",
21
+ "timeout": 60000
22
+ },
23
+ "type": "module",
24
+ "sideEffects": false,
25
+ "engines": {
26
+ "node": ">=20.10.0"
27
+ },
28
+ "unpkg": "./dist/arazzo-runner.browser.min.js",
29
+ "main": "./src/index.cjs",
30
+ "exports": {
31
+ "types": "./types/runner.d.ts",
32
+ "import": "./src/index.mjs",
33
+ "require": "./src/index.cjs"
34
+ },
35
+ "types": "./types/runner.d.ts",
36
+ "scripts": {
37
+ "build": "npm run clean && npm run build:es && run-p --max-parallel ${CPU_CORES:-2} typescript:declaration build:cjs build:umd:browser",
38
+ "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'",
39
+ "build:cjs": "cross-env BABEL_ENV=cjs babel src --out-dir src --extensions '.ts' --out-file-extension '.cjs' --root-mode 'upward'",
40
+ "build:umd:browser": "cross-env BABEL_ENV=browser webpack --config config/webpack/browser.config.js --progress",
41
+ "build:swagger-client": "webpack --config config/webpack/swagger-client.config.js --progress",
42
+ "lint": "eslint ./",
43
+ "lint:fix": "eslint ./ --fix",
44
+ "clean": "rimraf --glob 'src/**/*.mjs' 'src/**/*.cjs' 'test/**/*.mjs' ./dist ./types",
45
+ "typescript:check-types": "tsc --noEmit",
46
+ "typescript:declaration": "tsc -p tsconfig.declaration.json && api-extractor run -l -c ./config/api-extractor/api-extractor.json",
47
+ "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",
48
+ "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",
49
+ "prepack": "copyfiles -u 2 ../../LICENSE . && copyfiles -u 2 ../../NOTICE .",
50
+ "postpack": "rimraf NOTICE LICENSE"
51
+ },
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "git+https://github.com/usearazzo/arazzo-toolkit.git"
55
+ },
56
+ "author": "Vladimir Gorej <vladimir.gorej@gmail.com>",
57
+ "license": "Apache-2.0",
58
+ "dependencies": {
59
+ "@babel/runtime-corejs3": "^8.0.7",
60
+ "@speclynx/apidom-core": "^6.1.0",
61
+ "@speclynx/apidom-datamodel": "^6.1.0",
62
+ "@speclynx/apidom-error": "^6.1.0",
63
+ "@speclynx/apidom-json-pointer": "^6.1.0",
64
+ "@speclynx/apidom-ns-arazzo-1": "^6.1.0",
65
+ "@speclynx/apidom-ns-openapi-2": "^6.1.0",
66
+ "@speclynx/apidom-ns-openapi-3-0": "^6.1.0",
67
+ "@speclynx/apidom-ns-openapi-3-1": "^6.1.0",
68
+ "@speclynx/apidom-reference": "^6.1.0",
69
+ "@speclynx/apidom-traverse": "^6.1.0",
70
+ "@swaggerexpert/arazzo-criterion": "^1.0.1",
71
+ "@swaggerexpert/arazzo-runtime-expression": "^3.3.0",
72
+ "@swaggerexpert/json-pointer": "^3.0.2",
73
+ "@swaggerexpert/jsonpath": "^4.0.5",
74
+ "@swaggerexpert/media-types": "^1.0.1",
75
+ "@usearazzo/parser": "1.0.1-alpha.11",
76
+ "@usearazzo/resolver": "1.0.1-alpha.11",
77
+ "@xmldom/xmldom": "^0.9.12",
78
+ "fontoxpath": "^3.34.0",
79
+ "ramda": "^0.32.0",
80
+ "ramda-adjunct": "^6.1.0",
81
+ "type-fest": "^5.10.0"
82
+ },
83
+ "files": [
84
+ "src/**/*.mjs",
85
+ "src/**/*.cjs",
86
+ "dist/",
87
+ "types/runner.d.ts",
88
+ "LICENSE",
89
+ "NOTICE",
90
+ "README.md",
91
+ "CHANGELOG.md"
92
+ ],
93
+ "devDependencies": {
94
+ "swagger-client": "^3.38.4"
95
+ },
96
+ "gitHead": "3cfffaf0045eff162d73df30f840c35cc593af77"
97
+ }
@@ -0,0 +1,122 @@
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 _DocumentRegistry = _interopRequireDefault(require("./registry/DocumentRegistry.cjs"));
9
+ var _OpenAPIOperationExecutor = _interopRequireDefault(require("./executor/OpenAPIOperationExecutor.cjs"));
10
+ var _StepExecutor = _interopRequireDefault(require("./executor/StepExecutor.cjs"));
11
+ var _WorkflowExecutor = _interopRequireDefault(require("./executor/WorkflowExecutor.cjs"));
12
+ var _InvalidEntryDocumentError = _interopRequireDefault(require("./errors/InvalidEntryDocumentError.cjs"));
13
+ /**
14
+ * Options for {@link ArazzoRunner.load}.
15
+ *
16
+ * Every option is a seam of a building block the runner wires: `registry` is
17
+ * the {@link DocumentRegistry} the documents load into (a fresh one with the
18
+ * default providers when omitted), `httpClient` and `requestInterceptor` go to
19
+ * the {@link OpenAPIOperationExecutor}, and the rest go to the
20
+ * {@link WorkflowExecutor}.
21
+ * @public
22
+ */
23
+
24
+ /**
25
+ * Options for the ArazzoRunner constructor.
26
+ * @public
27
+ */
28
+
29
+ /**
30
+ * Runs the workflows of one Arazzo document.
31
+ *
32
+ * A thin facade over the building blocks: it wires a {@link DocumentRegistry},
33
+ * an {@link OpenAPIOperationExecutor}, a {@link StepExecutor} and a
34
+ * {@link WorkflowExecutor} with their defaults, so running a workflow takes a
35
+ * `load` and an `execute`. The building blocks stay public for callers that
36
+ * need to compose them differently.
37
+ * @public
38
+ */
39
+ class ArazzoRunner {
40
+ document;
41
+ registry;
42
+ #executor;
43
+
44
+ /**
45
+ * Loads the entry Arazzo document at `uri` (a file system path or URL) and
46
+ * returns a runner bound to it.
47
+ *
48
+ * @throws UnmatchedProviderError - When no provider can load the document
49
+ * @throws InvalidEntryDocumentError - When the document is not an Arazzo
50
+ * document, or the given registry already backs another entry document
51
+ */
52
+ static async load(uri, options = {}) {
53
+ const {
54
+ registry = new _DocumentRegistry.default(),
55
+ ...rest
56
+ } = options;
57
+ // acquiring a second entry would pin it for good and, through the LRU
58
+ // order, could displace the first as the registry's entry; a registry that
59
+ // already backs one only looks the document up.
60
+ const entry = registry.entryDocument ?? (await registry.acquireEntryDocument(uri));
61
+ const document = await registry.acquire(uri);
62
+ if (document !== entry) {
63
+ throw new _InvalidEntryDocumentError.default(`Document at "${uri}" is not the entry document of the given registry`, {
64
+ uri
65
+ });
66
+ }
67
+ return new ArazzoRunner({
68
+ ...rest,
69
+ document: entry,
70
+ registry
71
+ });
72
+ }
73
+
74
+ /**
75
+ * Binds a runner to an entry document the caller already acquired.
76
+ *
77
+ * @throws InvalidEntryDocumentError - When `document` is not the entry document of `registry`
78
+ */
79
+ constructor(options) {
80
+ const {
81
+ document,
82
+ registry,
83
+ httpClient,
84
+ requestInterceptor,
85
+ ...workflowExecutorOptions
86
+ } = options;
87
+
88
+ // a registry pins every entry document it acquires but reports only the
89
+ // first as its entry, so one registry serves one entry document.
90
+ if (registry.entryDocument !== document) {
91
+ throw new _InvalidEntryDocumentError.default(`Document at "${document.uri}" is not the entry document of the given registry`, {
92
+ uri: document.uri
93
+ });
94
+ }
95
+ const operationExecutor = new _OpenAPIOperationExecutor.default({
96
+ httpClient,
97
+ requestInterceptor
98
+ });
99
+ const stepExecutor = new _StepExecutor.default({
100
+ document,
101
+ registry,
102
+ operationExecutor
103
+ });
104
+ this.document = document;
105
+ this.registry = registry;
106
+ this.#executor = new _WorkflowExecutor.default({
107
+ ...workflowExecutorOptions,
108
+ document,
109
+ registry,
110
+ stepExecutor
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Runs the named workflow to completion, returning its outcome; see
116
+ * {@link WorkflowExecutor.execute}.
117
+ */
118
+ execute(workflowId, options = {}) {
119
+ return this.#executor.execute(workflowId, options);
120
+ }
121
+ }
122
+ var _default = exports.default = ArazzoRunner;
@@ -0,0 +1,113 @@
1
+ import DocumentRegistry from "./registry/DocumentRegistry.mjs";
2
+ import OpenAPIOperationExecutor from "./executor/OpenAPIOperationExecutor.mjs";
3
+ import StepExecutor from "./executor/StepExecutor.mjs";
4
+ import WorkflowExecutor from "./executor/WorkflowExecutor.mjs";
5
+ import InvalidEntryDocumentError from "./errors/InvalidEntryDocumentError.mjs";
6
+ /**
7
+ * Options for {@link ArazzoRunner.load}.
8
+ *
9
+ * Every option is a seam of a building block the runner wires: `registry` is
10
+ * the {@link DocumentRegistry} the documents load into (a fresh one with the
11
+ * default providers when omitted), `httpClient` and `requestInterceptor` go to
12
+ * the {@link OpenAPIOperationExecutor}, and the rest go to the
13
+ * {@link WorkflowExecutor}.
14
+ * @public
15
+ */
16
+ /**
17
+ * Options for the ArazzoRunner constructor.
18
+ * @public
19
+ */
20
+ /**
21
+ * Runs the workflows of one Arazzo document.
22
+ *
23
+ * A thin facade over the building blocks: it wires a {@link DocumentRegistry},
24
+ * an {@link OpenAPIOperationExecutor}, a {@link StepExecutor} and a
25
+ * {@link WorkflowExecutor} with their defaults, so running a workflow takes a
26
+ * `load` and an `execute`. The building blocks stay public for callers that
27
+ * need to compose them differently.
28
+ * @public
29
+ */
30
+ class ArazzoRunner {
31
+ document;
32
+ registry;
33
+ #executor;
34
+
35
+ /**
36
+ * Loads the entry Arazzo document at `uri` (a file system path or URL) and
37
+ * returns a runner bound to it.
38
+ *
39
+ * @throws UnmatchedProviderError - When no provider can load the document
40
+ * @throws InvalidEntryDocumentError - When the document is not an Arazzo
41
+ * document, or the given registry already backs another entry document
42
+ */
43
+ static async load(uri, options = {}) {
44
+ const {
45
+ registry = new DocumentRegistry(),
46
+ ...rest
47
+ } = options;
48
+ // acquiring a second entry would pin it for good and, through the LRU
49
+ // order, could displace the first as the registry's entry; a registry that
50
+ // already backs one only looks the document up.
51
+ const entry = registry.entryDocument ?? (await registry.acquireEntryDocument(uri));
52
+ const document = await registry.acquire(uri);
53
+ if (document !== entry) {
54
+ throw new InvalidEntryDocumentError(`Document at "${uri}" is not the entry document of the given registry`, {
55
+ uri
56
+ });
57
+ }
58
+ return new ArazzoRunner({
59
+ ...rest,
60
+ document: entry,
61
+ registry
62
+ });
63
+ }
64
+
65
+ /**
66
+ * Binds a runner to an entry document the caller already acquired.
67
+ *
68
+ * @throws InvalidEntryDocumentError - When `document` is not the entry document of `registry`
69
+ */
70
+ constructor(options) {
71
+ const {
72
+ document,
73
+ registry,
74
+ httpClient,
75
+ requestInterceptor,
76
+ ...workflowExecutorOptions
77
+ } = options;
78
+
79
+ // a registry pins every entry document it acquires but reports only the
80
+ // first as its entry, so one registry serves one entry document.
81
+ if (registry.entryDocument !== document) {
82
+ throw new InvalidEntryDocumentError(`Document at "${document.uri}" is not the entry document of the given registry`, {
83
+ uri: document.uri
84
+ });
85
+ }
86
+ const operationExecutor = new OpenAPIOperationExecutor({
87
+ httpClient,
88
+ requestInterceptor
89
+ });
90
+ const stepExecutor = new StepExecutor({
91
+ document,
92
+ registry,
93
+ operationExecutor
94
+ });
95
+ this.document = document;
96
+ this.registry = registry;
97
+ this.#executor = new WorkflowExecutor({
98
+ ...workflowExecutorOptions,
99
+ document,
100
+ registry,
101
+ stepExecutor
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Runs the named workflow to completion, returning its outcome; see
107
+ * {@link WorkflowExecutor.execute}.
108
+ */
109
+ execute(workflowId, options = {}) {
110
+ return this.#executor.execute(workflowId, options);
111
+ }
112
+ }
113
+ export default ArazzoRunner;
@@ -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;