@nocobase/plugin-workflow 1.8.0-beta.1 → 1.8.0-beta.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.
Files changed (34) hide show
  1. package/dist/client/WorkflowTasks.d.ts +7 -0
  2. package/dist/client/{f9eeb46e5c6a9ffe.js → c3b6a4e98b30c0ce.js} +1 -1
  3. package/dist/client/cd148c8354d7084a.js +10 -0
  4. package/dist/client/f2ba2ac6e7edba30.js +10 -0
  5. package/dist/client/{a4111333ce86663c.js → f2c77bbdba9010bb.js} +1 -1
  6. package/dist/client/hooks/useWorkflowExecuted.d.ts +2 -2
  7. package/dist/client/hooks/useWorkflowFilterActionProps.d.ts +13 -0
  8. package/dist/client/index.js +1 -1
  9. package/dist/client/nodes/calculation.d.ts +1 -0
  10. package/dist/client/nodes/condition.d.ts +1 -0
  11. package/dist/client/schemas/executions.d.ts +1 -0
  12. package/dist/client/variable.d.ts +5 -2
  13. package/dist/common/collections/workflows.d.ts +14 -0
  14. package/dist/common/collections/workflows.js +1 -2
  15. package/dist/externalVersion.js +11 -10
  16. package/dist/locale/en-US.json +3 -2
  17. package/dist/locale/zh-CN.json +2 -1
  18. package/dist/node_modules/cron-parser/package.json +1 -1
  19. package/dist/node_modules/lru-cache/package.json +1 -1
  20. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  21. package/dist/server/Plugin.js +9 -5
  22. package/dist/server/actions/nodes.js +3 -4
  23. package/dist/server/actions/workflows.js +11 -3
  24. package/dist/server/instructions/CalculationInstruction.d.ts +10 -0
  25. package/dist/server/instructions/CalculationInstruction.js +15 -0
  26. package/dist/server/instructions/ConditionInstruction.d.ts +11 -0
  27. package/dist/server/instructions/ConditionInstruction.js +15 -0
  28. package/dist/server/migrations/20250619213102-add-missed-stats.d.ts +14 -0
  29. package/dist/server/migrations/20250619213102-add-missed-stats.js +61 -0
  30. package/dist/server/triggers/CollectionTrigger.js +5 -5
  31. package/dist/server/triggers/ScheduleTrigger/DateFieldScheduleTrigger.js +12 -3
  32. package/package.json +4 -3
  33. package/dist/client/3c67def1831d0b23.js +0 -10
  34. package/dist/client/a54c8c009524b6da.js +0 -10
@@ -78,4 +78,5 @@ export default class extends Instruction {
78
78
  label: any;
79
79
  };
80
80
  useInitializers(node: any): SchemaInitializerItemType;
81
+ testable: boolean;
81
82
  }
@@ -119,4 +119,5 @@ export default class extends Instruction {
119
119
  Component({ data }: {
120
120
  data: any;
121
121
  }): React.JSX.Element;
122
+ testable: boolean;
122
123
  }
@@ -152,6 +152,7 @@ export declare const executionSchema: {
152
152
  appends: string[];
153
153
  pageSize: number;
154
154
  sort: string[];
155
+ except: string[];
155
156
  filter: {};
156
157
  };
157
158
  };
