@nocobase/plugin-workflow 1.8.31 → 1.8.33

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.
@@ -122,9 +122,9 @@ export declare const executionSchema: {
122
122
  unique?: undefined;
123
123
  onDelete?: undefined;
124
124
  } | {
125
- interface: string;
126
125
  type: string;
127
126
  name: string;
127
+ interface: string;
128
128
  uiSchema: {
129
129
  type: string;
130
130
  title: string;
@@ -111,9 +111,9 @@ declare const _default: {
111
111
  unique?: undefined;
112
112
  onDelete?: undefined;
113
113
  } | {
114
- interface: string;
115
114
  type: string;
116
115
  name: string;
116
+ interface: string;
117
117
  uiSchema: {
118
118
  type: string;
119
119
  title: string;
@@ -110,9 +110,9 @@ var executions_default = {
110
110
  name: "output"
111
111
  },
112
112
  {
113
- interface: "createdAt",
114
113
  type: "datetime",
115
114
  name: "createdAt",
115
+ interface: "createdAt",
116
116
  uiSchema: {
117
117
  type: "datetime",
118
118
  title: `{{t("Triggered at", { ns: "${import_constants.NAMESPACE}" })}}`,
@@ -120,6 +120,18 @@ var executions_default = {
120
120
  "x-component-props": {},
121
121
  "x-read-pretty": true
122
122
  }
123
+ },
124
+ {
125
+ type: "boolean",
126
+ name: "manually",
127
+ interface: "checkbox",
128
+ uiSchema: {
129
+ type: "boolean",
130
+ title: `{{t("Triggered manually", { ns: "${import_constants.NAMESPACE}" })}}`,
131
+ "x-component": "Checkbox",
132
+ "x-component-props": {},
133
+ "x-read-pretty": true
134
+ }
123
135
  }
124
136
  ]
125
137
  };
@@ -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.31",
15
- "@nocobase/utils": "1.8.31",
14
+ "@nocobase/client": "1.8.33",
15
+ "@nocobase/utils": "1.8.33",
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.31",
23
+ "@nocobase/plugin-mobile": "1.8.33",
24
24
  "sequelize": "6.35.2",
25
- "@nocobase/database": "1.8.31",
26
- "@nocobase/server": "1.8.31",
27
- "@nocobase/data-source-manager": "1.8.31",
28
- "@nocobase/logger": "1.8.31",
29
- "@nocobase/evaluators": "1.8.31",
25
+ "@nocobase/database": "1.8.33",
26
+ "@nocobase/server": "1.8.33",
27
+ "@nocobase/data-source-manager": "1.8.33",
28
+ "@nocobase/logger": "1.8.33",
29
+ "@nocobase/evaluators": "1.8.33",
30
30
  "@formily/antd-v5": "1.2.3",
31
31
  "@formily/reactive": "2.3.0",
32
- "@nocobase/actions": "1.8.31",
32
+ "@nocobase/actions": "1.8.33",
33
33
  "dayjs": "1.11.13",
34
- "@nocobase/plugin-workflow-test": "1.8.31",
35
- "@nocobase/test": "1.8.31"
34
+ "@nocobase/plugin-workflow-test": "1.8.33",
35
+ "@nocobase/test": "1.8.33"
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-10-17T15:36:20.496Z"}
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-10-29T13:12:35.861Z"}
@@ -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-10-17T15:36:20.139Z"}
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-10-29T13:12:35.517Z"}
@@ -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-10-17T15:36:19.940Z"}
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-10-29T13:12:35.326Z"}
@@ -14,7 +14,7 @@ import type PluginWorkflowServer from './Plugin';
14
14
  type Pending = {
15
15
  execution: ExecutionModel;
16
16
  job?: JobModel;
17
- force?: boolean;
17
+ loaded?: boolean;
18
18
  };
19
19
  export type EventOptions = {
20
20
  eventKey?: string;
@@ -38,7 +38,7 @@ export default class Dispatcher {
38
38
  constructor(plugin: PluginWorkflowServer);
39
39
  readonly onQueueExecution: QueueEventOptions['process'];
40
40
  setReady(ready: boolean): void;
41
- isReady(): boolean;
41
+ private serving;
42
42
  getEventsCount(): number;
43
43
  trigger(workflow: WorkflowModel, context: object, options?: EventOptions): void | Promise<Processor | null>;
44
44
  resume(job: any): Promise<void>;
@@ -63,8 +63,8 @@ class Dispatcher {
63
63
  setReady(ready) {
64
64
  this.ready = ready;
65
65
  }
66
- isReady() {
67
- return this.ready;
66
+ serving() {
67
+ return this.plugin.app.serving(WORKER_JOB_WORKFLOW_PROCESS);
68
68
  }
69
69
  getEventsCount() {
70
70
  return this.eventsCount;
@@ -113,14 +113,14 @@ class Dispatcher {
113
113
  execution = await job.getExecution();
114
114
  }
115
115
  this.plugin.getLogger(execution.workflowId).info(`execution (${execution.id}) resuming from job (${job.id}) added to pending list`);
116
- this.run({ execution, job, force: true });
116
+ this.run({ execution, job, loaded: true });
117
117
  }
118
118
  async start(execution) {
119
119
  if (execution.status !== import_constants.EXECUTION_STATUS.STARTED) {
120
120
  return;
121
121
  }
122
122
  this.plugin.getLogger(execution.workflowId).info(`starting deferred execution (${execution.id})`);
123
- this.run({ execution, force: true });
123
+ this.run({ execution, loaded: true });
124
124
  }
125
125
  async beforeStop() {
126
126
  this.ready = false;
@@ -136,10 +136,6 @@ class Dispatcher {
136
136
  this.plugin.getLogger("dispatcher").warn(`app is not ready, new dispatching will be ignored`);
137
137
  return;
138
138
  }
139
- if (!this.plugin.app.serving(WORKER_JOB_WORKFLOW_PROCESS)) {
140
- this.plugin.getLogger("dispatcher").warn(`${WORKER_JOB_WORKFLOW_PROCESS} is not serving, new dispatching will be ignored`);
141
- return;
142
- }
143
139
  if (this.executing) {
144
140
  this.plugin.getLogger("dispatcher").warn(`workflow executing is not finished, new dispatching will be ignored`);
145
141
  return;
@@ -152,12 +148,16 @@ class Dispatcher {
152
148
  let execution = null;
153
149
  if (this.pending.length) {
154
150
  const pending = this.pending.shift();
155
- execution = pending.force ? pending.execution : await this.acquirePendingExecution(pending.execution);
151
+ execution = pending.loaded ? pending.execution : await this.acquirePendingExecution(pending.execution);
156
152
  if (execution) {
157
153
  next = [execution, pending.job];
158
154
  this.plugin.getLogger(next[0].workflowId).info(`pending execution (${next[0].id}) ready to process`);
159
155
  }
160
156
  } else {
157
+ if (!this.serving()) {
158
+ this.plugin.getLogger("dispatcher").warn(`${WORKER_JOB_WORKFLOW_PROCESS} is not serving on this instance, new dispatching will be ignored`);
159
+ return;
160
+ }
161
161
  execution = await this.acquireQueueingExecution();
162
162
  if (execution) {
163
163
  next = [execution];
@@ -238,6 +238,7 @@ class Dispatcher {
238
238
  key: workflow.key,
239
239
  eventKey: options.eventKey ?? (0, import_crypto.randomUUID)(),
240
240
  stack: options.stack,
241
+ manually: options.manually,
241
242
  status: deferred ? import_constants.EXECUTION_STATUS.STARTED : import_constants.EXECUTION_STATUS.QUEUEING
242
243
  },
243
244
  { transaction }
@@ -284,11 +285,13 @@ class Dispatcher {
284
285
  try {
285
286
  const execution = await this.createExecution(...event);
286
287
  if ((execution == null ? void 0 : execution.status) === import_constants.EXECUTION_STATUS.QUEUEING) {
287
- if (!this.executing && !this.pending.length) {
288
+ if (this.serving() && !this.executing && !this.pending.length) {
288
289
  logger.info(`local pending list is empty, adding execution (${execution.id}) to pending list`);
289
290
  this.pending.push({ execution });
290
291
  } else {
291
- logger.info(`local pending list is not empty, sending execution (${execution.id}) to queue`);
292
+ logger.info(
293
+ `instance is not serving as worker or local pending list is not empty, sending execution (${execution.id}) to queue`
294
+ );
292
295
  if (this.ready) {
293
296
  this.plugin.app.backgroundJobManager.publish(`${this.plugin.name}.pendingExecution`, {
294
297
  executionId: execution.id
@@ -138,7 +138,6 @@ class PluginWorkflowServer extends import_server.Plugin {
138
138
  // * add all hooks for enabled workflows
139
139
  // * add hooks for create/update[enabled]/delete workflow to add/remove specific hooks
140
140
  onAfterStart = async () => {
141
- this.dispatcher.setReady(true);
142
141
  const collection = this.db.getCollection("workflows");
143
142
  const workflows = await collection.repository.find({
144
143
  appends: ["versionStats"]
@@ -165,11 +164,12 @@ class PluginWorkflowServer extends import_server.Plugin {
165
164
  this.app.logger.info("workflow:dispatch");
166
165
  this.dispatcher.dispatch();
167
166
  });
167
+ this.dispatcher.setReady(true);
168
168
  this.getLogger("dispatcher").info("(starting) check for queueing executions");
169
169
  this.dispatcher.dispatch();
170
- this.dispatcher.setReady(true);
171
170
  };
172
171
  onBeforeStop = async () => {
172
+ this.dispatcher.setReady(false);
173
173
  this.app.logger.info(`stopping workflow plugin before app (${this.app.name}) shutdown...`);
174
174
  for (const workflow of this.enabledCache.values()) {
175
175
  this.toggle(workflow, false, { silent: true });
@@ -208,7 +208,7 @@ class PluginWorkflowServer extends import_server.Plugin {
208
208
  getLogger(workflowId = "dispatcher") {
209
209
  const now = /* @__PURE__ */ new Date();
210
210
  const date = `${now.getFullYear()}-${`0${now.getMonth() + 1}`.slice(-2)}-${`0${now.getDate()}`.slice(-2)}`;
211
- const key = `${date}-${workflowId}}`;
211
+ const key = `${date}-${workflowId}`;
212
212
  if (this.loggerCache.has(key)) {
213
213
  return this.loggerCache.get(key);
214
214
  }
@@ -297,7 +297,14 @@ class PluginWorkflowServer extends import_server.Plugin {
297
297
  max: 20,
298
298
  updateAgeOnGet: true,
299
299
  dispose(logger) {
300
- logger.end();
300
+ const cachedLogger = logger;
301
+ if (!cachedLogger) {
302
+ return;
303
+ }
304
+ cachedLogger.silent = true;
305
+ if (typeof cachedLogger.close === "function") {
306
+ cachedLogger.close();
307
+ }
301
308
  }
302
309
  });
303
310
  this.meter = this.app.telemetry.metric.getMeter();
@@ -158,7 +158,7 @@ async function destroy(context, next) {
158
158
  const repository = import_actions.utils.getRepositoryFromParams(context);
159
159
  const { filterByTk, keepBranch } = context.action.params;
160
160
  const keepBranchIndex = keepBranch == null || keepBranch === "" ? null : Number.parseInt(keepBranch, 10);
161
- const fields = ["id", "upstreamId", "downstreamId", "branchIndex"];
161
+ const fields = ["id", "upstreamId", "downstreamId", "branchIndex", "key"];
162
162
  const instance = await repository.findOne({
163
163
  filterByTk,
164
164
  fields: [...fields, "workflowId"],
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.31",
7
+ "version": "1.8.33",
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": "02ade1124cfbb5b3a2e8813ac4c141cbade7a443",
48
+ "gitHead": "0aa6b2823a7fe1d674f79512d9beaff96b647214",
49
49
  "keywords": [
50
50
  "Workflow"
51
51
  ]