@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.
- package/package.json +63 -0
- package/src/event/event.interface.ts +18 -0
- package/src/event/index.ts +1 -0
- package/src/execution/context.constants.ts +9 -0
- package/src/execution/context.interface.ts +39 -0
- package/src/execution/context.ts +72 -0
- package/src/execution/context.utils.ts +53 -0
- package/src/execution/index.ts +2 -0
- package/src/index.ts +6 -0
- package/src/integration/custom-integration.interface.ts +20 -0
- package/src/integration/index.ts +2 -0
- package/src/integration/integration-config.interface.ts +19 -0
- package/src/integration/integration.interface.ts +16 -0
- package/src/operator/index.ts +2 -0
- package/src/operator/operator.interface.ts +6 -0
- package/src/operator/operators/BooleanTrue.ts +20 -0
- package/src/operator/operators/StringContains.ts +27 -0
- package/src/resolvers/index.ts +2 -0
- package/src/resolvers/resolver.utils.ts +157 -0
- package/src/resolvers/resolvers.interface.ts +369 -0
- package/src/secret/index.ts +1 -0
- package/src/secret/secret.interface.ts +4 -0
- package/src/stateMachine/index.ts +2 -0
- package/src/stateMachine/stateMachine.constants.ts +12 -0
- package/src/stateMachine/stateMachine.interface.ts +145 -0
- package/src/stateMachine/stateMachine.utils.ts +733 -0
- package/src/steps/index.ts +3 -0
- package/src/steps/library/action/action.interface.ts +69 -0
- package/src/steps/library/action/action.step.ts +70 -0
- package/src/steps/library/action/index.ts +2 -0
- package/src/steps/library/conditional/conditional.interface.ts +82 -0
- package/src/steps/library/conditional/conditional.step.ts +96 -0
- package/src/steps/library/conditional/conditional.utils.ts +110 -0
- package/src/steps/library/conditional/index.ts +2 -0
- package/src/steps/library/delay/delay.interface.ts +71 -0
- package/src/steps/library/delay/delay.step.ts +51 -0
- package/src/steps/library/delay/index.ts +2 -0
- package/src/steps/library/fanout/fanout.interface.ts +46 -0
- package/src/steps/library/fanout/fanout.step.ts +68 -0
- package/src/steps/library/fanout/index.ts +2 -0
- package/src/steps/library/function/function.interface.ts +69 -0
- package/src/steps/library/function/function.step.ts +55 -0
- package/src/steps/library/function/index.ts +2 -0
- package/src/steps/library/index.ts +7 -0
- package/src/steps/library/integrationRequest/index.ts +2 -0
- package/src/steps/library/integrationRequest/integrationRequest.interface.ts +79 -0
- package/src/steps/library/integrationRequest/integrationRequest.step.ts +100 -0
- package/src/steps/library/request/index.ts +2 -0
- package/src/steps/library/request/request.interface.ts +159 -0
- package/src/steps/library/request/request.step.ts +117 -0
- package/src/steps/library/response/index.ts +2 -0
- package/src/steps/library/response/response.interface.ts +50 -0
- package/src/steps/library/response/response.step.ts +68 -0
- package/src/steps/step.constants.ts +4 -0
- package/src/steps/step.interface-base.ts +81 -0
- package/src/steps/step.interface.ts +31 -0
- package/src/steps/step.ts +136 -0
- package/src/steps/step.utils.ts +103 -0
- package/src/triggers/cron/cron.interface.ts +94 -0
- package/src/triggers/cron/cron.step.ts +52 -0
- package/src/triggers/cron/cron.utils.ts +117 -0
- package/src/triggers/cron/index.ts +3 -0
- package/src/triggers/endpoint/endpoint.interface.ts +66 -0
- package/src/triggers/endpoint/endpoint.step.ts +61 -0
- package/src/triggers/endpoint/index.ts +2 -0
- package/src/triggers/event/event.interface.ts +43 -0
- package/src/triggers/event/event.step.ts +41 -0
- package/src/triggers/event/index.ts +2 -0
- package/src/triggers/index.ts +4 -0
- package/src/triggers/integrationEnabled/index.ts +2 -0
- package/src/triggers/integrationEnabled/integrationEnabled.interface.ts +29 -0
- package/src/triggers/integrationEnabled/integrationEnabled.step.ts +33 -0
- package/src/triggers/trigger.interface.ts +28 -0
- package/src/triggers/trigger.ts +25 -0
- package/src/user/index.ts +2 -0
- package/src/user/user.interface.ts +4 -0
- package/src/user/user.ts +6 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/utils.ts +10 -0
- package/src/workflow/index.ts +2 -0
- package/src/workflow/workflow.interface.ts +50 -0
- package/src/workflow/workflow.ts +132 -0
- package/tsconfig.json +9 -0
- 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 @@
|
|
|
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
|
+
}
|
package/src/index.ts
ADDED
|
@@ -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,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,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,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
|
+
};
|