@@ -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) => boolean);
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 useGetCollectionFields(dataSourceName?: any): (collectionName: any) => import("@nocobase/client").CollectionFieldOptions[];
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;
@@ -170,8 +170,7 @@ var workflows_default = {
170
170
  target: "workflowStats",
171
171
  foreignKey: "key",
172
172
  sourceKey: "key",
173
- constraints: false,
174
- onDelete: "CASCADE"
173
+ constraints: false
175
174
  // interface: 'oho',
176
175
  // uiSchema: {
177
176
  // type: 'object',
@@ -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-beta.1",
15
- "@nocobase/utils": "1.8.0-beta.1",
14
+ "@nocobase/client": "1.8.0-beta.12",
15
+ "@nocobase/utils": "1.8.0-beta.12",
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-beta.12",
23
24
  "sequelize": "6.35.2",
24
- "@nocobase/database": "1.8.0-beta.1",
25
- "@nocobase/server": "1.8.0-beta.1",
26
- "@nocobase/data-source-manager": "1.8.0-beta.1",
27
- "@nocobase/logger": "1.8.0-beta.1",
28
- "@nocobase/evaluators": "1.8.0-beta.1",
25
+ "@nocobase/database": "1.8.0-beta.12",
26
+ "@nocobase/server": "1.8.0-beta.12",
27
+ "@nocobase/data-source-manager": "1.8.0-beta.12",
28
+ "@nocobase/logger": "1.8.0-beta.12",
29
+ "@nocobase/evaluators": "1.8.0-beta.12",
29
30
  "@formily/antd-v5": "1.2.3",
30
31
  "@formily/reactive": "2.3.0",
31
- "@nocobase/actions": "1.8.0-beta.1",
32
+ "@nocobase/actions": "1.8.0-beta.12",
32
33
  "dayjs": "1.11.13",
33
- "@nocobase/plugin-workflow-test": "1.8.0-beta.1",
34
- "@nocobase/test": "1.8.0-beta.1"
34
+ "@nocobase/plugin-workflow-test": "1.8.0-beta.12",
35
+ "@nocobase/test": "1.8.0-beta.12"
35
36
  };
@@ -208,5 +208,6 @@
208
208
  "After end of branches": "After end of branches",
209
209
  "Inside of branch": "Inside of branch",
210
210
  "Workflow todos": "Workflow todos",
211
- "New version enabled": "New version enabled"
212
- }
211
+ "New version enabled": "New version enabled",
212
+ "Workflow is not exists": "Workflow is not exists"
213
+ }
@@ -243,5 +243,6 @@
243
243
  "Inside of branch": "分支内",
244
244
 
245
245
  "Workflow todos": "流程待办",
246
- "New version enabled": "已启用新版本"
246
+ "New version enabled": "已启用新版本",
247
+ "Workflow is not exists": "工作流不存在"
247
248
  }
