@nocobase/plugin-workflow 0.19.0-alpha.4 → 0.19.0-alpha.6

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.
@@ -19,7 +19,7 @@ export declare abstract class Trigger {
19
19
  };
20
20
  useInitializers?(config: any): SchemaInitializerItemType | null;
21
21
  initializers?: any;
22
- useActionTriggerable?: boolean | (() => boolean);
22
+ isActionTriggerable?: boolean | ((config: object, context?: object) => boolean);
23
23
  }
24
24
  export declare const TriggerConfig: () => React.JSX.Element;
25
25
  export declare function useTrigger(): any;
@@ -2,21 +2,21 @@ module.exports = {
2
2
  "react": "18.2.0",
3
3
  "antd": "5.12.8",
4
4
  "@ant-design/icons": "5.2.6",
5
- "@nocobase/client": "0.19.0-alpha.4",
5
+ "@nocobase/client": "0.19.0-alpha.6",
6
6
  "react-router-dom": "6.21.0",
7
- "@nocobase/utils": "0.19.0-alpha.4",
7
+ "@nocobase/utils": "0.19.0-alpha.6",
8
8
  "react-i18next": "11.18.6",
9
9
  "@formily/core": "2.3.0",
10
10
  "@formily/react": "2.3.0",
11
- "@nocobase/database": "0.19.0-alpha.4",
12
- "@nocobase/server": "0.19.0-alpha.4",
13
- "@nocobase/logger": "0.19.0-alpha.4",
14
- "@nocobase/evaluators": "0.19.0-alpha.4",
11
+ "@nocobase/database": "0.19.0-alpha.6",
12
+ "@nocobase/server": "0.19.0-alpha.6",
13
+ "@nocobase/logger": "0.19.0-alpha.6",
14
+ "@nocobase/evaluators": "0.19.0-alpha.6",
15
15
  "lodash": "4.17.21",
16
16
  "@formily/antd-v5": "1.1.9",
17
- "@nocobase/actions": "0.19.0-alpha.4",
17
+ "@nocobase/actions": "0.19.0-alpha.6",
18
18
  "sequelize": "6.35.2",
19
- "@nocobase/plugin-workflow-test": "0.19.0-alpha.4",
20
- "@nocobase/test": "0.19.0-alpha.4",
19
+ "@nocobase/plugin-workflow-test": "0.19.0-alpha.6",
20
+ "@nocobase/test": "0.19.0-alpha.6",
21
21
  "dayjs": "1.11.10"
22
22
  };
@@ -27,10 +27,18 @@
27
27
  "Trigger time": "触发时间",
28
28
  "Triggered at": "触发时间",
29
29
 
30
+ "Execute mode": "执行模式",
31
+ "Execute workflow asynchronously or synchronously based on trigger type, and could not be changed after created.": "基于触发类型异步或同步执行工作流,创建后不可更改。",
32
+ "Asynchronously": "异步",
33
+ "Synchronously": "同步",
34
+ "Will be executed in the background as a queued task.": "将作为队列任务在后台执行。",
35
+ "For user actions that require immediate feedback. Can not use asynchronous nodes in such mode, and it is not recommended to perform time-consuming operations under synchronous mode.":
36
+ "适用于需要即时反馈的用户操作。不能在此模式下使用异步节点,并且不建议在同步模式下执行耗时的操作。",
37
+
30
38
  "Bind workflows": "绑定工作流",
31
- "Workflow will be triggered after submitting succeeded.": "提交成功后触发工作流。",
32
- "Workflow will be triggered after saving succeeded.": "保存成功后触发工作流。",
39
+ "Workflow will be triggered before or after submitting succeeded based on workflow type.": "工作流会基于其类型在提交成功之前或之后触发。",
33
40
  "Workflow will be triggered directly once the button clicked, without data saving.": "按钮点击后直接触发工作流,但不会保存数据。",
41
+ "Workflow will be triggered before deleting succeeded.": "删除成功之前触发工作流。",
34
42
  "Submit to workflow": "提交至工作流",
35
43
  "Add workflow": "添加工作流",
36
44
  "Select workflow": "选择工作流",
