@nocobase/flow-engine 2.0.0-beta.11 → 2.0.0-beta.13
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.
- package/lib/JSRunner.d.ts +6 -0
- package/lib/JSRunner.js +2 -1
- package/lib/acl/Acl.js +13 -3
- package/lib/components/settings/wrappers/component/SwitchWithTitle.js +2 -1
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +11 -3
- package/lib/executor/FlowExecutor.js +9 -3
- package/lib/flowContext.d.ts +2 -1
- package/lib/flowContext.js +116 -34
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +5 -0
- package/lib/utils/params-resolvers.js +16 -9
- package/lib/utils/runjsTemplateCompat.d.ts +35 -0
- package/lib/utils/runjsTemplateCompat.js +392 -0
- package/lib/views/createViewMeta.d.ts +0 -7
- package/lib/views/createViewMeta.js +19 -70
- package/lib/views/index.d.ts +0 -1
- package/lib/views/index.js +0 -3
- package/lib/views/useDialog.js +0 -1
- package/lib/views/useDrawer.js +0 -1
- package/lib/views/usePage.js +0 -1
- package/lib/views/usePopover.js +4 -1
- package/package.json +4 -4
- package/src/JSRunner.ts +8 -1
- package/src/__tests__/createViewMeta.popup.test.ts +62 -1
- package/src/__tests__/runjsPreprocessDefault.test.ts +49 -0
- package/src/acl/Acl.tsx +3 -3
- package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +2 -1
- package/src/components/settings/wrappers/component/__tests__/InlineControls.test.tsx +74 -0
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +11 -3
- package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +63 -4
- package/src/executor/FlowExecutor.ts +13 -4
- package/src/executor/__tests__/flowExecutor.test.ts +66 -0
- package/src/flowContext.ts +155 -43
- package/src/models/__tests__/flowModel.test.ts +16 -0
- package/src/utils/__tests__/params-resolvers.test.ts +40 -0
- package/src/utils/__tests__/runjsTemplateCompat.test.ts +126 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/params-resolvers.ts +23 -9
- package/src/utils/runjsTemplateCompat.ts +435 -0
- package/src/views/__tests__/useDialog.closeDestroy.test.tsx +0 -4
- package/src/views/createViewMeta.ts +22 -75
- package/src/views/index.tsx +0 -1
- package/src/views/useDialog.tsx +0 -1
- package/src/views/useDrawer.tsx +0 -1
- package/src/views/usePage.tsx +0 -1
- package/src/views/usePopover.tsx +4 -1
package/lib/JSRunner.d.ts
CHANGED
|
@@ -11,6 +11,12 @@ export interface JSRunnerOptions {
|
|
|
11
11
|
timeoutMs?: number;
|
|
12
12
|
globals?: Record<string, any>;
|
|
13
13
|
version?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Enable RunJS template compatibility preprocessing for `{{ ... }}`.
|
|
16
|
+
* When enabled via `ctx.runjs(code, vars, { preprocessTemplates: true })` (default),
|
|
17
|
+
* the code will be rewritten to call `ctx.resolveJsonTemplate(...)` at runtime.
|
|
18
|
+
*/
|
|
19
|
+
preprocessTemplates?: boolean;
|
|
14
20
|
}
|
|
15
21
|
export declare class JSRunner {
|
|
16
22
|
private globals;
|
package/lib/JSRunner.js
CHANGED
|
@@ -62,7 +62,8 @@ const _JSRunner = class _JSRunner {
|
|
|
62
62
|
* 异步运行代码,带错误处理和超时机制
|
|
63
63
|
*/
|
|
64
64
|
async run(code) {
|
|
65
|
-
|
|
65
|
+
const search = typeof location !== "undefined" ? location.search : void 0;
|
|
66
|
+
if (typeof search === "string" && search.includes("skipRunJs=true")) {
|
|
66
67
|
return { success: true, value: null };
|
|
67
68
|
}
|
|
68
69
|
const wrapped = `(async () => {
|
package/lib/acl/Acl.js
CHANGED
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
var __create = Object.create;
|
|
10
11
|
var __defProp = Object.defineProperty;
|
|
11
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
13
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
13
15
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
16
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
15
17
|
var __export = (target, all) => {
|
|
@@ -24,13 +26,21 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
24
26
|
}
|
|
25
27
|
return to;
|
|
26
28
|
};
|
|
29
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
30
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
31
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
32
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
33
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
34
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
35
|
+
mod
|
|
36
|
+
));
|
|
27
37
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
38
|
var Acl_exports = {};
|
|
29
39
|
__export(Acl_exports, {
|
|
30
40
|
ACL: () => ACL
|
|
31
41
|
});
|
|
32
42
|
module.exports = __toCommonJS(Acl_exports);
|
|
33
|
-
var import_lodash = require("lodash");
|
|
43
|
+
var import_lodash = __toESM(require("lodash"));
|
|
34
44
|
const _ACL = class _ACL {
|
|
35
45
|
constructor(flowEngine) {
|
|
36
46
|
this.flowEngine = flowEngine;
|
|
@@ -43,10 +53,10 @@ const _ACL = class _ACL {
|
|
|
43
53
|
// 记录上一次用于鉴权的 token,用于识别登录态变更
|
|
44
54
|
lastToken = null;
|
|
45
55
|
setData(data) {
|
|
46
|
-
this.data = data;
|
|
56
|
+
this.data = import_lodash.default.cloneDeep(data);
|
|
47
57
|
}
|
|
48
58
|
setMeta(data) {
|
|
49
|
-
this.meta = data;
|
|
59
|
+
this.meta = import_lodash.default.cloneDeep(data);
|
|
50
60
|
}
|
|
51
61
|
async load() {
|
|
52
62
|
var _a, _b, _c, _d;
|
|
@@ -73,7 +73,8 @@ const SwitchWithTitle = (0, import_reactive.observer)(
|
|
|
73
73
|
setChecked(val);
|
|
74
74
|
onChange == null ? void 0 : onChange({ [itemKey]: val });
|
|
75
75
|
}, "handleChange");
|
|
76
|
-
const handleWrapperClick = /* @__PURE__ */ __name(() => {
|
|
76
|
+
const handleWrapperClick = /* @__PURE__ */ __name((e) => {
|
|
77
|
+
e.stopPropagation();
|
|
77
78
|
if (disabled) return;
|
|
78
79
|
handleChange(!checked);
|
|
79
80
|
}, "handleWrapperClick");
|
|
@@ -153,6 +153,9 @@ const DefaultSettingsIcon = /* @__PURE__ */ __name(({
|
|
|
153
153
|
const [visible, setVisible] = (0, import_react.useState)(false);
|
|
154
154
|
const [refreshTick, setRefreshTick] = (0, import_react.useState)(0);
|
|
155
155
|
const [extraMenuItems, setExtraMenuItems] = (0, import_react.useState)([]);
|
|
156
|
+
const closeDropdown = (0, import_react.useCallback)(() => {
|
|
157
|
+
setVisible(false);
|
|
158
|
+
}, []);
|
|
156
159
|
const handleOpenChange = (0, import_react.useCallback)((nextOpen, info) => {
|
|
157
160
|
if (info.source === "trigger" || nextOpen) {
|
|
158
161
|
(0, import_react.startTransition)(() => {
|
|
@@ -249,6 +252,7 @@ const DefaultSettingsIcon = /* @__PURE__ */ __name(({
|
|
|
249
252
|
[model, copyUidToClipboard]
|
|
250
253
|
);
|
|
251
254
|
const handleDelete = (0, import_react.useCallback)(() => {
|
|
255
|
+
closeDropdown();
|
|
252
256
|
import_antd.Modal.confirm({
|
|
253
257
|
title: t("Confirm delete"),
|
|
254
258
|
icon: /* @__PURE__ */ import_react.default.createElement(import_icons.ExclamationCircleOutlined, null),
|
|
@@ -269,7 +273,7 @@ const DefaultSettingsIcon = /* @__PURE__ */ __name(({
|
|
|
269
273
|
}
|
|
270
274
|
}
|
|
271
275
|
});
|
|
272
|
-
}, [model]);
|
|
276
|
+
}, [closeDropdown, model, t]);
|
|
273
277
|
const handleStepConfiguration = (0, import_react.useCallback)(
|
|
274
278
|
(key) => {
|
|
275
279
|
const keyParts = key.split(":");
|
|
@@ -294,6 +298,7 @@ const DefaultSettingsIcon = /* @__PURE__ */ __name(({
|
|
|
294
298
|
[flowKey, stepKey] = keyParts;
|
|
295
299
|
}
|
|
296
300
|
try {
|
|
301
|
+
closeDropdown();
|
|
297
302
|
targetModel.openFlowSettings({
|
|
298
303
|
flowKey,
|
|
299
304
|
stepKey
|
|
@@ -302,23 +307,26 @@ const DefaultSettingsIcon = /* @__PURE__ */ __name(({
|
|
|
302
307
|
console.log(t("Configuration popup cancelled or error"), ":", error);
|
|
303
308
|
}
|
|
304
309
|
},
|
|
305
|
-
[model]
|
|
310
|
+
[closeDropdown, model, t]
|
|
306
311
|
);
|
|
307
312
|
const handleMenuClick = (0, import_react.useCallback)(
|
|
308
313
|
({ key }) => {
|
|
309
314
|
const originalKey = key;
|
|
310
315
|
const cleanKey = key.includes("-") && /^(.+)-\d+$/.test(key) ? key.replace(/-\d+$/, "") : key;
|
|
311
316
|
if (cleanKey.startsWith("copy-pop-uid:")) {
|
|
317
|
+
closeDropdown();
|
|
312
318
|
handleCopyPopupUid(cleanKey);
|
|
313
319
|
return;
|
|
314
320
|
}
|
|
315
321
|
const extra = extraMenuItems.find((it) => (it == null ? void 0 : it.key) === originalKey || (it == null ? void 0 : it.key) === cleanKey);
|
|
316
322
|
if (extra == null ? void 0 : extra.onClick) {
|
|
323
|
+
closeDropdown();
|
|
317
324
|
extra.onClick();
|
|
318
325
|
return;
|
|
319
326
|
}
|
|
320
327
|
switch (cleanKey) {
|
|
321
328
|
case "copy-uid":
|
|
329
|
+
closeDropdown();
|
|
322
330
|
handleCopyUid();
|
|
323
331
|
break;
|
|
324
332
|
case "delete":
|
|
@@ -329,7 +337,7 @@ const DefaultSettingsIcon = /* @__PURE__ */ __name(({
|
|
|
329
337
|
break;
|
|
330
338
|
}
|
|
331
339
|
},
|
|
332
|
-
[handleCopyUid, handleDelete, handleStepConfiguration, handleCopyPopupUid, extraMenuItems]
|
|
340
|
+
[closeDropdown, handleCopyUid, handleDelete, handleStepConfiguration, handleCopyPopupUid, extraMenuItems]
|
|
333
341
|
);
|
|
334
342
|
const getModelConfigurableFlowsAndSteps = (0, import_react.useCallback)(
|
|
335
343
|
async (targetModel, modelKey) => {
|
|
@@ -238,7 +238,6 @@ const _FlowExecutor = class _FlowExecutor {
|
|
|
238
238
|
});
|
|
239
239
|
return Promise.resolve(stepResults);
|
|
240
240
|
}
|
|
241
|
-
// runAutoFlows 已移除:统一通过 dispatchEvent('beforeRender') + useCache 控制
|
|
242
241
|
/**
|
|
243
242
|
* Dispatch an event to flows bound via flow.on and execute them.
|
|
244
243
|
*/
|
|
@@ -279,10 +278,17 @@ const _FlowExecutor = class _FlowExecutor {
|
|
|
279
278
|
if (typeof on === "object") return on.eventName === eventName;
|
|
280
279
|
return false;
|
|
281
280
|
});
|
|
281
|
+
const isRouterReplayClick = eventName === "click" && (inputArgs == null ? void 0 : inputArgs.triggerByRouter) === true;
|
|
282
|
+
const flowsToRun = isRouterReplayClick ? flows.filter((flow) => {
|
|
283
|
+
var _a2;
|
|
284
|
+
const reg = flow["flowRegistry"];
|
|
285
|
+
const type = (_a2 = reg == null ? void 0 : reg.constructor) == null ? void 0 : _a2._type;
|
|
286
|
+
return type !== "instance";
|
|
287
|
+
}) : flows;
|
|
282
288
|
const scheduledCancels = [];
|
|
283
289
|
const execute = /* @__PURE__ */ __name(async () => {
|
|
284
290
|
if (sequential) {
|
|
285
|
-
const flowsWithIndex =
|
|
291
|
+
const flowsWithIndex = flowsToRun.map((f, i) => ({ f, i }));
|
|
286
292
|
const ordered = flowsWithIndex.slice().sort((a, b) => {
|
|
287
293
|
var _a2, _b2;
|
|
288
294
|
const regA = a.f["flowRegistry"];
|
|
@@ -396,7 +402,7 @@ const _FlowExecutor = class _FlowExecutor {
|
|
|
396
402
|
return results2;
|
|
397
403
|
}
|
|
398
404
|
const results = await Promise.all(
|
|
399
|
-
|
|
405
|
+
flowsToRun.map(async (flow) => {
|
|
400
406
|
logger.debug(`BaseModel '${model.uid}' dispatching event '${eventName}' to flow '${flow.key}'.`);
|
|
401
407
|
try {
|
|
402
408
|
return await this.runFlow(model, flow.key, inputArgs, runId, eventName);
|
package/lib/flowContext.d.ts
CHANGED
|
@@ -147,7 +147,7 @@ declare class BaseFlowEngineContext extends FlowContext {
|
|
|
147
147
|
dataSourceManager: DataSourceManager;
|
|
148
148
|
requireAsync: (url: string) => Promise<any>;
|
|
149
149
|
importAsync: (url: string) => Promise<any>;
|
|
150
|
-
createJSRunner: (options?: JSRunnerOptions) => JSRunner
|
|
150
|
+
createJSRunner: (options?: JSRunnerOptions) => Promise<JSRunner>;
|
|
151
151
|
pageInfo: {
|
|
152
152
|
version?: 'v1' | 'v2';
|
|
153
153
|
};
|
|
@@ -172,6 +172,7 @@ declare class BaseFlowEngineContext extends FlowContext {
|
|
|
172
172
|
location: Location;
|
|
173
173
|
sql: FlowSQLRepository;
|
|
174
174
|
logger: pino.Logger;
|
|
175
|
+
constructor();
|
|
175
176
|
}
|
|
176
177
|
declare class BaseFlowModelContext extends BaseFlowEngineContext {
|
|
177
178
|
model: FlowModel;
|
package/lib/flowContext.js
CHANGED
|
@@ -74,6 +74,7 @@ var import_utils = require("./utils");
|
|
|
74
74
|
var import_exceptions = require("./utils/exceptions");
|
|
75
75
|
var import_params_resolvers = require("./utils/params-resolvers");
|
|
76
76
|
var import_serverContextParams = require("./utils/serverContextParams");
|
|
77
|
+
var import_variablesParams = require("./utils/variablesParams");
|
|
77
78
|
var import_registry = require("./runjs-context/registry");
|
|
78
79
|
var import_createEphemeralContext = require("./utils/createEphemeralContext");
|
|
79
80
|
var import_dayjs = __toESM(require("dayjs"));
|
|
@@ -96,6 +97,50 @@ function filterBuilderOutputByPaths(built, neededPaths) {
|
|
|
96
97
|
return void 0;
|
|
97
98
|
}
|
|
98
99
|
__name(filterBuilderOutputByPaths, "filterBuilderOutputByPaths");
|
|
100
|
+
function topLevelOf(subPath) {
|
|
101
|
+
if (!subPath) return void 0;
|
|
102
|
+
const m = String(subPath).match(/^([^.[]+)/);
|
|
103
|
+
return m == null ? void 0 : m[1];
|
|
104
|
+
}
|
|
105
|
+
__name(topLevelOf, "topLevelOf");
|
|
106
|
+
function inferSelectsFromUsage(paths = []) {
|
|
107
|
+
if (!Array.isArray(paths) || paths.length === 0) {
|
|
108
|
+
return { generatedAppends: void 0, generatedFields: void 0 };
|
|
109
|
+
}
|
|
110
|
+
const appendSet = /* @__PURE__ */ new Set();
|
|
111
|
+
const fieldSet = /* @__PURE__ */ new Set();
|
|
112
|
+
const normalizePath = /* @__PURE__ */ __name((raw) => {
|
|
113
|
+
if (!raw) return "";
|
|
114
|
+
let s = String(raw);
|
|
115
|
+
s = s.replace(/\[(?:\d+)\]/g, "");
|
|
116
|
+
s = s.replace(/\[(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')\]/g, (_m, g1, g2) => `.${g1 || g2}`);
|
|
117
|
+
s = s.replace(/\.\.+/g, ".");
|
|
118
|
+
s = s.replace(/^\./, "").replace(/\.$/, "");
|
|
119
|
+
return s;
|
|
120
|
+
}, "normalizePath");
|
|
121
|
+
for (let path of paths) {
|
|
122
|
+
if (!path) continue;
|
|
123
|
+
while (/^\[(\d+)\](\.|$)/.test(path)) {
|
|
124
|
+
path = path.replace(/^\[(\d+)\]\.?/, "");
|
|
125
|
+
}
|
|
126
|
+
const norm = normalizePath(path);
|
|
127
|
+
if (!norm) continue;
|
|
128
|
+
const segments = norm.split(".").filter(Boolean);
|
|
129
|
+
if (segments.length === 0) continue;
|
|
130
|
+
if (segments.length === 1) {
|
|
131
|
+
fieldSet.add(segments[0]);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
135
|
+
appendSet.add(segments.slice(0, i + 1).join("."));
|
|
136
|
+
}
|
|
137
|
+
fieldSet.add(segments.join("."));
|
|
138
|
+
}
|
|
139
|
+
const generatedAppends = appendSet.size ? Array.from(appendSet) : void 0;
|
|
140
|
+
const generatedFields = fieldSet.size ? Array.from(fieldSet) : void 0;
|
|
141
|
+
return { generatedAppends, generatedFields };
|
|
142
|
+
}
|
|
143
|
+
__name(inferSelectsFromUsage, "inferSelectsFromUsage");
|
|
99
144
|
const _FlowContext = class _FlowContext {
|
|
100
145
|
constructor() {
|
|
101
146
|
__privateAdd(this, _FlowContext_instances);
|
|
@@ -670,6 +715,23 @@ toTreeNode_fn = /* @__PURE__ */ __name(function(name, metaOrFactory, paths = [na
|
|
|
670
715
|
__name(_FlowContext, "FlowContext");
|
|
671
716
|
let FlowContext = _FlowContext;
|
|
672
717
|
const _BaseFlowEngineContext = class _BaseFlowEngineContext extends FlowContext {
|
|
718
|
+
constructor() {
|
|
719
|
+
super();
|
|
720
|
+
this.defineMethod(
|
|
721
|
+
"runjs",
|
|
722
|
+
async function(code, variables, options) {
|
|
723
|
+
const { preprocessTemplates, ...runnerOptions } = options || {};
|
|
724
|
+
const mergedGlobals = { ...(runnerOptions == null ? void 0 : runnerOptions.globals) || {}, ...variables || {} };
|
|
725
|
+
const runner = await this.createJSRunner({
|
|
726
|
+
...runnerOptions || {},
|
|
727
|
+
globals: mergedGlobals
|
|
728
|
+
});
|
|
729
|
+
const shouldPreprocessTemplates = preprocessTemplates !== false;
|
|
730
|
+
const jsCode = await (0, import_utils.prepareRunJsCode)(String(code ?? ""), { preprocessTemplates: shouldPreprocessTemplates });
|
|
731
|
+
return runner.run(jsCode);
|
|
732
|
+
}
|
|
733
|
+
);
|
|
734
|
+
}
|
|
673
735
|
};
|
|
674
736
|
__name(_BaseFlowEngineContext, "BaseFlowEngineContext");
|
|
675
737
|
let BaseFlowEngineContext = _BaseFlowEngineContext;
|
|
@@ -706,14 +768,6 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
|
|
|
706
768
|
this.defineMethod("t", (keyOrTemplate, options) => {
|
|
707
769
|
return i18n.translate(keyOrTemplate, options);
|
|
708
770
|
});
|
|
709
|
-
this.defineMethod("runjs", async (code, variables, options) => {
|
|
710
|
-
const mergedGlobals = { ...(options == null ? void 0 : options.globals) || {}, ...variables || {} };
|
|
711
|
-
const runner = await this.createJSRunner({
|
|
712
|
-
...options || {},
|
|
713
|
-
globals: mergedGlobals
|
|
714
|
-
});
|
|
715
|
-
return runner.run(code);
|
|
716
|
-
});
|
|
717
771
|
this.defineMethod("renderJson", function(template) {
|
|
718
772
|
return this.resolveJsonTemplate(template);
|
|
719
773
|
});
|
|
@@ -745,6 +799,21 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
|
|
|
745
799
|
const needServer = Object.keys(serverVarPaths).length > 0;
|
|
746
800
|
let serverResolved = template;
|
|
747
801
|
if (needServer) {
|
|
802
|
+
const inferRecordRefWithMeta = /* @__PURE__ */ __name((ctx) => {
|
|
803
|
+
var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
804
|
+
const ref = (0, import_variablesParams.inferRecordRef)(ctx);
|
|
805
|
+
if (ref) return ref;
|
|
806
|
+
try {
|
|
807
|
+
const tk = (_b2 = (_a2 = ctx == null ? void 0 : ctx.resource) == null ? void 0 : _a2.getMeta) == null ? void 0 : _b2.call(_a2, "currentFilterByTk");
|
|
808
|
+
if (typeof tk === "undefined" || tk === null) return void 0;
|
|
809
|
+
const collection = ((_c = ctx == null ? void 0 : ctx.collection) == null ? void 0 : _c.name) || ((_j = (_i = (_h = (_g = (_f = (_e = (_d = ctx == null ? void 0 : ctx.resource) == null ? void 0 : _d.getResourceName) == null ? void 0 : _e.call(_d)) == null ? void 0 : _f.split) == null ? void 0 : _g.call(_f, ".")) == null ? void 0 : _h.slice) == null ? void 0 : _i.call(_h, -1)) == null ? void 0 : _j[0]);
|
|
810
|
+
if (!collection) return void 0;
|
|
811
|
+
const dataSourceKey = ((_k = ctx == null ? void 0 : ctx.collection) == null ? void 0 : _k.dataSourceKey) || ((_m = (_l = ctx == null ? void 0 : ctx.resource) == null ? void 0 : _l.getDataSourceKey) == null ? void 0 : _m.call(_l));
|
|
812
|
+
return { collection, dataSourceKey, filterByTk: tk };
|
|
813
|
+
} catch (_2) {
|
|
814
|
+
return void 0;
|
|
815
|
+
}
|
|
816
|
+
}, "inferRecordRefWithMeta");
|
|
748
817
|
const collectFromMeta = /* @__PURE__ */ __name(async () => {
|
|
749
818
|
var _a2;
|
|
750
819
|
const out = {};
|
|
@@ -780,6 +849,43 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
|
|
|
780
849
|
}, "collectFromMeta");
|
|
781
850
|
const inputFromMeta = await collectFromMeta();
|
|
782
851
|
const autoInput = { ...inputFromMeta };
|
|
852
|
+
try {
|
|
853
|
+
const varName = "formValues";
|
|
854
|
+
const neededPaths = serverVarPaths[varName] || [];
|
|
855
|
+
if (neededPaths.length) {
|
|
856
|
+
const requiredTop = /* @__PURE__ */ new Set();
|
|
857
|
+
for (const p of neededPaths) {
|
|
858
|
+
const top = topLevelOf(p);
|
|
859
|
+
if (top) requiredTop.add(top);
|
|
860
|
+
}
|
|
861
|
+
const metaOut = inputFromMeta == null ? void 0 : inputFromMeta[varName];
|
|
862
|
+
const builtTop = /* @__PURE__ */ new Set();
|
|
863
|
+
if (metaOut && typeof metaOut === "object" && !Array.isArray(metaOut) && !isRecordRefLike(metaOut)) {
|
|
864
|
+
Object.keys(metaOut).forEach((k) => builtTop.add(k));
|
|
865
|
+
}
|
|
866
|
+
const missing = [...requiredTop].filter((k) => !builtTop.has(k));
|
|
867
|
+
if (missing.length) {
|
|
868
|
+
const ref = inferRecordRefWithMeta(this);
|
|
869
|
+
if (ref) {
|
|
870
|
+
const { generatedFields, generatedAppends } = inferSelectsFromUsage(neededPaths);
|
|
871
|
+
const recordRef = {
|
|
872
|
+
...ref,
|
|
873
|
+
fields: generatedFields,
|
|
874
|
+
appends: generatedAppends
|
|
875
|
+
};
|
|
876
|
+
const existing = autoInput[varName];
|
|
877
|
+
if (existing && typeof existing === "object" && !Array.isArray(existing) && !isRecordRefLike(existing)) {
|
|
878
|
+
for (const [k, v] of Object.entries(existing)) {
|
|
879
|
+
autoInput[`${varName}.${k}`] = v;
|
|
880
|
+
}
|
|
881
|
+
delete autoInput[varName];
|
|
882
|
+
}
|
|
883
|
+
autoInput[varName] = recordRef;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
} catch (_2) {
|
|
888
|
+
}
|
|
783
889
|
const autoContextParams = Object.keys(autoInput).length ? (0, import_serverContextParams.buildServerContextParams)(this, autoInput) : void 0;
|
|
784
890
|
if (!autoContextParams) {
|
|
785
891
|
const keys = Object.keys(serverVarPaths);
|
|
@@ -964,11 +1070,8 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
|
|
|
964
1070
|
}
|
|
965
1071
|
const version = (options == null ? void 0 : options.version) || "v1";
|
|
966
1072
|
const modelClass = (0, import_registry.getModelClassName)(this);
|
|
967
|
-
const Ctor = import_registry.RunJSContextRegistry.resolve(version, modelClass) ||
|
|
968
|
-
|
|
969
|
-
if (Ctor) {
|
|
970
|
-
runCtx = new Ctor(this);
|
|
971
|
-
}
|
|
1073
|
+
const Ctor = import_registry.RunJSContextRegistry.resolve(version, modelClass) || FlowRunJSContext;
|
|
1074
|
+
const runCtx = new Ctor(this);
|
|
972
1075
|
const globals = { ctx: runCtx, ...(options == null ? void 0 : options.globals) || {} };
|
|
973
1076
|
const { timeoutMs } = options || {};
|
|
974
1077
|
return new import_JSRunner.JSRunner({ globals, timeoutMs });
|
|
@@ -1045,13 +1148,6 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
|
|
|
1045
1148
|
this.defineMethod("onRefReady", (ref, cb, timeout) => {
|
|
1046
1149
|
this.engine.reactView.onRefReady(ref, cb, timeout);
|
|
1047
1150
|
});
|
|
1048
|
-
this.defineMethod("runjs", async (code, variables, options) => {
|
|
1049
|
-
const runner = await this.createJSRunner({
|
|
1050
|
-
globals: variables,
|
|
1051
|
-
version: options == null ? void 0 : options.version
|
|
1052
|
-
});
|
|
1053
|
-
return runner.run(code);
|
|
1054
|
-
});
|
|
1055
1151
|
this.defineProperty("model", {
|
|
1056
1152
|
value: model
|
|
1057
1153
|
});
|
|
@@ -1183,13 +1279,6 @@ const _FlowForkModelContext = class _FlowForkModelContext extends BaseFlowModelC
|
|
|
1183
1279
|
return stableRef;
|
|
1184
1280
|
}, "get")
|
|
1185
1281
|
});
|
|
1186
|
-
this.defineMethod("runjs", async (code, variables, options) => {
|
|
1187
|
-
const runner = await this.createJSRunner({
|
|
1188
|
-
globals: variables,
|
|
1189
|
-
version: options == null ? void 0 : options.version
|
|
1190
|
-
});
|
|
1191
|
-
return runner.run(code);
|
|
1192
|
-
});
|
|
1193
1282
|
}
|
|
1194
1283
|
};
|
|
1195
1284
|
__name(_FlowForkModelContext, "FlowForkModelContext");
|
|
@@ -1234,13 +1323,6 @@ const _FlowRuntimeContext = class _FlowRuntimeContext extends BaseFlowModelConte
|
|
|
1234
1323
|
this.defineMethod("onRefReady", (ref, cb, timeout) => {
|
|
1235
1324
|
this.engine.reactView.onRefReady(ref, cb, timeout);
|
|
1236
1325
|
});
|
|
1237
|
-
this.defineMethod("runjs", async (code, variables, options) => {
|
|
1238
|
-
const runner = await this.createJSRunner({
|
|
1239
|
-
globals: variables,
|
|
1240
|
-
version: options == null ? void 0 : options.version
|
|
1241
|
-
});
|
|
1242
|
-
return runner.run(code);
|
|
1243
|
-
});
|
|
1244
1326
|
}
|
|
1245
1327
|
stepResults = {};
|
|
1246
1328
|
_getOwnProperty(key) {
|
package/lib/utils/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { extractPropertyPath, formatPathToVariable, isVariableExpression } from
|
|
|
21
21
|
export { clearAutoFlowError, getAutoFlowError, setAutoFlowError, type AutoFlowError } from './autoFlowError';
|
|
22
22
|
export { parsePathnameToViewParams, type ViewParam } from './parsePathnameToViewParams';
|
|
23
23
|
export { createSafeDocument, createSafeWindow, createSafeNavigator } from './safeGlobals';
|
|
24
|
+
export { prepareRunJsCode, preprocessRunJsTemplates } from './runjsTemplateCompat';
|
|
24
25
|
export { createEphemeralContext } from './createEphemeralContext';
|
|
25
26
|
export { pruneFilter } from './pruneFilter';
|
|
26
27
|
export { isBeforeRenderFlow } from './flows';
|
package/lib/utils/index.js
CHANGED
|
@@ -58,6 +58,8 @@ __export(utils_exports, {
|
|
|
58
58
|
isInheritedFrom: () => import_inheritance.isInheritedFrom,
|
|
59
59
|
isVariableExpression: () => import_context.isVariableExpression,
|
|
60
60
|
parsePathnameToViewParams: () => import_parsePathnameToViewParams.parsePathnameToViewParams,
|
|
61
|
+
prepareRunJsCode: () => import_runjsTemplateCompat.prepareRunJsCode,
|
|
62
|
+
preprocessRunJsTemplates: () => import_runjsTemplateCompat.preprocessRunJsTemplates,
|
|
61
63
|
pruneFilter: () => import_pruneFilter.pruneFilter,
|
|
62
64
|
resolveCreateModelOptions: () => import_params_resolvers.resolveCreateModelOptions,
|
|
63
65
|
resolveDefaultParams: () => import_params_resolvers.resolveDefaultParams,
|
|
@@ -85,6 +87,7 @@ var import_context = require("./context");
|
|
|
85
87
|
var import_autoFlowError = require("./autoFlowError");
|
|
86
88
|
var import_parsePathnameToViewParams = require("./parsePathnameToViewParams");
|
|
87
89
|
var import_safeGlobals = require("./safeGlobals");
|
|
90
|
+
var import_runjsTemplateCompat = require("./runjsTemplateCompat");
|
|
88
91
|
var import_createEphemeralContext = require("./createEphemeralContext");
|
|
89
92
|
var import_pruneFilter = require("./pruneFilter");
|
|
90
93
|
var import_flows = require("./flows");
|
|
@@ -122,6 +125,8 @@ var import_flows = require("./flows");
|
|
|
122
125
|
isInheritedFrom,
|
|
123
126
|
isVariableExpression,
|
|
124
127
|
parsePathnameToViewParams,
|
|
128
|
+
prepareRunJsCode,
|
|
129
|
+
preprocessRunJsTemplates,
|
|
125
130
|
pruneFilter,
|
|
126
131
|
resolveCreateModelOptions,
|
|
127
132
|
resolveDefaultParams,
|
|
@@ -266,8 +266,9 @@ async function preprocessExpression(expression, ctx) {
|
|
|
266
266
|
__name(preprocessExpression, "preprocessExpression");
|
|
267
267
|
async function compileExpression(expression, ctx) {
|
|
268
268
|
const matchDotOnly = /* @__PURE__ */ __name((expr) => {
|
|
269
|
-
const m = expr.trim().match(/^ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*(?:\.[a-zA-Z_$][a-zA-Z0-9_$]*)*)
|
|
270
|
-
|
|
269
|
+
const m = expr.trim().match(/^ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*)(?:\.([a-zA-Z_$][a-zA-Z0-9_$-]*(?:\.[a-zA-Z_$][a-zA-Z0-9_$-]*)*))?$/);
|
|
270
|
+
if (!m) return null;
|
|
271
|
+
return m[2] ? `${m[1]}.${m[2]}` : m[1];
|
|
271
272
|
}, "matchDotOnly");
|
|
272
273
|
const resolveDotOnlyPath = /* @__PURE__ */ __name(async (dotPath) => {
|
|
273
274
|
const segs = dotPath.split(".");
|
|
@@ -277,20 +278,26 @@ async function compileExpression(expression, ctx) {
|
|
|
277
278
|
if (segs.length === 0) return base;
|
|
278
279
|
return (0, import_shared.getValuesByPath)(base, segs.join("."));
|
|
279
280
|
}, "resolveDotOnlyPath");
|
|
281
|
+
const resolveInnerExpression = /* @__PURE__ */ __name(async (innerExpr) => {
|
|
282
|
+
const dotPath = matchDotOnly(innerExpr);
|
|
283
|
+
if (dotPath) {
|
|
284
|
+
const resolved = await resolveDotOnlyPath(dotPath);
|
|
285
|
+
if (resolved === void 0 && dotPath.includes("-")) {
|
|
286
|
+
return await processExpression(innerExpr, ctx);
|
|
287
|
+
}
|
|
288
|
+
return resolved;
|
|
289
|
+
}
|
|
290
|
+
return await processExpression(innerExpr, ctx);
|
|
291
|
+
}, "resolveInnerExpression");
|
|
280
292
|
const singleMatch = expression.match(/^\s*\{\{\s*([^{}]+?)\s*\}\}\s*$/);
|
|
281
293
|
if (singleMatch) {
|
|
282
294
|
const inner = singleMatch[1];
|
|
283
|
-
|
|
284
|
-
if (dotPath) {
|
|
285
|
-
return await resolveDotOnlyPath(dotPath);
|
|
286
|
-
}
|
|
287
|
-
return await processExpression(inner, ctx);
|
|
295
|
+
return await resolveInnerExpression(inner);
|
|
288
296
|
}
|
|
289
297
|
const matches = [...expression.matchAll(/\{\{\s*(.+?)\s*\}\}/g)];
|
|
290
298
|
let result = expression;
|
|
291
299
|
for (const [fullMatch, innerExpr] of matches) {
|
|
292
|
-
const
|
|
293
|
-
const value = dotPath ? await resolveDotOnlyPath(dotPath) : await processExpression(innerExpr, ctx);
|
|
300
|
+
const value = await resolveInnerExpression(innerExpr);
|
|
294
301
|
if (value !== void 0) {
|
|
295
302
|
const replacement = typeof value === "object" && value !== null ? JSON.stringify(value) : String(value);
|
|
296
303
|
result = result.replace(fullMatch, replacement);
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
type PrepareRunJsCodeOptions = {
|
|
10
|
+
preprocessTemplates?: boolean;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* 预处理 RunJS 源码,兼容旧版 `{{ ... }}` 占位符。
|
|
14
|
+
*
|
|
15
|
+
* 注意:这不是“变量解析”(这里不会计算任何值)。
|
|
16
|
+
* 它会把代码重写为合法的 JS,并在执行期间调用 `ctx.resolveJsonTemplate(...)` 来解析 {{ ... }}。
|
|
17
|
+
*
|
|
18
|
+
* 设计说明:
|
|
19
|
+
* - 为避免出现 “await is only valid in async functions” 之类的语法错误,会把所有模板解析提升到
|
|
20
|
+
* RunJS 程序的顶层,再用变量替换各处的出现位置。
|
|
21
|
+
* - 对于字符串/模板字面量,不在原位置直接包一层 `await ...`。而是保留原字面量表达式,并通过
|
|
22
|
+
* 一个小 helper 用 `.split().join()` 做替换,以匹配 `resolveJsonTemplate` 对 object/undefined
|
|
23
|
+
* 的字符串替换行为。
|
|
24
|
+
*/
|
|
25
|
+
export declare function preprocessRunJsTemplates(code: string, options?: {
|
|
26
|
+
processBarePlaceholders?: boolean;
|
|
27
|
+
processStringLiterals?: boolean;
|
|
28
|
+
}): string;
|
|
29
|
+
/**
|
|
30
|
+
* 为执行准备用户的 RunJS 源码。
|
|
31
|
+
* - 可选:运行时模板兼容重写
|
|
32
|
+
* - JSX 转换(sucrase),确保 RunJS 可以安全使用 JSX
|
|
33
|
+
*/
|
|
34
|
+
export declare function prepareRunJsCode(code: string, options?: PrepareRunJsCodeOptions): Promise<string>;
|
|
35
|
+
export {};
|