@nocobase/plugin-workflow 0.14.0-alpha.7 → 0.15.0-alpha.1

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 (50) hide show
  1. package/dist/client/AddButton.d.ts +2 -1
  2. package/dist/client/Branch.d.ts +4 -2
  3. package/dist/client/WorkflowProvider.d.ts +1 -0
  4. package/dist/client/constant.d.ts +2 -0
  5. package/dist/client/constants.d.ts +2 -0
  6. package/dist/client/hooks/useGetAriaLabelOfAddButton.d.ts +6 -0
  7. package/dist/client/index.d.ts +8 -2
  8. package/dist/client/index.js +138 -120
  9. package/dist/client/nodes/aggregate.d.ts +3 -3
  10. package/dist/client/nodes/calculation.d.ts +21 -7
  11. package/dist/client/nodes/create.d.ts +3 -2
  12. package/dist/client/nodes/index.d.ts +2 -2
  13. package/dist/client/nodes/loop.d.ts +4 -5
  14. package/dist/client/nodes/manual/SchemaConfig.d.ts +1 -1
  15. package/dist/client/nodes/manual/index.d.ts +3 -3
  16. package/dist/client/nodes/query.d.ts +5 -5
  17. package/dist/client/nodes/request.d.ts +15 -10
  18. package/dist/client/nodes/sql.d.ts +11 -2
  19. package/dist/client/schemas/collection.d.ts +1 -1
  20. package/dist/client/triggers/collection.d.ts +1 -0
  21. package/dist/client/triggers/form.d.ts +2 -0
  22. package/dist/client/triggers/index.d.ts +4 -0
  23. package/dist/client/variable.d.ts +20 -3
  24. package/dist/externalVersion.js +9 -10
  25. package/dist/locale/zh-CN.d.ts +5 -3
  26. package/dist/locale/zh-CN.js +5 -3
  27. package/dist/node_modules/cron-parser/package.json +1 -1
  28. package/dist/node_modules/lru-cache/package.json +1 -1
  29. package/dist/server/Plugin.js +4 -1
  30. package/dist/server/Processor.d.ts +4 -4
  31. package/dist/server/Processor.js +9 -6
  32. package/dist/server/actions/workflows.d.ts +1 -0
  33. package/dist/server/actions/workflows.js +13 -52
  34. package/dist/server/collections/flow_nodes.js +4 -0
  35. package/dist/server/constants.d.ts +2 -0
  36. package/dist/server/constants.js +4 -2
  37. package/dist/server/index.d.ts +1 -0
  38. package/dist/server/index.js +2 -0
  39. package/dist/server/instructions/index.d.ts +3 -1
  40. package/dist/server/migrations/20230221162902-jsonb-to-json.js +0 -16
  41. package/dist/server/migrations/20230809113132-workflow-options.js +5 -2
  42. package/dist/server/migrations/20231024172342-add-node-key.d.ts +4 -0
  43. package/dist/server/migrations/20231024172342-add-node-key.js +80 -0
  44. package/dist/server/triggers/form.d.ts +3 -3
  45. package/dist/server/triggers/form.js +15 -11
  46. package/dist/server/triggers/index.d.ts +2 -0
  47. package/dist/server/triggers/index.js +1 -1
  48. package/dist/server/triggers/schedule.js +2 -2
  49. package/dist/server/utils.js +5 -4
  50. package/package.json +2 -3
@@ -3,3 +3,4 @@ export declare function update(context: Context, next: any): Promise<void>;
3
3
  export declare function destroy(context: Context, next: any): Promise<void>;
4
4
  export declare function revision(context: Context, next: any): Promise<void>;
5
5
  export declare function sync(context: Context, next: any): Promise<void>;
6
+ export declare function trigger(context: Context, next: any): Promise<any>;
@@ -30,6 +30,7 @@ __export(workflows_exports, {
30
30
  destroy: () => destroy,
31
31
  revision: () => revision,
32
32
  sync: () => sync,
33
+ trigger: () => trigger,
33
34
  update: () => update
34
35
  });