@@ -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":"2024-01-26T14:15:53.300Z"}
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":"2024-02-07T12:21:29.401Z"}
@@ -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":"2024-01-26T14:15:52.969Z"}
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":"2024-02-07T12:21:29.047Z"}
@@ -33,7 +33,7 @@ export default class PluginWorkflowServer extends Plugin {
33
33
  load(): Promise<void>;
34
34
  toggle(workflow: WorkflowModel, enable?: boolean): void;
35
35
  trigger(workflow: WorkflowModel, context: object, options?: {
36
- context?: any;
36
+ [key: string]: any;
37
37
  } & Transactionable): void | Promise<Processor | null>;
38
38
  private triggerSync;
39
39
  resume(job: any): Promise<void>;
@@ -182,6 +182,7 @@ class PluginWorkflowServer extends import_server.Plugin {
182
182
  "workflows.nodes:*",
183
183
  "executions:list",
184
184
  "executions:get",
185
+ "executions:cancel",
185
186
  "flow_nodes:update",
186
187
  "flow_nodes:destroy"
187
188
  ]
@@ -217,8 +218,8 @@ class PluginWorkflowServer extends import_server.Plugin {
217
218
  this.dispatch();
218
219
  });
219
220
  this.app.on("beforeStop", async () => {
220
- const collection = db.getCollection("workflows");
221
- const workflows = await collection.repository.find({
221
+ const repository = db.getRepository("workflows");
222
+ const workflows = await repository.find({
222
223
  filter: { enabled: true }
223
224
  });
224
225
  workflows.forEach((workflow) => {
@@ -240,7 +241,7 @@ class PluginWorkflowServer extends import_server.Plugin {
240
241
  this.getLogger(workflow.id).error(`trigger type ${workflow.type} of workflow ${workflow.id} is not implemented`);
241
242
  return;
242
243
  }
243
- if (typeof enable !== "undefined" ? enable : workflow.get("enabled")) {
244
+ if (enable ?? workflow.get("enabled")) {
244
245
  const prev = workflow.previous();
245
246
  if (prev.config) {
246
247
  trigger.off({ ...workflow.get(), ...prev });
@@ -264,7 +265,8 @@ class PluginWorkflowServer extends import_server.Plugin {
264
265
  if (this.isWorkflowSync(workflow)) {
265
266
  return this.triggerSync(workflow, context, options);
266
267
  }
267
- this.events.push([workflow, context, { context: options.context }]);
268
+ const { transaction, ...rest } = options;
269
+ this.events.push([workflow, context, rest]);
268
270
  this.eventsCount = this.events.length;
269
271
  logger.info(`new event triggered, now events: ${this.events.length}`);
270
272
  logger.debug(`event data:`, {
@@ -304,22 +306,15 @@ class PluginWorkflowServer extends import_server.Plugin {
304
306
  return new import_Processor.default(execution, { ...options, plugin: this });
305
307
  }
306
308
  async createExecution(workflow, context, options) {
307
- var _a;
308
- if ((_a = options.context) == null ? void 0 : _a.executionId) {
309
- const existed = await workflow.countExecutions({
310
- where: {
311
- id: options.context.executionId
312
- },
313
- transaction: options.transaction
314
- });
315
- if (existed) {
316
- this.getLogger(workflow.id).warn(
317
- `workflow ${workflow.id} has already been triggered in same execution (${options.context.executionId}), and newly triggering will be skipped.`
318
- );
319
- return null;
309
+ const { transaction = await this.db.sequelize.transaction() } = options;
310
+ const trigger = this.triggers.get(workflow.type);
311
+ const valid = await trigger.validateEvent(workflow, context, { ...options, transaction });
312
+ if (!valid) {
313
+ if (!options.transaction) {
314
+ await transaction.commit();
320
315
  }
316
+ return null;
321
317
  }
322
- const { transaction = await this.db.sequelize.transaction() } = options;
323
318
  const execution = await workflow.createExecution(
324
319
  {
325
320
  context,
@@ -351,6 +346,9 @@ class PluginWorkflowServer extends import_server.Plugin {
351
346
  return execution;
352
347
  }
353
348
  prepare = async () => {
349
+ if (this.executing && this.db.options.dialect === "sqlite") {
350
+ await this.executing;
351
+ }
354
352
  const event = this.events.shift();
355
353
  this.eventsCount = this.events.length;
356
354
  if (!event) {
@@ -361,7 +359,7 @@ class PluginWorkflowServer extends import_server.Plugin {
361
359
  logger.info(`preparing execution for event`);
362
360
  try {
363
361
  const execution = await this.createExecution(...event);
364
- if (!this.executing && !this.pending.length) {
362
+ if (execution && !this.executing && !this.pending.length) {
365
363
  this.pending.push([execution]);
366
364
  }
367
365
  } catch (err) {
@@ -382,6 +380,9 @@ class PluginWorkflowServer extends import_server.Plugin {
382
380
  this.getLogger("dispatcher").warn(`workflow executing is not finished, new dispatching will be ignored`);
383
381
  return;
384
382
  }
383
+ if (this.events.length) {
384
+ return this.prepare();
385
+ }
385
386
  this.executing = (async () => {
386
387
  let next = null;
387
388
  if (this.pending.length) {
@@ -413,12 +414,12 @@ class PluginWorkflowServer extends import_server.Plugin {
413
414
  }
414
415
  })();
415
416
  }
416
- async process(execution, job, { transaction } = {}) {
417
+ async process(execution, job, options = {}) {
417
418
  var _a, _b;
418
419
  if (execution.status === import_constants.EXECUTION_STATUS.QUEUEING) {
419
- await execution.update({ status: import_constants.EXECUTION_STATUS.STARTED }, { transaction });
420
+ await execution.update({ status: import_constants.EXECUTION_STATUS.STARTED }, { transaction: options.transaction });
420
421
  }
421
- const processor = this.createProcessor(execution, { transaction });
422
+ const processor = this.createProcessor(execution, options);
422
423
  this.getLogger(execution.workflowId).info(`execution (${execution.id}) ${job ? "resuming" : "starting"}...`);
423
424
  try {
424
425
  await (job ? processor.resume(job) : processor.start());
@@ -4,6 +4,7 @@ import type Plugin from './Plugin';
4
4
  import type { ExecutionModel, FlowNodeModel, JobModel } from './types';
5
5
  export interface ProcessorOptions extends Transactionable {
6
6
  plugin: Plugin;
7
+ [key: string]: any;
7
8
  }
8
9
  export default class Processor {
9
10
  execution: ExecutionModel;
@@ -96,7 +96,9 @@ async function revision(context, next) {
96
96
  const revisionData = filter.key ? {
97
97
  key: filter.key,
98
98
  title: origin.title,
99
- allExecuted: origin.allExecuted
99
+ triggerTitle: origin.triggerTitle,
100
+ allExecuted: origin.allExecuted,
101
+ sync: origin.sync
100
102
  } : values;
101
103
  const instance = await repository.create({
102
104
  values: {
@@ -32,7 +32,7 @@ class CreateInstruction extends import__.Instruction {
32
32
  const created = await repository.create({
33
33
  ...options,
34
34
  context: {
35
- executionId: processor.execution.id
35
+ stack: Array.from(new Set((processor.execution.context.stack ?? []).concat(processor.execution.id)))
36
36
  },
37
37
  transaction: processor.transaction
38
38
  });
@@ -31,7 +31,7 @@ class DestroyInstruction extends import__.Instruction {
31
31
  const result = await repo.destroy({
32
32
  ...options,
33
33
  context: {
34
- executionId: processor.execution.id
34
+ stack: Array.from(new Set((processor.execution.context.stack ?? []).concat(processor.execution.id)))
35
35
  },
36
36
  transaction: processor.transaction
37
37
  });
@@ -2,7 +2,5 @@ import Instruction from '.';
2
2
  import Processor from '../Processor';
3
3
  import { FlowNodeModel } from '../types';
4
4
  export default class extends Instruction {
5
- run(node: FlowNodeModel, prevJob: any, processor: Processor): Promise<{
6
- status: number;
7
- }>;
5
+ run(node: FlowNodeModel, prevJob: any, processor: Processor): Promise<any>;
8
6
  }
@@ -34,9 +34,13 @@ var import__ = __toESM(require("."));
34
34
  var import_constants = require("../constants");
35
35
  class EndInstruction_default extends import__.default {
36
36
  async run(node, prevJob, processor) {
37
- const { endStatus } = node.config;
38
- return {
39
- status: endStatus ?? import_constants.JOB_STATUS.RESOLVED
40
- };
37
+ const { endStatus = import_constants.JOB_STATUS.RESOLVED } = node.config;
38
+ await processor.saveJob({
39
+ status: endStatus,
40
+ nodeId: node.id,
41
+ nodeKey: node.key,
42
+ upstreamId: (prevJob == null ? void 0 : prevJob.id) ?? null
43
+ });
44
+ return processor.exit(endStatus);
41
45
  }
42
46
  }
@@ -31,7 +31,7 @@ class UpdateInstruction extends import__.Instruction {
31
31
  const result = await repo.update({
32
32
  ...options,
33
33
  context: {
34
- executionId: processor.execution.id
34
+ stack: Array.from(new Set((processor.execution.context.stack ?? []).concat(processor.execution.id)))
35
35
  },
36
36
  transaction: processor.transaction
37
37
  });
@@ -26,7 +26,6 @@ class add_node_key_to_job_default extends import_server.Migration {
26
26
  on = "afterSync";
27
27
  async up() {
28
28
  const { db } = this.context;
29
- const PluginModel = db.getModel("applicationPlugins");
30
29
  const JobRepo = db.getRepository("jobs");
31
30
  await db.sequelize.transaction(async (transaction) => {
32
31
  const jobs = await JobRepo.find({
@@ -1,3 +1,4 @@
1
+ import { Transactionable } from '@nocobase/database';
1
2
  import Trigger from '.';
2
3
  import type { WorkflowModel } from '../types';
3
4
  export interface CollectionChangeTriggerConfig {
@@ -9,4 +10,5 @@ export default class CollectionTrigger extends Trigger {
9
10
  events: Map<any, any>;
10
11
  on(workflow: WorkflowModel): void;
11
12
  off(workflow: WorkflowModel): void;
13
+ validateEvent(workflow: WorkflowModel, context: any, options: Transactionable): Promise<boolean>;
12
14
  }
@@ -89,20 +89,13 @@ async function handler(workflow, data, options) {
89
89
  if (workflow.sync) {
90
90
  await this.workflow.trigger(
91
91
  workflow,
92
- { data: json },
92
+ { data: json, stack: context == null ? void 0 : context.stack },
93
93
  {
94
- context,
95
94
  transaction
96
95
  }
97
96
  );
98
97
  } else {
99
- this.workflow.trigger(
100
- workflow,
101
- { data: json },
102
- {
103
- context
104
- }
105
- );
98
+ this.workflow.trigger(workflow, { data: json, stack: context == null ? void 0 : context.stack });
106
99
  }
107
100
  }
108
101
  class CollectionTrigger extends import__.default {
@@ -151,4 +144,21 @@ class CollectionTrigger extends import__.default {
151
144
  }
152
145
  }
153
146
  }
147
+ async validateEvent(workflow, context, options) {
148
+ if (context.stack) {
149
+ const existed = await workflow.countExecutions({
150
+ where: {
151
+ id: context.stack
152
+ },
153
+ transaction: options.transaction
154
+ });
155
+ if (existed) {
156
+ this.workflow.getLogger(workflow.id).warn(
157
+ `workflow ${workflow.id} has already been triggered in stack executions (${context.stack}), and newly triggering will be skipped.`
158
+ );
159
+ return false;
160
+ }
161
+ }
162
+ return true;
163
+ }
154
164
  }
@@ -6,6 +6,7 @@ export declare abstract class Trigger {
6
6
  constructor(workflow: Plugin);
7
7
  abstract on(workflow: WorkflowModel): void;
8
8
  abstract off(workflow: WorkflowModel): void;
9
+ validateEvent(workflow: WorkflowModel, context: any, options: Transactionable): boolean | Promise<boolean>;
9
10
  duplicateConfig?(workflow: WorkflowModel, options: Transactionable): object | Promise<object>;
10
11
  sync?: boolean;
11
12
  }
@@ -25,6 +25,9 @@ class Trigger {
25
25
  constructor(workflow) {
26
26
  this.workflow = workflow;
27
27
  }
28
+ validateEvent(workflow, context, options) {
29
+ return true;
30
+ }
28
31
  sync;
29
32
  }
30
33
  var triggers_default = Trigger;
package/package.json CHANGED
@@ -4,11 +4,13 @@
4
4
  "displayName.zh-CN": "工作流",
5
5
  "description": "A powerful workflow plugin designed to support business process management and automation.",
6
6
  "description.zh-CN": "工作流插件,为业务流程管理和自动化提供支持。",
7
- "version": "0.19.0-alpha.4",
7
+ "version": "0.19.0-alpha.6",
8
8
  "license": "AGPL-3.0",
9
9
  "main": "./dist/server/index.js",
10
+ "homepage": "https://docs.nocobase.com/plugins/workflow",
11
+ "homepage.zh-CN": "https://docs-cn.nocobase.com/plugins/workflow",
10
12
  "dependencies": {
11
- "@nocobase/plugin-workflow-test": "0.19.0-alpha.4"
13
+ "@nocobase/plugin-workflow-test": "0.19.0-alpha.6"
12
14
  },
13
15
  "devDependencies": {
14
16
  "@ant-design/icons": "5.x",
@@ -43,5 +45,8 @@
43
45
  "@nocobase/test": "0.x",
44
46
  "@nocobase/utils": "0.x"
45
47
  },
46
- "gitHead": "9583023f7bea828da5192384a5c002782c341b65"
48
+ "gitHead": "2eb524db98c7f4136fe1a9a1b1259cd72cf6635f",
49
+ "keywords": [
50
+ "workflow"
51
+ ]
47
52
  }