@nocobase/flow-engine 2.0.37 → 2.0.39

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.
@@ -231,6 +231,34 @@ function normalizeSubPath(raw) {
231
231
  return { subPath: s, wildcard: false };
232
232
  }
233
233
  __name(normalizeSubPath, "normalizeSubPath");
234
+ function extractCtxRootUsage(expr) {
235
+ const raw = String(expr || "").trim();
236
+ if (!raw || raw === "ctx") return null;
237
+ const dotMatch = raw.match(/^ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*)([\s\S]*)$/);
238
+ if (dotMatch) {
239
+ const varName = dotMatch[1] || "";
240
+ const rest = dotMatch[2] || "";
241
+ const normalized = normalizeSubPath(rest);
242
+ return {
243
+ varName,
244
+ subPath: normalized.subPath,
245
+ wildcard: normalized.wildcard
246
+ };
247
+ }
248
+ const bracketMatch = raw.match(/^ctx\s*\[\s*(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\1\s*\]([\s\S]*)$/);
249
+ if (bracketMatch) {
250
+ const varName = bracketMatch[2] || "";
251
+ const rest = bracketMatch[3] || "";
252
+ const normalized = normalizeSubPath(rest);
253
+ return {
254
+ varName,
255
+ subPath: normalized.subPath,
256
+ wildcard: normalized.wildcard
257
+ };
258
+ }
259
+ return null;
260
+ }
261
+ __name(extractCtxRootUsage, "extractCtxRootUsage");
234
262
  function extractUsedVariablePathsFromRunJS(code) {
235
263
  if (typeof code !== "string" || !code.trim()) return {};
236
264
  const src = stripStringsAndComments(code);
@@ -242,23 +270,25 @@ function extractUsedVariablePathsFromRunJS(code) {
242
270
  set.add(subPath || "");
243
271
  usage.set(varName, set);
244
272
  }, "add");
273
+ const addCtxUsage = /* @__PURE__ */ __name((expr) => {
274
+ const hit = extractCtxRootUsage(expr);
275
+ if (!(hit == null ? void 0 : hit.varName)) return;
276
+ add(hit.varName, hit.wildcard ? "" : hit.subPath);
277
+ }, "addCtxUsage");
245
278
  const dotRe = /ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*(?:(?:\.[a-zA-Z_$][a-zA-Z0-9_$]*)|(?:\[[^\]]+\]))*)(?!\s*\()/g;
246
279
  let match;
247
280
  while (match = dotRe.exec(src)) {
248
- const pathAfterCtx = match[1] || "";
249
- const firstKeyMatch = pathAfterCtx.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*)/);
250
- if (!firstKeyMatch) continue;
251
- const firstKey = firstKeyMatch[1];
252
- const rest = pathAfterCtx.slice(firstKey.length);
253
- const { subPath, wildcard } = normalizeSubPath(rest);
254
- add(firstKey, wildcard ? "" : subPath);
281
+ addCtxUsage(`ctx.${match[1] || ""}`);
255
282
  }
