feat: compute step parameters with prior steps
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@automatisch/web": "0.1.0",
|
"@automatisch/web": "0.1.0",
|
||||||
"@octokit/oauth-methods": "^1.2.6",
|
"@octokit/oauth-methods": "^1.2.6",
|
||||||
|
"@types/lodash.get": "^4.4.6",
|
||||||
"axios": "0.24.0",
|
"axios": "0.24.0",
|
||||||
"bcrypt": "^5.0.1",
|
"bcrypt": "^5.0.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
"graphql-type-json": "^0.3.2",
|
"graphql-type-json": "^0.3.2",
|
||||||
"http-errors": "~1.6.3",
|
"http-errors": "~1.6.3",
|
||||||
"knex": "^0.95.11",
|
"knex": "^0.95.11",
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"nodemailer": "6.7.0",
|
"nodemailer": "6.7.0",
|
||||||
"objection": "^3.0.0",
|
"objection": "^3.0.0",
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import Step from '../../models/step';
|
import Step from '../../models/step';
|
||||||
import flowType, { flowInputType } from '../types/flow';
|
import flowType, { flowInputType } from '../types/flow';
|
||||||
import RequestWithCurrentUser from '../../types/express/request-with-current-user';
|
import RequestWithCurrentUser from '../../types/express/request-with-current-user';
|
||||||
import StepEnumType from '../../types/step-enum-type';
|
import { StepType } from '../../types/step';
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
input: {
|
input: {
|
||||||
@@ -21,7 +21,7 @@ const createFlowResolver = async (
|
|||||||
|
|
||||||
await Step.query().insert({
|
await Step.query().insert({
|
||||||
flowId: flow.id,
|
flowId: flow.id,
|
||||||
type: StepEnumType.Trigger,
|
type: StepType.Trigger,
|
||||||
position: 1,
|
position: 1,
|
||||||
appKey,
|
appKey,
|
||||||
});
|
});
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { GraphQLNonNull } from 'graphql';
|
import { GraphQLNonNull } from 'graphql';
|
||||||
import stepType, { stepInputType } from '../types/step';
|
import stepType, { stepInputType } from '../types/step';
|
||||||
import RequestWithCurrentUser from '../../types/express/request-with-current-user';
|
import RequestWithCurrentUser from '../../types/express/request-with-current-user';
|
||||||
import StepEnumType from '../../types/step-enum-type';
|
import { StepType } from '../../types/step';
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
input: {
|
input: {
|
||||||
@@ -42,7 +42,7 @@ const createStepResolver = async (
|
|||||||
const step = await flow.$relatedQuery('steps').insertAndFetch({
|
const step = await flow.$relatedQuery('steps').insertAndFetch({
|
||||||
key: input.key,
|
key: input.key,
|
||||||
appKey: input.appKey,
|
appKey: input.appKey,
|
||||||
type: StepEnumType.Action,
|
type: StepType.Action,
|
||||||
position: previousStep.position + 1,
|
position: previousStep.position + 1,
|
||||||
parameters: {},
|
parameters: {},
|
||||||
});
|
});
|
||||||
|
@@ -2,14 +2,14 @@ import Base from './base';
|
|||||||
import Flow from './flow';
|
import Flow from './flow';
|
||||||
import Connection from './connection';
|
import Connection from './connection';
|
||||||
import ExecutionStep from './execution-step';
|
import ExecutionStep from './execution-step';
|
||||||
import StepEnumType from '../types/step-enum-type';
|
import { StepType } from '../types/step';
|
||||||
|
|
||||||
class Step extends Base {
|
class Step extends Base {
|
||||||
id!: number;
|
id!: number;
|
||||||
flowId!: string;
|
flowId!: string;
|
||||||
key: string;
|
key: string;
|
||||||
appKey: string;
|
appKey: string;
|
||||||
type!: StepEnumType;
|
type!: StepType;
|
||||||
connectionId?: string;
|
connectionId?: string;
|
||||||
status: string;
|
status: string;
|
||||||
position: number;
|
position: number;
|
||||||
|
@@ -1,13 +1,19 @@
|
|||||||
|
import get from 'lodash.get';
|
||||||
import App from '../models/app';
|
import App from '../models/app';
|
||||||
import Flow from '../models/flow';
|
import Flow from '../models/flow';
|
||||||
import Step from '../models/step';
|
import Step from '../models/step';
|
||||||
import Execution from '../models/execution';
|
import Execution from '../models/execution';
|
||||||
import ExecutionStep from '../models/execution-step';
|
import ExecutionStep from '../models/execution-step';
|
||||||
|
import { StepType } from '../types/step';
|
||||||
|
|
||||||
|
type ExecutionSteps = Record<string, ExecutionStep>;
|
||||||
|
|
||||||
class Processor {
|
class Processor {
|
||||||
flow: Flow;
|
flow: Flow;
|
||||||
untilStep: Step;
|
untilStep: Step;
|
||||||
|
|
||||||
|
static variableRegExp = /({{step\.\d*\..+?}})/g;
|
||||||
|
|
||||||
constructor(flow: Flow, untilStep: Step) {
|
constructor(flow: Flow, untilStep: Step) {
|
||||||
this.flow = flow;
|
this.flow = flow;
|
||||||
this.untilStep = untilStep;
|
this.untilStep = untilStep;
|
||||||
@@ -26,48 +32,71 @@ class Processor {
|
|||||||
|
|
||||||
let previousExecutionStep: ExecutionStep;
|
let previousExecutionStep: ExecutionStep;
|
||||||
let fetchedData;
|
let fetchedData;
|
||||||
|
const priorExecutionSteps: ExecutionSteps = {};
|
||||||
|
|
||||||
for await (const step of steps) {
|
for await (const step of steps) {
|
||||||
const appData = App.findOneByKey(step.appKey);
|
const appData = App.findOneByKey(step.appKey);
|
||||||
|
const {
|
||||||
|
appKey,
|
||||||
|
connection,
|
||||||
|
key,
|
||||||
|
type,
|
||||||
|
parameters: rawParameters = {},
|
||||||
|
id
|
||||||
|
} = step;
|
||||||
|
const isTrigger = type === StepType.Trigger;
|
||||||
|
const AppClass = (await import(`../apps/${appKey}`)).default;
|
||||||
|
const computedParameters = Processor.computeParameters(rawParameters, priorExecutionSteps);
|
||||||
|
const appInstance = new AppClass(appData, connection.data, computedParameters);
|
||||||
|
const commands = isTrigger ? appInstance.triggers : appInstance.actions;
|
||||||
|
const command = commands[key];
|
||||||
|
fetchedData = await command.run();
|
||||||
|
|
||||||
if (step.type.toString() === 'trigger') {
|
previousExecutionStep = await execution
|
||||||
const appClass = (await import(`../apps/${step.appKey}`)).default;
|
.$relatedQuery('executionSteps')
|
||||||
const appInstance = new appClass(appData, step.connection.data);
|
.insertAndFetch({
|
||||||
fetchedData = await appInstance.triggers[step.key].run();
|
stepId: id,
|
||||||
|
status: 'success',
|
||||||
|
dataIn: previousExecutionStep?.dataOut,
|
||||||
|
dataOut: fetchedData,
|
||||||
|
});
|
||||||
|
|
||||||
previousExecutionStep = await execution
|
priorExecutionSteps[id] = previousExecutionStep;
|
||||||
.$relatedQuery('executionSteps')
|
|
||||||
.insertAndFetch({
|
|
||||||
stepId: step.id,
|
|
||||||
status: 'success',
|
|
||||||
dataOut: fetchedData,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const appClass = (await import(`../apps/${step.appKey}`)).default;
|
|
||||||
const appInstance = new appClass(
|
|
||||||
appData,
|
|
||||||
step.connection.data,
|
|
||||||
step.parameters
|
|
||||||
);
|
|
||||||
fetchedData = await appInstance.actions[step.key].run();
|
|
||||||
|
|
||||||
previousExecutionStep = await execution
|
if (id === this.untilStep.id) {
|
||||||
.$relatedQuery('executionSteps')
|
|
||||||
.insertAndFetch({
|
|
||||||
stepId: step.id,
|
|
||||||
status: 'success',
|
|
||||||
dataIn: previousExecutionStep.dataOut,
|
|
||||||
dataOut: fetchedData,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (step.id === this.untilStep.id) {
|
|
||||||
return fetchedData;
|
return fetchedData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fetchedData;
|
return fetchedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static computeParameters(parameters: Step["parameters"], executionSteps: ExecutionSteps): Step["parameters"] {
|
||||||
|
const entries = Object.entries(parameters);
|
||||||
|
return entries.reduce((result, [key, value]: [string, string]) => {
|
||||||
|
const parts = value.split(Processor.variableRegExp);
|
||||||
|
|
||||||
|
const computedValue = parts.map((part: string) => {
|
||||||
|
const isVariable = part.match(Processor.variableRegExp);
|
||||||
|
if (isVariable) {
|
||||||
|
const stepIdAndKeyPath = part.replace(/{{step.|}}/g, '') as string;
|
||||||
|
const [stepId, ...keyPaths] = stepIdAndKeyPath.split('.');
|
||||||
|
const keyPath = keyPaths.join('.');
|
||||||
|
const executionStep = executionSteps[stepId.toString() as string];
|
||||||
|
const data = executionStep?.dataOut;
|
||||||
|
const dataValue = get(data, keyPath);
|
||||||
|
return dataValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return part;
|
||||||
|
}).join('');
|
||||||
|
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
[key]: computedValue,
|
||||||
|
}
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Processor;
|
export default Processor;
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
enum StepEnumType {
|
|
||||||
Trigger = 'trigger',
|
|
||||||
Action = 'action',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default StepEnumType;
|
|
4
packages/backend/src/types/step.ts
Normal file
4
packages/backend/src/types/step.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export enum StepType {
|
||||||
|
Trigger = 'trigger',
|
||||||
|
Action = 'action',
|
||||||
|
}
|
@@ -4166,6 +4166,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||||
|
|
||||||
|
"@types/lodash.get@^4.4.6":
|
||||||
|
version "4.4.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash.get/-/lodash.get-4.4.6.tgz#0c7ac56243dae0f9f09ab6f75b29471e2e777240"
|
||||||
|
integrity sha512-E6zzjR3GtNig8UJG/yodBeJeIOtgPkMgsLjDU3CbgCAPC++vJ0eCMnJhVpRZb/ENqEFlov1+3K9TKtY4UdWKtQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/lodash" "*"
|
||||||
|
|
||||||
"@types/lodash.template@^4.5.0":
|
"@types/lodash.template@^4.5.0":
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/lodash.template/-/lodash.template-4.5.0.tgz#277654af717ed37ce2687c69f8f221c550276b7a"
|
resolved "https://registry.yarnpkg.com/@types/lodash.template/-/lodash.template-4.5.0.tgz#277654af717ed37ce2687c69f8f221c550276b7a"
|
||||||
|
Reference in New Issue
Block a user