@nocobase/plugin-workflow 1.8.10 → 1.8.12

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.
@@ -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.10",
15
- "@nocobase/utils": "1.8.10",
14
+ "@nocobase/client": "1.8.12",
15
+ "@nocobase/utils": "1.8.12",
16
16
  "antd": "5.24.2",
17
17
  "@ant-design/icons": "5.6.1",
18
18
  "react-router-dom": "6.28.1",
@@ -20,17 +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.10",
23
+ "@nocobase/plugin-mobile": "1.8.12",
24
24
  "sequelize": "6.35.2",
25
- "@nocobase/database": "1.8.10",
26
- "@nocobase/server": "1.8.10",
27
- "@nocobase/data-source-manager": "1.8.10",
28
- "@nocobase/logger": "1.8.10",
29
- "@nocobase/evaluators": "1.8.10",
25
+ "@nocobase/database": "1.8.12",
26
+ "@nocobase/server": "1.8.12",
27
+ "@nocobase/data-source-manager": "1.8.12",
28
+ "@nocobase/logger": "1.8.12",
29
+ "@nocobase/evaluators": "1.8.12",
30
30
  "@formily/antd-v5": "1.2.3",
31
31
  "@formily/reactive": "2.3.0",
32
- "@nocobase/actions": "1.8.10",
32
+ "@nocobase/actions": "1.8.12",
33
33
  "dayjs": "1.11.13",
34
- "@nocobase/plugin-workflow-test": "1.8.10",
35
- "@nocobase/test": "1.8.10"
34
+ "@nocobase/plugin-workflow-test": "1.8.12",
35
+ "@nocobase/test": "1.8.12"
36
36
  };