256
283
  const bracketRootRe = /ctx\s*\[\s*(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\1\s*\]((?:(?:\.[a-zA-Z_$][a-zA-Z0-9_$]*)|(?:\[[^\]]+\]))*)(?!\s*\()/g;
257
284
  while (match = bracketRootRe.exec(srcWithStrings)) {
258
- const varName = match[2] || "";
259
- const rest = match[3] || "";
260
- const { subPath, wildcard } = normalizeSubPath(rest);
261
- add(varName, wildcard ? "" : subPath);
285
+ addCtxUsage(`ctx['${match[2] || ""}']${match[3] || ""}`);
286
+ }
287
+ const getVarRe = /ctx\.getVar\s*\(\s*(['"])((?:\\.|(?!\1)[\s\S])*)\1\s*\)/g;
288
+ while (match = getVarRe.exec(srcWithStrings)) {
289
+ const expr = String(match[2] || "").replace(/\\'/g, "'").replace(/\\"/g, '"').trim();
290
+ if (!expr.startsWith("ctx")) continue;
291
+ addCtxUsage(expr);
262
292
  }
263
293
  const out = {};
264
294
  for (const [k, set] of usage.entries()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/flow-engine",
3
- "version": "2.0.37",
3
+ "version": "2.0.39",
4
4
  "private": false,
5
5
  "description": "A standalone flow engine for NocoBase, managing workflows, models, and actions.",
6
6
  "main": "lib/index.js",
@@ -8,8 +8,8 @@
8
8
  "dependencies": {
9
9
  "@formily/antd-v5": "1.x",
10
10
  "@formily/reactive": "2.x",
11
- "@nocobase/sdk": "2.0.37",
12
- "@nocobase/shared": "2.0.37",
11
+ "@nocobase/sdk": "2.0.39",
12
+ "@nocobase/shared": "2.0.39",
13
13
  "ahooks": "^3.7.2",
14
14
  "axios": "^1.7.0",
15
15
  "dayjs": "^1.11.9",
@@ -37,5 +37,5 @@
37
37
  ],
38
38
  "author": "NocoBase Team",
39
39
  "license": "Apache-2.0",
40
- "gitHead": "816b2b1e151dcdca857c4284ad91adea16f1904d"
40
+ "gitHead": "1bef474287b73aeef2580e2b949a587435639756"
41
41
  }
@@ -41,4 +41,15 @@ describe('runjsValue utils', () => {
41
41
  expect(out.someVar).toContain('');
42
42
  expect(out.user).toContain('name');
43
43
  });
44
+
45
+ it('extractUsedVariablePathsFromRunJS: extracts ctx.getVar string paths', () => {
46
+ const code = `
47
+ const phone = await ctx.getVar('ctx.item.value.phone');
48
+ const assignee = await ctx.getVar("ctx.user.profile.name");
49
+ return [phone, assignee];
50
+ `;
51
+ const out = extractUsedVariablePathsFromRunJS(code);
52
+ expect(out.item).toContain('value.phone');
53
+ expect(out.user).toContain('profile.name');
54
+ });
44
55
  });
@@ -236,6 +236,37 @@ function normalizeSubPath(raw: string): { subPath: string; wildcard: boolean } {
236
236
  return { subPath: s, wildcard: false };
237
237
  }
238
238
 
239
+ function extractCtxRootUsage(expr: string): { varName: string; subPath: string; wildcard: boolean } | null {
240
+ const raw = String(expr || '').trim();
241
+ if (!raw || raw === 'ctx') return null;
242
+
243
+ const dotMatch = raw.match(/^ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*)([\s\S]*)$/);
244
+ if (dotMatch) {
245
+ const varName = dotMatch[1] || '';
246
+ const rest = dotMatch[2] || '';
247
+ const normalized = normalizeSubPath(rest);
248
+ return {
249
+ varName,
250
+ subPath: normalized.subPath,
251
+ wildcard: normalized.wildcard,
252
+ };
253
+ }
254
+
255
+ const bracketMatch = raw.match(/^ctx\s*\[\s*(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\1\s*\]([\s\S]*)$/);
256
+ if (bracketMatch) {
257
+ const varName = bracketMatch[2] || '';
258
+ const rest = bracketMatch[3] || '';
259
+ const normalized = normalizeSubPath(rest);
260
+ return {
261
+ varName,
262
+ subPath: normalized.subPath,
263
+ wildcard: normalized.wildcard,
264
+ };
265
+ }
266
+
267
+ return null;
268
+ }
269
+
239
270
  /**
240
271
  * Heuristic extraction of ctx variable usage from RunJS code.
241
272
  *
@@ -256,27 +287,35 @@ export function extractUsedVariablePathsFromRunJS(code: string): Record<string,
256
287
  usage.set(varName, set);
257
288
  };
258
289
 
290
+ const addCtxUsage = (expr: string) => {
291
+ const hit = extractCtxRootUsage(expr);
292
+ if (!hit?.varName) return;
293
+ add(hit.varName, hit.wildcard ? '' : hit.subPath);
294
+ };
295
+
259
296
  // dot form: ctx.foo.bar / ctx.foo[0].bar (excluding ctx.method(...))
260
297
  const dotRe = /ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*(?:(?:\.[a-zA-Z_$][a-zA-Z0-9_$]*)|(?:\[[^\]]+\]))*)(?!\s*\()/g;
261
298
  let match: RegExpExecArray | null;
262
299
  while ((match = dotRe.exec(src))) {
263
- const pathAfterCtx = match[1] || '';
264
- const firstKeyMatch = pathAfterCtx.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*)/);
265
- if (!firstKeyMatch) continue;
266
- const firstKey = firstKeyMatch[1];
267
- const rest = pathAfterCtx.slice(firstKey.length);
268
- const { subPath, wildcard } = normalizeSubPath(rest);
269
- add(firstKey, wildcard ? '' : subPath);
300
+ addCtxUsage(`ctx.${match[1] || ''}`);
270
301
  }
271
302
 
272
303
  // bracket root: ctx['foo'].bar / ctx["foo"][0] (excluding ctx['method'](...))
273
304
  const bracketRootRe =
274
305
  /ctx\s*\[\s*(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\1\s*\]((?:(?:\.[a-zA-Z_$][a-zA-Z0-9_$]*)|(?:\[[^\]]+\]))*)(?!\s*\()/g;
275
306
  while ((match = bracketRootRe.exec(srcWithStrings))) {
276
- const varName = match[2] || '';
277
- const rest = match[3] || '';
278
- const { subPath, wildcard } = normalizeSubPath(rest);
279
- add(varName, wildcard ? '' : subPath);
307
+ addCtxUsage(`ctx['${match[2] || ''}']${match[3] || ''}`);
308
+ }
309
+
310
+ // async-safe helper form: await ctx.getVar('ctx.foo.bar')
311
+ const getVarRe = /ctx\.getVar\s*\(\s*(['"])((?:\\.|(?!\1)[\s\S])*)\1\s*\)/g;
312
+ while ((match = getVarRe.exec(srcWithStrings))) {
313
+ const expr = String(match[2] || '')
314
+ .replace(/\\'/g, "'")
315
+ .replace(/\\"/g, '"')
316
+ .trim();
317
+ if (!expr.startsWith('ctx')) continue;
318
+ addCtxUsage(expr);
280
319
  }
281
320
 
282
321
  const out: Record<string, string[]> = {};