@useparagon/core 0.0.1-canary.1

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 (84) hide show
  1. package/package.json +63 -0
  2. package/src/event/event.interface.ts +18 -0
  3. package/src/event/index.ts +1 -0
  4. package/src/execution/context.constants.ts +9 -0
  5. package/src/execution/context.interface.ts +39 -0
  6. package/src/execution/context.ts +72 -0
  7. package/src/execution/context.utils.ts +53 -0
  8. package/src/execution/index.ts +2 -0
  9. package/src/index.ts +6 -0
  10. package/src/integration/custom-integration.interface.ts +20 -0
  11. package/src/integration/index.ts +2 -0
  12. package/src/integration/integration-config.interface.ts +19 -0
  13. package/src/integration/integration.interface.ts +16 -0
  14. package/src/operator/index.ts +2 -0
  15. package/src/operator/operator.interface.ts +6 -0
  16. package/src/operator/operators/BooleanTrue.ts +20 -0
  17. package/src/operator/operators/StringContains.ts +27 -0
  18. package/src/resolvers/index.ts +2 -0
  19. package/src/resolvers/resolver.utils.ts +157 -0
  20. package/src/resolvers/resolvers.interface.ts +369 -0
  21. package/src/secret/index.ts +1 -0
  22. package/src/secret/secret.interface.ts +4 -0
  23. package/src/stateMachine/index.ts +2 -0
  24. package/src/stateMachine/stateMachine.constants.ts +12 -0
  25. package/src/stateMachine/stateMachine.interface.ts +145 -0
  26. package/src/stateMachine/stateMachine.utils.ts +733 -0
  27. package/src/steps/index.ts +3 -0
  28. package/src/steps/library/action/action.interface.ts +69 -0
  29. package/src/steps/library/action/action.step.ts +70 -0
  30. package/src/steps/library/action/index.ts +2 -0
  31. package/src/steps/library/conditional/conditional.interface.ts +82 -0
  32. package/src/steps/library/conditional/conditional.step.ts +96 -0
  33. package/src/steps/library/conditional/conditional.utils.ts +110 -0
  34. package/src/steps/library/conditional/index.ts +2 -0
  35. package/src/steps/library/delay/delay.interface.ts +71 -0
  36. package/src/steps/library/delay/delay.step.ts +51 -0
  37. package/src/steps/library/delay/index.ts +2 -0
  38. package/src/steps/library/fanout/fanout.interface.ts +46 -0
  39. package/src/steps/library/fanout/fanout.step.ts +68 -0
  40. package/src/steps/library/fanout/index.ts +2 -0
  41. package/src/steps/library/function/function.interface.ts +69 -0
  42. package/src/steps/library/function/function.step.ts +55 -0
  43. package/src/steps/library/function/index.ts +2 -0
  44. package/src/steps/library/index.ts +7 -0
  45. package/src/steps/library/integrationRequest/index.ts +2 -0
  46. package/src/steps/library/integrationRequest/integrationRequest.interface.ts +79 -0
  47. package/src/steps/library/integrationRequest/integrationRequest.step.ts +100 -0
  48. package/src/steps/library/request/index.ts +2 -0
  49. package/src/steps/library/request/request.interface.ts +159 -0
  50. package/src/steps/library/request/request.step.ts +117 -0
  51. package/src/steps/library/response/index.ts +2 -0
  52. package/src/steps/library/response/response.interface.ts +50 -0
  53. package/src/steps/library/response/response.step.ts +68 -0
  54. package/src/steps/step.constants.ts +4 -0
  55. package/src/steps/step.interface-base.ts +81 -0
  56. package/src/steps/step.interface.ts +31 -0
  57. package/src/steps/step.ts +136 -0
  58. package/src/steps/step.utils.ts +103 -0
  59. package/src/triggers/cron/cron.interface.ts +94 -0
  60. package/src/triggers/cron/cron.step.ts +52 -0
  61. package/src/triggers/cron/cron.utils.ts +117 -0
  62. package/src/triggers/cron/index.ts +3 -0
  63. package/src/triggers/endpoint/endpoint.interface.ts +66 -0
  64. package/src/triggers/endpoint/endpoint.step.ts +61 -0
  65. package/src/triggers/endpoint/index.ts +2 -0
  66. package/src/triggers/event/event.interface.ts +43 -0
  67. package/src/triggers/event/event.step.ts +41 -0
  68. package/src/triggers/event/index.ts +2 -0
  69. package/src/triggers/index.ts +4 -0
  70. package/src/triggers/integrationEnabled/index.ts +2 -0
  71. package/src/triggers/integrationEnabled/integrationEnabled.interface.ts +29 -0
  72. package/src/triggers/integrationEnabled/integrationEnabled.step.ts +33 -0
  73. package/src/triggers/trigger.interface.ts +28 -0
  74. package/src/triggers/trigger.ts +25 -0
  75. package/src/user/index.ts +2 -0
  76. package/src/user/user.interface.ts +4 -0
  77. package/src/user/user.ts +6 -0
  78. package/src/utils/index.ts +1 -0
  79. package/src/utils/utils.ts +10 -0
  80. package/src/workflow/index.ts +2 -0
  81. package/src/workflow/workflow.interface.ts +50 -0
  82. package/src/workflow/workflow.ts +132 -0
  83. package/tsconfig.json +9 -0
  84. package/tsconfig.release.json +8 -0
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@useparagon/core",
3
+ "version": "0.0.1-canary.1",
4
+ "description": "Core libraries for paragraph",
5
+ "repository": "https://github.com/useparagon/paragraph",
6
+ "packageManager": "yarn@3.4.1",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.js",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./src/index.ts",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./*": {
15
+ "import": "./src/*/index.ts",
16
+ "require": "./dist/*/index.js"
17
+ }
18
+ },
19
+ "typesVersions": {
20
+ "*": {
21
+ "*": [
22
+ "./dist/*/index.d.js",
23
+ "./dist/index.d.ts"
24
+ ]
25
+ }
26
+ },
27
+ "scripts": {
28
+ "build": "yarn clean && tsc -b tsconfig.release.json",
29
+ "build:watch": "tsc -b tsconfig.release.json -w",
30
+ "build:dev": "tsc -b tsconfig.json",
31
+ "build:dev:watch": "tsc -b tsconfig.json -w",
32
+ "clean": "rimraf ./dist ./coverage",
33
+ "format": "prettier --ignore-path ../../.prettierignore --config ../../.prettierrc --write .",
34
+ "format:check": "prettier --ignore-path ../../.prettierignore --config ../../.prettierrc --check .",
35
+ "lint": "eslint --ignore-path ../../.eslintignore --config ../../.eslintrc.json --ext .ts .",
36
+ "lint:fix": "eslint --ignore-path ../../.eslintignore --config ../../.eslintrc.json --ext .ts --fix .",
37
+ "release:publish:canary": "npm publish --access restricted --tag next",
38
+ "start:dev": "ts-node -r tsconfig-paths/register src/index.ts"
39
+ },
40
+ "dependencies": {
41
+ "cron-parser": "^4.9.0",
42
+ "stacktrace-parser": "^0.1.8",
43
+ "tslib": "2.3.1",
44
+ "uuid": "^9.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "@trivago/prettier-plugin-sort-imports": "^4.2.0",
48
+ "@types/node": "^18.13.0",
49
+ "@types/uuid": "^9.0.1",
50
+ "@typescript-eslint/eslint-plugin": "^5.21.0",
51
+ "@typescript-eslint/parser": "^5.21.0",
52
+ "eslint": "^8.14.0",
53
+ "eslint-config-prettier": "^8.5.0",
54
+ "eslint-plugin-import": "^2.26.0",
55
+ "eslint-plugin-jest": "^27.0.1",
56
+ "prettier": "^2.2.1",
57
+ "prettier-plugin-organize-imports": "^3.2.3",
58
+ "rimraf": "~4.4.0",
59
+ "ts-node": "10.9.1",
60
+ "tsconfig-paths": "^4.2.0",
61
+ "typescript": "^4.4.4"
62
+ }
63
+ }
@@ -0,0 +1,18 @@
1
+ export interface IEvent<
2
+ T extends Record<string, unknown> = Record<string, unknown>,
3
+ > {
4
+ /**
5
+ * id of event
6
+ */
7
+ id?: string;
8
+
9
+ /**
10
+ * name of event
11
+ */
12
+ name: string;
13
+
14
+ /**
15
+ * schema of event
16
+ */
17
+ schema: T;
18
+ }
@@ -0,0 +1 @@
1
+ export * from './event.interface';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * special reserved key used by proxies to get keys accessed while traversing an object
3
+ */
4
+ export const PROXY_KEY_GET_KEYS: string = '@@__PROXY_KEY_GET_KEYS__@@';
5
+
6
+ /**
7
+ * special reserved key used by proxies to get the step which the proxy refers to
8
+ */
9
+ export const PROXY_KEY_GET_STEP: string = '@@__PROXY_KEY_GET_STEP__@@';
@@ -0,0 +1,39 @@
1
+ import { ISecretOutput } from '../secret';
2
+ import { IActionStep } from '../steps/library/action/action.interface';
3
+ import { IFanOutStep } from '../steps/library/fanout/fanout.interface';
4
+ import { IFunctionStep } from '../steps/library/function';
5
+ import { IEventStep } from '../triggers/event/event.interface';
6
+
7
+ /**
8
+ * creates a type from the first elememt of an array
9
+ *
10
+ * @todo move to utility file
11
+ */
12
+ export type FirstElementType<T> = T extends [infer U, ...unknown[]] ? U : never;
13
+
14
+ /**
15
+ * an object containing methods to get metadata about an execution
16
+ */
17
+ export interface IContext {
18
+ /**
19
+ * get a reference to the output of a step execution
20
+ * @param step
21
+ */
22
+ getOutput<S extends IEventStep<any>>(step: S): S['schema'];
23
+ getOutput<I extends Record<string, unknown>, O, S extends IActionStep>(
24
+ step: S,
25
+ ): O;
26
+ getOutput<
27
+ S extends IFanOutStep,
28
+ O = FirstElementType<S['parameters']['iterator']>,
29
+ >(
30
+ step: S,
31
+ ): O;
32
+ getOutput<S extends IFunctionStep>(step: S): { result: any };
33
+
34
+ /**
35
+ * get a reference to an environment secret
36
+ * @param key
37
+ */
38
+ getEnvironmentSecret(key: string): ISecretOutput;
39
+ }
@@ -0,0 +1,72 @@
1
+ import { ISecretOutput } from '../secret/secret.interface';
2
+ import { IActionStep } from '../steps/library/action/action.interface';
3
+ import { IFanOutStep } from '../steps/library/fanout/fanout.interface';
4
+ import { IFunctionStep } from '../steps/library/function/function.interface';
5
+ import { IStep } from '../steps/step.interface';
6
+ import { IEventStep } from '../triggers/event/event.interface';
7
+ import { PROXY_KEY_GET_KEYS, PROXY_KEY_GET_STEP } from './context.constants';
8
+ import { FirstElementType, IContext } from './context.interface';
9
+
10
+ export enum TokenizedIdentifiers {
11
+ START = '__TOKENIZED_START__',
12
+ END = '__TOKENIZED_END__',
13
+ }
14
+
15
+ export class Context implements IContext {
16
+ /**
17
+ * get a reference to the output of a step execution
18
+ *
19
+ * @param step
20
+ * @todo implement recursive proxy
21
+ * @todo add missing type definitions for steps
22
+ */
23
+ getOutput<S extends IEventStep>(step: S): S['parameters']['payload'];
24
+ getOutput<I extends Record<string, unknown>, O, S extends IActionStep>(
25
+ step: S,
26
+ ): O;
27
+ getOutput<
28
+ S extends IFanOutStep,
29
+ O = FirstElementType<S['parameters']['iterator']>,
30
+ >(step: S): O;
31
+ getOutput<S extends IFunctionStep>(step: S): { result: any };
32
+ getOutput(step: IStep): any {
33
+ const keys: string[] = [];
34
+ const proxy = new Proxy(step, {
35
+ get(_target: any, property: string | Symbol): any {
36
+ if (property === '_isMockFunction') {
37
+ return false;
38
+ } else if (
39
+ typeof property === 'string' &&
40
+ property.startsWith('@@__IMMUTABLE_')
41
+ ) {
42
+ return undefined;
43
+ } else if (property === Symbol.toPrimitive) {
44
+ return () =>
45
+ `${TokenizedIdentifiers.START}steps:${step.id}:${keys.join('.')}${
46
+ TokenizedIdentifiers.END
47
+ }`;
48
+ } else if (property === PROXY_KEY_GET_KEYS) {
49
+ return (): string[] => [...keys];
50
+ } else if (property === PROXY_KEY_GET_STEP) {
51
+ return (): IStep => step;
52
+ }
53
+
54
+ if (!keys.includes(property.toString())) {
55
+ keys.push(property.toString());
56
+ }
57
+ return proxy;
58
+ },
59
+ });
60
+ return proxy;
61
+ }
62
+
63
+ /**
64
+ * get a reference to an environment secret
65
+ *
66
+ * @param key
67
+ * @todo implement `getEnvironmentSecret` method
68
+ */
69
+ getEnvironmentSecret(_key: string): ISecretOutput {
70
+ throw new Error('Not implemented!');
71
+ }
72
+ }
@@ -0,0 +1,53 @@
1
+ import nodeUtils from 'node:util';
2
+
3
+ import { DataType, VariableSource } from '../resolvers/resolvers.interface';
4
+ import { IStep } from '../steps';
5
+ import { PROXY_KEY_GET_KEYS, PROXY_KEY_GET_STEP } from './context.constants';
6
+
7
+ /**
8
+ * determines if an object is an instance of a Proxy
9
+ *
10
+ * @param maybeProxy
11
+ */
12
+ export function isProxy(maybeProxy: any): boolean {
13
+ return nodeUtils.types.isProxy(maybeProxy);
14
+ }
15
+
16
+ /**
17
+ * returns the keys that were accessed in the proxy
18
+ *
19
+ * @param proxy
20
+ * @returns
21
+ */
22
+ export function getKeysAccessedFromProxy(proxy: any): string[] {
23
+ return proxy[PROXY_KEY_GET_KEYS]();
24
+ }
25
+
26
+ /**
27
+ * returns the step that a proxy references
28
+ *
29
+ * @param proxy
30
+ * @returns
31
+ */
32
+ export function getStepFromProxy(proxy: any): IStep {
33
+ return proxy[PROXY_KEY_GET_STEP]();
34
+ }
35
+
36
+ /**
37
+ * converts a proxy to variable source
38
+ *
39
+ * @param proxy
40
+ * @returns
41
+ */
42
+ export function proxyToVariableSource<T extends DataType>(
43
+ proxy: any,
44
+ ): VariableSource<T> {
45
+ const step: IStep = getStepFromProxy(proxy);
46
+ const keys: string[] = getKeysAccessedFromProxy(proxy);
47
+
48
+ return {
49
+ type: 'VARIABLE',
50
+ stepId: step.id,
51
+ path: keys,
52
+ };
53
+ }
@@ -0,0 +1,2 @@
1
+ export * from './context';
2
+ export * from './context.interface';
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './integration';
2
+ export { StateMachine } from './stateMachine/stateMachine.interface';
3
+ export * from './steps';
4
+ export * from './triggers';
5
+ export * from './user';
6
+ export * from './workflow';
@@ -0,0 +1,20 @@
1
+ import { IIntegration } from './integration.interface';
2
+
3
+ /**
4
+ * different mechanisms for authentication
5
+ */
6
+ export enum AuthenticationScheme {
7
+ BASIC = 'basic',
8
+ OAUTH = 'oauth',
9
+ OAUTH_CLIENT_CREDENTIAL = 'oauth_client_credential',
10
+ SERVICE_ACCOUNT = 'service_account',
11
+ OAUTH_APP = 'oauth_app',
12
+ IMPERSONATED_APP = 'impersonated_app',
13
+ }
14
+
15
+ /**
16
+ * an entity representing a custom integration
17
+ */
18
+ export interface ICustomIntegration extends IIntegration {
19
+ authenticationType: AuthenticationScheme;
20
+ }
@@ -0,0 +1,2 @@
1
+ export * from './integration.interface';
2
+ export * from './integration-config.interface';
@@ -0,0 +1,19 @@
1
+ /**
2
+ * configuration for an integration
3
+ */
4
+ export interface IIntegrationConfig {
5
+ /**
6
+ * a short description for the integration
7
+ */
8
+ description: string;
9
+
10
+ /**
11
+ * a detailed description for the integration displayed in the Connect Portal
12
+ */
13
+ overviewText: string;
14
+
15
+ /**
16
+ * scopes needed for the integration
17
+ */
18
+ scopes: string;
19
+ }
@@ -0,0 +1,16 @@
1
+ import { IBaseStep, StepType } from '../steps/step.interface-base';
2
+
3
+ /**
4
+ * an entity representing an outside datasource
5
+ */
6
+ export interface IIntegration {}
7
+
8
+ /**
9
+ * an action step used by an integration
10
+ */
11
+ export interface IIntegrationActionStep extends IBaseStep {
12
+ /**
13
+ * the step type
14
+ */
15
+ type: StepType.ACTION;
16
+ }
@@ -0,0 +1,2 @@
1
+ export { default as BooleanTrue } from './operators/BooleanTrue';
2
+ export { default as StringContains } from './operators/StringContains';
@@ -0,0 +1,6 @@
1
+ import { VariableSource } from '../resolvers/resolvers.interface';
2
+
3
+ /**
4
+ * a value that can be used in an operator function
5
+ */
6
+ export type IOperatorValue = VariableSource | string | number | boolean;
@@ -0,0 +1,20 @@
1
+ import { resolveToSource } from '../../resolvers/resolver.utils';
2
+ import {
3
+ Condition,
4
+ DataType,
5
+ Operator,
6
+ } from '../../resolvers/resolvers.interface';
7
+ import { IOperatorValue } from '../operator.interface';
8
+
9
+ /**
10
+ * evaluates whether a value is truthy
11
+ *
12
+ * @param variable value to evaluate
13
+ */
14
+ export default function BooleanTrue(variable: IOperatorValue): Condition {
15
+ const variableAsSource = resolveToSource(variable, DataType.BOOLEAN);
16
+ return {
17
+ operator: Operator.BooleanTrue,
18
+ variable: variableAsSource,
19
+ };
20
+ }
@@ -0,0 +1,27 @@
1
+ import { resolveToSource } from '../../resolvers/resolver.utils';
2
+ import {
3
+ Condition,
4
+ DataType,
5
+ Operator,
6
+ } from '../../resolvers/resolvers.interface';
7
+ import { IOperatorValue } from '../operator.interface';
8
+
9
+ /**
10
+ * constructs a `StringContains` operator
11
+ *
12
+ * @param variable
13
+ * @param argument
14
+ */
15
+ export default function StringContains(
16
+ variable: IOperatorValue,
17
+ argument: IOperatorValue,
18
+ ): Condition {
19
+ const variableAsSource = resolveToSource(variable, DataType.STRING);
20
+ const argumentAsSource = resolveToSource(argument, DataType.STRING);
21
+
22
+ return {
23
+ operator: Operator.StringContains,
24
+ variable: variableAsSource,
25
+ argument: argumentAsSource,
26
+ };
27
+ }
@@ -0,0 +1,2 @@
1
+ export * from './resolver.utils';
2
+ export * from './resolvers.interface';
@@ -0,0 +1,157 @@
1
+ import { TokenizedIdentifiers } from '../execution/context';
2
+ import { isProxy, proxyToVariableSource } from '../execution/context.utils';
3
+ import {
4
+ isConditionalInput,
5
+ parseConditionInput,
6
+ } from '../steps/library/conditional/conditional.utils';
7
+ import {
8
+ DataType,
9
+ DataTypeValues,
10
+ KeyedSource,
11
+ Source,
12
+ TokenizedValue,
13
+ } from './resolvers.interface';
14
+
15
+ /**
16
+ * break tokenized string to parts
17
+ * @param input
18
+ * @returns
19
+ */
20
+ const tokenizedStringToParts = (input: string): string[] => {
21
+ const parts: string[] = [];
22
+ let count: number = 0;
23
+ input
24
+ .split(/(__TOKENIZED_START__|__TOKENIZED_END__)/)
25
+ .forEach((part: string) =>
26
+ part === TokenizedIdentifiers.START
27
+ ? count++
28
+ : part === TokenizedIdentifiers.END && count > 0
29
+ ? count--
30
+ : count > 0
31
+ ? parts.push(
32
+ `${TokenizedIdentifiers.START}${part}${TokenizedIdentifiers.END}`,
33
+ )
34
+ : part && parts.push(part),
35
+ );
36
+ return parts;
37
+ };
38
+
39
+ /**
40
+ * check if string is valid json or not
41
+ * @param maybeJson
42
+ * @returns
43
+ */
44
+ const isValidJSON = (maybeJson: unknown): boolean => {
45
+ if (
46
+ !maybeJson ||
47
+ !(typeof maybeJson === 'string' || typeof maybeJson === 'object')
48
+ ) {
49
+ return false;
50
+ } else if (typeof maybeJson === 'string') {
51
+ try {
52
+ const parsedJson = JSON.parse(maybeJson);
53
+ if (parsedJson === null) {
54
+ return false;
55
+ }
56
+ } catch {
57
+ return false;
58
+ }
59
+ }
60
+ return true;
61
+ };
62
+
63
+ /**
64
+ * resolve source string to source object
65
+ * @param value
66
+ * @param dataType
67
+ * @returns
68
+ */
69
+ export const resolveToSource = <T extends DataType>(
70
+ value: unknown,
71
+ dataType: T,
72
+ ): Source<T> => {
73
+ if (isProxy(value)) {
74
+ return { ...proxyToVariableSource(value), dataType };
75
+ } else if (typeof value === 'number') {
76
+ return {
77
+ dataType,
78
+ type: 'VALUE',
79
+ value: value,
80
+ } as DataTypeValues[T];
81
+ } else if (
82
+ typeof value === 'string' &&
83
+ value.includes(TokenizedIdentifiers.START)
84
+ ) {
85
+ const parts: string[] = tokenizedStringToParts(value);
86
+
87
+ return {
88
+ dataType,
89
+ type: 'TOKENIZED',
90
+ parts: parts.map((part: string): TokenizedValue<DataType> => {
91
+ if (part.startsWith(TokenizedIdentifiers.START)) {
92
+ const sanitizedPart: string = part
93
+ .replace(TokenizedIdentifiers.START, '')
94
+ .replace(TokenizedIdentifiers.END, '');
95
+ const [type, typeId, paths]: string[] = sanitizedPart.split(':');
96
+
97
+ switch (type) {
98
+ case 'steps':
99
+ return {
100
+ dataType,
101
+ type: 'VARIABLE',
102
+ stepId: typeId,
103
+ path: paths.split('.'),
104
+ };
105
+ default:
106
+ throw new Error('Invalid tokenized string passed');
107
+ }
108
+ } else {
109
+ let dataType: string = DataType.STRING;
110
+ if (isValidJSON(part)) {
111
+ dataType = DataType.OBJECT;
112
+ }
113
+
114
+ return {
115
+ dataType,
116
+ type: 'VALUE',
117
+ value: part,
118
+ } as DataTypeValues[T];
119
+ }
120
+ }),
121
+ };
122
+ } else if (isConditionalInput(value)) {
123
+ return {
124
+ type: 'CONDITION',
125
+ condition: parseConditionInput(value),
126
+ };
127
+ }
128
+
129
+ return {
130
+ type: 'VALUE',
131
+ value: value as DataTypeValues[T],
132
+ dataType,
133
+ };
134
+ };
135
+
136
+ /**
137
+ * convert {key:value} to [{key:source}]
138
+ * @param param
139
+ */
140
+ export const resolveParamsToSources = <T extends DataType = DataType.ANY>(
141
+ param: Record<string, unknown>,
142
+ dataType: T = DataType.ANY as T,
143
+ ): KeyedSource<T>[] => {
144
+ const paramsWithSources: KeyedSource<T>[] = Object.keys(param).reduce(
145
+ (sources: KeyedSource<T>[], key: string): KeyedSource<T>[] => {
146
+ const value = param[key];
147
+ const keyedSource: KeyedSource<T> = {
148
+ key,
149
+ source: resolveToSource(value, dataType),
150
+ };
151
+ return [...sources, keyedSource];
152
+ },
153
+ [],
154
+ );
155
+
156
+ return paramsWithSources;
157
+ };