@tachybase/module-workflow 1.6.0 → 1.6.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 (64) hide show
  1. package/dist/client/components/ColletionTreeSelect.d.ts +16 -0
  2. package/dist/client/components/EnabledStatusFilter.d.ts +2 -0
  3. package/dist/client/components/index.d.ts +1 -0
  4. package/dist/client/features/script/Script.instruction.d.ts +136 -0
  5. package/dist/client/features/script/ScriptCodeEditor.d.ts +9 -0
  6. package/dist/client/features/script/SyncRemoteCodeButton.d.ts +6 -0
  7. package/dist/client/features/trigger-instruction/TriggerInstruction.d.ts +164 -5
  8. package/dist/client/index.js +85 -59
  9. package/dist/client/nodes/select.d.ts +235 -0
  10. package/dist/externalVersion.js +9 -9
  11. package/dist/locale/en-US.json +47 -1
  12. package/dist/locale/es-ES.json +17 -1
  13. package/dist/locale/fr-FR.json +16 -0
  14. package/dist/locale/ja-JP.json +17 -1
  15. package/dist/locale/ko_KR.json +17 -1
  16. package/dist/locale/pt-BR.json +17 -1
  17. package/dist/locale/ru-RU.json +18 -2
  18. package/dist/locale/tr-TR.json +18 -2
  19. package/dist/locale/zh-CN.json +50 -1
  20. package/dist/node_modules/@babel/core/lib/index.js +77 -77
  21. package/dist/node_modules/@babel/core/node_modules/.bin/parser +4 -4
  22. package/dist/node_modules/@babel/core/package.json +1 -1
  23. package/dist/node_modules/@babel/preset-env/lib/index.js +88 -88
  24. package/dist/node_modules/@babel/preset-env/package.json +1 -1
  25. package/dist/node_modules/@babel/preset-react/lib/index.js +80 -80
  26. package/dist/node_modules/@babel/preset-react/package.json +1 -1
  27. package/dist/node_modules/@babel/preset-typescript/lib/index.js +77 -77
  28. package/dist/node_modules/@babel/preset-typescript/package.json +1 -1
  29. package/dist/node_modules/cron-parser/package.json +1 -1
  30. package/dist/node_modules/form-data/package.json +1 -1
  31. package/dist/node_modules/jsonata/package.json +1 -1
  32. package/dist/node_modules/lru-cache/package.json +1 -1
  33. package/dist/node_modules/mime-types/package.json +1 -1
  34. package/dist/node_modules/qrcode/package.json +1 -1
  35. package/dist/server/Plugin.js +57 -1
  36. package/dist/server/actions/executions.d.ts +3 -3
  37. package/dist/server/actions/executions.js +33 -33
  38. package/dist/server/actions/index.js +3 -2
  39. package/dist/server/actions/nodes.d.ts +13 -6
  40. package/dist/server/actions/nodes.js +160 -34
  41. package/dist/server/actions/workflows.d.ts +9 -9
  42. package/dist/server/actions/workflows.helpers.d.ts +6 -6
  43. package/dist/server/actions/workflows.helpers.js +14 -14
  44. package/dist/server/actions/workflows.js +85 -85
  45. package/dist/server/features/interception/RequestInterceptionTrigger.d.ts +1 -1
  46. package/dist/server/features/interception/RequestInterceptionTrigger.js +12 -12
  47. package/dist/server/features/manual/actions.d.ts +1 -1
  48. package/dist/server/features/manual/actions.js +12 -12
  49. package/dist/server/features/notice/actions.js +19 -19
  50. package/dist/server/features/notice/plugin.js +0 -3
  51. package/dist/server/features/omni-trigger/CustomActionTrigger.d.ts +2 -2
  52. package/dist/server/features/omni-trigger/CustomActionTrigger.js +27 -27
  53. package/dist/server/features/script/script.instruction.js +146 -4
  54. package/dist/server/features/trigger-instruction/TriggerInstruction.d.ts +4 -0
  55. package/dist/server/features/trigger-instruction/TriggerInstruction.js +71 -5
  56. package/dist/server/instructions/SelectInstruction.d.ts +13 -0
  57. package/dist/server/instructions/SelectInstruction.js +126 -0
  58. package/dist/server/services/remote-code-fetcher.d.ts +48 -0
  59. package/dist/server/services/remote-code-fetcher.js +370 -0
  60. package/dist/server/utils/get-remote-code-fetcher.d.ts +7 -0
  61. package/dist/server/utils/get-remote-code-fetcher.js +39 -0
  62. package/package.json +12 -12
  63. package/dist/server/features/trigger-instruction/index.d.ts +0 -0
  64. package/dist/server/features/trigger-instruction/index.js +0 -0
