refactor(plugin-workflow): adjust some api and packages (#3281)

* fix(plugin-workflow): fix locale and some api

* fix(plugin-workflow-test): fix test package

* fix(plugin-workflow): fix package and types

* test(plugin-workflow): test package
This commit is contained in:
Junyi 2023-12-29 09:29:37 +08:00 committed by GitHub
parent c9d5292d03
commit 7f0d699590
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 57 additions and 63 deletions

6
.vscode/launch.json vendored
View File

@ -14,14 +14,14 @@
{ {
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"name": "Debug Jest Tests", "name": "Debug Tests",
"runtimeExecutable": "yarn", "runtimeExecutable": "yarn",
"runtimeArgs": ["run", "--inspect-brk", "test", "--runInBand", "${file}"], "runtimeArgs": ["run", "--inspect-brk", "test", "${file}"],
"skipFiles": ["<node_internals>/**"], "skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal", "console": "integratedTerminal",
"internalConsoleOptions": "neverOpen", "internalConsoleOptions": "neverOpen",
"windows": { "windows": {
"runtimeArgs": ["run", "--inspect-brk", "test", "--runInBand", "/${fileBasename}"] "runtimeArgs": ["run", "--inspect-brk", "test", "/${fileBasename}"]
} }
}, },
{ {

View File

@ -8,6 +8,7 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"main": "./dist/server/index.js", "main": "./dist/server/index.js",
"devDependencies": { "devDependencies": {
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"antd": "5.x", "antd": "5.x",
"react": "18.x", "react": "18.x",
"react-i18next": "^11.15.1" "react-i18next": "^11.15.1"
@ -16,7 +17,6 @@
"@nocobase/client": "0.x", "@nocobase/client": "0.x",
"@nocobase/database": "0.x", "@nocobase/database": "0.x",
"@nocobase/plugin-workflow": ">=0.17.0-alpha.3", "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x" "@nocobase/test": "0.x"
}, },

View File

@ -8,6 +8,7 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"main": "./dist/server/index.js", "main": "./dist/server/index.js",
"devDependencies": { "devDependencies": {
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"antd": "5.x", "antd": "5.x",
"react": "18.x", "react": "18.x",
"react-i18next": "^11.15.1" "react-i18next": "^11.15.1"
@ -16,7 +17,6 @@
"@nocobase/client": "0.x", "@nocobase/client": "0.x",
"@nocobase/database": "0.x", "@nocobase/database": "0.x",
"@nocobase/plugin-workflow": ">=0.17.0-alpha.3", "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x" "@nocobase/test": "0.x"
}, },

View File

@ -12,6 +12,7 @@
"@formily/antd-v5": "1.x", "@formily/antd-v5": "1.x",
"@formily/core": "2.x", "@formily/core": "2.x",
"@formily/react": "2.x", "@formily/react": "2.x",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"antd": "5.x", "antd": "5.x",
"lodash": "4.17.21", "lodash": "4.17.21",
"react": "18.x", "react": "18.x",
@ -24,7 +25,6 @@
"@nocobase/evaluators": "0.x", "@nocobase/evaluators": "0.x",
"@nocobase/plugin-collection-manager": "0.x", "@nocobase/plugin-collection-manager": "0.x",
"@nocobase/plugin-workflow": ">=0.17.0-alpha.3", "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x", "@nocobase/test": "0.x",
"@nocobase/utils": "0.x" "@nocobase/utils": "0.x"

View File

@ -8,6 +8,7 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"main": "./dist/server/index.js", "main": "./dist/server/index.js",
"devDependencies": { "devDependencies": {
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"antd": "5.x", "antd": "5.x",
"react": "18.x", "react": "18.x",
"react-i18next": "^11.15.1" "react-i18next": "^11.15.1"
@ -16,7 +17,6 @@
"@nocobase/client": "0.x", "@nocobase/client": "0.x",
"@nocobase/database": "0.x", "@nocobase/database": "0.x",
"@nocobase/plugin-workflow": ">=0.17.0-alpha.3", "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x" "@nocobase/test": "0.x"
}, },

View File

@ -9,6 +9,7 @@
"main": "./dist/server/index.js", "main": "./dist/server/index.js",
"devDependencies": { "devDependencies": {
"@ant-design/icons": "5.x", "@ant-design/icons": "5.x",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"react": "18.x", "react": "18.x",
"react-i18next": "^11.15.1" "react-i18next": "^11.15.1"
}, },
@ -16,7 +17,6 @@
"@nocobase/client": "0.x", "@nocobase/client": "0.x",
"@nocobase/database": "0.x", "@nocobase/database": "0.x",
"@nocobase/plugin-workflow": ">=0.17.0-alpha.3", "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x" "@nocobase/test": "0.x"
}, },

View File

@ -4,6 +4,5 @@
"Loop index": "当前索引", "Loop index": "当前索引",
"Loop length": "循环长度", "Loop length": "循环长度",
"By using a loop node, you can perform the same operation on multiple sets of data. The source of these sets can be either multiple records from a query node or multiple associated records of a single record. Loop node can also be used for iterating a certain number of times or for looping through each character in a string. However, excessive looping may cause performance issues, so use with caution.": "使用循环节点可以对多条数据进行同样的操作,多条数据的来源可以是查询节点的多条结果,或者一条数据的多条关系数据。也可以用于一定次数的循环,或者对字符串中每一个字符的循环处理。循环次数过高可能引起性能问题,请谨慎使用。", "By using a loop node, you can perform the same operation on multiple sets of data. The source of these sets can be either multiple records from a query node or multiple associated records of a single record. Loop node can also be used for iterating a certain number of times or for looping through each character in a string. However, excessive looping may cause performance issues, so use with caution.": "使用循环节点可以对多条数据进行同样的操作,多条数据的来源可以是查询节点的多条结果,或者一条数据的多条关系数据。也可以用于一定次数的循环,或者对字符串中每一个字符的循环处理。循环次数过高可能引起性能问题,请谨慎使用。",
"Scope variables": "局域变量",
"A single number will be treated as a loop count, a single string will be treated as an array of characters, and other non-array values will be converted to arrays. The loop node ends when the loop count is reached, or when the array loop is completed. You can also add condition nodes to the loop to terminate it.": "单一数字值将被视为循环次数,单一字符串值将被视为字符数组,其他非数组值将被转换为数组。达到循环次数,或者将数组循环完成后,循环节点结束。你也可以在循环中添加条件节点,以终止循环。" "A single number will be treated as a loop count, a single string will be treated as an array of characters, and other non-array values will be converted to arrays. The loop node ends when the loop count is reached, or when the array loop is completed. You can also add condition nodes to the loop to terminate it.": "单一数字值将被视为循环次数,单一字符串值将被视为字符数组,其他非数组值将被转换为数组。达到循环次数,或者将数组循环完成后,循环节点结束。你也可以在循环中添加条件节点,以终止循环。"
} }