35
36
  module.exports = __toCommonJS(workflows_exports);
@@ -78,48 +79,8 @@ async function destroy(context, next) {
78
79
  });
79
80
  next();
80
81
  }
81
- function typeOf(value) {
82
- if (Array.isArray(value)) {
83
- return "array";
84
- } else if (value instanceof Date) {
85
- return "date";
86
- } else if (value === null) {
87
- return "null";
88
- }
89
- return typeof value;
90
- }
91
- function migrateConfig(config, oldToNew) {
92
- function migrate(value) {
93
- var _a, _b;
94
- switch (typeOf(value)) {
95
- case "object":
96
- if (value.type === "$jobsMapByNodeId") {
97
- return {
98
- ...value,
99
- options: {
100
- ...value.options,
101
- nodeId: (_b = oldToNew.get((_a = value.options) == null ? void 0 : _a.nodeId)) == null ? void 0 : _b.id
102
- }
103
- };
104
- }
105
- return Object.keys(value).reduce((result, key) => ({ ...result, [key]: migrate(value[key]) }), {});
106
- case "array":
107
- return value.map((item) => migrate(item));
108
- case "string":
109
- return value.replace(/({{\$jobsMapByNodeId|{{\$scopes)\.([\w-]+)/g, (_, jobVar, oldNodeId) => {
110
- const newNode = oldToNew.get(Number.parseInt(oldNodeId, 10));
111
- if (!newNode) {
112
- throw new Error("node configurated for result is not existed");
113
- }
114
- return `${jobVar}.${newNode.id}`;
115
- });
116
- default:
117
- return value;
118
- }
119
- }
120
- return migrate(config);
121
- }
122
82
  async function revision(context, next) {
83
+ const plugin = context.app.getPlugin("workflow");
123
84
  const { db } = context;
124
85
  const repository = import_actions.utils.getRepositoryFromParams(context);
125
86
  const { filterByTk, filter = {}, values = {} } = context.action.params;
@@ -131,6 +92,7 @@ async function revision(context, next) {
131
92
  context,
132
93
  transaction
133
94
  });
95
+ const trigger2 = plugin.triggers.get(origin.type);
134
96
  const revisionData = filter.key ? {
135
97
  key: filter.key,
136
98
  title: origin.title,
@@ -140,9 +102,9 @@ async function revision(context, next) {
140
102
  values: {
141
103
  title: `${origin.title} copy`,
142
104
  description: origin.description,
105
+ ...revisionData,
143
106
  type: origin.type,
144
- config: origin.config,
145
- ...revisionData
107
+ config: typeof trigger2.duplicateConfig === "function" ? await trigger2.duplicateConfig(origin, { transaction }) : origin.config
146
108
  },
147
109
  transaction
148
110
  });
@@ -153,10 +115,12 @@ async function revision(context, next) {
153
115
  const oldToNew = /* @__PURE__ */ new Map();
154
116
  const newToOld = /* @__PURE__ */ new Map();
155
117
  for await (const node of origin.nodes) {
118
+ const instruction = plugin.instructions.get(node.type);
156
119
  const newNode = await instance.createNode(
157
120
  {
158
121
  type: node.type,
159
- config: node.config,
122
+ key: node.key,
123
+ config: typeof instruction.duplicateConfig === "function" ? await instruction.duplicateConfig(node, { transaction }) : node.config,
160
124
  title: node.title,
161
125
  branchIndex: node.branchIndex
162
126
  },
@@ -169,17 +133,10 @@ async function revision(context, next) {
169
133
  const oldNode = originalNodesMap.get(oldId);
170
134
  const newUpstream = oldNode.upstreamId ? oldToNew.get(oldNode.upstreamId) : null;
171
135
  const newDownstream = oldNode.downstreamId ? oldToNew.get(oldNode.downstreamId) : null;
172
- let migratedConfig;
173
- try {
174
- migratedConfig = migrateConfig(oldNode.config, oldToNew);
175
- } catch (err) {
176
- return context.throw(400, err.message);
177
- }
178
136
  await newNode.update(
179
137
  {
180
138
  upstreamId: (newUpstream == null ? void 0 : newUpstream.id) ?? null,
181
- downstreamId: (newDownstream == null ? void 0 : newDownstream.id) ?? null,
182
- config: migratedConfig
139
+ downstreamId: (newDownstream == null ? void 0 : newDownstream.id) ?? null
183
140
  },
184
141
  { transaction }
185
142
  );
@@ -203,10 +160,14 @@ async function sync(context, next) {
203
160
  context.status = 204;
204
161
  await next();
205
162
  }
163
+ async function trigger(context, next) {
164
+ return next();
165
+ }
206
166
  // Annotate the CommonJS export names for ESM import in node:
207
167
  0 && (module.exports = {
208
168
  destroy,
209
169
  revision,
210
170
  sync,
171
+ trigger,
211
172
  update
212
173
  });
@@ -25,6 +25,10 @@ var flow_nodes_default = {
25
25
  duplicator: "required",
26
26
  name: "flow_nodes",
27
27
  fields: [
28
+ {
29
+ type: "uid",
30
+ name: "key"
31
+ },
28
32
  {
29
33
  type: "string",
30
34
  name: "title"
@@ -7,6 +7,7 @@ export declare const EXECUTION_STATUS: {
7
7
  ABORTED: number;
8
8
  CANCELED: number;
9
9
  REJECTED: number;
10
+ RETRY_NEEDED: number;
10
11
  };
11
12
  export declare const JOB_STATUS: {
12
13
  PENDING: number;
@@ -16,6 +17,7 @@ export declare const JOB_STATUS: {
16
17
  ABORTED: number;
17
18
  CANCELED: number;
18
19
  REJECTED: number;
20
+ RETRY_NEEDED: number;
19
21
  };
20
22
  export declare const BRANCH_INDEX: {
21
23
  DEFAULT: any;
@@ -30,7 +30,8 @@ const EXECUTION_STATUS = {
30
30
  ERROR: -2,
31
31
  ABORTED: -3,
32
32
  CANCELED: -4,
33
- REJECTED: -5
33
+ REJECTED: -5,
34
+ RETRY_NEEDED: -6
34
35
  };
35
36
  const JOB_STATUS = {
36
37
  PENDING: 0,
@@ -39,7 +40,8 @@ const JOB_STATUS = {
39
40
  ERROR: -2,
40
41
  ABORTED: -3,
41
42
  CANCELED: -4,
42
- REJECTED: -5
43
+ REJECTED: -5,
44
+ RETRY_NEEDED: -6
43
45
  };
44
46
  const BRANCH_INDEX = {
45
47
  DEFAULT: null,
@@ -1,3 +1,4 @@
1
+ export * from './utils';
1
2
  export * from './constants';
2
3
  export type * from './instructions';
3
4
  export { Trigger } from './triggers';
@@ -33,6 +33,7 @@ __export(server_exports, {
33
33
  default: () => import_Plugin.default
34
34
  });
35
35
  module.exports = __toCommonJS(server_exports);
36
+ __reExport(server_exports, require("./utils"), module.exports);
36
37
  __reExport(server_exports, require("./constants"), module.exports);
37
38
  var import_triggers = require("./triggers");
38
39
  var import_Processor = __toESM(require("./Processor"));
@@ -42,6 +43,7 @@ __reExport(server_exports, require("./types"), module.exports);
42
43
  0 && (module.exports = {
43
44
  Processor,
44
45
  Trigger,
46
+ ...require("./utils"),
45
47
  ...require("./constants"),
46
48
  ...require("./types")
47
49
  });
@@ -1,3 +1,4 @@
1
+ import { Transactionable } from '@nocobase/database';
1
2
  import Plugin from '..';
2
3
  import Processor from '../Processor';
3
4
  import type { FlowNodeModel } from '../types';
@@ -11,7 +12,8 @@ export type Runner = (node: FlowNodeModel, input: any, processor: Processor) =>
11
12
  export interface Instruction {
12
13
  run: Runner;
13
14
  resume?: Runner;
14
- getScope?: (node: FlowNodeModel, job: any, processor: Processor) => any;
15
+ getScope?: (node: FlowNodeModel, data: any, processor: Processor) => any;
16
+ duplicateConfig?: (node: FlowNodeModel, options: Transactionable) => object | Promise<object>;
15
17
  }
16
18
  type InstructionConstructor<T> = {
17
19
  new (p: Plugin): T;
@@ -48,22 +48,6 @@ class jsonb_to_json_default extends import_server.Migration {
48
48
  },
49
49
  { transaction }
50
50
  );
51
- await queryInterface.changeColumn(
52
- db.getCollection("executions").model.getTableName(),
53
- "context",
54
- {
55
- type: import_database.DataTypes.JSON
56
- },
57
- { transaction }
58
- );
59
- await queryInterface.changeColumn(
60
- db.getCollection("jobs").model.getTableName(),
61
- "result",
62
- {
63
- type: import_database.DataTypes.JSON
64
- },
65
- { transaction }
66
- );
67
51
  });
68
52
  }
69
53
  }
@@ -23,18 +23,21 @@ module.exports = __toCommonJS(workflow_options_exports);
23
23
  var import_server = require("@nocobase/server");
24
24
  class workflow_options_default extends import_server.Migration {
25
25
  async up() {
26
- const match = await this.app.version.satisfies("<0.11.0-alpha.2");
26
+ const match = await this.app.version.satisfies("<0.14.0-alpha.8");
27
27
  if (!match) {
28
28
  return;
29
29
  }
30
30
  const { db } = this.context;
31
- const WorkflowRepo = db.getRepository("flow_nodes");
31
+ const WorkflowRepo = db.getRepository("workflows");
32
32
  await db.sequelize.transaction(async (transaction) => {
33
33
  const workflows = await WorkflowRepo.find({
34
34
  transaction
35
35
  });
36
36
  await workflows.reduce(
37
37
  (promise, workflow) => promise.then(() => {
38
+ if (!workflow.useTransaction) {
39
+ return;
40
+ }
38
41
  workflow.set("options", {
39
42
  useTransaction: workflow.get("useTransaction")
40
43
  });
@@ -0,0 +1,4 @@
1
+ import { Migration } from '@nocobase/server';
2
+ export default class extends Migration {
3
+ up(): Promise<void>;
4
+ }
@@ -0,0 +1,80 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var add_node_key_exports = {};
19
+ __export(add_node_key_exports, {
20
+ default: () => add_node_key_default
21
+ });
22
+ module.exports = __toCommonJS(add_node_key_exports);
23
+ var import_sequelize = require("sequelize");
24
+ var import_server = require("@nocobase/server");
25
+ var import_utils = require("@nocobase/utils");
26
+ function migrateNodeConfig(config = {}, nodesMap) {
27
+ Object.keys(config).forEach((key) => {
28
+ const valueType = typeof config[key];
29
+ if (valueType === "string") {
30
+ config[key] = config[key].replace(/{{\s*\$jobsMapByNodeId\.(\d+)(\.[^}]+)?\s*}}/g, (matched, id, path) => {
31
+ return `{{$jobsMapByNodeKey.${nodesMap[id].key}${path || ""}}}`;
32
+ }).replace(/{{\s*\$scopes\.(\d+)(\.[^}]+)?\s*}}/g, (matched, id, path) => {
33
+ return `{{$scopes.${nodesMap[id].key}${path || ""}}}`;
34
+ });
35
+ } else if (valueType === "object" && config[key]) {
36
+ migrateNodeConfig(config[key], nodesMap);
37
+ }
38
+ });
39
+ return config;
40
+ }
41
+ class add_node_key_default extends import_server.Migration {
42
+ async up() {
43
+ const match = await this.app.version.satisfies("<0.14.0-alpha.8");
44
+ if (!match) {
45
+ return;
46
+ }
47
+ const { db } = this.context;
48
+ const NodeCollection = db.getCollection("flow_nodes");
49
+ const NodeRepo = NodeCollection.repository;
50
+ const tableName = NodeCollection.getTableNameWithSchema();
51
+ await db.sequelize.transaction(async (transaction) => {
52
+ if (!await NodeCollection.getField("key").existsInDb()) {
53
+ await this.queryInterface.addColumn(tableName, "key", import_sequelize.DataTypes.STRING, {
54
+ transaction
55
+ });
56
+ }
57
+ const nodes = await NodeRepo.find({
58
+ transaction
59
+ });
60
+ const nodesMap = nodes.reduce((map, node) => {
61
+ map[node.id] = node;
62
+ if (!node.get("key")) {
63
+ node.set("key", (0, import_utils.uid)());
64
+ }
65
+ return map;
66
+ }, {});
67
+ await nodes.reduce(
68
+ (promise, node) => promise.then(() => {
69
+ node.set("config", migrateNodeConfig(node.config, nodesMap));
70
+ node.changed("config", true);
71
+ return node.save({
72
+ silent: true,
73
+ transaction
74
+ });
75
+ }),
76
+ Promise.resolve()
77
+ );
78
+ });
79
+ }
80
+ }
@@ -3,9 +3,9 @@ import Plugin from '..';
3
3
  import { WorkflowModel } from '../types';
4
4
  export default class FormTrigger extends Trigger {
5
5
  constructor(plugin: Plugin);
6
- triggerAction: (context: any, next: any) => Promise<any>;
7
- middleware: (context: any, next: any) => Promise<void>;
8
- trigger(context: any): Promise<void>;
6
+ triggerAction(context: any, next: any): Promise<any>;
7
+ middleware: (context: any, next: any) => Promise<any>;
8
+ private trigger;
9
9
  on(workflow: WorkflowModel): void;
10
10
  off(workflow: WorkflowModel): void;
11
11
  }
@@ -28,11 +28,8 @@ class FormTrigger extends import__.Trigger {
28
28
  constructor(plugin) {
29
29
  super(plugin);
30
30
  plugin.app.resourcer.use(this.middleware);
31
- plugin.app.actions({
32
- ["workflows:trigger"]: this.triggerAction
33
- });
34
31
  }
35
- triggerAction = async (context, next) => {
32
+ async triggerAction(context, next) {
36
33
  const { triggerWorkflows } = context.action.params;
37
34
  if (!triggerWorkflows) {
38
35
  return context.throw(400);
@@ -40,20 +37,27 @@ class FormTrigger extends import__.Trigger {
40
37
  context.status = 202;
41
38
  await next();
42
39
  this.trigger(context);
43
- };
40
+ }
44
41
  middleware = async (context, next) => {
42
+ const {
43
+ resourceName,
44
+ actionName,
45
+ params: { triggerWorkflows }
46
+ } = context.action;
47
+ if (resourceName === "workflows" && actionName === "trigger") {
48
+ return this.triggerAction(context, next);
49
+ }
45
50
  await next();
46
- const { resourceName, actionName } = context.action;
47
- if (resourceName === "workflows" && actionName === "trigger" || !["create", "update"].includes(actionName)) {
51
+ if (!triggerWorkflows) {
52
+ return;
53
+ }
54
+ if (!["create", "update"].includes(actionName)) {
48
55
  return;
49
56
  }
50
57
  this.trigger(context);
51
58
  };
52
59
  async trigger(context) {
53
- const { triggerWorkflows, values } = context.action.params;
54
- if (!triggerWorkflows) {
55
- return;
56
- }
60
+ const { triggerWorkflows = "", values } = context.action.params;
57
61
  const { currentUser } = context.state;
58
62
  const triggers = triggerWorkflows.split(",").map((trigger) => trigger.split("!"));
59
63
  const workflowRepo = this.plugin.db.getRepository("workflows");
@@ -1,3 +1,4 @@
1
+ import { Transactionable } from '@nocobase/database';
1
2
  import Plugin from '..';
2
3
  import type { WorkflowModel } from '../types';
3
4
  export declare abstract class Trigger {
@@ -5,6 +6,7 @@ export declare abstract class Trigger {
5
6
  constructor(plugin: Plugin);
6
7
  abstract on(workflow: WorkflowModel): void;
7
8
  abstract off(workflow: WorkflowModel): void;
9
+ duplicateConfig?(workflow: WorkflowModel, options: Transactionable): object | Promise<object>;
8
10
  }
9
11
  export default function <T extends Trigger>(plugin: any, more?: {
10
12
  [key: string]: {
@@ -31,8 +31,8 @@ __export(triggers_exports, {
31
31
  default: () => triggers_default
32
32
  });
33
33
  module.exports = __toCommonJS(triggers_exports);
34
- var import_utils = require("@nocobase/utils");
35
34
  var import_path = __toESM(require("path"));
35
+ var import_utils = require("@nocobase/utils");
36
36
  class Trigger {
37
37
  constructor(plugin) {
38
38
  this.plugin = plugin;
@@ -362,7 +362,7 @@ class ScheduleTrigger extends import__.Trigger {
362
362
  });
363
363
  }
364
364
  init() {
365
- if (this.plugin.app.name !== "main") {
365
+ if (this.plugin.app.getPlugin("multi-app-share-collection").enabled && this.plugin.app.name !== "main") {
366
366
  return;
367
367
  }
368
368
  if (this.timer) {
@@ -428,7 +428,7 @@ class ScheduleTrigger extends import__.Trigger {
428
428
  workflows.forEach(async (workflow) => {
429
429
  const should = await this.shouldCache(workflow, now);
430
430
  if (should) {
431
- this.plugin.app.logger.info("caching scheduled workflow will run in next minute:", workflow.id);
431
+ this.plugin.getLogger(workflow.id).info("caching scheduled workflow will run in next minute");
432
432
  }
433
433
  this.setCache(workflow, !should);
434
434
  });
@@ -20,16 +20,17 @@ __export(utils_exports, {
20
20
  toJSON: () => toJSON
21
21
  });
22
22
  module.exports = __toCommonJS(utils_exports);
23
+ var import_database = require("@nocobase/database");
23
24
  function toJSON(data) {
24
- if (typeof data !== "object" || !data) {
25
- return data;
26
- }
27
25
  if (Array.isArray(data)) {
28
26
  return data.map(toJSON);
29
27
  }
28
+ if (!(data instanceof import_database.Model) || !data) {
29
+ return data;
30
+ }
30
31
  const result = data.get();
31
32
  Object.keys(data.constructor.associations).forEach((key) => {
32
- if (result[key] != null) {
33
+ if (result[key] != null && typeof result[key] === "object") {
33
34
  result[key] = toJSON(result[key]);
34
35
  }
35
36
  });
package/package.json CHANGED
@@ -4,12 +4,11 @@
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.14.0-alpha.7",
7
+ "version": "0.15.0-alpha.1",
8
8
  "license": "AGPL-3.0",
9
9
  "main": "./dist/server/index.js",
10
10
  "devDependencies": {
11
11
  "@ant-design/icons": "5.x",
12
- "@emotion/css": "^11.7.1",
13
12
  "@formily/antd-v5": "1.x",
14
13
  "@formily/core": "2.x",
15
14
  "@formily/react": "2.x",
@@ -42,5 +41,5 @@
42
41
  "@nocobase/test": "0.x",
43
42
  "@nocobase/utils": "0.x"
44
43
  },
45
- "gitHead": "dc958417d27ed0753439bcef192be91a03dfc30f"
44
+ "gitHead": "8bbeab858a818fbe0a1f954ecf1f61337d06c065"
46
45
  }