@@ -47,20 +47,20 @@ class CustomActionInterceptionError extends Error {
47
47
  const _OmniTrigger = class _OmniTrigger extends import_triggers.default {
48
48
  constructor(workflow) {
49
49
  super(workflow);
50
- this.triggerAction = async (context, next) => {
50
+ this.triggerAction = async (ctx, next) => {
51
51
  const {
52
52
  params: { filterByTk, values, triggerWorkflows = "", filter, resourceName, actionName }
53
- } = context.action;
53
+ } = ctx.action;
54
54
  if (actionName !== "trigger" || resourceName === "workflows") {
55
55
  return next();
56
56
  }
57
- const { currentUser, currentRole } = context.state;
57
+ const { currentUser, currentRole } = ctx.state;
58
58
  const { model: UserModel } = this.workflow.db.getCollection("users");
59
59
  const userInfo = {
60
60
  user: UserModel.build(currentUser).desensitize(),
61
61
  roleName: currentRole
62
62
  };
63
- const dataSourceHeader = context.get("x-data-source");
63
+ const dataSourceHeader = ctx.get("x-data-source");
64
64
  const jointCollectionName = (0, import_server.joinCollectionName)(dataSourceHeader, resourceName);
65
65
  const triggerWorkflowsMap = /* @__PURE__ */ new Map();
66
66
  const triggerWorkflowsArray = [];
@@ -92,7 +92,7 @@ const _OmniTrigger = class _OmniTrigger extends import_triggers.default {
92
92
  const [dataSourceName, collectionName] = (0, import_server.parseCollectionName)(workflow.config.collection);
93
93
  const dataPath = triggerWorkflowsMap.get(workflow.key);
94
94
  const event = [workflow];
95
- const { repository } = context.app.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName);
95
+ const { repository } = ctx.tego.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName);
96
96
  const formData = dataPath ? import_lodash.default.get(values, dataPath) : values;
97
97
  let data = formData;
98
98
  if (filterByTk != null) {
@@ -116,9 +116,9 @@ const _OmniTrigger = class _OmniTrigger extends import_triggers.default {
116
116
  (workflow.sync ? syncGroup : asyncGroup).push(event);
117
117
  }
118
118
  for (const event of syncGroup) {
119
- const processor = await this.workflow.trigger(event[0], event[1], { httpContext: context });
119
+ const processor = await this.workflow.trigger(event[0], event[1], { httpContext: ctx });
120
120
  if (!processor) {
121
- return context.throw(500);
121
+ return ctx.throw(500);
122
122
  }
123
123
  const { lastSavedJob, nodesMap } = processor;
124
124
  const lastNode = nodesMap.get(lastSavedJob == null ? void 0 : lastSavedJob.nodeId);
@@ -130,34 +130,34 @@ const _OmniTrigger = class _OmniTrigger extends import_triggers.default {
130
130
  }
131
131
  if (processor.execution.status < import_constants.EXECUTION_STATUS.STARTED) {
132
132
  if ((lastNode == null ? void 0 : lastNode.type) !== "end") {
133
- return context.throw(
133
+ return ctx.throw(
134
134
  500,
135
- context.t("Workflow on your action failed, please contact the administrator", { ns: "workflow" })
135
+ ctx.t("Workflow on your action failed, please contact the administrator", { ns: "workflow" })
136
136
  );
137
137
  }
138
138
  const err = new CustomActionInterceptionError("Request is intercepted by workflow");
139
139
  err.status = 400;
140
- err.messages = context.state.messages;
141
- return context.throw(err.status, err);
140
+ err.messages = ctx.state.messages;
141
+ return ctx.throw(err.status, err);
142
142
  }
143
- return context.throw(500, "Workflow on your action hangs, please contact the administrator");
143
+ return ctx.throw(500, "Workflow on your action hangs, please contact the administrator");
144
144
  }
145
145
  for (const event of asyncGroup) {
146
146
  this.workflow.trigger(event[0], event[1]);
147
147
  }
148
148
  await next();
149
149
  };
150
- this.middleware = async (context, next) => {
150
+ this.middleware = async (ctx, next) => {
151
151
  const {
152
152
  resourceName,
153
153
  actionName,
154
154
  params: { triggerWorkflows, beforeWorkflows }
155
- } = context.action;
155
+ } = ctx.action;
156
156
  if (beforeWorkflows) {
157
- await this.trigger(context, beforeWorkflows, "before");
157
+ await this.trigger(ctx, beforeWorkflows, "before");
158
158
  }
159
159
  if (resourceName === "workflows" && actionName === "trigger") {
160
- return this.triggerAction(context, next);
160
+ return this.triggerAction(ctx, next);
161
161
  }
162
162
  await next();
163
163
  if (!triggerWorkflows) {
@@ -166,7 +166,7 @@ const _OmniTrigger = class _OmniTrigger extends import_triggers.default {
166
166
  if (!["create", "update"].includes(actionName)) {
167
167
  return;
168
168
  }
169
- return this.trigger(context, triggerWorkflows);
169
+ return this.trigger(ctx, triggerWorkflows);
170
170
  };
171
171
  this.workflow.app.resourcer.registerActionHandler("trigger", this.triggerAction);
172
172
  this.workflow.app.acl.allow("*", "trigger", "loggedIn");
@@ -181,13 +181,13 @@ const _OmniTrigger = class _OmniTrigger extends import_triggers.default {
181
181
  );
182
182
  workflow.app.resourcer.use(this.middleware, { tag: "workflowTrigger", after: "acl" });
183
183
  }
184
- async trigger(context, workflowList, order = "after") {
184
+ async trigger(ctx, workflowList, order = "after") {
185
185
  if (!workflowList) {
186
186
  return;
187
187
  }
188
- const { values } = context.action.params;
189
- const dataSourceHeader = context.get("x-data-source") || "main";
190
- const { currentUser, currentRole } = context.state;
188
+ const { values } = ctx.action.params;
189
+ const dataSourceHeader = ctx.get("x-data-source") || "main";
190
+ const { currentUser, currentRole } = ctx.state;
191
191
  const { model: UserModel } = this.workflow.db.getCollection("users");
192
192
  const userInfo = {
193
193
  user: UserModel.build(currentUser).desensitize(),
@@ -210,19 +210,19 @@ const _OmniTrigger = class _OmniTrigger extends import_triggers.default {
210
210
  const [dataSourceName, collectionName] = (0, import_server.parseCollectionName)(collection);
211
211
  const trigger = triggers.find((trigger2) => trigger2[0] === workflow.key);
212
212
  const event = [workflow];
213
- if (context.action.resourceName !== "workflows") {
213
+ if (ctx.action.resourceName !== "workflows") {
214
214
  if (order === "before") {
215
- event.push({ data: context.action.params, ...userInfo });
215
+ event.push({ data: ctx.action.params, ...userInfo });
216
216
  (workflow.sync ? syncGroup : asyncGroup).push(event);
217
217
  continue;
218
218
  }
219
- if (!context.body) {
219
+ if (!ctx.body) {
220
220
  continue;
221
221
  }
222
222
  if (dataSourceName !== dataSourceHeader) {
223
223
  continue;
224
224
  }
225
- const { body: data } = context;
225
+ const { body: data } = ctx;
226
226
  for (const row of Array.isArray(data) ? data : [data]) {
227
227
  let payload = row;
228
228
  if (trigger[1]) {
@@ -251,7 +251,7 @@ const _OmniTrigger = class _OmniTrigger extends import_triggers.default {
251
251
  event.push({ data: (0, import_utils.toJSON)(payload), ...userInfo });
252
252
  }
253
253
  } else {
254
- const { model, repository } = context.app.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName);
254
+ const { model, repository } = ctx.tego.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName);
255
255
  let data = trigger[1] ? (0, import_lodash.get)(values, trigger[1]) : values;
256
256
  const pk = (0, import_lodash.get)(data, model.primaryKeyAttribute);
257
257
  if (appends.length && pk != null) {
@@ -265,7 +265,7 @@ const _OmniTrigger = class _OmniTrigger extends import_triggers.default {
265
265
  (workflow.sync ? syncGroup : asyncGroup).push(event);
266
266
  }
267
267
  for (const event of syncGroup) {
268
- await this.workflow.trigger(event[0], event[1], { httpContext: context });
268
+ await this.workflow.trigger(event[0], event[1], { httpContext: ctx });
269
269
  }
270
270
  for (const event of asyncGroup) {
271
271
  this.workflow.trigger(event[0], event[1]);
@@ -38,9 +38,151 @@ var import_jsonata = __toESM(require("jsonata"));
38
38
  var import_lodash = __toESM(require("lodash"));
39
39
  var import_qrcode = __toESM(require("qrcode"));
40
40
  var import__ = require("../..");
41
+ var import_get_remote_code_fetcher = require("../../utils/get-remote-code-fetcher");
41
42
  class ScriptInstruction extends import__.Instruction {
42
43
  async run(node, input, processor) {
43
- const { sourceArray, type, code = "", model } = node.config;
44
+ const {
45
+ sourceArray,
46
+ type,
47
+ code = "",
48
+ model,
49
+ codeSource = "local",
50
+ codeType,
51
+ codeUrl,
52
+ codeBranch = "main",
53
+ codeAuthType,
54
+ codeAuthToken,
55
+ codeAuthUsername
56
+ } = node.config;
57
+ let actualCode = code;
58
+ if (codeSource === "remote" && codeUrl && codeType) {
59
+ try {
60
+ const app = processor.options.plugin.app;
61
+ const remoteCodeFetcher = (0, import_get_remote_code_fetcher.getRemoteCodeFetcher)(app);
62
+ if (remoteCodeFetcher) {
63
+ const codeCache = node.config.codeCache;
64
+ if (codeCache == null ? void 0 : codeCache.content) {
65
+ app.logger.info(`[Workflow Node ${node.id}] Using cached remote code from database`);
66
+ actualCode = codeCache.content;
67
+ } else {
68
+ app.logger.info(
69
+ `[Workflow Node ${node.id}] No cache found, fetching remote code from ${codeUrl} (type: ${codeType}, branch: ${codeBranch || "main"})`
70
+ );
71
+ actualCode = await remoteCodeFetcher.fetchCode(
72
+ codeUrl,
73
+ codeType,
74
+ codeBranch || "main",
75
+ // 使用配置的分支,默认为 'main'
76
+ void 0,
77
+ // codePath - 使用默认值
78
+ codeAuthType,
79
+ codeAuthToken,
80
+ codeAuthUsername
81
+ );
82
+ const nodeRepo = app.db.getRepository("flow_nodes");
83
+ await nodeRepo.update({
84
+ filterByTk: node.id,
85
+ values: {
86
+ config: {
87
+ ...node.config,
88
+ codeCache: {
89
+ content: actualCode,
90
+ timestamp: Date.now()
91
+ // 保留 timestamp 用于记录,但不用于验证
92
+ }
93
+ }
94
+ }
95
+ });
96
+ app.logger.info(`[Workflow Node ${node.id}] Remote code fetched and cached successfully`);
97
+ }
98
+ } else {
99
+ const codeCache = node.config.codeCache;
100
+ if (codeCache == null ? void 0 : codeCache.content) {
101
+ app.logger.info(`[Workflow Node ${node.id}] Using cached remote code from database (fallback mode)`);
102
+ actualCode = codeCache.content;
103
+ } else {
104
+ const http = require("node:http");
105
+ const https = require("node:https");
106
+ const { URL } = require("node:url");
107
+ const urlObj = new URL(codeUrl);
108
+ const client = urlObj.protocol === "https:" ? https : http;
109
+ app.logger.info(
110
+ `[Workflow Node ${node.id}] No cache found, fetching remote code via HTTP (type: ${codeType}, branch: ${codeBranch || "main"})`
111
+ );
112
+ actualCode = await new Promise((resolve, reject) => {
113
+ const headers = {
114
+ "User-Agent": "TegoWorkflow/1.0"
115
+ };
116
+ if (codeAuthType === "token" && codeAuthToken) {
117
+ headers["Authorization"] = `Bearer ${codeAuthToken}`;
118
+ } else if (codeAuthType === "basic" && codeAuthUsername && codeAuthToken) {
119
+ const credentials = Buffer.from(`${codeAuthUsername}:${codeAuthToken}`).toString("base64");
120
+ headers["Authorization"] = `Basic ${credentials}`;
121
+ }
122
+ const request = client.get(
123
+ {
124
+ hostname: urlObj.hostname,
125
+ port: urlObj.port || (urlObj.protocol === "https:" ? 443 : 80),
126
+ path: urlObj.pathname + urlObj.search,
127
+ headers,
128
+ timeout: 1e4
129
+ },
130
+ (res) => {
131
+ if (res.statusCode !== 200) {
132
+ reject(new Error(`Failed to fetch: HTTP ${res.statusCode}`));
133
+ return;
134
+ }
135
+ let data2 = "";
136
+ res.on("data", (chunk) => {
137
+ data2 += chunk;
138
+ });
139
+ res.on("end", () => {
140
+ resolve(data2);
141
+ });
142
+ }
143
+ );
144
+ request.on("error", reject);
145
+ request.on("timeout", () => {
146
+ request.destroy();
147
+ reject(new Error("Request timeout"));
148
+ });
149
+ });
150
+ const nodeRepo = app.db.getRepository("flow_nodes");
151
+ await nodeRepo.update({
152
+ filterByTk: node.id,
153
+ values: {
154
+ config: {
155
+ ...node.config,
156
+ codeCache: {
157
+ content: actualCode,
158
+ timestamp: Date.now()
159
+ // 保留 timestamp 用于记录,但不用于验证
160
+ }
161
+ }
162
+ }
163
+ });
164
+ app.logger.info(`[Workflow Node ${node.id}] Remote code fetched and cached successfully (fallback mode)`);
165
+ }
166
+ }
167
+ } catch (error) {
168
+ const app = processor.options.plugin.app;
169
+ app.logger.error("Failed to fetch remote code for script node", {
170
+ error: error instanceof Error ? error.message : String(error),
171
+ nodeId: node.id,
172
+ codeUrl
173
+ });
174
+ const codeCache = node.config.codeCache;
175
+ if (codeCache == null ? void 0 : codeCache.content) {
176
+ app.logger.warn(`[Workflow Node ${node.id}] Remote fetch failed, using cached code as fallback`);
177
+ actualCode = codeCache.content;
178
+ } else if (!code) {
179
+ throw new Error(`Failed to fetch remote code: ${error instanceof Error ? error.message : String(error)}`);
180
+ } else {
181
+ app.logger.warn(`[Workflow Node ${node.id}] Remote code fetch failed, falling back to local code`);
182
+ actualCode = code;
183
+ }
184
+ }
185
+ }
44
186
  let data = {};
45
187
  switch (sourceArray.length) {
46
188
  case 0: {
@@ -74,13 +216,13 @@ class ScriptInstruction extends import__.Instruction {
74
216
  let result = {};
75
217
  switch (type) {
76
218
  case "jsonata":
77
- result = await convertByJSONata(code, data);
219
+ result = await convertByJSONata(actualCode, data);
78
220
  break;
79
221
  case "js":
80
- result = await convertByJsCode(code, data);
222
+ result = await convertByJsCode(actualCode, data);
81
223
  break;
82
224
  case "ts":
83
- result = await convertByTsCode(code, data, processor);
225
+ result = await convertByTsCode(actualCode, data, processor);
84
226
  break;
85
227
  default:
86
228
  }
@@ -11,5 +11,9 @@ export declare class TriggerInstruction extends Instruction {
11
11
  status: 0;
12
12
  result?: undefined;
13
13
  }>;
14
+ /**
15
+ * 将数据按照 model 配置进行字段映射
16
+ */
17
+ private mapModel;
14
18
  resume(node: any, prevJob: any, processor: Processor): Promise<any>;
15
19
  }
@@ -30,12 +30,13 @@ __export(TriggerInstruction_exports, {
30
30
  TriggerInstruction: () => TriggerInstruction
31
31
  });
32
32
  module.exports = __toCommonJS(TriggerInstruction_exports);
33
+ var import_lodash = __toESM(require("lodash"));
33
34
  var import_constants = require("../../constants");
34
35
  var import_instructions = __toESM(require("../../instructions"));
35
36
  class TriggerInstruction extends import_instructions.default {
36
37
  async run(node, input, processor) {
37
38
  var _a;
38
- const workflowKey = node.config.workflowKey;
39
+ const { workflowKey, sourceArray = [], model } = node.config;
39
40
  const wfRepo = this.workflow.db.getRepository("workflows");
40
41
  const wf = await wfRepo.findOne({ filter: { key: workflowKey, enabled: true } });
41
42
  if (!wf) {
@@ -52,8 +53,41 @@ class TriggerInstruction extends import_instructions.default {
52
53
  );
53
54
  }
54
55
  try {
56
+ let triggerData = input.result;
57
+ if (sourceArray && sourceArray.length > 0) {
58
+ let data = {};
59
+ switch (sourceArray.length) {
60
+ case 0: {
61
+ data = {};
62
+ break;
63
+ }
64
+ case 1: {
65
+ const keyName = sourceArray[0]["keyName"];
66
+ const sourcePath = sourceArray[0]["sourcePath"];
67
+ const rawData = processor.getParsedValue(sourcePath, node.id);
68
+ if (keyName) {
69
+ data = {
70
+ [keyName]: rawData
71
+ };
72
+ } else {
73
+ data = rawData;
74
+ }
75
+ break;
76
+ }
77
+ default: {
78
+ data = sourceArray.reduce(
79
+ (cookedData, { keyName, sourcePath }) => ({
80
+ ...cookedData,
81
+ [keyName]: processor.getParsedValue(sourcePath, node.id)
82
+ }),
83
+ {}
84
+ );
85
+ }
86
+ }
87
+ triggerData = data;
88
+ }
55
89
  if (wf.sync) {
56
- const p = await this.workflow.trigger(wf, input.result, processor.options);
90
+ const p = await this.workflow.trigger(wf, triggerData, processor.options);
57
91
  if (!p) {
58
92
  return {
59
93
  status: import_constants.JOB_STATUS.FAILED,
@@ -67,12 +101,20 @@ class TriggerInstruction extends import_instructions.default {
67
101
  result: `Sub-workflow execution failed: ${lastSavedJob.result}`
68
102
  };
69
103
  }
104
+ let result = lastSavedJob == null ? void 0 : lastSavedJob.result;
105
+ if (typeof result === "object" && result && (model == null ? void 0 : model.length)) {
106
+ if (Array.isArray(result)) {
107
+ result = result.map((item) => this.mapModel(item, model));
108
+ } else {
109
+ result = this.mapModel(result, model);
110
+ }
111
+ }
70
112
  return {
71
113
  status: import_constants.JOB_STATUS.RESOLVED,
72
- result: lastSavedJob == null ? void 0 : lastSavedJob.result
114
+ result
73
115
  };
74
116
  } else {
75
- this.workflow.trigger(wf, input.result, {
117
+ this.workflow.trigger(wf, triggerData, {
76
118
  ...processor.options,
77
119
  parentNode: node.id,
78
120
  parent: processor.execution
@@ -89,8 +131,32 @@ class TriggerInstruction extends import_instructions.default {
89
131
  };
90
132
  }
91
133
  }
134
+ /**
135
+ * 将数据按照 model 配置进行字段映射
136
+ */
137
+ mapModel(data, model) {
138
+ if (typeof data !== "object" || data === null) {
139
+ throw new Error("Invalid data: data should be a non-null object");
140
+ }
141
+ const result = model.reduce((acc, { path, alias }) => {
142
+ const key = alias ?? path.replace(/\./g, "_");
143
+ const value = import_lodash.default.get(data, path);
144
+ acc[key] = value;
145
+ return acc;
146
+ }, {});
147
+ return result;
148
+ }
92
149
  async resume(node, prevJob, processor) {
93
- prevJob.set("result", prevJob.result);
150
+ const { model } = node.config;
151
+ let result = prevJob.result;
152
+ if (typeof result === "object" && result && (model == null ? void 0 : model.length)) {
153
+ if (Array.isArray(result)) {
154
+ result = result.map((item) => this.mapModel(item, model));
155
+ } else {
156
+ result = this.mapModel(result, model);
157
+ }
158
+ }
159
+ prevJob.set("result", result);
94
160
  prevJob.set("status", prevJob.status);
95
161
  return prevJob;
96
162
  }
@@ -0,0 +1,13 @@
1
+ import Instruction from '.';
2
+ import type Processor from '../Processor';
3
+ import type { FlowNodeModel } from '../types';
4
+ export declare class SelectInstruction extends Instruction {
5
+ run(node: FlowNodeModel, input: any, processor: Processor): Promise<{
6
+ result: any;
7
+ status: -1;
8
+ } | {
9
+ result: any;
10
+ status: 1;
11
+ }>;
12
+ }
13
+ export default SelectInstruction;
@@ -0,0 +1,126 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var SelectInstruction_exports = {};
29
+ __export(SelectInstruction_exports, {
30
+ SelectInstruction: () => SelectInstruction,
31
+ default: () => SelectInstruction_default
32
+ });
33
+ module.exports = __toCommonJS(SelectInstruction_exports);
34
+ var import_server = require("@tego/server");
35
+ var import_lodash = require("lodash");
36
+ var import__ = __toESM(require("."));
37
+ var import_constants = require("../constants");
38
+ var import_utils = require("../utils");
39
+ class SelectInstruction extends import__.default {
40
+ async run(node, input, processor) {
41
+ var _a, _b, _c, _d;
42
+ const { collection, multiple, isTree, params = {}, failOnEmpty = false } = node.config;
43
+ const otherOptions = {};
44
+ if (isTree) {
45
+ otherOptions.tree = true;
46
+ }
47
+ const [dataSourceName, collectionName] = (0, import_server.parseCollectionName)(collection);
48
+ const { repository, fields } = this.workflow.app.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName);
49
+ const { page, pageSize, sort = [], paginate = true, ...options } = processor.getParsedValue(params, node.id);
50
+ const appends = ((_a = options.summary) == null ? void 0 : _a.includes(".")) ? [options.summary] : [];
51
+ if (options.summary && !((_b = options.summary) == null ? void 0 : _b.includes("."))) {
52
+ if (["belongsTo", "hasOne", "hasMany", "belongsToMany"].includes((_c = fields.get(options.summary)) == null ? void 0 : _c.type)) {
53
+ appends.push(options.summary);
54
+ }
55
+ }
56
+ let pageArgs = paginate ? import_server.utils.pageArgsToLimitArgs(page, pageSize) : {};
57
+ const data = await (multiple ? repository.find : repository.findOne).call(repository, {
58
+ ...options,
59
+ ...otherOptions,
60
+ ...pageArgs,
61
+ sort: sort.filter((item) => item.field).map((item) => {
62
+ var _a2;
63
+ return `${((_a2 = item.direction) == null ? void 0 : _a2.toLowerCase()) === "desc" ? "-" : ""}${item.field}`;
64
+ }),
65
+ appends,
66
+ transaction: this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction)
67
+ });
68
+ let result;
69
+ const summary = ((_d = options.summary) == null ? void 0 : _d.length) ? options.summary.split(".") : null;
70
+ if (summary) {
71
+ if ((0, import_lodash.isArray)(data)) {
72
+ result = [];
73
+ data.forEach((item) => {
74
+ const filteredValue = findField(item, summary[0], 0, summary, multiple, true);
75
+ const value = (0, import_lodash.isArray)(filteredValue) ? filteredValue : [filteredValue];
76
+ result.push(...value);
77
+ });
78
+ } else {
79
+ result = findField(data, summary[0], 0, summary, multiple, true);
80
+ }
81
+ result = (0, import_lodash.isArray)(result) ? multiple ? result : result[0] : result;
82
+ }
83
+ if (failOnEmpty && (multiple ? !data.length : !data)) {
84
+ return {
85
+ result: summary ? result : data,
86
+ status: import_constants.JOB_STATUS.FAILED
87
+ };
88
+ }
89
+ return {
90
+ result: (0, import_utils.toJSON)(summary ? result : data),
91
+ status: import_constants.JOB_STATUS.RESOLVED
92
+ };
93
+ }
94
+ }
95
+ var SelectInstruction_default = SelectInstruction;
96
+ const findField = (record, field, index, summary, multiple, isOne) => {
97
+ if (record == null) {
98
+ return void 0;
99
+ }
100
+ if (!multiple && !isOne) {
101
+ return;
102
+ }
103
+ let isOneField = isOne;
104
+ const current = record[field];
105
+ if (index === summary.length - 1) {
106
+ if (!multiple && isOne) {
107
+ isOneField = false;
108
+ }
109
+ return current;
110
+ }
111
+ const nextField = summary[index + 1];
112
+ if (Array.isArray(current)) {
113
+ const results = [];
114
+ current.forEach((item) => {
115
+ const v = findField(item, nextField, index + 1, summary, multiple, isOneField);
116
+ if (v === void 0) return;
117
+ results.push(v);
118
+ });
119
+ return results;
120
+ }
121
+ return findField(current, nextField, index + 1, summary, multiple, isOneField);
122
+ };
123
+ // Annotate the CommonJS export names for ESM import in node:
124
+ 0 && (module.exports = {
125
+ SelectInstruction
126
+ });
@@ -0,0 +1,48 @@
1
+ /**
2
+ * 远程代码获取服务(Workflow 模块专用)
3
+ * 支持从 CDN 和 Git 仓库获取代码
4
+ */
5
+ export declare class WorkflowRemoteCodeFetcher {
6
+ private logger;
7
+ /**
8
+ * 从 CDN 获取代码
9
+ * @param url 代码 URL
10
+ * @param timeout 超时时间(毫秒)
11
+ * @param authType 认证类型: 'none' | 'token' | 'basic'
12
+ * @param authToken Bearer Token 或 Basic Auth 的密码
13
+ * @param authUsername Basic Auth 的用户名
14
+ */
15
+ private fetchFromCDN;
16
+ /**
17
+ * 检测 URL 是否已经是 Raw 文件 URL(可以直接访问)
18
+ */
19
+ private isRawFileUrl;
20
+ /**
21
+ * 从 URL 中解析分支和文件路径
22
+ */
23
+ private parseGitUrl;
24
+ /**
25
+ * 从 Git 仓库获取代码(通过 Raw 文件 URL)
26
+ */
27
+ private fetchFromGit;
28
+ /**
29
+ * 获取远程代码
30
+ * @param codeUrl 代码地址
31
+ * @param codeType 代码类型:'cdn' 或 'git'
32
+ * @param codeBranch Git 分支名称(仅 Git 类型需要)
33
+ * @param codePath Git 文件路径(仅 Git 类型需要)
34
+ * @param authType 认证类型: 'none' | 'token' | 'basic'
35
+ * @param authToken Bearer Token 或 Basic Auth 的密码
36
+ * @param authUsername Basic Auth 的用户名
37
+ */
38
+ fetchCode(codeUrl: string, codeType: 'cdn' | 'git', codeBranch?: string, codePath?: string, authType?: string, authToken?: string, authUsername?: string): Promise<string>;
39
+ /**
40
+ * 检查缓存是否有效(默认缓存 1 小时)
41
+ * @param cache 缓存对象,包含 content 和 timestamp
42
+ * @param maxAge 最大缓存时间(毫秒),默认 1 小时 (3600000ms)
43
+ */
44
+ isCacheValid(cache: {
45
+ content: string;
46
+ timestamp: number;
47
+ } | null, maxAge?: number): boolean;
48
+ }