View File

@ -12,6 +12,7 @@
"@formily/antd-v5": "1.x", "@formily/antd-v5": "1.x",
"@formily/core": "2.x", "@formily/core": "2.x",
"@formily/react": "2.x", "@formily/react": "2.x",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"antd": "5.x", "antd": "5.x",
"lodash": "4.17.21", "lodash": "4.17.21",
"react": "18.x", "react": "18.x",
@ -24,7 +25,6 @@
"@nocobase/plugin-collection-manager": "0.x", "@nocobase/plugin-collection-manager": "0.x",
"@nocobase/plugin-users": "0.x", "@nocobase/plugin-users": "0.x",
"@nocobase/plugin-workflow": ">=0.17.0-alpha.3", "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x", "@nocobase/test": "0.x",
"@nocobase/utils": "0.x" "@nocobase/utils": "0.x"

View File

@ -1,5 +1,4 @@
import Database from '@nocobase/database'; import Database from '@nocobase/database';
import UserPlugin from '@nocobase/plugin-users';
import { MockServer } from '@nocobase/test'; import { MockServer } from '@nocobase/test';
import { EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow'; import { EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow';
import { getApp, sleep } from '@nocobase/plugin-workflow-test'; import { getApp, sleep } from '@nocobase/plugin-workflow-test';
@ -38,7 +37,6 @@ describe('workflow > instructions > manual', () => {
{ id: 2, nickname: 'b' }, { id: 2, nickname: 'b' },
]); ]);
const userPlugin = app.getPlugin('users') as UserPlugin;
userAgents = users.map((user) => app.agent().login(user)); userAgents = users.map((user) => app.agent().login(user));
workflow = await WorkflowModel.create({ workflow = await WorkflowModel.create({

View File

@ -12,7 +12,7 @@ export async function submit(context: Context, next) {
return context.throw(401); return context.throw(401);
} }
const plugin: WorkflowPlugin = context.app.pm.get('workflow') as WorkflowPlugin; const plugin: WorkflowPlugin = context.app.getPlugin(WorkflowPlugin);
const instruction = plugin.instructions.get('manual') as ManualInstruction; const instruction = plugin.instructions.get('manual') as ManualInstruction;
const userJob = await repository.findOne({ const userJob = await repository.findOne({

View File

@ -9,6 +9,7 @@
"main": "./dist/server/index.js", "main": "./dist/server/index.js",
"devDependencies": { "devDependencies": {
"@ant-design/icons": "5.x", "@ant-design/icons": "5.x",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"antd": "5.x", "antd": "5.x",
"react": "18.x", "react": "18.x",
"react-i18next": "^11.15.1" "react-i18next": "^11.15.1"
@ -17,7 +18,6 @@
"@nocobase/client": "0.x", "@nocobase/client": "0.x",
"@nocobase/database": "0.x", "@nocobase/database": "0.x",
"@nocobase/plugin-workflow": ">=0.17.0-alpha.3", "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x" "@nocobase/test": "0.x"
}, },

View File

@ -8,6 +8,7 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"main": "./dist/server/index.js", "main": "./dist/server/index.js",
"devDependencies": { "devDependencies": {
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"antd": "5.x", "antd": "5.x",
"react": "18.x", "react": "18.x",
"react-i18next": "^11.15.1" "react-i18next": "^11.15.1"
@ -16,7 +17,6 @@
"@nocobase/client": "0.x", "@nocobase/client": "0.x",
"@nocobase/database": "0.x", "@nocobase/database": "0.x",
"@nocobase/plugin-workflow": ">=0.17.0-alpha.3", "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x" "@nocobase/test": "0.x"
}, },

View File

@ -8,6 +8,7 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"main": "./dist/server/index.js", "main": "./dist/server/index.js",
"devDependencies": { "devDependencies": {
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"antd": "5.x", "antd": "5.x",
"react": "18.x", "react": "18.x",
"react-i18next": "^11.15.1" "react-i18next": "^11.15.1"
@ -16,7 +17,6 @@
"@nocobase/client": "0.x", "@nocobase/client": "0.x",
"@nocobase/database": "0.x", "@nocobase/database": "0.x",
"@nocobase/plugin-workflow": ">=0.17.0-alpha.3", "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x" "@nocobase/test": "0.x"
}, },

View File

@ -55,24 +55,24 @@ export async function getApp({
...options, ...options,
autoStart, autoStart,
cleanDb, cleanDb,
plugins: ['workflow', 'workflow-test', ...plugins], plugins: [
[
'workflow',
{
instructions,
functions,
},
],
WorkflowTestPlugin,
...plugins,
],
}); });
} }
export default class extends Plugin { export default class WorkflowTestPlugin extends Plugin {
async load() { async load() {
await this.db.import({ await this.db.import({
directory: path.resolve(__dirname, 'collections'), directory: path.resolve(__dirname, 'collections'),
}); });
const workflow = this.app.getPlugin<any>('workflow');
for (const [key, instruction] of Object.entries(instructions)) {
workflow.instructions.register(key, instruction);
}
for (const [key, func] of Object.entries(functions)) {
workflow.functions.register(key, func);
}
} }
} }

View File

@ -13,6 +13,7 @@ export default {
error: { error: {
run(node, input, processor) { run(node, input, processor) {
throw new Error('definite error'); throw new Error('definite error');
return null;
}, },
}, },
@ -45,6 +46,7 @@ export default {
}, },
resume(node, input, processor) { resume(node, input, processor) {
throw new Error('input failed'); throw new Error('input failed');
return null;
}, },
}, },

View File

@ -13,6 +13,7 @@
"@formily/core": "2.x", "@formily/core": "2.x",
"@formily/react": "2.x", "@formily/react": "2.x",
"@types/ejs": "^3.1.1", "@types/ejs": "^3.1.1",
"@nocobase/plugin-workflow-test": ">= 0.18.0-alpha.2",
"antd": "5.x", "antd": "5.x",
"axios": "^0.26.1", "axios": "^0.26.1",
"classnames": "^2.3.1", "classnames": "^2.3.1",
@ -24,8 +25,7 @@
"react-i18next": "^11.15.1", "react-i18next": "^11.15.1",
"react-js-cron": "^3.1.0", "react-js-cron": "^3.1.0",
"react-router-dom": "^6.11.2", "react-router-dom": "^6.11.2",
"sequelize": "^6.26.0", "sequelize": "^6.26.0"
"winston": "^3.8.2"
}, },
"peerDependencies": { "peerDependencies": {
"@nocobase/actions": "0.x", "@nocobase/actions": "0.x",
@ -36,11 +36,10 @@
"@nocobase/plugin-collection-manager": "0.x", "@nocobase/plugin-collection-manager": "0.x",
"@nocobase/plugin-error-handler": "0.x", "@nocobase/plugin-error-handler": "0.x",
"@nocobase/plugin-users": "0.x", "@nocobase/plugin-users": "0.x",
"@nocobase/plugin-workflow-test": ">=0.17.0-alpha.3",
"@nocobase/resourcer": "0.x", "@nocobase/resourcer": "0.x",
"@nocobase/server": "0.x", "@nocobase/server": "0.x",
"@nocobase/test": "0.x", "@nocobase/utils": "0.x",
"@nocobase/utils": "0.x" "@nocobase/test": "0.x"
}, },
"gitHead": "ce588eefb0bfc50f7d5bbee575e0b5e843bf6644" "gitHead": "ce588eefb0bfc50f7d5bbee575e0b5e843bf6644"
} }

