@tachybase/module-workflow 1.6.0 → 1.6.3

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
@@ -21,25 +21,27 @@ __export(nodes_exports, {
21
21
  destroy: () => destroy,
22
22
  moveDown: () => moveDown,
23
23
  moveUp: () => moveUp,
24
+ syncRemoteCode: () => syncRemoteCode,
24
25
  update: () => update
25
26
  });
26
27
  module.exports = __toCommonJS(nodes_exports);
27
28
  var import_server = require("@tego/server");
28
- async function create(context, next) {
29
- const { db } = context;
30
- const repository = import_server.utils.getRepositoryFromParams(context);
31
- const { whitelist, blacklist, updateAssociationValues, values, associatedIndex: workflowId } = context.action.params;
32
- context.body = await db.sequelize.transaction(async (transaction) => {
29
+ var import_get_remote_code_fetcher = require("../utils/get-remote-code-fetcher");
30
+ async function create(ctx, next) {
31
+ const { db } = ctx;
32
+ const repository = import_server.utils.getRepositoryFromParams(ctx);
33
+ const { whitelist, blacklist, updateAssociationValues, values, associatedIndex: workflowId } = ctx.action.params;
34
+ ctx.body = await db.sequelize.transaction(async (transaction) => {
33
35
  const workflow = await repository.getSourceModel(transaction);
34
36
  if (workflow.executed) {
35
- context.throw(400, "Node could not be created in executed workflow");
37
+ ctx.throw(400, "Node could not be created in executed workflow");
36
38
  }
37
39
  const instance = await repository.create({
38
40
  values,
39
41
  whitelist,
40
42
  blacklist,
41
43
  updateAssociationValues,
42
- context,
44
+ context: ctx,
43
45
  transaction
44
46
  });
45
47
  if (!instance.upstreamId) {
@@ -115,10 +117,10 @@ function searchBranchDownstreams(nodes, from) {
115
117
  }
116
118
  return result;
117
119
  }
118
- async function destroy(context, next) {
119
- const { db } = context;
120
- const repository = import_server.utils.getRepositoryFromParams(context);
121
- const { filterByTk } = context.action.params;
120
+ async function destroy(ctx, next) {
121
+ const { db } = ctx;
122
+ const repository = import_server.utils.getRepositoryFromParams(ctx);
123
+ const { filterByTk } = ctx.action.params;
122
124
  const fields = ["id", "upstreamId", "downstreamId", "branchIndex"];
123
125
  const instance = await repository.findOne({
124
126
  filterByTk,
@@ -126,7 +128,7 @@ async function destroy(context, next) {
126
128
  appends: ["upstream", "downstream", "workflow"]
127
129
  });
128
130
  if (instance.workflow.executed) {
129
- context.throw(400, "Nodes in executed workflow could not be deleted");
131
+ ctx.throw(400, "Nodes in executed workflow could not be deleted");
130
132
  }
131
133
  await db.sequelize.transaction(async (transaction) => {
132
134
  const { upstream, downstream } = instance.get();
@@ -172,21 +174,21 @@ async function destroy(context, next) {
172
174
  transaction
173
175
  });
174
176
  });
175
- context.body = instance;
177
+ ctx.body = instance;
176
178
  await next();
177
179
  }
178
- async function update(context, next) {
179
- const { db } = context;
180
- const repository = import_server.utils.getRepositoryFromParams(context);
181
- const { filterByTk, values, whitelist, blacklist, filter, updateAssociationValues } = context.action.params;
182
- context.body = await db.sequelize.transaction(async (transaction) => {
180
+ async function update(ctx, next) {
181
+ const { db } = ctx;
182
+ const repository = import_server.utils.getRepositoryFromParams(ctx);
183
+ const { filterByTk, values, whitelist, blacklist, filter, updateAssociationValues } = ctx.action.params;
184
+ ctx.body = await db.sequelize.transaction(async (transaction) => {
183
185
  const { workflow } = await repository.findOne({
184
186
  filterByTk,
185
187
  appends: ["workflow.executed"],
186
188
  transaction
187
189
  });
188
190
  if (workflow.executed) {
189
- context.throw(400, "Nodes in executed workflow could not be reconfigured");
191
+ ctx.throw(400, "Nodes in executed workflow could not be reconfigured");
190
192
  }
191
193
  return repository.update({
192
194
  filterByTk,
@@ -195,16 +197,16 @@ async function update(context, next) {
195
197
  blacklist,
196
198
  filter,
197
199
  updateAssociationValues,
198
- context,
200
+ context: ctx,
199
201
  transaction
200
202
  });
201
203
  });
202
204
  await next();
203
205
  }
204
- async function moveUp(context, next) {
205
- const { db } = context;
206
- const repository = import_server.utils.getRepositoryFromParams(context);
207
- const { filterByTk } = context.action.params;
206
+ async function moveUp(ctx, next) {
207
+ const { db } = ctx;
208
+ const repository = import_server.utils.getRepositoryFromParams(ctx);
209
+ const { filterByTk } = ctx.action.params;
208
210
  const fields = ["id", "upstreamId", "downstreamId", "branchIndex", "key"];
209
211
  const instance = await repository.findOne({
210
212
  filterByTk,
@@ -212,12 +214,12 @@ async function moveUp(context, next) {
212
214
  appends: ["upstream", "downstream", "workflow"]
213
215
  });
214
216
  if (instance.workflow.executed) {
215
- context.throw(400, "Nodes in executed workflow could not be deleted");
217
+ ctx.throw(400, "Nodes in executed workflow could not be deleted");
216
218
  }
217
219
  await db.sequelize.transaction(async (transaction) => {
218
220
  const { upstream, downstream } = instance.get();
219
221
  if (!upstream) {
220
- context.throw(400, "First node could not be moved up");
222
+ ctx.throw(400, "First node could not be moved up");
221
223
  }
222
224
  const upUpStreamId = upstream.upstreamId;
223
225
  const upStreamId = upstream.id;
@@ -257,13 +259,13 @@ async function moveUp(context, next) {
257
259
  );
258
260
  }
259
261
  });
260
- context.body = instance;
262
+ ctx.body = instance;
261
263
  await next();
262
264
  }
263
- async function moveDown(context, next) {
264
- const { db } = context;
265
- const repository = import_server.utils.getRepositoryFromParams(context);
266
- const { filterByTk } = context.action.params;
265
+ async function moveDown(ctx, next) {
266
+ const { db } = ctx;
267
+ const repository = import_server.utils.getRepositoryFromParams(ctx);
268
+ const { filterByTk } = ctx.action.params;
267
269
  const fields = ["id", "upstreamId", "downstreamId", "branchIndex", "key"];
268
270
  const instance = await repository.findOne({
269
271
  filterByTk,
@@ -271,13 +273,13 @@ async function moveDown(context, next) {
271
273
  appends: ["upstream", "downstream", "workflow"]
272
274
  });
273
275
  if (instance.workflow.executed) {
274
- context.throw(400, "Nodes in executed workflow could not be deleted");
276
+ ctx.throw(400, "Nodes in executed workflow could not be deleted");
275
277
  }
276
278
  await db.sequelize.transaction(async (transaction) => {
277
279
  const { upstream, downstream } = instance.get();
278
280
  const downDownstreamId = downstream.downstreamId;
279
281
  if (!downstream) {
280
- context.throw(400, "Last node could not be moved up");
282
+ ctx.throw(400, "Last node could not be moved up");
281
283
  }
282
284
  if (upstream) {
283
285
  await upstream.update(
@@ -317,14 +319,138 @@ async function moveDown(context, next) {
317
319
  });
318
320
  }
319
321
  });
320
- context.body = instance;
322
+ ctx.body = instance;
321
323
  await next();
322
324
  }
325
+ async function syncRemoteCode(ctx, next) {
326
+ var _a;
327
+ const params = ctx.action.params.values || ctx.action.params || {};
328
+ const { codeUrl, codeType, codeBranch = "main", codeAuthType, codeAuthToken, codeAuthUsername, nodeId } = params;
329
+ if (!codeUrl || !codeType) {
330
+ ctx.throw(400, "codeUrl and codeType are required");
331
+ }
332
+ try {
333
+ const remoteCodeFetcher = (0, import_get_remote_code_fetcher.getRemoteCodeFetcher)(ctx.app);
334
+ if (codeType === "git" && !remoteCodeFetcher) {
335
+ ctx.throw(500, "WorkflowRemoteCodeFetcher service is required for Git type.");
336
+ return;
337
+ }
338
+ ctx.logger.info(
339
+ `Syncing remote code (force refresh): ${codeUrl} (type: ${codeType}, branch: ${codeBranch || "main"})`
340
+ );
341
+ if (!remoteCodeFetcher) {
342
+ if (codeType === "cdn") {
343
+ const http = require("node:http");
344
+ const https = require("node:https");
345
+ const { URL } = require("node:url");
346
+ const urlObj = new URL(codeUrl);
347
+ const client = urlObj.protocol === "https:" ? https : http;
348
+ const code = await new Promise((resolve, reject) => {
349
+ const headers = {
350
+ "User-Agent": "TegoWorkflow/1.0"
351
+ };
352
+ if (codeAuthType === "token" && codeAuthToken) {
353
+ headers["Authorization"] = `Bearer ${codeAuthToken}`;
354
+ } else if (codeAuthType === "basic" && codeAuthUsername && codeAuthToken) {
355
+ const credentials = Buffer.from(`${codeAuthUsername}:${codeAuthToken}`).toString("base64");
356
+ headers["Authorization"] = `Basic ${credentials}`;
357
+ }
358
+ const request = client.get(
359
+ {
360
+ hostname: urlObj.hostname,
361
+ port: urlObj.port || (urlObj.protocol === "https:" ? 443 : 80),
362
+ path: urlObj.pathname + urlObj.search,
363
+ headers,
364
+ timeout: 1e4
365
+ },
366
+ (res) => {
367
+ if (res.statusCode !== 200) {
368
+ reject(new Error(`Failed to fetch: HTTP ${res.statusCode}`));
369
+ return;
370
+ }
371
+ let data = "";
372
+ res.on("data", (chunk) => {
373
+ data += chunk;
374
+ });
375
+ res.on("end", () => {
376
+ resolve(data);
377
+ });
378
+ }
379
+ );
380
+ request.on("error", reject);
381
+ request.on("timeout", () => {
382
+ request.destroy();
383
+ reject(new Error("Request timeout"));
384
+ });
385
+ });
386
+ ctx.body = {
387
+ code
388
+ };
389
+ } else {
390
+ ctx.throw(500, `Unsupported code type: ${codeType}. RemoteCodeFetcher service is required.`);
391
+ return;
392
+ }
393
+ } else {
394
+ const code = await remoteCodeFetcher.fetchCode(
395
+ codeUrl,
396
+ codeType,
397
+ codeBranch || "main",
398
+ // 使用配置的分支,默认为 'main'
399
+ void 0,
400
+ // codePath - 使用默认值
401
+ codeAuthType,
402
+ codeAuthToken,
403
+ codeAuthUsername
404
+ );
405
+ ctx.body = {
406
+ code
407
+ };
408
+ }
409
+ if (nodeId && ((_a = ctx.body) == null ? void 0 : _a.code)) {
410
+ try {
411
+ const repository = ctx.db.getRepository("flow_nodes");
412
+ const node = await repository.findOne({
413
+ filterByTk: nodeId
414
+ });
415
+ if (node) {
416
+ const currentConfig = node.get("config") || {};
417
+ const config = JSON.parse(JSON.stringify(currentConfig));
418
+ const syncTime = (/* @__PURE__ */ new Date()).toISOString();
419
+ config.lastSyncTime = syncTime;
420
+ config.codeCache = {
421
+ content: ctx.body.code,
422
+ timestamp: Date.now()
423
+ };
424
+ await repository.update({
425
+ filterByTk: nodeId,
426
+ values: {
427
+ config
428
+ }
429
+ });
430
+ }
431
+ } catch (error) {
432
+ ctx.logger.warn("Failed to update lastSyncTime and codeCache", {
433
+ error: error instanceof Error ? error.message : String(error),
434
+ nodeId
435
+ });
436
+ }
437
+ }
438
+ await next();
439
+ } catch (error) {
440
+ ctx.logger.error("Failed to sync remote code", {
441
+ error: error instanceof Error ? error.message : String(error),
442
+ stack: error instanceof Error ? error.stack : void 0,
443
+ params
444
+ });
445
+ ctx.throw(500, `Failed to fetch remote code: ${error instanceof Error ? error.message : String(error)}`);
446
+ }
447
+ }
323
448
  // Annotate the CommonJS export names for ESM import in node:
324
449
  0 && (module.exports = {
325
450
  create,
326
451
  destroy,
327
452
  moveDown,
328
453
  moveUp,
454
+ syncRemoteCode,
329
455
  update
330
456
  });
@@ -7,14 +7,14 @@ import { Context, Next } from '@tego/server';
7
7
  *
8
8
  * 使用 listExtended 作为 action 名称,避免覆盖默认的 list,便于后续扩展
9
9
  */
10
- export declare function listExtended(context: Context, next: Next): Promise<Context>;
11
- export declare function update(context: Context, next: any): Promise<void>;
12
- export declare function destroy(context: Context, next: any): Promise<void>;
13
- export declare function dump(context: Context, next: Next): Promise<void>;
14
- export declare function load(context: Context, next: Next): Promise<void>;
15
- export declare function test(context: Context, next: Next): Promise<never>;
16
- export declare function revision(context: Context, next: Next): Promise<void>;
17
- export declare function retry(context: Context, next: Next): Promise<any>;
18
- export declare function sync(context: Context, next: any): Promise<void>;
10
+ export declare function listExtended(ctx: Context, next: Next): Promise<Context>;
11
+ export declare function update(ctx: Context, next: any): Promise<void>;
12
+ export declare function destroy(ctx: Context, next: any): Promise<void>;
13
+ export declare function dump(ctx: Context, next: Next): Promise<void>;
14
+ export declare function load(ctx: Context, next: Next): Promise<void>;
15
+ export declare function test(ctx: Context, next: Next): Promise<never>;
16
+ export declare function revision(ctx: Context, next: Next): Promise<void>;
17
+ export declare function retry(ctx: Context, next: Next): Promise<any>;
18
+ export declare function sync(ctx: Context, next: any): Promise<void>;
19
19
  export declare function trigger(ctx: Context, next: Next): Promise<void>;
20
20
  export declare function moveWorkflow(ctx: Context, next: Next): Promise<void>;
@@ -8,12 +8,12 @@ export declare function getWorkflowData(workflow: any): {
8
8
  };
9
9
  /**
10
10
  * 查询单个工作流的最新执行时间
11
- * @param context 上下文对象
11
+ * @param ctx 上下文对象
12
12
  * @param workflowId 工作流 ID(优先使用,可利用外键索引)
13
13
  * @param workflowKey 工作流 Key(备用)
14
14
  * @returns UTC ISO 格式的时间字符串,如果不存在则返回 null
15
15
  */
16
- export declare function getLatestExecutedTimeForWorkflow(context: Context, workflowId?: number, workflowKey?: string): Promise<string | null>;
16
+ export declare function getLatestExecutedTimeForWorkflow(ctx: Context, workflowId?: number, workflowKey?: string): Promise<string | null>;
17
17
  /**
18
18
  * 为工作流对象设置最新执行时间
19
19
  * 支持 Model 和普通对象两种格式
@@ -21,11 +21,11 @@ export declare function getLatestExecutedTimeForWorkflow(context: Context, workf
21
21
  export declare function setLatestExecutedTime(row: any, executedTime: string | null): void;
22
22
  /**
23
23
  * 查询单个工作流关联的事件源名称
24
- * @param context 上下文对象
24
+ * @param ctx 上下文对象
25
25
  * @param workflowKey 工作流 Key
26
26
  * @returns 事件源名称,如果不存在则返回 null
27
27
  */
28
- export declare function getEventSourceNameForWorkflow(context: Context, workflowKey?: string): Promise<string | null>;
28
+ export declare function getEventSourceNameForWorkflow(ctx: Context, workflowKey?: string): Promise<string | null>;
29
29
  /**
30
30
  * 为工作流对象设置事件源名称
31
31
  * 支持 Model 和普通对象两种格式
@@ -34,12 +34,12 @@ export declare function setEventSourceName(row: any, eventSourceName: string | n
34
34
  /**
35
35
  * 查询单个工作流的分类信息
36
36
  * 优先从 workflow 对象中获取已加载的分类数据(通过 appends),如果不存在则查询数据库
37
- * @param context 上下文对象
37
+ * @param ctx 上下文对象
38
38
  * @param workflow 工作流对象(可能包含已加载的分类数据)
39
39
  * @param workflowKey 工作流 Key(用于查询数据库)
40
40
  * @returns 分类信息数组,格式:{ id, name, color? }[]
41
41
  */
42
- export declare function getCategoriesForWorkflow(context: Context, workflow?: any, workflowKey?: string): Promise<Array<{
42
+ export declare function getCategoriesForWorkflow(ctx: Context, workflow?: any, workflowKey?: string): Promise<Array<{
43
43
  id: number;
44
44
  name: string;
45
45
  color?: string;
@@ -40,12 +40,12 @@ var import_dayjs = __toESM(require("dayjs"));
40
40
  function getWorkflowData(workflow) {
41
41
  return workflow && typeof workflow.toJSON === "function" ? workflow.toJSON() : workflow;
42
42
  }
43
- async function getLatestExecutedTimeForWorkflow(context, workflowId, workflowKey) {
43
+ async function getLatestExecutedTimeForWorkflow(ctx, workflowId, workflowKey) {
44
44
  if (!workflowId && !workflowKey) {
45
45
  return null;
46
46
  }
47
47
  try {
48
- const ExecutionRepo = context.db.getRepository("executions");
48
+ const ExecutionRepo = ctx.db.getRepository("executions");
49
49
  const filter = {};
50
50
  if (workflowId) {
51
51
  filter.workflowId = workflowId;
@@ -56,11 +56,11 @@ async function getLatestExecutedTimeForWorkflow(context, workflowId, workflowKey
56
56
  filter,
57
57
  fields: ["id", "key", "createdAt", "workflowId"],
58
58
  sort: ["-createdAt"],
59
- context
59
+ context: ctx
60
60
  });
61
61
  return (latestExecution == null ? void 0 : latestExecution.createdAt) ? (0, import_dayjs.default)(latestExecution.createdAt).utc().toISOString() : null;
62
62
  } catch (error) {
63
- context.log.error("Failed to fetch latest executed time:", error);
63
+ ctx.log.error("Failed to fetch latest executed time:", error);
64
64
  return null;
65
65
  }
66
66
  }
@@ -70,20 +70,20 @@ function setLatestExecutedTime(row, executedTime) {
70
70
  row.setDataValue("latestExecutedTime", executedTime);
71
71
  }
72
72
  }
73
- async function getEventSourceNameForWorkflow(context, workflowKey) {
73
+ async function getEventSourceNameForWorkflow(ctx, workflowKey) {
74
74
  if (!workflowKey) {
75
75
  return null;
76
76
  }
77
77
  try {
78
- const WebhookRepo = context.db.getRepository("webhooks");
78
+ const WebhookRepo = ctx.db.getRepository("webhooks");
79
79
  const eventSource = await WebhookRepo.findOne({
80
80
  filter: { workflowKey },
81
81
  fields: ["id", "name"],
82
- context
82
+ context: ctx
83
83
  });
84
84
  return (eventSource == null ? void 0 : eventSource.name) || null;
85
85
  } catch (error) {
86
- context.log.error("Failed to fetch event source name:", error);
86
+ ctx.log.error("Failed to fetch event source name:", error);
87
87
  return null;
88
88
  }
89
89
  }
@@ -93,7 +93,7 @@ function setEventSourceName(row, eventSourceName) {
93
93
  row.setDataValue("eventSourceName", eventSourceName);
94
94
  }
95
95
  }
96
- async function getCategoriesForWorkflow(context, workflow, workflowKey) {
96
+ async function getCategoriesForWorkflow(ctx, workflow, workflowKey) {
97
97
  var _a;
98
98
  if (workflow) {
99
99
  const workflowData = workflow && typeof workflow.toJSON === "function" ? workflow.toJSON() : workflow;
@@ -113,12 +113,12 @@ async function getCategoriesForWorkflow(context, workflow, workflowKey) {
113
113
  return null;
114
114
  }
115
115
  try {
116
- const WorkflowCategoryRepo = context.db.getRepository("workflowCategory");
117
- const CategoryRepo = context.db.getRepository("workflowCategories");
116
+ const WorkflowCategoryRepo = ctx.db.getRepository("workflowCategory");
117
+ const CategoryRepo = ctx.db.getRepository("workflowCategories");
118
118
  const workflowCategories = await WorkflowCategoryRepo.find({
119
119
  filter: { workflowKey: key },
120
120
  fields: ["categoryId"],
121
- context
121
+ context: ctx
122
122
  });
123
123
  if (!workflowCategories || workflowCategories.length === 0) {
124
124
  return [];
@@ -134,7 +134,7 @@ async function getCategoriesForWorkflow(context, workflow, workflowKey) {
134
134
  filter: { id: categoryIds },
135
135
  fields: ["id", "name", "color"],
136
136
  sort: ["sort"],
137
- context
137
+ context: ctx
138
138
  });
139
139
  return categories.map((cat) => {
140
140
  const data = cat && typeof cat.toJSON === "function" ? cat.toJSON() : cat;
@@ -145,7 +145,7 @@ async function getCategoriesForWorkflow(context, workflow, workflowKey) {
145
145
  };
146
146
  });
147
147
  } catch (error) {
148
- context.log.error("Failed to fetch categories:", error);
148
+ ctx.log.error("Failed to fetch categories:", error);
149
149
  return null;
150
150
  }
151
151
  }