@@ -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-06-03T16:07:49.657Z"}
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-03T08:31:50.099Z"}
@@ -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-06-03T16:07:49.333Z"}
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-03T08:31:49.751Z"}
@@ -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-06-03T16:07:49.140Z"}
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-03T08:31:49.578Z"}
@@ -147,17 +147,21 @@ class PluginWorkflowServer extends import_server.Plugin {
147
147
  this.ready = true;
148
148
  const collection = this.db.getCollection("workflows");
149
149
  const workflows = await collection.repository.find({
150
- filter: { enabled: true },
151
- appends: ["stats", "versionStats"]
150
+ appends: ["versionStats"]
152
151
  });
153
152
  for (const workflow of workflows) {
154
- if (!workflow.stats) {
155
- workflow.stats = await workflow.createStats({ executed: 0 });
153
+ if (workflow.current) {
154
+ workflow.stats = await workflow.getStats();
155
+ if (!workflow.stats) {
156
+ workflow.stats = await workflow.createStats({ executed: 0 });
157
+ }
156
158
  }
157
159
  if (!workflow.versionStats) {
158
160
  workflow.versionStats = await workflow.createVersionStats({ executed: 0 });
159
161
  }
160
- this.toggle(workflow, true, { silent: true });
162
+ if (workflow.enabled) {
163
+ this.toggle(workflow, true, { silent: true });
164
+ }
161
165
  }
162
166
  this.checker = setInterval(() => {
163
167
  this.getLogger("dispatcher").info(`(cycling) check for queueing executions`);
@@ -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
- const { executed } = workflow.versionStats;
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
- context.body = await repository.destroy({
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 (!executed && autoRevision) {
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
+ }
@@ -67,7 +67,7 @@ function getFieldRawName(collection, name) {
67
67
  class CollectionTrigger extends import__.default {
68
68
  events = /* @__PURE__ */ new Map();
69
69
  // async function, should return promise
70
- static async handler(workflowId, data, options) {
70
+ static async handler(workflowId, eventType, data, options) {
71
71
  const workflow = this.workflow.enabledCache.get(workflowId);
72
72
  const { skipWorkflow = false, stack } = options.context ?? {};
73
73
  if (skipWorkflow) {
@@ -75,7 +75,7 @@ class CollectionTrigger extends import__.default {
75
75
  }
76
76
  const [dataSourceName] = (0, import_data_source_manager.parseCollectionName)(workflow.config.collection);
77
77
  const transaction = this.workflow.useDataSourceTransaction(dataSourceName, options.transaction);
78
- const ctx = await this.prepare(workflow, data, { ...options, transaction });
78
+ const ctx = await this.prepare(workflow, data, { ...options, transaction, eventType });
79
79
  if (!ctx) {
80
80
  return;
81
81
  }
@@ -99,7 +99,7 @@ class CollectionTrigger extends import__.default {
99
99
  const [dataSourceName, collectionName] = (0, import_data_source_manager.parseCollectionName)(workflow.config.collection);
100
100
  const { collectionManager } = this.workflow.app.dataSourceManager.dataSources.get(dataSourceName);
101
101
  const collection = collectionManager.getCollection(collectionName);
102
- const { transaction, context } = options;
102
+ const { transaction, context, eventType } = options;
103
103
  const { repository, filterTargetKey } = collection;
104
104
  let target = data;
105
105
  let filterByTk;
@@ -113,7 +113,7 @@ class CollectionTrigger extends import__.default {
113
113
  filterByTk = target;
114
114
  loadNeeded = true;
115
115
  }
116
- if (target instanceof import_database.Model && changed && changed.length && changed.filter((name) => {
116
+ if (eventType === MODE_BITMAP_EVENTS.get(MODE_BITMAP.UPDATE) && target instanceof import_database.Model && changed && changed.length && changed.filter((name) => {
117
117
  const field = collection.getField(name);
118
118
  return field && !["linkTo", "hasOne", "hasMany", "belongsToMany"].includes(field.options.type);
119
119
  }).every((name) => !target.changedWithAssociations(getFieldRawName(collection, name)))) {
@@ -162,7 +162,7 @@ class CollectionTrigger extends import__.default {
162
162
  const name = getHookId(workflow, `${collection}.${type}`);
163
163
  if (mode & key) {
164
164
  if (!this.events.has(name)) {
165
- const listener = this.constructor.handler.bind(this, workflow.id);
165
+ const listener = this.constructor.handler.bind(this, workflow.id, type);
166
166
  this.events.set(name, listener);
167
167
  db.on(event, listener);
168
168
  }
@@ -44,6 +44,7 @@ var import_cron_parser = __toESM(require("cron-parser"));
44
44
  var import_utils = require("./utils");
45
45
  var import_data_source_manager = require("@nocobase/data-source-manager");
46
46
  var import_lodash = require("lodash");
47
+ var import_utils2 = require("../../utils");
47
48
  function getOnTimestampWithOffset({ field, offset = 0, unit = 1e3 }, now) {
48
49
  if (!field) {
49
50
  return null;
@@ -317,16 +318,24 @@ class DateFieldScheduleTrigger {
317
318
  });
318
319
  const eventKey = `${workflow.id}:${recordPk}@${nextTime}`;
319
320
  this.cache.delete(eventKey);
320
- this.workflow.trigger(
321
+ const json = (0, import_utils2.toJSON)(data);
322
+ const args = [
321
323
  workflow,
322
324
  {
323
- data: data.toJSON(),
325
+ data: json,
324
326
  date: new Date(nextTime)
325
327
  },
326
328
  {
327
329
  eventKey
328
330
  }
329
- );
331
+ ];
332
+ if (transaction) {
333
+ transaction.afterCommit(() => {
334
+ this.workflow.trigger(...args);
335
+ });
336
+ } else {
337
+ this.workflow.trigger(...args);
338
+ }
330
339
  if (!workflow.config.repeat || workflow.config.limit && workflow.stats.executed >= workflow.config.limit - 1) {
331
340
  return;
332
341
  }
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-beta.1",
7
+ "version": "1.8.0-beta.12",
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-beta.1"
13
+ "@nocobase/plugin-workflow-test": "1.8.0-beta.12"
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": "103935669123174f2942247202e3d9ff15f0d4ed",
50
+ "gitHead": "b244f9b23ce35bd75baf7b357c6d53d0fbddf3be",
50
51
  "keywords": [
51
52
  "Workflow"
52
53
  ]
@@ -1,10 +0,0 @@
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
- "use strict";(self.webpackChunk_nocobase_plugin_workflow=self.webpackChunk_nocobase_plugin_workflow||[]).push([["383"],{8958:function(e,t,n){n.d(t,{a:function(){return a}});var o=n(8156),r=n.n(o),c=n(3238),i=n(6128),l=n(3772),u=n(7893),a=function(){var e=(0,c.useTranslation)().t,t=(0,l.useRecord)().id,n=(0,l.useActionContext)().setVisible;return r().createElement(i.Link,{to:(0,u.s_)(t),onClick:function(){return n(!1)}},e("View"))}},2266:function(e,t,n){n.d(t,{P:function(){return b},r:function(){return v}});var o=n(8156),r=n.n(o),c=n(2721),i=n(482),l=n(3238),u=n(3772),a=n(9144),s=n(573);function p(){return(p=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e}).apply(this,arguments)}function f(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},o=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),o.forEach(function(t){var o;o=n[t],t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o})}return e}function d(){var e,t,n=(e=["\n display: flex;\n "],t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}})));return d=function(){return n},n}function m(e){var t,n=(0,u.useCompile)()(e.label),o=(null!=(t=a.uy[e.value])?t:{}).color;return r().createElement(c.Tag,{color:o,closable:e.closable,onClose:e.onClose},n)}function y(e){var t=(0,u.useCompile)();return r().createElement(r().Fragment,null,r().createElement(m,e),e.description?r().createElement("span",null,t(e.description)):null)}function b(e){var t,n,o=p({},function(e){if(null==e)throw TypeError("Cannot destructure "+e);return e}(e)),i=o.multiple?"multiple":null;return r().createElement(c.Select,(t=f({role:"button","data-testid":"select-".concat(i||"single")},o),n=n={mode:i,optionLabelProp:"label",tagRender:m},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):(function(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n.push.apply(n,o)}return n})(Object(n)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}),t),a.C6.filter(function(e){return!!e.value&&e.value!==a.r9.ABORTED}).map(function(e){return r().createElement(c.Select.Option,f({key:e.value},e),r().createElement(y,e))}))}function v(e){var t=(0,l.useTranslation)().t,n=(0,u.useResourceActionContext)().refresh,a=(0,u.useResourceContext)().resource,p=(0,u.useRecord)(),f=(0,o.useCallback)(function(){c.Modal.confirm({title:(0,s.KQ)("Cancel the execution"),icon:r().createElement(i.ExclamationCircleFilled,null),content:(0,s.KQ)("Are you sure you want to cancel the execution?"),onOk:function(){a.cancel({filterByTk:p.id}).then(function(){c.message.success(t("Operation succeeded")),n()}).catch(function(e){console.error(e.data.error)})}})},[p]);return r().createElement("div",{className:(0,u.css)(d())},e.children,p.status?null:r().createElement(c.Tooltip,{title:(0,s.KQ)("Cancel the execution")},r().createElement(c.Button,{type:"link",danger:!0,onClick:f,shape:"circle",size:"small",icon:r().createElement(i.StopOutlined,null)})))}},2659:function(e,t,n){n.d(t,{V:function(){return b}});var o,r=n(8156),c=n.n(r),i=n(6128),l=n(3238),u=n(2721),a=n(3772),s=n(1768),p=n(9144),f=n(573),d=n(7893);function m(e,t,n,o,r,c,i){try{var l=e[c](i),u=l.value}catch(e){n(e);return}l.done?t(u):Promise.resolve(u).then(o,r)}function y(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var b={type:"void",name:"executionHistoryDrawer",title:'{{t("Execution history", { ns: "'.concat(f.A7,'" })}}'),"x-component":"Action.Drawer",properties:{content:{type:"void","x-decorator":"ExecutionResourceProvider","x-decorator-props":{collection:s.Z,resourceName:"executions",request:{resource:"executions",action:"list",params:{appends:["workflow.id","workflow.title"],pageSize:20,sort:["-createdAt"],filter:{}}}},properties:{actions:{type:"void","x-component":"ActionBar","x-component-props":{style:{marginBottom:16}},properties:{refresher:{type:"void",title:'{{ t("Refresh") }}',"x-component":"Action","x-use-component-props":"useRefreshActionProps","x-component-props":{icon:"ReloadOutlined"}},delete:{type:"void",title:'{{t("Delete")}}',"x-component":"Action","x-component-props":{icon:"DeleteOutlined",useAction:"{{ cm.useBulkDestroyAction }}",confirm:{title:"{{t('Delete record')}}",content:"{{t('Are you sure you want to delete it?')}}"}}},clear:{type:"void",title:'{{t("Clear")}}',"x-component":"Action","x-component-props":{useAction:function(){var e=(0,l.useTranslation)().t,t=(0,a.useResourceActionContext)(),n=t.refresh,o=t.defaultRequest,r=(0,a.useResourceContext)().resource,c=(0,a.useActionContext)().setVisible;return{run:function(){var t;return(t=function(){var t;return function(e,t){var n,o,r,c,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return c={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(c[Symbol.iterator]=function(){return this}),c;function l(c){return function(l){var u=[c,l];if(n)throw TypeError("Generator is already executing.");for(;i;)try{if(n=1,o&&(r=2&u[0]?o.return:u[0]?o.throw||((r=o.return)&&r.call(o),0):o.next)&&!(r=r.call(o,u[1])).done)return r;switch(o=0,r&&(u=[2&u[0],r.value]),u[0]){case 0:case 1:r=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,o=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(r=(r=i.trys).length>0&&r[r.length-1])&&(6===u[0]||2===u[0])){i=0;continue}if(3===u[0]&&(!r||u[1]>r[0]&&u[1]<r[3])){i.label=u[1];break}if(6===u[0]&&i.label<r[1]){i.label=r[1],r=u;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(u);break}r[2]&&i.ops.pop(),i.trys.pop();continue}u=t.call(e,i)}catch(e){u=[6,e],o=0}finally{n=r=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}}}(this,function(i){switch(i.label){case 0:return[4,r.destroy({filter:null==(t=o.params)?void 0:t.filter})];case 1:return i.sent(),u.message.success(e("Operation succeeded")),n(),c(!1),[2]}})},function(){var e=this,n=arguments;return new Promise(function(o,r){var c=t.apply(e,n);function i(e){m(c,o,r,i,l,"next",e)}function l(e){m(c,o,r,i,l,"throw",e)}i(void 0)})})()}}},confirm:{title:'{{t("Clear all executions", { ns: "'.concat(f.A7,'" })}}'),content:'{{t("Clear executions will not reset executed count, and started executions will not be deleted, are you sure you want to delete them all?", { ns: "'.concat(f.A7,'" })}}')}}}}},table:{type:"void","x-component":"Table.Void","x-component-props":{rowKey:"id",rowSelection:{type:"checkbox"},useDataSource:"{{ cm.useDataSourceFromRAC }}"},properties:{id:{type:"void","x-decorator":"Table.Column.Decorator","x-component":"Table.Column",properties:{id:{type:"number","x-component":"CollectionField","x-read-pretty":!0}}},createdAt:{type:"void","x-decorator":"Table.Column.Decorator","x-component":"Table.Column",properties:{createdAt:{type:"string","x-component":"CollectionField","x-component-props":{showTime:!0},"x-read-pretty":!0}}},workflowId:{type:"void","x-decorator":"Table.Column.Decorator","x-component":"Table.Column",title:'{{t("Version", { ns: "'.concat(f.A7,'" })}}'),properties:{workflowId:(y(o={type:"number"},"x-component",function(e){var t=e.value,n=(0,a.useActionContext)().setVisible;return c().createElement(i.Link,{to:(0,d.SI)(t),onClick:function(){return n(!1)}},"#".concat(t))}),y(o,"x-read-pretty",!0),o)}},status:{type:"void","x-decorator":"Table.Column.Decorator","x-component":"Table.Column",title:'{{t("Status", { ns: "'.concat(f.A7,'" })}}'),properties:{status:{type:"number","x-decorator":"ExecutionStatusColumn","x-component":"CollectionField","x-read-pretty":!0}}},actions:{type:"void",title:'{{ t("Actions") }}',"x-component":"Table.Column",properties:{actions:{type:"void","x-component":"Space","x-component-props":{split:"|"},properties:{link:{type:"void","x-component":"ExecutionLink"},delete:{type:"void",title:'{{ t("Delete") }}',"x-component":"Action.Link","x-component-props":{confirm:{title:"{{t('Delete record')}}",content:"{{t('Are you sure you want to delete it?')}}"},useAction:"{{ cm.useDestroyActionAndRefreshCM }}"},"x-reactions":[{dependencies:["..status"],fulfill:{state:{visible:"{{ $deps[0] !== ".concat(p.r9.STARTED," }}")}}}]}}}}}}}}}}}},8327:function(e,t,n){n.d(t,{X:function(){return c}});var o=n(3772);function r(e,t,n,o,r,c,i){try{var l=e[c](i),u=l.value}catch(e){n(e);return}l.done?t(u):Promise.resolve(u).then(o,r)}function c(){var e=(0,o.useResourceActionContext)();return{onClick:function(){var t;return(t=function(){var t;return function(e,t){var n,o,r,c,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return c={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(c[Symbol.iterator]=function(){return this}),c;function l(c){return function(l){var u=[c,l];if(n)throw TypeError("Generator is already executing.");for(;i;)try{if(n=1,o&&(r=2&u[0]?o.return:u[0]?o.throw||((r=o.return)&&r.call(o),0):o.next)&&!(r=r.call(o,u[1])).done)return r;switch(o=0,r&&(u=[2&u[0],r.value]),u[0]){case 0:case 1:r=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,o=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(r=(r=i.trys).length>0&&r[r.length-1])&&(6===u[0]||2===u[0])){i=0;continue}if(3===u[0]&&(!r||u[1]>r[0]&&u[1]<r[3])){i.label=u[1];break}if(6===u[0]&&i.label<r[1]){i.label=r[1],r=u;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(u);break}r[2]&&i.ops.pop(),i.trys.pop();continue}u=t.call(e,i)}catch(e){u=[6,e],o=0}finally{n=r=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}}}(this,function(n){return null==e||null==(t=e.refresh)||t.call(e),[2]})},function(){var e=this,n=arguments;return new Promise(function(o,c){var i=t.apply(e,n);function l(e){r(i,o,c,l,u,"next",e)}function u(e){r(i,o,c,l,u,"throw",e)}l(void 0)})})()}}}}}]);