View File

@ -162,7 +162,7 @@ function Calculation({ calculator, operands = [], onChange }) {
aria-label="select-operator-calc" aria-label="select-operator-calc"
value={calculator} value={calculator}
onChange={(v) => onChange({ operands, calculator: v })} onChange={(v) => onChange({ operands, calculator: v })}
placeholder={lang('Calculator')} placeholder={lang('Operator')}
popupMatchSelectWidth={false} popupMatchSelectWidth={false}
> >
{calculatorGroups {calculatorGroups

View File

@ -88,13 +88,15 @@ export function useNodeContext() {
return useContext(NodeContext); return useContext(NodeContext);
} }
export function useAvailableUpstreams(node) { export function useAvailableUpstreams(node, filter?) {
const stack: any[] = []; const stack: any[] = [];
if (!node) { if (!node) {
return []; return [];
} }
for (let current = node.upstream; current; current = current.upstream) { for (let current = node.upstream; current; current = current.upstream) {
stack.push(current); if (typeof filter !== 'function' || filter(current)) {
stack.push(current);
}
} }
return stack; return stack;

View File

@ -58,7 +58,7 @@
"Null": "Null", "Null": "Null",
"Boolean": "Boolean", "Boolean": "Boolean",
"String": "String", "String": "String",
"Calculator": "Calculator", "Operator": "Operator",
"Arithmetic calculation": "Arithmetic calculation", "Arithmetic calculation": "Arithmetic calculation",
"String operation": "String operation", "String operation": "String operation",
"Executed at": "Executed at", "Executed at": "Executed at",

View File

@ -58,7 +58,7 @@
"Null": "Null", "Null": "Null",
"Boolean": "Booleano", "Boolean": "Booleano",
"String": "Cadena", "String": "Cadena",
"Calculator": "Calculadora", "Operator": "Calculadora",
"Arithmetic calculation": "Cálculo aritmético", "Arithmetic calculation": "Cálculo aritmético",
"String operation": "Operación de Cadena", "String operation": "Operación de Cadena",
"Executed at": "Ejecutado en", "Executed at": "Ejecutado en",

View File

@ -58,7 +58,7 @@
"Null": "Null", "Null": "Null",
"Boolean": "Booléen", "Boolean": "Booléen",
"String": "Chaîne de caractères", "String": "Chaîne de caractères",
"Calculator": "Calculatrice", "Operator": "Calculatrice",
"Arithmetic calculation": "Calcul arithmétique", "Arithmetic calculation": "Calcul arithmétique",
"String operation": "Opération sur les chaînes de caractères", "String operation": "Opération sur les chaînes de caractères",
"Executed at": "Exécuté à", "Executed at": "Exécuté à",

View File

@ -58,7 +58,7 @@
"Null": "Nulo", "Null": "Nulo",
"Boolean": "Booleano", "Boolean": "Booleano",
"String": "String", "String": "String",
"Calculator": "Calculadora", "Operator": "Calculadora",
"Arithmetic calculation": "Cálculo aritmético", "Arithmetic calculation": "Cálculo aritmético",
"String operation": "Operação de string", "String operation": "Operação de string",
"Executed at": "Executado em", "Executed at": "Executado em",

View File

@ -83,7 +83,9 @@
"End": "结束", "End": "结束",
"Node result": "节点数据", "Node result": "节点数据",
"Variable key of node": "节点变量标识", "Variable key of node": "节点变量标识",
"Calculator": "运算", "Scope variables": "局域变量",
"Operator": "运算符",
"Calculate an expression based on a calculation engine and obtain a value as the result. Variables in the upstream nodes can be used in the expression. The expression can be static or dynamic one from an expression collections.": "Calculate an expression based on a calculation engine and obtain a value as the result. Variables in the upstream nodes can be used in the expression. The expression can be static or dynamic one from an expression collections.":
"基于计算引擎对一个表达式进行计算,并获得一个值作为结果。表达式中可以使用上游节点里的变量。表达式可以是静态的,也可以是表达式表中的动态表达式。", "基于计算引擎对一个表达式进行计算,并获得一个值作为结果。表达式中可以使用上游节点里的变量。表达式可以是静态的,也可以是表达式表中的动态表达式。",
"String operation": "字符串", "String operation": "字符串",

View File

@ -1,13 +1,12 @@
import path from 'path'; import path from 'path';
import LRUCache from 'lru-cache'; import LRUCache from 'lru-cache';
import winston from 'winston';
import { Op } from '@nocobase/database'; import { Op } from '@nocobase/database';
import { Plugin } from '@nocobase/server'; import { Plugin } from '@nocobase/server';
import { Registry } from '@nocobase/utils'; import { Registry } from '@nocobase/utils';
import { createLogger, getLoggerFilePath, getLoggerLevel, Logger, LoggerOptions } from '@nocobase/logger'; import { Logger, LoggerOptions } from '@nocobase/logger';
import Processor from './Processor'; import Processor from './Processor';
import initActions from './actions'; import initActions from './actions';
import { EXECUTION_STATUS } from './constants'; import { EXECUTION_STATUS } from './constants';
@ -15,7 +14,7 @@ import initFunctions, { CustomFunction } from './functions';
import Trigger from './triggers'; import Trigger from './triggers';
import CollectionTrigger from './triggers/CollectionTrigger'; import CollectionTrigger from './triggers/CollectionTrigger';
import ScheduleTrigger from './triggers/ScheduleTrigger'; import ScheduleTrigger from './triggers/ScheduleTrigger';
import Instruction from './instructions'; import { Instruction, InstructionInterface } from './instructions';
import CalculationInstruction from './instructions/CalculationInstruction'; import CalculationInstruction from './instructions/CalculationInstruction';
import ConditionInstruction from './instructions/ConditionInstruction'; import ConditionInstruction from './instructions/ConditionInstruction';
import CreateInstruction from './instructions/CreateInstruction'; import CreateInstruction from './instructions/CreateInstruction';
@ -32,7 +31,7 @@ type Pending = [ExecutionModel, JobModel?];
type CachedEvent = [WorkflowModel, any, { context?: any }]; type CachedEvent = [WorkflowModel, any, { context?: any }];
export default class WorkflowPlugin extends Plugin { export default class WorkflowPlugin extends Plugin {
instructions: Registry<Instruction> = new Registry(); instructions: Registry<InstructionInterface> = new Registry();
triggers: Registry<Trigger> = new Registry(); triggers: Registry<Trigger> = new Registry();
functions: Registry<CustomFunction> = new Registry(); functions: Registry<CustomFunction> = new Registry();
@ -118,7 +117,7 @@ export default class WorkflowPlugin extends Plugin {
} }
} }
registerInstruction<T extends Instruction>(type: string, instruction: T | { new (p: Plugin): T }) { registerInstruction(type: string, instruction: InstructionInterface | { new (p: Plugin): InstructionInterface }) {
if (typeof instruction === 'function') { if (typeof instruction === 'function') {
this.instructions.register(type, new instruction(this)); this.instructions.register(type, new instruction(this));
} else if (instruction) { } else if (instruction) {

View File

@ -6,22 +6,14 @@ import { JOB_STATUS } from '../constants';
import type { FlowNodeModel } from '../types'; import type { FlowNodeModel } from '../types';
export interface CalculationConfig { export interface CalculationConfig {
dynamic?: boolean | string;
engine?: string; engine?: string;
expression?: string; expression?: string;
} }
export class CalculationInstruction extends Instruction { export class CalculationInstruction extends Instruction {
async run(node: FlowNodeModel, prevJob, processor: Processor) { async run(node: FlowNodeModel, prevJob, processor: Processor) {
const { dynamic = false } = <CalculationConfig>node.config || {}; const { engine = 'math.js', expression = '' } = node.config;
let { engine = 'math.js', expression = '' } = node.config; const scope = processor.getScope(node.id);
let scope = processor.getScope(node.id);
if (dynamic) {
const parsed = parse(dynamic)(scope) ?? {};
engine = parsed.engine;
expression = parsed.expression;
scope = parse(node.config.scope ?? '')(scope) ?? {};
}
const evaluator = <Evaluator | undefined>evaluators.get(engine); const evaluator = <Evaluator | undefined>evaluators.get(engine);

View File

@ -15,18 +15,19 @@ export type InstructionResult = IJob | Promise<IJob> | null;
export type Runner = (node: FlowNodeModel, input: any, processor: Processor) => InstructionResult; export type Runner = (node: FlowNodeModel, input: any, processor: Processor) => InstructionResult;
export type InstructionInterface = {
run: Runner;
resume?: Runner;
getScope?: (node: FlowNodeModel, data: any, processor: Processor) => any;
duplicateConfig?: (node: FlowNodeModel, options: Transactionable) => object | Promise<object>;
};
// what should a instruction do? // what should a instruction do?
// - base on input and context, do any calculations or system call (io), and produce a result or pending. // - base on input and context, do any calculations or system call (io), and produce a result or pending.
export abstract class Instruction { export abstract class Instruction implements InstructionInterface {
constructor(public workflow: Plugin) {} constructor(public workflow: Plugin) {}
abstract run(node: FlowNodeModel, input: any, processor: Processor): InstructionResult; abstract run(node: FlowNodeModel, input: any, processor: Processor): InstructionResult;
resume?(node: FlowNodeModel, input: any, processor: Processor): InstructionResult;
getScope?(node: FlowNodeModel, data: any, processor: Processor): any;
duplicateConfig?(node: FlowNodeModel, options: Transactionable): object | Promise<object>;
} }
export default Instruction; export default Instruction;