@nocobase/plugin-workflow 1.8.0-beta.8 → 1.8.0
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/dist/client/256475f279fb46d1.js +10 -0
- package/dist/client/48fc0fadf459229d.js +10 -0
- package/dist/client/69d4f948046f2ad2.js +10 -0
- package/dist/client/98ae71d4cff2436b.js +10 -0
- package/dist/client/WorkflowTasks.d.ts +16 -4
- package/dist/client/components/NotificationFieldset.d.ts +12 -0
- package/dist/client/components/UsersSelect.d.ts +19 -0
- package/dist/client/components/index.d.ts +1 -0
- package/dist/client/hooks/useWorkflowExecuted.d.ts +2 -2
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/nodes/calculation.d.ts +1 -0
- package/dist/client/nodes/condition.d.ts +1 -0
- package/dist/client/schemas/executions.d.ts +1 -0
- package/dist/client/variable.d.ts +5 -2
- package/dist/common/collections/workflows.d.ts +14 -0
- package/dist/common/collections/workflows.js +1 -2
- package/dist/externalVersion.js +11 -10
- package/dist/locale/en-US.json +4 -1
- package/dist/locale/zh-CN.json +5 -1
- package/dist/node_modules/cron-parser/package.json +1 -1
- package/dist/node_modules/lru-cache/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/server/Plugin.d.ts +3 -1
- package/dist/server/Plugin.js +58 -18
- package/dist/server/actions/nodes.js +3 -4
- package/dist/server/actions/workflows.js +11 -3
- package/dist/server/instructions/CalculationInstruction.d.ts +10 -0
- package/dist/server/instructions/CalculationInstruction.js +15 -0
- package/dist/server/instructions/ConditionInstruction.d.ts +11 -0
- package/dist/server/instructions/ConditionInstruction.js +15 -0
- package/dist/server/migrations/20250619213102-add-missed-stats.d.ts +14 -0
- package/dist/server/migrations/20250619213102-add-missed-stats.js +61 -0
- package/package.json +4 -3
- package/dist/client/3c67def1831d0b23.js +0 -10
- package/dist/client/8e2ad933533030aa.js +0 -10
- package/dist/client/a4111333ce86663c.js +0 -10
- package/dist/client/f9eeb46e5c6a9ffe.js +0 -10
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import React from 'react';
|
|
10
|
+
import { CollectionManager } from '@nocobase/client';
|
|
10
11
|
export type VariableOption = {
|
|
11
12
|
key?: string;
|
|
12
13
|
value?: string;
|
|
@@ -21,7 +22,9 @@ export type VariableDataType = 'boolean' | 'number' | 'string' | 'date' | {
|
|
|
21
22
|
multiple?: boolean;
|
|
22
23
|
entity?: boolean;
|
|
23
24
|
};
|
|
24
|
-
} | ((field: any
|
|
25
|
+
} | ((field: any, options: {
|
|
26
|
+
collectionManager?: CollectionManager;
|
|
27
|
+
}) => boolean);
|
|
25
28
|
export type UseVariableOptions = {
|
|
26
29
|
types?: VariableDataType[];
|
|
27
30
|
fieldNames?: {
|
|
@@ -70,7 +73,7 @@ export declare const BaseTypeSets: {
|
|
|
70
73
|
};
|
|
71
74
|
export declare function useWorkflowVariableOptions(options?: UseVariableOptions): any[];
|
|
72
75
|
export declare function getCollectionFieldOptions(options: any): VariableOption[];
|
|
73
|
-
export declare function
|
|
76
|
+
export declare function useGetDataSourceCollectionManager(dataSourceName?: any): CollectionManager;
|
|
74
77
|
export declare function WorkflowVariableInput({ variableOptions, ...props }: {
|
|
75
78
|
[x: string]: any;
|
|
76
79
|
variableOptions: any;
|
|
@@ -223,6 +223,20 @@ declare const _default: {
|
|
|
223
223
|
constraints?: undefined;
|
|
224
224
|
through?: undefined;
|
|
225
225
|
otherKey?: undefined;
|
|
226
|
+
} | {
|
|
227
|
+
type: string;
|
|
228
|
+
name: string;
|
|
229
|
+
target: string;
|
|
230
|
+
foreignKey: string;
|
|
231
|
+
sourceKey: string;
|
|
232
|
+
constraints: boolean;
|
|
233
|
+
interface?: undefined;
|
|
234
|
+
uiSchema?: undefined;
|
|
235
|
+
defaultValue?: undefined;
|
|
236
|
+
required?: undefined;
|
|
237
|
+
onDelete?: undefined;
|
|
238
|
+
through?: undefined;
|
|
239
|
+
otherKey?: undefined;
|
|
226
240
|
} | {
|
|
227
241
|
type: string;
|
|
228
242
|
name: string;
|
package/dist/externalVersion.js
CHANGED
|
@@ -11,8 +11,8 @@ module.exports = {
|
|
|
11
11
|
"react": "18.2.0",
|
|
12
12
|
"@formily/core": "2.3.0",
|
|
13
13
|
"@formily/react": "2.3.0",
|
|
14
|
-
"@nocobase/client": "1.8.0
|
|
15
|
-
"@nocobase/utils": "1.8.0
|
|
14
|
+
"@nocobase/client": "1.8.0",
|
|
15
|
+
"@nocobase/utils": "1.8.0",
|
|
16
16
|
"antd": "5.24.2",
|
|
17
17
|
"@ant-design/icons": "5.6.1",
|
|
18
18
|
"react-router-dom": "6.28.1",
|
|
@@ -20,16 +20,17 @@ module.exports = {
|
|
|
20
20
|
"lodash": "4.17.21",
|
|
21
21
|
"@dnd-kit/core": "6.1.0",
|
|
22
22
|
"@formily/shared": "2.3.2",
|
|
23
|
+
"@nocobase/plugin-mobile": "1.8.0",
|
|
23
24
|
"sequelize": "6.35.2",
|
|
24
|
-
"@nocobase/database": "1.8.0
|
|
25
|
-
"@nocobase/server": "1.8.0
|
|
26
|
-
"@nocobase/data-source-manager": "1.8.0
|
|
27
|
-
"@nocobase/logger": "1.8.0
|
|
28
|
-
"@nocobase/evaluators": "1.8.0
|
|
25
|
+
"@nocobase/database": "1.8.0",
|
|
26
|
+
"@nocobase/server": "1.8.0",
|
|
27
|
+
"@nocobase/data-source-manager": "1.8.0",
|
|
28
|
+
"@nocobase/logger": "1.8.0",
|
|
29
|
+
"@nocobase/evaluators": "1.8.0",
|
|
29
30
|
"@formily/antd-v5": "1.2.3",
|
|
30
31
|
"@formily/reactive": "2.3.0",
|
|
31
|
-
"@nocobase/actions": "1.8.0
|
|
32
|
+
"@nocobase/actions": "1.8.0",
|
|
32
33
|
"dayjs": "1.11.13",
|
|
33
|
-
"@nocobase/plugin-workflow-test": "1.8.0
|
|
34
|
-
"@nocobase/test": "1.8.0
|
|
34
|
+
"@nocobase/plugin-workflow-test": "1.8.0",
|
|
35
|
+
"@nocobase/test": "1.8.0"
|
|
35
36
|
};
|
package/dist/locale/en-US.json
CHANGED
|
@@ -209,5 +209,8 @@
|
|
|
209
209
|
"Inside of branch": "Inside of branch",
|
|
210
210
|
"Workflow todos": "Workflow todos",
|
|
211
211
|
"New version enabled": "New version enabled",
|
|
212
|
-
"Workflow is not exists": "Workflow is not exists"
|
|
212
|
+
"Workflow is not exists": "Workflow is not exists",
|
|
213
|
+
"Select users": "Select users",
|
|
214
|
+
"Query users": "Query users",
|
|
215
|
+
"Add": "Add"
|
|
213
216
|
}
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"cron-parser","version":"4.4.0","description":"Node.js library for parsing crontab instructions","main":"lib/parser.js","types":"index.d.ts","typesVersions":{"<4.1":{"*":["types/ts3/*"]}},"directories":{"test":"test"},"scripts":{"test:tsd":"tsd","test:unit":"TZ=UTC tap ./test/*.js","test:cover":"TZ=UTC tap --coverage-report=html ./test/*.js","lint":"eslint .","lint:fix":"eslint --fix .","test":"npm run lint && npm run test:unit && npm run test:tsd"},"repository":{"type":"git","url":"https://github.com/harrisiirak/cron-parser.git"},"keywords":["cron","crontab","parser"],"author":"Harri Siirak","contributors":["Nicholas Clawson","Daniel Prentis <daniel@salsitasoft.com>","Renault John Lecoultre","Richard Astbury <richard.astbury@gmail.com>","Meaglin Wasabi <Meaglin.wasabi@gmail.com>","Mike Kusold <hello@mikekusold.com>","Alex Kit <alex.kit@atmajs.com>","Santiago Gimeno <santiago.gimeno@gmail.com>","Daniel <darc.tec@gmail.com>","Christian Steininger <christian.steininger.cs@gmail.com>","Mykola Piskovyi <m.piskovyi@gmail.com>","Brian Vaughn <brian.david.vaughn@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Yasuhiroki <yasuhiroki.duck@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Brendan Warkentin <faazshift@gmail.com>","Charlie Fish <fishcharlie.code@gmail.com>","Ian Graves <ian+diskimage@iangrav.es>","Andy Thompson <me@andytson.com>","Regev Brody <regevbr@gmail.com>"],"license":"MIT","dependencies":{"luxon":"^1.28.0"},"devDependencies":{"eslint":"^8.2.0","sinon":"^10.0.0","tap":"^16.0.1","tsd":"^0.19.0"},"engines":{"node":">=0.8"},"browser":{"fs":false},"tap":{"check-coverage":false},"tsd":{"directory":"test","compilerOptions":{"lib":["es2017","dom"]}},"_lastModified":"2025-
|
|
1
|
+
{"name":"cron-parser","version":"4.4.0","description":"Node.js library for parsing crontab instructions","main":"lib/parser.js","types":"index.d.ts","typesVersions":{"<4.1":{"*":["types/ts3/*"]}},"directories":{"test":"test"},"scripts":{"test:tsd":"tsd","test:unit":"TZ=UTC tap ./test/*.js","test:cover":"TZ=UTC tap --coverage-report=html ./test/*.js","lint":"eslint .","lint:fix":"eslint --fix .","test":"npm run lint && npm run test:unit && npm run test:tsd"},"repository":{"type":"git","url":"https://github.com/harrisiirak/cron-parser.git"},"keywords":["cron","crontab","parser"],"author":"Harri Siirak","contributors":["Nicholas Clawson","Daniel Prentis <daniel@salsitasoft.com>","Renault John Lecoultre","Richard Astbury <richard.astbury@gmail.com>","Meaglin Wasabi <Meaglin.wasabi@gmail.com>","Mike Kusold <hello@mikekusold.com>","Alex Kit <alex.kit@atmajs.com>","Santiago Gimeno <santiago.gimeno@gmail.com>","Daniel <darc.tec@gmail.com>","Christian Steininger <christian.steininger.cs@gmail.com>","Mykola Piskovyi <m.piskovyi@gmail.com>","Brian Vaughn <brian.david.vaughn@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Yasuhiroki <yasuhiroki.duck@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Brendan Warkentin <faazshift@gmail.com>","Charlie Fish <fishcharlie.code@gmail.com>","Ian Graves <ian+diskimage@iangrav.es>","Andy Thompson <me@andytson.com>","Regev Brody <regevbr@gmail.com>"],"license":"MIT","dependencies":{"luxon":"^1.28.0"},"devDependencies":{"eslint":"^8.2.0","sinon":"^10.0.0","tap":"^16.0.1","tsd":"^0.19.0"},"engines":{"node":">=0.8"},"browser":{"fs":false},"tap":{"check-coverage":false},"tsd":{"directory":"test","compilerOptions":{"lib":["es2017","dom"]}},"_lastModified":"2025-07-07T11:16:51.530Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"lru-cache","description":"A cache object that deletes the least-recently-used items.","version":"8.0.5","author":"Isaac Z. Schlueter <i@izs.me>","keywords":["mru","lru","cache"],"sideEffects":false,"scripts":{"build":"npm run prepare","preprepare":"rm -rf dist","prepare":"tsc -p tsconfig.json && tsc -p tsconfig-esm.json","postprepare":"bash fixup.sh","pretest":"npm run prepare","presnap":"npm run prepare","test":"c8 tap","snap":"c8 tap","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","format":"prettier --write .","typedoc":"typedoc --tsconfig tsconfig-esm.json ./src/*.ts","benchmark-results-typedoc":"bash scripts/benchmark-results-typedoc.sh","prebenchmark":"npm run prepare","benchmark":"make -C benchmark","preprofile":"npm run prepare","profile":"make -C benchmark profile"},"main":"./dist/cjs/index-cjs.js","module":"./dist/mjs/index.js","types":"./dist/mjs/index.d.ts","exports":{"./min":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.min.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.min.js"}},".":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index-cjs.js"}}},"repository":"git://github.com/isaacs/node-lru-cache.git","devDependencies":{"@size-limit/preset-small-lib":"^7.0.8","@types/node":"^17.0.31","@types/tap":"^15.0.6","benchmark":"^2.1.4","c8":"^7.11.2","clock-mock":"^1.0.6","esbuild":"^0.17.11","eslint-config-prettier":"^8.5.0","marked":"^4.2.12","mkdirp":"^2.1.5","prettier":"^2.6.2","size-limit":"^7.0.8","tap":"^16.3.4","ts-node":"^10.7.0","tslib":"^2.4.0","typedoc":"^0.23.24","typescript":"^4.6.4"},"license":"ISC","files":["dist"],"engines":{"node":">=16.14"},"prettier":{"semi":false,"printWidth":70,"tabWidth":2,"useTabs":false,"singleQuote":true,"jsxSingleQuote":false,"bracketSameLine":true,"arrowParens":"avoid","endOfLine":"lf"},"tap":{"coverage":false,"node-arg":["--expose-gc","--no-warnings","--loader","ts-node/esm"],"ts":false},"size-limit":[{"path":"./dist/mjs/index.js"}],"_lastModified":"2025-
|
|
1
|
+
{"name":"lru-cache","description":"A cache object that deletes the least-recently-used items.","version":"8.0.5","author":"Isaac Z. Schlueter <i@izs.me>","keywords":["mru","lru","cache"],"sideEffects":false,"scripts":{"build":"npm run prepare","preprepare":"rm -rf dist","prepare":"tsc -p tsconfig.json && tsc -p tsconfig-esm.json","postprepare":"bash fixup.sh","pretest":"npm run prepare","presnap":"npm run prepare","test":"c8 tap","snap":"c8 tap","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","format":"prettier --write .","typedoc":"typedoc --tsconfig tsconfig-esm.json ./src/*.ts","benchmark-results-typedoc":"bash scripts/benchmark-results-typedoc.sh","prebenchmark":"npm run prepare","benchmark":"make -C benchmark","preprofile":"npm run prepare","profile":"make -C benchmark profile"},"main":"./dist/cjs/index-cjs.js","module":"./dist/mjs/index.js","types":"./dist/mjs/index.d.ts","exports":{"./min":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.min.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.min.js"}},".":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index-cjs.js"}}},"repository":"git://github.com/isaacs/node-lru-cache.git","devDependencies":{"@size-limit/preset-small-lib":"^7.0.8","@types/node":"^17.0.31","@types/tap":"^15.0.6","benchmark":"^2.1.4","c8":"^7.11.2","clock-mock":"^1.0.6","esbuild":"^0.17.11","eslint-config-prettier":"^8.5.0","marked":"^4.2.12","mkdirp":"^2.1.5","prettier":"^2.6.2","size-limit":"^7.0.8","tap":"^16.3.4","ts-node":"^10.7.0","tslib":"^2.4.0","typedoc":"^0.23.24","typescript":"^4.6.4"},"license":"ISC","files":["dist"],"engines":{"node":">=16.14"},"prettier":{"semi":false,"printWidth":70,"tabWidth":2,"useTabs":false,"singleQuote":true,"jsxSingleQuote":false,"bracketSameLine":true,"arrowParens":"avoid","endOfLine":"lf"},"tap":{"coverage":false,"node-arg":["--expose-gc","--no-warnings","--loader","ts-node/esm"],"ts":false},"size-limit":[{"path":"./dist/mjs/index.js"}],"_lastModified":"2025-07-07T11:16:51.184Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"nodejs-snowflake","collaborators":["Utkarsh Srivastava <utkarsh@sagacious.dev>"],"description":"Generate time sortable 64 bits unique ids for distributed systems (inspired from twitter snowflake)","version":"2.0.1","license":"Apache 2.0","repository":{"type":"git","url":"https://github.com/utkarsh-pro/nodejs-snowflake.git"},"files":["nodejs_snowflake_bg.wasm","nodejs_snowflake.js","nodejs_snowflake.d.ts"],"main":"nodejs_snowflake.js","types":"nodejs_snowflake.d.ts","_lastModified":"2025-
|
|
1
|
+
{"name":"nodejs-snowflake","collaborators":["Utkarsh Srivastava <utkarsh@sagacious.dev>"],"description":"Generate time sortable 64 bits unique ids for distributed systems (inspired from twitter snowflake)","version":"2.0.1","license":"Apache 2.0","repository":{"type":"git","url":"https://github.com/utkarsh-pro/nodejs-snowflake.git"},"files":["nodejs_snowflake_bg.wasm","nodejs_snowflake.js","nodejs_snowflake.d.ts"],"main":"nodejs_snowflake.js","types":"nodejs_snowflake.d.ts","_lastModified":"2025-07-07T11:16:50.984Z"}
|
package/dist/server/Plugin.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ import Processor from './Processor';
|
|
|
15
15
|
import { CustomFunction } from './functions';
|
|
16
16
|
import Trigger from './triggers';
|
|
17
17
|
import { InstructionInterface } from './instructions';
|
|
18
|
-
import type { ExecutionModel, WorkflowModel } from './types';
|
|
18
|
+
import type { ExecutionModel, JobModel, WorkflowModel } from './types';
|
|
19
19
|
type ID = number | string;
|
|
20
20
|
export type EventOptions = {
|
|
21
21
|
eventKey?: string;
|
|
@@ -41,6 +41,7 @@ export default class PluginWorkflowServer extends Plugin {
|
|
|
41
41
|
private loggerCache;
|
|
42
42
|
private meter;
|
|
43
43
|
private checker;
|
|
44
|
+
private onQueueExecution;
|
|
44
45
|
private onBeforeSave;
|
|
45
46
|
private onAfterCreate;
|
|
46
47
|
private onAfterUpdate;
|
|
@@ -74,6 +75,7 @@ export default class PluginWorkflowServer extends Plugin {
|
|
|
74
75
|
private toggle;
|
|
75
76
|
trigger(workflow: WorkflowModel, context: object, options?: EventOptions): void | Promise<Processor | null>;
|
|
76
77
|
private triggerSync;
|
|
78
|
+
run(execution: ExecutionModel, job?: JobModel): Promise<void>;
|
|
77
79
|
resume(job: any): Promise<void>;
|
|
78
80
|
/**
|
|
79
81
|
* Start a deferred execution
|
package/dist/server/Plugin.js
CHANGED
|
@@ -61,6 +61,7 @@ var import_DestroyInstruction = __toESM(require("./instructions/DestroyInstructi
|
|
|
61
61
|
var import_QueryInstruction = __toESM(require("./instructions/QueryInstruction"));
|
|
62
62
|
var import_UpdateInstruction = __toESM(require("./instructions/UpdateInstruction"));
|
|
63
63
|
var import_WorkflowRepository = __toESM(require("./repositories/WorkflowRepository"));
|
|
64
|
+
const WORKER_JOB_WORKFLOW_PROCESS = "workflow:process";
|
|
64
65
|
class PluginWorkflowServer extends import_server.Plugin {
|
|
65
66
|
instructions = new import_utils.Registry();
|
|
66
67
|
triggers = new import_utils.Registry();
|
|
@@ -75,6 +76,22 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
75
76
|
loggerCache;
|
|
76
77
|
meter = null;
|
|
77
78
|
checker = null;
|
|
79
|
+
onQueueExecution = async (event) => {
|
|
80
|
+
const ExecutionRepo = this.db.getRepository("executions");
|
|
81
|
+
const execution = await ExecutionRepo.findOne({
|
|
82
|
+
filterByTk: event.executionId
|
|
83
|
+
});
|
|
84
|
+
if (!execution || execution.status !== import_constants.EXECUTION_STATUS.QUEUEING) {
|
|
85
|
+
this.getLogger("dispatcher").info(
|
|
86
|
+
`execution (${event.executionId}) from queue not found or not in queueing status, skip`
|
|
87
|
+
);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.getLogger(execution.workflowId).info(
|
|
91
|
+
`execution (${execution.id}) received from queue, adding to pending list`
|
|
92
|
+
);
|
|
93
|
+
this.run(execution);
|
|
94
|
+
};
|
|
78
95
|
onBeforeSave = async (instance, { transaction, cycling }) => {
|
|
79
96
|
if (cycling) {
|
|
80
97
|
return;
|
|
@@ -176,6 +193,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
176
193
|
this.ready = true;
|
|
177
194
|
};
|
|
178
195
|
onBeforeStop = async () => {
|
|
196
|
+
this.app.logger.info(`stopping workflow plugin before app (${this.app.name}) shutdown...`);
|
|
179
197
|
for (const workflow of this.enabledCache.values()) {
|
|
180
198
|
this.toggle(workflow, false, { silent: true });
|
|
181
199
|
}
|
|
@@ -289,6 +307,12 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
289
307
|
this.snowflake = new import_nodejs_snowflake.Snowflake({
|
|
290
308
|
custom_epoch: pluginRecord == null ? void 0 : pluginRecord.createdAt.getTime()
|
|
291
309
|
});
|
|
310
|
+
if (this.app.serving(WORKER_JOB_WORKFLOW_PROCESS)) {
|
|
311
|
+
this.app.backgroundJobManager.subscribe(`${this.name}.pendingExecution`, {
|
|
312
|
+
idle: () => !this.executing && !this.pending.length && !this.events.length,
|
|
313
|
+
process: this.onQueueExecution
|
|
314
|
+
});
|
|
315
|
+
}
|
|
292
316
|
}
|
|
293
317
|
/**
|
|
294
318
|
* @internal
|
|
@@ -426,19 +450,25 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
426
450
|
}
|
|
427
451
|
return null;
|
|
428
452
|
}
|
|
429
|
-
async
|
|
430
|
-
|
|
431
|
-
job.execution = await job.getExecution();
|
|
432
|
-
}
|
|
433
|
-
this.getLogger(job.execution.workflowId).info(
|
|
434
|
-
`execution (${job.execution.id}) resuming from job (${job.id}) added to pending list`
|
|
435
|
-
);
|
|
436
|
-
this.pending.push([job.execution, job]);
|
|
437
|
-
if (this.executing) {
|
|
453
|
+
async run(execution, job) {
|
|
454
|
+
while (this.executing) {
|
|
438
455
|
await this.executing;
|
|
439
456
|
}
|
|
457
|
+
this.executing = this.process(execution, job);
|
|
458
|
+
await this.executing;
|
|
459
|
+
this.executing = null;
|
|
440
460
|
this.dispatch();
|
|
441
461
|
}
|
|
462
|
+
async resume(job) {
|
|
463
|
+
let { execution } = job;
|
|
464
|
+
if (!execution) {
|
|
465
|
+
execution = await job.getExecution();
|
|
466
|
+
}
|
|
467
|
+
this.getLogger(execution.workflowId).info(
|
|
468
|
+
`execution (${execution.id}) resuming from job (${job.id}) added to pending list`
|
|
469
|
+
);
|
|
470
|
+
this.run(execution, job);
|
|
471
|
+
}
|
|
442
472
|
/**
|
|
443
473
|
* Start a deferred execution
|
|
444
474
|
* @experimental
|
|
@@ -448,11 +478,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
448
478
|
return;
|
|
449
479
|
}
|
|
450
480
|
this.getLogger(execution.workflowId).info(`starting deferred execution (${execution.id})`);
|
|
451
|
-
this.
|
|
452
|
-
if (this.executing) {
|
|
453
|
-
await this.executing;
|
|
454
|
-
}
|
|
455
|
-
this.dispatch();
|
|
481
|
+
this.run(execution);
|
|
456
482
|
}
|
|
457
483
|
async validateEvent(workflow, context, options) {
|
|
458
484
|
const trigger = this.triggers.get(workflow.type);
|
|
@@ -545,8 +571,14 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
545
571
|
logger.info(`preparing execution for event`);
|
|
546
572
|
try {
|
|
547
573
|
const execution = await this.createExecution(...event);
|
|
548
|
-
if ((execution == null ? void 0 : execution.status) === import_constants.EXECUTION_STATUS.QUEUEING
|
|
549
|
-
this.pending.
|
|
574
|
+
if ((execution == null ? void 0 : execution.status) === import_constants.EXECUTION_STATUS.QUEUEING) {
|
|
575
|
+
if (!this.executing && !this.pending.length) {
|
|
576
|
+
logger.info(`local pending list is empty, adding execution (${execution.id}) to pending list`);
|
|
577
|
+
this.pending.push([execution]);
|
|
578
|
+
} else {
|
|
579
|
+
logger.info(`local pending list is not empty, sending execution (${execution.id}) to queue`);
|
|
580
|
+
this.app.backgroundJobManager.publish(`${this.name}.pendingExecution`, { executionId: execution.id });
|
|
581
|
+
}
|
|
550
582
|
}
|
|
551
583
|
} catch (error) {
|
|
552
584
|
logger.error(`failed to create execution:`, { error });
|
|
@@ -566,6 +598,12 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
566
598
|
this.getLogger("dispatcher").warn(`app is not ready, new dispatching will be ignored`);
|
|
567
599
|
return;
|
|
568
600
|
}
|
|
601
|
+
if (!this.app.serving(WORKER_JOB_WORKFLOW_PROCESS)) {
|
|
602
|
+
this.getLogger("dispatcher").warn(
|
|
603
|
+
`${WORKER_JOB_WORKFLOW_PROCESS} is not serving, new dispatching will be ignored`
|
|
604
|
+
);
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
569
607
|
if (this.executing) {
|
|
570
608
|
this.getLogger("dispatcher").warn(`workflow executing is not finished, new dispatching will be ignored`);
|
|
571
609
|
return;
|
|
@@ -587,7 +625,9 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
587
625
|
async (transaction) => {
|
|
588
626
|
const execution = await this.db.getRepository("executions").findOne({
|
|
589
627
|
filter: {
|
|
590
|
-
status:
|
|
628
|
+
status: {
|
|
629
|
+
[import_database.Op.is]: import_constants.EXECUTION_STATUS.QUEUEING
|
|
630
|
+
},
|
|
591
631
|
"workflow.enabled": true
|
|
592
632
|
},
|
|
593
633
|
sort: "id",
|
|
@@ -631,7 +671,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
631
671
|
if (execution.status === import_constants.EXECUTION_STATUS.QUEUEING) {
|
|
632
672
|
const transaction = await this.useDataSourceTransaction("main", options.transaction);
|
|
633
673
|
await execution.update({ status: import_constants.EXECUTION_STATUS.STARTED }, { transaction });
|
|
634
|
-
logger.info(`
|
|
674
|
+
logger.info(`execution (${execution.id}) from pending list updated to started`);
|
|
635
675
|
}
|
|
636
676
|
const processor = this.createProcessor(execution, options);
|
|
637
677
|
logger.info(`execution (${execution.id}) ${job ? "resuming" : "starting"}...`);
|
|
@@ -52,8 +52,7 @@ async function create(context, next) {
|
|
|
52
52
|
context.body = await db.sequelize.transaction(async (transaction) => {
|
|
53
53
|
const workflow = await repository.getSourceModel(transaction);
|
|
54
54
|
workflow.versionStats = await workflow.getVersionStats({ transaction });
|
|
55
|
-
|
|
56
|
-
if (executed) {
|
|
55
|
+
if (workflow.versionStats.executed > 0) {
|
|
57
56
|
context.throw(400, "Node could not be created in executed workflow");
|
|
58
57
|
}
|
|
59
58
|
const instance = await repository.create({
|
|
@@ -147,7 +146,7 @@ async function destroy(context, next) {
|
|
|
147
146
|
fields: [...fields, "workflowId"],
|
|
148
147
|
appends: ["upstream", "downstream", "workflow.versionStats.executed"]
|
|
149
148
|
});
|
|
150
|
-
if (instance.workflow.versionStats.executed) {
|
|
149
|
+
if (instance.workflow.versionStats.executed > 0) {
|
|
151
150
|
context.throw(400, "Nodes in executed workflow could not be deleted");
|
|
152
151
|
}
|
|
153
152
|
await db.sequelize.transaction(async (transaction) => {
|
|
@@ -207,7 +206,7 @@ async function update(context, next) {
|
|
|
207
206
|
appends: ["workflow.versionStats.executed"],
|
|
208
207
|
transaction
|
|
209
208
|
});
|
|
210
|
-
if (workflow.versionStats.executed) {
|
|
209
|
+
if (workflow.versionStats.executed > 0) {
|
|
211
210
|
context.throw(400, "Nodes in executed workflow could not be reconfigured");
|
|
212
211
|
}
|
|
213
212
|
return repository.update({
|
|
@@ -57,7 +57,7 @@ async function update(context, next) {
|
|
|
57
57
|
filterByTk,
|
|
58
58
|
appends: ["versionStats"]
|
|
59
59
|
});
|
|
60
|
-
if (workflow.versionStats.executed) {
|
|
60
|
+
if (workflow.versionStats.executed > 0) {
|
|
61
61
|
return context.throw(400, "config of executed workflow can not be updated");
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -84,11 +84,19 @@ async function destroy(context, next) {
|
|
|
84
84
|
transaction
|
|
85
85
|
});
|
|
86
86
|
revisions.forEach((item) => ids.add(item.id));
|
|
87
|
-
|
|
87
|
+
const deleted = await repository.destroy({
|
|
88
88
|
filterByTk: Array.from(ids),
|
|
89
89
|
individualHooks: true,
|
|
90
90
|
transaction
|
|
91
91
|
});
|
|
92
|
+
const StatsRepo = context.db.getRepository("workflowStats");
|
|
93
|
+
await StatsRepo.destroy({
|
|
94
|
+
filter: {
|
|
95
|
+
key: Array.from(keysSet)
|
|
96
|
+
},
|
|
97
|
+
transaction
|
|
98
|
+
});
|
|
99
|
+
context.body = deleted;
|
|
92
100
|
});
|
|
93
101
|
next();
|
|
94
102
|
}
|
|
@@ -150,7 +158,7 @@ async function execute(context, next) {
|
|
|
150
158
|
filter: { key: workflow.key }
|
|
151
159
|
});
|
|
152
160
|
let newVersion;
|
|
153
|
-
if (
|
|
161
|
+
if (executed == 0 && autoRevision) {
|
|
154
162
|
newVersion = await repository.revision({
|
|
155
163
|
filterByTk: workflow.id,
|
|
156
164
|
filter: { key: workflow.key },
|
|
@@ -21,5 +21,15 @@ export declare class CalculationInstruction extends Instruction {
|
|
|
21
21
|
result: any;
|
|
22
22
|
status: -2;
|
|
23
23
|
}>;
|
|
24
|
+
test({ engine, expression }: {
|
|
25
|
+
engine?: string;
|
|
26
|
+
expression?: string;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
result: any;
|
|
29
|
+
status: 1;
|
|
30
|
+
} | {
|
|
31
|
+
result: any;
|
|
32
|
+
status: -2;
|
|
33
|
+
}>;
|
|
24
34
|
}
|
|
25
35
|
export default CalculationInstruction;
|
|
@@ -51,6 +51,21 @@ class CalculationInstruction extends import__.Instruction {
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
async test({ engine = "math.js", expression = "" }) {
|
|
55
|
+
const evaluator = import_evaluators.evaluators.get(engine);
|
|
56
|
+
try {
|
|
57
|
+
const result = evaluator && expression ? evaluator(expression) : null;
|
|
58
|
+
return {
|
|
59
|
+
result,
|
|
60
|
+
status: import_constants.JOB_STATUS.RESOLVED
|
|
61
|
+
};
|
|
62
|
+
} catch (e) {
|
|
63
|
+
return {
|
|
64
|
+
result: e.toString(),
|
|
65
|
+
status: import_constants.JOB_STATUS.ERROR
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
54
69
|
}
|
|
55
70
|
var CalculationInstruction_default = CalculationInstruction;
|
|
56
71
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -29,5 +29,16 @@ export declare class ConditionInstruction extends Instruction {
|
|
|
29
29
|
result: boolean;
|
|
30
30
|
}>;
|
|
31
31
|
resume(node: FlowNodeModel, branchJob: JobModel, processor: Processor): Promise<any>;
|
|
32
|
+
test({ engine, calculation, expression }: {
|
|
33
|
+
engine: any;
|
|
34
|
+
calculation: any;
|
|
35
|
+
expression?: string;
|
|
36
|
+
}): Promise<{
|
|
37
|
+
result: any;
|
|
38
|
+
status: 1;
|
|
39
|
+
} | {
|
|
40
|
+
result: any;
|
|
41
|
+
status: -2;
|
|
42
|
+
}>;
|
|
32
43
|
}
|
|
33
44
|
export default ConditionInstruction;
|
|
@@ -84,6 +84,21 @@ class ConditionInstruction extends import__.Instruction {
|
|
|
84
84
|
}
|
|
85
85
|
return processor.exit(branchJob.status);
|
|
86
86
|
}
|
|
87
|
+
async test({ engine, calculation, expression = "" }) {
|
|
88
|
+
const evaluator = import_evaluators.evaluators.get(engine);
|
|
89
|
+
try {
|
|
90
|
+
const result = evaluator ? evaluator(expression) : (0, import_logicCalculate.logicCalculate)(calculation);
|
|
91
|
+
return {
|
|
92
|
+
result,
|
|
93
|
+
status: import_constants.JOB_STATUS.RESOLVED
|
|
94
|
+
};
|
|
95
|
+
} catch (e) {
|
|
96
|
+
return {
|
|
97
|
+
result: e.toString(),
|
|
98
|
+
status: import_constants.JOB_STATUS.ERROR
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
87
102
|
}
|
|
88
103
|
var ConditionInstruction_default = ConditionInstruction;
|
|
89
104
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Migration } from '@nocobase/server';
|
|
10
|
+
export default class extends Migration {
|
|
11
|
+
appVersion: string;
|
|
12
|
+
on: string;
|
|
13
|
+
up(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var add_missed_stats_exports = {};
|
|
28
|
+
__export(add_missed_stats_exports, {
|
|
29
|
+
default: () => add_missed_stats_default
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(add_missed_stats_exports);
|
|
32
|
+
var import_server = require("@nocobase/server");
|
|
33
|
+
class add_missed_stats_default extends import_server.Migration {
|
|
34
|
+
appVersion = "<1.8.0";
|
|
35
|
+
on = "afterLoad";
|
|
36
|
+
async up() {
|
|
37
|
+
const { db } = this.context;
|
|
38
|
+
const WorkflowRepo = db.getRepository("workflows");
|
|
39
|
+
const ExecutionRepo = db.getRepository("executions");
|
|
40
|
+
await db.sequelize.transaction(async (transaction) => {
|
|
41
|
+
const workflows = await WorkflowRepo.find({
|
|
42
|
+
filter: {
|
|
43
|
+
current: true
|
|
44
|
+
},
|
|
45
|
+
appends: ["stats"],
|
|
46
|
+
transaction
|
|
47
|
+
});
|
|
48
|
+
for (const workflow of workflows) {
|
|
49
|
+
if (!workflow.stats) {
|
|
50
|
+
const executed = await ExecutionRepo.count({
|
|
51
|
+
filter: {
|
|
52
|
+
key: workflow.key
|
|
53
|
+
},
|
|
54
|
+
transaction
|
|
55
|
+
}) || workflow.allExecuted || 0;
|
|
56
|
+
await workflow.createStats({ executed }, { transaction });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
package/package.json
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
"displayName.zh-CN": "工作流",
|
|
5
5
|
"description": "A powerful BPM tool that provides foundational support for business automation, with the capability to extend unlimited triggers and nodes.",
|
|
6
6
|
"description.zh-CN": "一个强大的 BPM 工具,为业务自动化提供基础支持,并且可任意扩展更多的触发器和节点。",
|
|
7
|
-
"version": "1.8.0
|
|
7
|
+
"version": "1.8.0",
|
|
8
8
|
"license": "AGPL-3.0",
|
|
9
9
|
"main": "./dist/server/index.js",
|
|
10
10
|
"homepage": "https://docs.nocobase.com/handbook/workflow",
|
|
11
11
|
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/workflow",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@nocobase/plugin-workflow-test": "1.8.0
|
|
13
|
+
"@nocobase/plugin-workflow-test": "1.8.0"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@ant-design/icons": "5.x",
|
|
@@ -40,13 +40,14 @@
|
|
|
40
40
|
"@nocobase/logger": "1.x",
|
|
41
41
|
"@nocobase/plugin-data-source-main": "1.x",
|
|
42
42
|
"@nocobase/plugin-error-handler": "1.x",
|
|
43
|
+
"@nocobase/plugin-mobile": "1.x",
|
|
43
44
|
"@nocobase/plugin-users": "1.x",
|
|
44
45
|
"@nocobase/resourcer": "1.x",
|
|
45
46
|
"@nocobase/server": "1.x",
|
|
46
47
|
"@nocobase/test": "1.x",
|
|
47
48
|
"@nocobase/utils": "1.x"
|
|
48
49
|
},
|
|
49
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "043de5b0f70cbeac2a0f83e992eaa0e09c90d53d",
|
|
50
51
|
"keywords": [
|
|
51
52
|
"Workflow"
|
|
52
53
|
]
|