@@ -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-07-24T13:56:55.643Z"}
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-08-01T14:25:13.594Z"}
@@ -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-07-24T13:56:55.332Z"}
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-08-01T14:25:13.251Z"}
@@ -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-07-24T13:56:55.169Z"}
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-08-01T14:25:13.055Z"}
@@ -43,7 +43,7 @@ export default class Processor {
43
43
  /**
44
44
  * @experimental
45
45
  */
46
- nodesMap: Map<number, FlowNodeModel>;
46
+ nodesMap: Map<string | number, FlowNodeModel>;
47
47
  private jobsMapByNodeKey;
48
48
  private jobResultsMapByNodeKey;
49
49
  private jobsToSave;
@@ -61,7 +61,7 @@ export default class Processor {
61
61
  run(node: any, input?: any): any;
62
62
  end(node: any, job: JobModel): Promise<any>;
63
63
  private recall;
64
- exit(s?: number): Promise<any>;
64
+ exit(s?: number | true): Promise<any>;
65
65
  /**
66
66
  * @experimental
67
67
  */
@@ -95,7 +95,7 @@ export default class Processor {
95
95
  /**
96
96
  * @experimental
97
97
  */
98
- getScope(sourceNodeId: number, includeSelfScope?: boolean): {
98
+ getScope(sourceNodeId: number | string, includeSelfScope?: boolean): {
99
99
  $context: any;
100
100
  $jobsMapByNodeKey: {
101
101
  [key: string]: any;
@@ -107,7 +107,7 @@ export default class Processor {
107
107
  /**
108
108
  * @experimental
109
109
  */
110
- getParsedValue(value: any, sourceNodeId: number, { additionalScope, includeSelfScope }?: {
110
+ getParsedValue(value: any, sourceNodeId: number | string, { additionalScope, includeSelfScope }?: {
111
111
  additionalScope?: {};
112
112
  includeSelfScope?: boolean;
113
113
  }): any;
@@ -39,6 +39,7 @@ __export(Processor_exports, {
39
39
  default: () => Processor
40
40
  });
41
41
  module.exports = __toCommonJS(Processor_exports);
42
+ var import_sequelize = require("sequelize");
42
43
  var import_database = require("@nocobase/database");
43
44
  var import_evaluators = require("@nocobase/evaluators");
44
45
  var import_utils = require("@nocobase/utils");
@@ -120,7 +121,20 @@ class Processor {
120
121
  const nodes = await execution.workflow.getNodes({ transaction });
121
122
  execution.workflow.nodes = nodes;
122
123
  this.makeNodes(nodes);
124
+ const JobDBModel = plugin.db.getModel("jobs");
125
+ const jobIds = await JobDBModel.findAll({
126
+ attributes: ["executionId", "nodeId", [(0, import_sequelize.fn)("MAX", (0, import_sequelize.col)("id")), "id"]],
127
+ group: ["executionId", "nodeId"],
128
+ where: {
129
+ executionId: execution.id
130
+ },
131
+ raw: true,
132
+ transaction
133
+ });
123
134
  const jobs = await execution.getJobs({
135
+ where: {
136
+ id: jobIds.map((item) => item.id)
137
+ },
124
138
  order: [["id", "ASC"]],
125
139
  transaction
126
140
  });
@@ -154,12 +168,14 @@ class Processor {
154
168
  async exec(instruction, node, prevJob) {
155
169
  let job;
156
170
  try {
157
- this.logger.info(`execution (${this.execution.id}) run instruction [${node.type}] for node (${node.id})`);
158
171
  this.logger.debug(`config of node`, { data: node.config });
159
172
  job = await instruction(node, prevJob, this);
160
- if (!job) {
173
+ if (job === null) {
161
174
  return this.exit();
162
175
  }
176
+ if (!job) {
177
+ return this.exit(true);
178
+ }
163
179
  } catch (err) {
164
180
  this.logger.error(
165
181
  `execution (${this.execution.id}) run instruction [${node.type}] for node (${node.id}) failed: `,
@@ -201,6 +217,7 @@ class Processor {
201
217
  if (typeof instruction.run !== "function") {
202
218
  return Promise.reject(new Error("`run` should be implemented for customized execution of the node"));
203
219
  }
220
+ this.logger.info(`execution (${this.execution.id}) run instruction [${node.type}] for node (${node.id})`);
204
221
  return this.exec(instruction.run.bind(instruction), node, input);
205
222
  }
206
223
  // parent node should take over the control
@@ -225,16 +242,35 @@ class Processor {
225
242
  new Error(`"resume" method should be implemented for [${node.type}] instruction of node (#${node.id})`)
226
243
  );
227
244
  }
245
+ this.logger.info(`execution (${this.execution.id}) resume instruction [${node.type}] for node (${node.id})`);
228
246
  return this.exec(instruction.resume.bind(instruction), node, job);
229
247
  }
230
248
  async exit(s) {
249
+ if (s === true) {
250
+ return;
251
+ }
231
252
  if (this.jobsToSave.size) {
232
253
  const newJobs = [];
233
254
  for (const job of this.jobsToSave.values()) {
234
255
  if (job.isNewRecord) {
235
256
  newJobs.push(job);
236
257
  } else {
237
- await job.save({ transaction: this.mainTransaction });
258
+ const JobCollection = this.options.plugin.db.getCollection("jobs");
259
+ const changes = [];
260
+ if (job.changed("status")) {
261
+ changes.push([`status`, job.status]);
262
+ job.changed("status", false);
263
+ }
264
+ if (job.changed("result")) {
265
+ changes.push([`result`, JSON.stringify(job.result ?? null)]);
266
+ job.changed("result", false);
267
+ }
268
+ if (changes.length) {
269
+ await this.options.plugin.db.sequelize.query(
270
+ `UPDATE ${JobCollection.quotedTableName()} SET ${changes.map(([key]) => `${key} = ?`)} WHERE id='${job.id}'`,
271
+ { replacements: changes.map(([, value]) => value), transaction: this.mainTransaction }
272
+ );
273
+ }
238
274
  }
239
275
  }
240
276
  if (newJobs.length) {
@@ -273,18 +309,24 @@ class Processor {
273
309
  job = payload;
274
310
  job.set("updatedAt", /* @__PURE__ */ new Date());
275
311
  } else {
276
- job = model.build({
277
- ...payload,
278
- id: this.options.plugin.snowflake.getUniqueID().toString(),
279
- createdAt: /* @__PURE__ */ new Date(),
280
- updatedAt: /* @__PURE__ */ new Date(),
281
- executionId: this.execution.id
282
- });
312
+ job = model.build(
313
+ {
314
+ ...payload,
315
+ id: this.options.plugin.snowflake.getUniqueID().toString(),
316
+ createdAt: /* @__PURE__ */ new Date(),
317
+ updatedAt: /* @__PURE__ */ new Date(),
318
+ executionId: this.execution.id
319
+ },
320
+ {
321
+ isNewRecord: true
322
+ }
323
+ );
283
324
  }
284
325
  this.jobsToSave.set(job.id, job);
285
326
  this.lastSavedJob = job;
286
327
  this.jobsMapByNodeKey[job.nodeKey] = job;
287
328
  this.jobResultsMapByNodeKey[job.nodeKey] = job.result;
329
+ this.logger.debug(`job added to save list: ${JSON.stringify(job)}`);
288
330
  return job;
289
331
  }
290
332
  /**
@@ -362,8 +404,8 @@ class Processor {
362
404
  execution: this.execution,
363
405
  node
364
406
  };
365
- for (const [name, fn] of this.options.plugin.functions.getEntities()) {
366
- (0, import_set.default)(systemFns, name, fn.bind(scope));
407
+ for (const [name, fn2] of this.options.plugin.functions.getEntities()) {
408
+ (0, import_set.default)(systemFns, name, fn2.bind(scope));
367
409
  }
368
410
  const $scopes = {};
369
411
  for (let n = includeSelfScope ? node : this.findBranchParentNode(node); n; n = this.findBranchParentNode(n)) {
@@ -70,14 +70,14 @@ async function cancel(context, next) {
70
70
  await context.db.sequelize.transaction(async (transaction) => {
71
71
  await execution.update(
72
72
  {
73
- status: import_constants.EXECUTION_STATUS.CANCELED
73
+ status: import_constants.EXECUTION_STATUS.ABORTED
74
74
  },
75
75
  { transaction }
76
76
  );
77
77
  const pendingJobs = execution.jobs.filter((job) => job.status === import_constants.JOB_STATUS.PENDING);
78
78
  await JobRepo.update({
79
79
  values: {
80
- status: import_constants.JOB_STATUS.CANCELED
80
+ status: import_constants.JOB_STATUS.ABORTED
81
81
  },
82
82
  filter: {
83
83
  id: pendingJobs.map((job) => job.id)
@@ -75,7 +75,6 @@ class ConditionInstruction extends import__.Instruction {
75
75
  }
76
76
  const savedJob = processor.saveJob(job);
77
77
  await processor.run(branchNode, savedJob);
78
- return null;
79
78
  }
80
79
  async resume(node, branchJob, processor) {
81
80
  const job = processor.findBranchParentJob(branchJob, node);
@@ -15,7 +15,7 @@ export interface IJob {
15
15
  result?: unknown;
16
16
  [key: string]: unknown;
17
17
  }
18
- export type InstructionResult = IJob | Promise<IJob> | null;
18
+ export type InstructionResult = IJob | Promise<IJob> | Promise<void> | null | void;
19
19
  export type Runner = (node: FlowNodeModel, input: any, processor: Processor) => InstructionResult;
20
20
  export type InstructionInterface = {
21
21
  run: Runner;
package/package.json CHANGED
@@ -4,7 +4,7 @@
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.10",
7
+ "version": "1.8.12",
8
8
  "license": "AGPL-3.0",
9
9
  "main": "./dist/server/index.js",
10
10
  "homepage": "https://docs.nocobase.com/handbook/workflow",
@@ -45,7 +45,7 @@
45
45
  "@nocobase/test": "1.x",
46
46
  "@nocobase/utils": "1.x"
47
47
  },
48
- "gitHead": "47fd4ef9bff0e1e779154b004d93387ea05b21e9",
48
+ "gitHead": "d919db5f68f8b98209befae7343a8644e926021d",
49
49
  "keywords": [
50
50
  "Workflow"
51
51
  ]