@usearazzo/runner 0.0.0-stage → 1.0.1-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +777 -2
- package/dist/arazzo-runner.browser.js +113254 -0
- package/dist/arazzo-runner.browser.min.js +1 -0
- package/package.json +91 -4
- package/src/action/ActionResolver.cjs +160 -0
- package/src/action/ActionResolver.mjs +150 -0
- package/src/assembler/OpenAPI2DocumentAssembler.cjs +111 -0
- package/src/assembler/OpenAPI2DocumentAssembler.mjs +104 -0
- package/src/assembler/OpenAPI30DocumentAssembler.cjs +110 -0
- package/src/assembler/OpenAPI30DocumentAssembler.mjs +103 -0
- package/src/assembler/OpenAPI31DocumentAssembler.cjs +111 -0
- package/src/assembler/OpenAPI31DocumentAssembler.mjs +104 -0
- package/src/assembler/OpenAPIDocumentAssembler.cjs +58 -0
- package/src/assembler/OpenAPIDocumentAssembler.mjs +50 -0
- package/src/client/HTTPClient.cjs +5 -0
- package/src/client/HTTPClient.mjs +1 -0
- package/src/client/HTTPClientFetch.cjs +16 -0
- package/src/client/HTTPClientFetch.mjs +10 -0
- package/src/client/OpenAPIOperationRequest.cjs +5 -0
- package/src/client/OpenAPIOperationRequest.mjs +1 -0
- package/src/client/OpenAPIOperationResponse.cjs +42 -0
- package/src/client/OpenAPIOperationResponse.mjs +36 -0
- package/src/client/OpenAPIOperationResponseNormalizer.cjs +48 -0
- package/src/client/OpenAPIOperationResponseNormalizer.mjs +40 -0
- package/src/client/ParameterDelivery.cjs +119 -0
- package/src/client/ParameterDelivery.mjs +113 -0
- package/src/constants.cjs +9 -0
- package/src/constants.mjs +3 -0
- package/src/criterion/CriterionEvaluator.cjs +205 -0
- package/src/criterion/CriterionEvaluator.mjs +196 -0
- package/src/criterion/JSONPathCriterionEvaluator.cjs +47 -0
- package/src/criterion/JSONPathCriterionEvaluator.mjs +40 -0
- package/src/criterion/RegexCriterionEvaluator.cjs +67 -0
- package/src/criterion/RegexCriterionEvaluator.mjs +60 -0
- package/src/criterion/SimpleCriterionEvaluator.cjs +50 -0
- package/src/criterion/SimpleCriterionEvaluator.mjs +43 -0
- package/src/criterion/XPathCriterionEvaluator.cjs +117 -0
- package/src/criterion/XPathCriterionEvaluator.mjs +109 -0
- package/src/document/APIDocument.cjs +35 -0
- package/src/document/APIDocument.mjs +30 -0
- package/src/document/ArazzoDocument.cjs +81 -0
- package/src/document/ArazzoDocument.mjs +74 -0
- package/src/document/ArazzoSourceDescriptionIndex.cjs +26 -0
- package/src/document/ArazzoSourceDescriptionIndex.mjs +20 -0
- package/src/document/ArazzoStepIndex.cjs +25 -0
- package/src/document/ArazzoStepIndex.mjs +19 -0
- package/src/document/ArazzoWorkflowIndex.cjs +17 -0
- package/src/document/ArazzoWorkflowIndex.mjs +11 -0
- package/src/document/OpenAPIDocument.cjs +28 -0
- package/src/document/OpenAPIDocument.mjs +21 -0
- package/src/document/OpenAPIOperationIndex.cjs +24 -0
- package/src/document/OpenAPIOperationIndex.mjs +18 -0
- package/src/document/ParameterIdentity.cjs +93 -0
- package/src/document/ParameterIdentity.mjs +88 -0
- package/src/document/openapi-types.cjs +5 -0
- package/src/document/openapi-types.mjs +1 -0
- package/src/errors/ArazzoRunnerError.cjs +10 -0
- package/src/errors/ArazzoRunnerError.mjs +5 -0
- package/src/errors/AssemblerError.cjs +11 -0
- package/src/errors/AssemblerError.mjs +4 -0
- package/src/errors/ClientError.cjs +11 -0
- package/src/errors/ClientError.mjs +4 -0
- package/src/errors/CriterionError.cjs +11 -0
- package/src/errors/CriterionError.mjs +4 -0
- package/src/errors/ExecutionError.cjs +11 -0
- package/src/errors/ExecutionError.mjs +4 -0
- package/src/errors/ExtractionError.cjs +11 -0
- package/src/errors/ExtractionError.mjs +4 -0
- package/src/errors/InvalidEntryDocumentError.cjs +11 -0
- package/src/errors/InvalidEntryDocumentError.mjs +4 -0
- package/src/errors/NormalizationError.cjs +11 -0
- package/src/errors/NormalizationError.mjs +4 -0
- package/src/errors/ResolverError.cjs +11 -0
- package/src/errors/ResolverError.mjs +4 -0
- package/src/errors/RuntimeExpressionError.cjs +11 -0
- package/src/errors/RuntimeExpressionError.mjs +4 -0
- package/src/errors/UnmatchedProviderError.cjs +11 -0
- package/src/errors/UnmatchedProviderError.mjs +4 -0
- package/src/executor/ArazzoWorkflowLocatorNormalizer.cjs +147 -0
- package/src/executor/ArazzoWorkflowLocatorNormalizer.mjs +137 -0
- package/src/executor/OpenAPIOperationExecutor.cjs +458 -0
- package/src/executor/OpenAPIOperationExecutor.mjs +447 -0
- package/src/executor/OpenAPIOperationLocatorNormalizer.cjs +197 -0
- package/src/executor/OpenAPIOperationLocatorNormalizer.mjs +189 -0
- package/src/executor/SourceDescriptionsLocatorNormalizer.cjs +44 -0
- package/src/executor/SourceDescriptionsLocatorNormalizer.mjs +38 -0
- package/src/executor/StepExecutor.cjs +333 -0
- package/src/executor/StepExecutor.mjs +326 -0
- package/src/executor/StepRetryRunner.cjs +226 -0
- package/src/executor/StepRetryRunner.mjs +215 -0
- package/src/executor/StepTransitionInterpreter.cjs +159 -0
- package/src/executor/StepTransitionInterpreter.mjs +151 -0
- package/src/executor/WorkflowCallStack.cjs +116 -0
- package/src/executor/WorkflowCallStack.mjs +106 -0
- package/src/executor/WorkflowExecutor.cjs +1091 -0
- package/src/executor/WorkflowExecutor.mjs +1077 -0
- package/src/executor/abort.cjs +70 -0
- package/src/executor/abort.mjs +60 -0
- package/src/expression/RuntimeExpressionContext.cjs +5 -0
- package/src/expression/RuntimeExpressionContext.mjs +1 -0
- package/src/expression/RuntimeExpressionEvaluator.cjs +337 -0
- package/src/expression/RuntimeExpressionEvaluator.mjs +328 -0
- package/src/extractor/ArazzoStepExtractor.cjs +48 -0
- package/src/extractor/ArazzoStepExtractor.mjs +41 -0
- package/src/extractor/ArazzoWorkflowExtractor.cjs +50 -0
- package/src/extractor/ArazzoWorkflowExtractor.mjs +43 -0
- package/src/extractor/OpenAPIOperationExtractor.cjs +84 -0
- package/src/extractor/OpenAPIOperationExtractor.mjs +77 -0
- package/src/index.cjs +419 -0
- package/src/index.mjs +73 -0
- package/src/normalizer/ArazzoStepNormalizer.cjs +23 -0
- package/src/normalizer/ArazzoStepNormalizer.mjs +17 -0
- package/src/normalizer/ArazzoWorkflowNormalizer.cjs +214 -0
- package/src/normalizer/ArazzoWorkflowNormalizer.mjs +206 -0
- package/src/normalizer/OpenAPI2OperationNormalizer.cjs +128 -0
- package/src/normalizer/OpenAPI2OperationNormalizer.mjs +120 -0
- package/src/normalizer/OpenAPI30OperationNormalizer.cjs +129 -0
- package/src/normalizer/OpenAPI30OperationNormalizer.mjs +121 -0
- package/src/normalizer/OpenAPI31OperationNormalizer.cjs +131 -0
- package/src/normalizer/OpenAPI31OperationNormalizer.mjs +123 -0
- package/src/normalizer/OpenAPIOperationNormalizer.cjs +58 -0
- package/src/normalizer/OpenAPIOperationNormalizer.mjs +50 -0
- package/src/registry/DocumentRegistry.cjs +160 -0
- package/src/registry/DocumentRegistry.mjs +151 -0
- package/src/registry/providers/ArazzoDocumentRegistryProvider.cjs +154 -0
- package/src/registry/providers/ArazzoDocumentRegistryProvider.mjs +146 -0
- package/src/registry/providers/DocumentRegistryProvider.cjs +31 -0
- package/src/registry/providers/DocumentRegistryProvider.mjs +25 -0
- package/src/registry/providers/OpenAPIDocumentRegistryProvider.cjs +122 -0
- package/src/registry/providers/OpenAPIDocumentRegistryProvider.mjs +114 -0
- package/src/resolver/ArazzoValueResolver.cjs +42 -0
- package/src/resolver/ArazzoValueResolver.mjs +37 -0
- package/src/resolver/OpenAPIOperationParameterResolver.cjs +117 -0
- package/src/resolver/OpenAPIOperationParameterResolver.mjs +110 -0
- package/src/resolver/OutputResolver.cjs +71 -0
- package/src/resolver/OutputResolver.mjs +64 -0
- package/src/resolver/RequestBodyResolver.cjs +227 -0
- package/src/resolver/RequestBodyResolver.mjs +220 -0
- package/src/resolver/ResolverScope.cjs +5 -0
- package/src/resolver/ResolverScope.mjs +1 -0
- package/src/resolver/StepParameterResolver.cjs +22 -0
- package/src/resolver/StepParameterResolver.mjs +15 -0
- package/src/resolver/WorkflowParameterResolver.cjs +73 -0
- package/src/resolver/WorkflowParameterResolver.mjs +66 -0
- package/src/state/WorkflowExecutionState.cjs +99 -0
- package/src/state/WorkflowExecutionState.mjs +93 -0
- package/src/vendor/swagger-client.cjs +1 -0
- package/src/vendor/swagger-client.mjs +1 -0
- package/types/runner.d.ts +2341 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
|
|
4
|
+
var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.providerOptionsOverride = exports.default = void 0;
|
|
9
|
+
var _parser = require("@usearazzo/parser");
|
|
10
|
+
var _resolver = require("@usearazzo/resolver");
|
|
11
|
+
var _apidomDatamodel = require("@speclynx/apidom-datamodel");
|
|
12
|
+
var _empty = require("@speclynx/apidom-reference/configuration/empty");
|
|
13
|
+
var _apidomTraverse = require("@speclynx/apidom-traverse");
|
|
14
|
+
var _apidomCore = require("@speclynx/apidom-core");
|
|
15
|
+
var constants = _interopRequireWildcard(require("../../constants.cjs"));
|
|
16
|
+
var _OpenAPIDocument = _interopRequireDefault(require("../../document/OpenAPIDocument.cjs"));
|
|
17
|
+
var _DocumentRegistryProvider = _interopRequireWildcard(require("./DocumentRegistryProvider.cjs"));
|
|
18
|
+
var _OpenAPIOperationIndex = _interopRequireDefault(require("../../document/OpenAPIOperationIndex.cjs"));
|
|
19
|
+
/**
|
|
20
|
+
* Options for loading an OpenAPI document.
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Default options for loading an OpenAPI document.
|
|
26
|
+
*/
|
|
27
|
+
const providerOptionsOverride = exports.providerOptionsOverride = {
|
|
28
|
+
resolve: {
|
|
29
|
+
resolverOpts: {
|
|
30
|
+
cache: {
|
|
31
|
+
maxEntries: constants.MAX_HTTP_CACHE_ENTRIES,
|
|
32
|
+
maxStaleAge: constants.MAX_HTTP_CACHE_STALE_AGE
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
dereference: {
|
|
37
|
+
immutable: false,
|
|
38
|
+
circular: 'replace',
|
|
39
|
+
circularReplacer: _DocumentRegistryProvider.circularReplacer
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Provides OpenAPIDocument instances for the DocumentRegistry.
|
|
45
|
+
*
|
|
46
|
+
* Parses, dereferences, and builds an OperationIndex for OpenAPI documents.
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
class OpenAPIDocumentRegistryProvider extends _DocumentRegistryProvider.default {
|
|
50
|
+
#options;
|
|
51
|
+
constructor(options = {}) {
|
|
52
|
+
super();
|
|
53
|
+
this.#options = (0, _empty.mergeOptions)(providerOptionsOverride, options);
|
|
54
|
+
}
|
|
55
|
+
async canProvide(uri) {
|
|
56
|
+
try {
|
|
57
|
+
const options = this.#buildParseOptions();
|
|
58
|
+
const data = await (0, _empty.readFile)(uri, options);
|
|
59
|
+
const file = new _empty.File({
|
|
60
|
+
uri,
|
|
61
|
+
data
|
|
62
|
+
});
|
|
63
|
+
const parsers = options.parse.parsers.filter(p => p.name.startsWith('openapi'));
|
|
64
|
+
for (const parser of parsers) {
|
|
65
|
+
if (await parser.canParse(file)) return true;
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (error instanceof _empty.UnmatchedResolverError) return false;
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Loads an OpenAPI document from a URI and produces an OpenAPIDocument.
|
|
76
|
+
*/
|
|
77
|
+
async provide(uri) {
|
|
78
|
+
const parseResult = await (0, _parser.parseOpenAPI)(uri, this.#buildParseOptions());
|
|
79
|
+
const operationIndex = await this.#buildOperationIndex(parseResult);
|
|
80
|
+
return new _OpenAPIDocument.default(uri, parseResult, operationIndex);
|
|
81
|
+
}
|
|
82
|
+
async #buildOperationIndex(parseResult) {
|
|
83
|
+
const index = new _OpenAPIOperationIndex.default();
|
|
84
|
+
const dereferenceOptions = this.#buildDereferenceOptions(parseResult);
|
|
85
|
+
const apiDereferenced = await (0, _apidomTraverse.traverseAsync)(parseResult.api, {
|
|
86
|
+
async PathItemElement(path) {
|
|
87
|
+
const pathItem = path.node;
|
|
88
|
+
if (!pathItem.hasMetaProperty('path')) return path.skip();
|
|
89
|
+
if (!(0, _apidomDatamodel.isStringElement)(pathItem.$ref)) return;
|
|
90
|
+
const pathItemDereferenced = await (0, _resolver.dereferenceOpenAPIElement)(pathItem, dereferenceOptions);
|
|
91
|
+
path.replaceWith(pathItemDereferenced);
|
|
92
|
+
},
|
|
93
|
+
OperationElement(path) {
|
|
94
|
+
const operation = path.node;
|
|
95
|
+
const operationId = (0, _apidomCore.toValue)(operation.operationId);
|
|
96
|
+
if (typeof operationId !== 'string') return path.skip();
|
|
97
|
+
if (operationId === '') return path.skip();
|
|
98
|
+
index.set(operationId, path.formatPath('jsonpointer'));
|
|
99
|
+
path.skip();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
parseResult.replaceResult(apiDereferenced);
|
|
103
|
+
return index;
|
|
104
|
+
}
|
|
105
|
+
#buildParseOptions() {
|
|
106
|
+
return (0, _empty.mergeOptions)(_parser.defaultParseOpenAPIOptions, this.#options);
|
|
107
|
+
}
|
|
108
|
+
#buildDereferenceOptions(parseResult) {
|
|
109
|
+
let options = (0, _empty.mergeOptions)(_resolver.defaultDereferenceOpenAPIOptions, this.#options);
|
|
110
|
+
if (parseResult) {
|
|
111
|
+
options = (0, _empty.mergeOptions)(options, {
|
|
112
|
+
dereference: {
|
|
113
|
+
strategyOpts: {
|
|
114
|
+
parseResult
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return options;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
var _default = exports.default = OpenAPIDocumentRegistryProvider;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { parseOpenAPI, defaultParseOpenAPIOptions } from '@usearazzo/parser';
|
|
2
|
+
import { dereferenceOpenAPIElement, defaultDereferenceOpenAPIOptions } from '@usearazzo/resolver';
|
|
3
|
+
import { isStringElement } from '@speclynx/apidom-datamodel';
|
|
4
|
+
import { readFile, File, mergeOptions } from '@speclynx/apidom-reference/configuration/empty';
|
|
5
|
+
import { UnmatchedResolverError } from '@speclynx/apidom-reference/configuration/empty';
|
|
6
|
+
import { traverseAsync } from '@speclynx/apidom-traverse';
|
|
7
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
8
|
+
import * as constants from "../../constants.mjs";
|
|
9
|
+
import OpenAPIDocument from "../../document/OpenAPIDocument.mjs";
|
|
10
|
+
import DocumentRegistryProvider, { circularReplacer } from "./DocumentRegistryProvider.mjs";
|
|
11
|
+
import OpenAPIOperationIndex from "../../document/OpenAPIOperationIndex.mjs";
|
|
12
|
+
/**
|
|
13
|
+
* Options for loading an OpenAPI document.
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Default options for loading an OpenAPI document.
|
|
18
|
+
*/
|
|
19
|
+
export const providerOptionsOverride = {
|
|
20
|
+
resolve: {
|
|
21
|
+
resolverOpts: {
|
|
22
|
+
cache: {
|
|
23
|
+
maxEntries: constants.MAX_HTTP_CACHE_ENTRIES,
|
|
24
|
+
maxStaleAge: constants.MAX_HTTP_CACHE_STALE_AGE
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
dereference: {
|
|
29
|
+
immutable: false,
|
|
30
|
+
circular: 'replace',
|
|
31
|
+
circularReplacer
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Provides OpenAPIDocument instances for the DocumentRegistry.
|
|
37
|
+
*
|
|
38
|
+
* Parses, dereferences, and builds an OperationIndex for OpenAPI documents.
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
class OpenAPIDocumentRegistryProvider extends DocumentRegistryProvider {
|
|
42
|
+
#options;
|
|
43
|
+
constructor(options = {}) {
|
|
44
|
+
super();
|
|
45
|
+
this.#options = mergeOptions(providerOptionsOverride, options);
|
|
46
|
+
}
|
|
47
|
+
async canProvide(uri) {
|
|
48
|
+
try {
|
|
49
|
+
const options = this.#buildParseOptions();
|
|
50
|
+
const data = await readFile(uri, options);
|
|
51
|
+
const file = new File({
|
|
52
|
+
uri,
|
|
53
|
+
data
|
|
54
|
+
});
|
|
55
|
+
const parsers = options.parse.parsers.filter(p => p.name.startsWith('openapi'));
|
|
56
|
+
for (const parser of parsers) {
|
|
57
|
+
if (await parser.canParse(file)) return true;
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (error instanceof UnmatchedResolverError) return false;
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Loads an OpenAPI document from a URI and produces an OpenAPIDocument.
|
|
68
|
+
*/
|
|
69
|
+
async provide(uri) {
|
|
70
|
+
const parseResult = await parseOpenAPI(uri, this.#buildParseOptions());
|
|
71
|
+
const operationIndex = await this.#buildOperationIndex(parseResult);
|
|
72
|
+
return new OpenAPIDocument(uri, parseResult, operationIndex);
|
|
73
|
+
}
|
|
74
|
+
async #buildOperationIndex(parseResult) {
|
|
75
|
+
const index = new OpenAPIOperationIndex();
|
|
76
|
+
const dereferenceOptions = this.#buildDereferenceOptions(parseResult);
|
|
77
|
+
const apiDereferenced = await traverseAsync(parseResult.api, {
|
|
78
|
+
async PathItemElement(path) {
|
|
79
|
+
const pathItem = path.node;
|
|
80
|
+
if (!pathItem.hasMetaProperty('path')) return path.skip();
|
|
81
|
+
if (!isStringElement(pathItem.$ref)) return;
|
|
82
|
+
const pathItemDereferenced = await dereferenceOpenAPIElement(pathItem, dereferenceOptions);
|
|
83
|
+
path.replaceWith(pathItemDereferenced);
|
|
84
|
+
},
|
|
85
|
+
OperationElement(path) {
|
|
86
|
+
const operation = path.node;
|
|
87
|
+
const operationId = toValue(operation.operationId);
|
|
88
|
+
if (typeof operationId !== 'string') return path.skip();
|
|
89
|
+
if (operationId === '') return path.skip();
|
|
90
|
+
index.set(operationId, path.formatPath('jsonpointer'));
|
|
91
|
+
path.skip();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
parseResult.replaceResult(apiDereferenced);
|
|
95
|
+
return index;
|
|
96
|
+
}
|
|
97
|
+
#buildParseOptions() {
|
|
98
|
+
return mergeOptions(defaultParseOpenAPIOptions, this.#options);
|
|
99
|
+
}
|
|
100
|
+
#buildDereferenceOptions(parseResult) {
|
|
101
|
+
let options = mergeOptions(defaultDereferenceOpenAPIOptions, this.#options);
|
|
102
|
+
if (parseResult) {
|
|
103
|
+
options = mergeOptions(options, {
|
|
104
|
+
dereference: {
|
|
105
|
+
strategyOpts: {
|
|
106
|
+
parseResult
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return options;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export default OpenAPIDocumentRegistryProvider;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _apidomCore = require("@speclynx/apidom-core");
|
|
8
|
+
var _arazzoRuntimeExpression = require("@swaggerexpert/arazzo-runtime-expression");
|
|
9
|
+
/**
|
|
10
|
+
* Resolves a runtime expression to its value.
|
|
11
|
+
*
|
|
12
|
+
* Bridged to a lenient runtime expression evaluator
|
|
13
|
+
* (`(expression) => runtimeExpressionEvaluator.evaluate(expression)`), so an
|
|
14
|
+
* unresolvable reference yields `undefined` rather than throwing.
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Base of every resolver of authored Arazzo values — the single home of the
|
|
20
|
+
* literal-vs-expression rule they all share.
|
|
21
|
+
*
|
|
22
|
+
* Per Arazzo 1.0.1, an authored value (a parameter's `value`, an `outputs`
|
|
23
|
+
* entry, a `requestBody` replacement value) is either a literal or a whole
|
|
24
|
+
* runtime expression — there is no embedded/interpolated expression. So a
|
|
25
|
+
* value that is a string is resolved as an expression only when the entire
|
|
26
|
+
* string is a valid runtime expression; every other value (a non-expression
|
|
27
|
+
* string such as `"{$inputs.x}"`, a number, boolean, object, array, or null)
|
|
28
|
+
* is a literal and is used as-is. This is deliberately not template
|
|
29
|
+
* interpolation. The one exception is a `requestBody` payload, which "can
|
|
30
|
+
* contain" runtime expressions — {@link RequestBodyResolver} walks it instead.
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
class ArazzoValueResolver {
|
|
34
|
+
/**
|
|
35
|
+
* Resolves one authored value element by the rule above.
|
|
36
|
+
*/
|
|
37
|
+
resolveValue(element, resolve) {
|
|
38
|
+
const value = (0, _apidomCore.toValue)(element);
|
|
39
|
+
return typeof value === 'string' && (0, _arazzoRuntimeExpression.test)(value) ? resolve(value) : value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
var _default = exports.default = ArazzoValueResolver;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
2
|
+
import { test as isRuntimeExpression } from '@swaggerexpert/arazzo-runtime-expression';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolves a runtime expression to its value.
|
|
6
|
+
*
|
|
7
|
+
* Bridged to a lenient runtime expression evaluator
|
|
8
|
+
* (`(expression) => runtimeExpressionEvaluator.evaluate(expression)`), so an
|
|
9
|
+
* unresolvable reference yields `undefined` rather than throwing.
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Base of every resolver of authored Arazzo values — the single home of the
|
|
15
|
+
* literal-vs-expression rule they all share.
|
|
16
|
+
*
|
|
17
|
+
* Per Arazzo 1.0.1, an authored value (a parameter's `value`, an `outputs`
|
|
18
|
+
* entry, a `requestBody` replacement value) is either a literal or a whole
|
|
19
|
+
* runtime expression — there is no embedded/interpolated expression. So a
|
|
20
|
+
* value that is a string is resolved as an expression only when the entire
|
|
21
|
+
* string is a valid runtime expression; every other value (a non-expression
|
|
22
|
+
* string such as `"{$inputs.x}"`, a number, boolean, object, array, or null)
|
|
23
|
+
* is a literal and is used as-is. This is deliberately not template
|
|
24
|
+
* interpolation. The one exception is a `requestBody` payload, which "can
|
|
25
|
+
* contain" runtime expressions — {@link RequestBodyResolver} walks it instead.
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
class ArazzoValueResolver {
|
|
29
|
+
/**
|
|
30
|
+
* Resolves one authored value element by the rule above.
|
|
31
|
+
*/
|
|
32
|
+
resolveValue(element, resolve) {
|
|
33
|
+
const value = toValue(element);
|
|
34
|
+
return typeof value === 'string' && isRuntimeExpression(value) ? resolve(value) : value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export default ArazzoValueResolver;
|
|
@@ -0,0 +1,117 @@
|
|
|
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 _ParameterDelivery = _interopRequireDefault(require("../client/ParameterDelivery.cjs"));
|
|
11
|
+
var _ParameterIdentity = _interopRequireDefault(require("../document/ParameterIdentity.cjs"));
|
|
12
|
+
var _ResolverError = _interopRequireDefault(require("../errors/ResolverError.cjs"));
|
|
13
|
+
var _StepParameterResolver = _interopRequireDefault(require("./StepParameterResolver.cjs"));
|
|
14
|
+
/**
|
|
15
|
+
* Resolves the `parameters` of a step targeting an OpenAPI operation into the
|
|
16
|
+
* map the operation is executed with.
|
|
17
|
+
*
|
|
18
|
+
* Values follow the family-wide literal-vs-expression rule of
|
|
19
|
+
* {@link ArazzoValueResolver}. Keys and their first-wins claiming are
|
|
20
|
+
* `ParameterDelivery`'s: `'{in}.{name}'` for a location the client
|
|
21
|
+
* can address — a parameter is unique by `(name, in)`, so keying by name
|
|
22
|
+
* alone would collapse two parameters that differ only in their location into
|
|
23
|
+
* one entry and silently drop the other, where an operation legally declaring
|
|
24
|
+
* `token` both as a header and as a query parameter must receive both — and
|
|
25
|
+
* the bare name for Arazzo's `querystring`, which names no OpenAPI location.
|
|
26
|
+
* First-wins is the override order the specification requires: the list is
|
|
27
|
+
* ordered by precedence, most specific first, as `ArazzoWorkflowNormalizer`
|
|
28
|
+
* leaves it once a step's own parameters have been merged with the ones it
|
|
29
|
+
* inherits.
|
|
30
|
+
*
|
|
31
|
+
* What the map reports, this resolver judges. A parameter without a location
|
|
32
|
+
* throws {@link ResolverError}: a step targeting an operation requires one
|
|
33
|
+
* (the normalizer does not inherit input-shaped workflow parameters into such
|
|
34
|
+
* steps, so this is the step's own authoring error), and delivering it bare
|
|
35
|
+
* instead would let it capture *every* declared location of that name — see
|
|
36
|
+
* `ParameterDelivery` for the lookup order that makes it so. A
|
|
37
|
+
* non-string location throws for the same reason it deduplicates with nothing
|
|
38
|
+
* in the normalizer: it names no location. And two *different* parameters the
|
|
39
|
+
* map reports as colliding cannot both be delivered, so a collision throws
|
|
40
|
+
* rather than silently dropping one — whether they collide on one key (the
|
|
41
|
+
* scheme is not injective: a `querystring` parameter named `header.token` and
|
|
42
|
+
* a header parameter named `token` both produce `header.token`) or across a
|
|
43
|
+
* bare/qualified pair sharing a name (a `querystring` `token` next to a
|
|
44
|
+
* header `token`), where the client would consult the bare name first and
|
|
45
|
+
* silently capture the qualified value.
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
class OpenAPIOperationParameterResolver extends _StepParameterResolver.default {
|
|
49
|
+
/**
|
|
50
|
+
* Resolves each parameter's `value`, returning a
|
|
51
|
+
* `ParameterDelivery`-keyed record. Returns an empty object when
|
|
52
|
+
* there are no parameters.
|
|
53
|
+
*
|
|
54
|
+
* `scope` names the step in a thrown {@link ResolverError}.
|
|
55
|
+
*/
|
|
56
|
+
resolve(parameters, resolve, scope) {
|
|
57
|
+
const delivery = new _ParameterDelivery.default();
|
|
58
|
+
if (parameters === undefined) return delivery.toRecord();
|
|
59
|
+
// present but scalar: walking it would fail as a bare
|
|
60
|
+
// `TypeError: parameters is not iterable`, raised by the language rather
|
|
61
|
+
// than the runner. Reported here as the authoring error it is.
|
|
62
|
+
if (!(0, _apidomDatamodel.isArrayElement)(parameters)) {
|
|
63
|
+
throw new _ResolverError.default('`parameters` is present but is not a list', {
|
|
64
|
+
...scope,
|
|
65
|
+
target: 'parameters',
|
|
66
|
+
reason: 'malformed-parameters'
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
for (const parameter of parameters) {
|
|
70
|
+
if (!(0, _apidomNsArazzo.isParameterElement)(parameter)) continue;
|
|
71
|
+
// a Parameter Object without an identity has a missing or non-string
|
|
72
|
+
// name — reported as loudly as a malformed location below, rather than
|
|
73
|
+
// silently dropped from the request
|
|
74
|
+
const identity = _ParameterIdentity.default.of(parameter);
|
|
75
|
+
if (identity === undefined) {
|
|
76
|
+
throw new _ResolverError.default('Parameter has a missing or non-string name', {
|
|
77
|
+
...scope,
|
|
78
|
+
reason: 'missing-name'
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const {
|
|
82
|
+
name,
|
|
83
|
+
location
|
|
84
|
+
} = identity;
|
|
85
|
+
if (location === undefined) {
|
|
86
|
+
throw new _ResolverError.default(`Parameter "${name}" declares no location ("in"), which a step targeting an operation requires`, {
|
|
87
|
+
...scope,
|
|
88
|
+
target: name,
|
|
89
|
+
reason: 'missing-location'
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (location === null) {
|
|
93
|
+
throw new _ResolverError.default(`Parameter "${name}" has a non-string location ("in")`, {
|
|
94
|
+
...scope,
|
|
95
|
+
target: name,
|
|
96
|
+
reason: 'malformed-location'
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const {
|
|
100
|
+
key,
|
|
101
|
+
outcome
|
|
102
|
+
} = delivery.claim(location, name);
|
|
103
|
+
// the same parameter declared again: the earlier, more specific one won
|
|
104
|
+
if (outcome === 'duplicate') continue;
|
|
105
|
+
if (outcome === 'collision') {
|
|
106
|
+
throw new _ResolverError.default(`Parameter "${name}" (in: ${location}) collides with another parameter on the ` + `delivery key "${key}" and cannot be delivered unambiguously`, {
|
|
107
|
+
...scope,
|
|
108
|
+
target: name,
|
|
109
|
+
reason: 'ambiguous-delivery'
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
delivery.set(key, this.resolveValue(parameter.value, resolve));
|
|
113
|
+
}
|
|
114
|
+
return delivery.toRecord();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
var _default = exports.default = OpenAPIOperationParameterResolver;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { isArrayElement } from '@speclynx/apidom-datamodel';
|
|
2
|
+
import { isParameterElement } from '@speclynx/apidom-ns-arazzo-1';
|
|
3
|
+
import ParameterDelivery from "../client/ParameterDelivery.mjs";
|
|
4
|
+
import ParameterIdentity from "../document/ParameterIdentity.mjs";
|
|
5
|
+
import ResolverError from "../errors/ResolverError.mjs";
|
|
6
|
+
import StepParameterResolver from "./StepParameterResolver.mjs";
|
|
7
|
+
/**
|
|
8
|
+
* Resolves the `parameters` of a step targeting an OpenAPI operation into the
|
|
9
|
+
* map the operation is executed with.
|
|
10
|
+
*
|
|
11
|
+
* Values follow the family-wide literal-vs-expression rule of
|
|
12
|
+
* {@link ArazzoValueResolver}. Keys and their first-wins claiming are
|
|
13
|
+
* `ParameterDelivery`'s: `'{in}.{name}'` for a location the client
|
|
14
|
+
* can address — a parameter is unique by `(name, in)`, so keying by name
|
|
15
|
+
* alone would collapse two parameters that differ only in their location into
|
|
16
|
+
* one entry and silently drop the other, where an operation legally declaring
|
|
17
|
+
* `token` both as a header and as a query parameter must receive both — and
|
|
18
|
+
* the bare name for Arazzo's `querystring`, which names no OpenAPI location.
|
|
19
|
+
* First-wins is the override order the specification requires: the list is
|
|
20
|
+
* ordered by precedence, most specific first, as `ArazzoWorkflowNormalizer`
|
|
21
|
+
* leaves it once a step's own parameters have been merged with the ones it
|
|
22
|
+
* inherits.
|
|
23
|
+
*
|
|
24
|
+
* What the map reports, this resolver judges. A parameter without a location
|
|
25
|
+
* throws {@link ResolverError}: a step targeting an operation requires one
|
|
26
|
+
* (the normalizer does not inherit input-shaped workflow parameters into such
|
|
27
|
+
* steps, so this is the step's own authoring error), and delivering it bare
|
|
28
|
+
* instead would let it capture *every* declared location of that name — see
|
|
29
|
+
* `ParameterDelivery` for the lookup order that makes it so. A
|
|
30
|
+
* non-string location throws for the same reason it deduplicates with nothing
|
|
31
|
+
* in the normalizer: it names no location. And two *different* parameters the
|
|
32
|
+
* map reports as colliding cannot both be delivered, so a collision throws
|
|
33
|
+
* rather than silently dropping one — whether they collide on one key (the
|
|
34
|
+
* scheme is not injective: a `querystring` parameter named `header.token` and
|
|
35
|
+
* a header parameter named `token` both produce `header.token`) or across a
|
|
36
|
+
* bare/qualified pair sharing a name (a `querystring` `token` next to a
|
|
37
|
+
* header `token`), where the client would consult the bare name first and
|
|
38
|
+
* silently capture the qualified value.
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
class OpenAPIOperationParameterResolver extends StepParameterResolver {
|
|
42
|
+
/**
|
|
43
|
+
* Resolves each parameter's `value`, returning a
|
|
44
|
+
* `ParameterDelivery`-keyed record. Returns an empty object when
|
|
45
|
+
* there are no parameters.
|
|
46
|
+
*
|
|
47
|
+
* `scope` names the step in a thrown {@link ResolverError}.
|
|
48
|
+
*/
|
|
49
|
+
resolve(parameters, resolve, scope) {
|
|
50
|
+
const delivery = new ParameterDelivery();
|
|
51
|
+
if (parameters === undefined) return delivery.toRecord();
|
|
52
|
+
// present but scalar: walking it would fail as a bare
|
|
53
|
+
// `TypeError: parameters is not iterable`, raised by the language rather
|
|
54
|
+
// than the runner. Reported here as the authoring error it is.
|
|
55
|
+
if (!isArrayElement(parameters)) {
|
|
56
|
+
throw new ResolverError('`parameters` is present but is not a list', {
|
|
57
|
+
...scope,
|
|
58
|
+
target: 'parameters',
|
|
59
|
+
reason: 'malformed-parameters'
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
for (const parameter of parameters) {
|
|
63
|
+
if (!isParameterElement(parameter)) continue;
|
|
64
|
+
// a Parameter Object without an identity has a missing or non-string
|
|
65
|
+
// name — reported as loudly as a malformed location below, rather than
|
|
66
|
+
// silently dropped from the request
|
|
67
|
+
const identity = ParameterIdentity.of(parameter);
|
|
68
|
+
if (identity === undefined) {
|
|
69
|
+
throw new ResolverError('Parameter has a missing or non-string name', {
|
|
70
|
+
...scope,
|
|
71
|
+
reason: 'missing-name'
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const {
|
|
75
|
+
name,
|
|
76
|
+
location
|
|
77
|
+
} = identity;
|
|
78
|
+
if (location === undefined) {
|
|
79
|
+
throw new ResolverError(`Parameter "${name}" declares no location ("in"), which a step targeting an operation requires`, {
|
|
80
|
+
...scope,
|
|
81
|
+
target: name,
|
|
82
|
+
reason: 'missing-location'
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (location === null) {
|
|
86
|
+
throw new ResolverError(`Parameter "${name}" has a non-string location ("in")`, {
|
|
87
|
+
...scope,
|
|
88
|
+
target: name,
|
|
89
|
+
reason: 'malformed-location'
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const {
|
|
93
|
+
key,
|
|
94
|
+
outcome
|
|
95
|
+
} = delivery.claim(location, name);
|
|
96
|
+
// the same parameter declared again: the earlier, more specific one won
|
|
97
|
+
if (outcome === 'duplicate') continue;
|
|
98
|
+
if (outcome === 'collision') {
|
|
99
|
+
throw new ResolverError(`Parameter "${name}" (in: ${location}) collides with another parameter on the ` + `delivery key "${key}" and cannot be delivered unambiguously`, {
|
|
100
|
+
...scope,
|
|
101
|
+
target: name,
|
|
102
|
+
reason: 'ambiguous-delivery'
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
delivery.set(key, this.resolveValue(parameter.value, resolve));
|
|
106
|
+
}
|
|
107
|
+
return delivery.toRecord();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export default OpenAPIOperationParameterResolver;
|
|
@@ -0,0 +1,71 @@
|
|
|
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 _arazzoRuntimeExpression = require("@swaggerexpert/arazzo-runtime-expression");
|
|
11
|
+
var _ResolverError = _interopRequireDefault(require("../errors/ResolverError.cjs"));
|
|
12
|
+
var _ArazzoValueResolver = _interopRequireDefault(require("./ArazzoValueResolver.cjs"));
|
|
13
|
+
/**
|
|
14
|
+
* Resolves a step's or workflow's `outputs` to a plain map of name → value.
|
|
15
|
+
*
|
|
16
|
+
* The spec types `outputs` as `Map[string, {expression}]`, so a whole runtime
|
|
17
|
+
* expression is the *only* authored form — unlike a parameter's `value` or a
|
|
18
|
+
* `requestBody` payload (typed `Any`), where {@link ArazzoValueResolver} lets a
|
|
19
|
+
* literal through. An output that is not a valid runtime expression is an
|
|
20
|
+
* authoring error and throws a {@link ResolverError}.
|
|
21
|
+
*
|
|
22
|
+
* The result is the map an executor stores into the workflow execution state so
|
|
23
|
+
* later steps can read `$steps.{id}.outputs.{name}` / `$outputs.{name}`.
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
class OutputResolver extends _ArazzoValueResolver.default {
|
|
27
|
+
/**
|
|
28
|
+
* Resolves each output value, returning a `name` → value map. Returns an empty
|
|
29
|
+
* object when there are no outputs.
|
|
30
|
+
*
|
|
31
|
+
* `scope` names the step or workflow the outputs belong to, for a thrown
|
|
32
|
+
* {@link ResolverError}. An output value that is not a valid runtime
|
|
33
|
+
* expression throws with `reason: 'invalid-expression'`.
|
|
34
|
+
*/
|
|
35
|
+
resolve(outputs, resolve, scope) {
|
|
36
|
+
const result = {};
|
|
37
|
+
if (outputs === undefined) return result;
|
|
38
|
+
// present but not a map: the walk below would fail as a bare
|
|
39
|
+
// `TypeError: outputs.forEach is not a function`.
|
|
40
|
+
if (!(0, _apidomDatamodel.isObjectElement)(outputs)) {
|
|
41
|
+
throw new _ResolverError.default('`outputs` is present but is not a map', {
|
|
42
|
+
...scope,
|
|
43
|
+
target: 'outputs',
|
|
44
|
+
reason: 'malformed-outputs'
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
outputs.forEach((value, key) => {
|
|
48
|
+
const name = (0, _apidomCore.toValue)(key);
|
|
49
|
+
const expression = (0, _apidomCore.toValue)(value);
|
|
50
|
+
if (typeof expression !== 'string' || !(0, _arazzoRuntimeExpression.test)(expression)) {
|
|
51
|
+
throw new _ResolverError.default(`Output "${name}" is not a valid runtime expression`, {
|
|
52
|
+
...scope,
|
|
53
|
+
target: 'outputs',
|
|
54
|
+
reason: 'invalid-expression'
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// defined rather than assigned: a name like `__proto__` hits the
|
|
58
|
+
// Object.prototype accessor on bracket assignment, so no own property is
|
|
59
|
+
// ever created and the output is silently lost — and an object value
|
|
60
|
+
// additionally rewrites the record's prototype
|
|
61
|
+
Object.defineProperty(result, name, {
|
|
62
|
+
value: resolve(expression),
|
|
63
|
+
enumerable: true,
|
|
64
|
+
writable: true,
|
|
65
|
+
configurable: true
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
var _default = exports.default = OutputResolver;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
2
|
+
import { isObjectElement } from '@speclynx/apidom-datamodel';
|
|
3
|
+
import { test as isRuntimeExpression } from '@swaggerexpert/arazzo-runtime-expression';
|
|
4
|
+
import ResolverError from "../errors/ResolverError.mjs";
|
|
5
|
+
import ArazzoValueResolver from "./ArazzoValueResolver.mjs";
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a step's or workflow's `outputs` to a plain map of name → value.
|
|
8
|
+
*
|
|
9
|
+
* The spec types `outputs` as `Map[string, {expression}]`, so a whole runtime
|
|
10
|
+
* expression is the *only* authored form — unlike a parameter's `value` or a
|
|
11
|
+
* `requestBody` payload (typed `Any`), where {@link ArazzoValueResolver} lets a
|
|
12
|
+
* literal through. An output that is not a valid runtime expression is an
|
|
13
|
+
* authoring error and throws a {@link ResolverError}.
|
|
14
|
+
*
|
|
15
|
+
* The result is the map an executor stores into the workflow execution state so
|
|
16
|
+
* later steps can read `$steps.{id}.outputs.{name}` / `$outputs.{name}`.
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
class OutputResolver extends ArazzoValueResolver {
|
|
20
|
+
/**
|
|
21
|
+
* Resolves each output value, returning a `name` → value map. Returns an empty
|
|
22
|
+
* object when there are no outputs.
|
|
23
|
+
*
|
|
24
|
+
* `scope` names the step or workflow the outputs belong to, for a thrown
|
|
25
|
+
* {@link ResolverError}. An output value that is not a valid runtime
|
|
26
|
+
* expression throws with `reason: 'invalid-expression'`.
|
|
27
|
+
*/
|
|
28
|
+
resolve(outputs, resolve, scope) {
|
|
29
|
+
const result = {};
|
|
30
|
+
if (outputs === undefined) return result;
|
|
31
|
+
// present but not a map: the walk below would fail as a bare
|
|
32
|
+
// `TypeError: outputs.forEach is not a function`.
|
|
33
|
+
if (!isObjectElement(outputs)) {
|
|
34
|
+
throw new ResolverError('`outputs` is present but is not a map', {
|
|
35
|
+
...scope,
|
|
36
|
+
target: 'outputs',
|
|
37
|
+
reason: 'malformed-outputs'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
outputs.forEach((value, key) => {
|
|
41
|
+
const name = toValue(key);
|
|
42
|
+
const expression = toValue(value);
|
|
43
|
+
if (typeof expression !== 'string' || !isRuntimeExpression(expression)) {
|
|
44
|
+
throw new ResolverError(`Output "${name}" is not a valid runtime expression`, {
|
|
45
|
+
...scope,
|
|
46
|
+
target: 'outputs',
|
|
47
|
+
reason: 'invalid-expression'
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// defined rather than assigned: a name like `__proto__` hits the
|
|
51
|
+
// Object.prototype accessor on bracket assignment, so no own property is
|
|
52
|
+
// ever created and the output is silently lost — and an object value
|
|
53
|
+
// additionally rewrites the record's prototype
|
|
54
|
+
Object.defineProperty(result, name, {
|
|
55
|
+
value: resolve(expression),
|
|
56
|
+
enumerable: true,
|
|
57
|
+
writable: true,
|
|
58
|
+
configurable: true
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export default OutputResolver;
|