@nocobase/flow-engine 2.0.0-beta.17 → 2.0.0-beta.19
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/flowContext.js +55 -64
- package/lib/provider.js +5 -5
- package/lib/runjsLibs.d.ts +13 -0
- package/lib/runjsLibs.js +309 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +5 -0
- package/lib/utils/resolveModuleUrl.d.ts +58 -0
- package/lib/utils/resolveModuleUrl.js +65 -0
- package/lib/utils/runjsModuleLoader.d.ts +58 -0
- package/lib/utils/runjsModuleLoader.js +422 -0
- package/lib/utils/safeGlobals.d.ts +5 -9
- package/lib/utils/safeGlobals.js +129 -17
- package/lib/views/viewEvents.js +2 -0
- package/package.json +4 -4
- package/src/__tests__/runjsExternalLibs.test.ts +242 -0
- package/src/flowContext.ts +73 -65
- package/src/provider.tsx +7 -6
- package/src/runjsLibs.ts +404 -0
- package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +38 -0
- package/src/utils/__tests__/safeGlobals.test.ts +49 -2
- package/src/utils/index.ts +3 -0
- package/src/utils/resolveModuleUrl.ts +91 -0
- package/src/utils/runjsModuleLoader.ts +553 -0
- package/src/utils/safeGlobals.ts +133 -16
- package/src/views/__tests__/viewEvents.resolveOpenerEngine.test.ts +28 -0
- package/src/views/viewEvents.ts +4 -0
package/lib/flowContext.js
CHANGED
|
@@ -78,6 +78,7 @@ var import_registry = require("./runjs-context/registry");
|
|
|
78
78
|
var import_createEphemeralContext = require("./utils/createEphemeralContext");
|
|
79
79
|
var import_dayjs = __toESM(require("dayjs"));
|
|
80
80
|
var import_runjsLibs = require("./runjsLibs");
|
|
81
|
+
var import_runjsModuleLoader = require("./utils/runjsModuleLoader");
|
|
81
82
|
var _proxy, _FlowContext_instances, createChildNodes_fn, findMetaByPath_fn, findMetaInDelegatesDeep_fn, findMetaInProperty_fn, resolvePathInMeta_fn, resolvePathInMetaAsync_fn, buildParentTitles_fn, toTreeNode_fn;
|
|
82
83
|
function isRecordRefLike(val) {
|
|
83
84
|
return !!(val && typeof val === "object" && "collection" in val && "filterByTk" in val);
|
|
@@ -1003,7 +1004,8 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
|
|
|
1003
1004
|
user: this.user
|
|
1004
1005
|
}), "get")
|
|
1005
1006
|
});
|
|
1006
|
-
this.defineMethod("loadCSS", async (
|
|
1007
|
+
this.defineMethod("loadCSS", async (href) => {
|
|
1008
|
+
const url = (0, import_utils.resolveModuleUrl)(href);
|
|
1007
1009
|
return new Promise((resolve, reject) => {
|
|
1008
1010
|
const existingLink = document.querySelector(`link[href="${url}"]`);
|
|
1009
1011
|
if (existingLink) {
|
|
@@ -1019,51 +1021,14 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
|
|
|
1019
1021
|
});
|
|
1020
1022
|
});
|
|
1021
1023
|
this.defineMethod("requireAsync", async (url) => {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
reject(new Error("requirejs is not available"));
|
|
1025
|
-
return;
|
|
1026
|
-
}
|
|
1027
|
-
this.requirejs(
|
|
1028
|
-
[url],
|
|
1029
|
-
(...args) => {
|
|
1030
|
-
resolve(args[0]);
|
|
1031
|
-
},
|
|
1032
|
-
reject
|
|
1033
|
-
);
|
|
1034
|
-
});
|
|
1024
|
+
const u = (0, import_utils.resolveModuleUrl)(url, { raw: true });
|
|
1025
|
+
return await (0, import_runjsModuleLoader.runjsRequireAsync)(this.requirejs, u);
|
|
1035
1026
|
});
|
|
1036
|
-
this.defineMethod("importAsync", async (url)
|
|
1037
|
-
if (
|
|
1038
|
-
|
|
1027
|
+
this.defineMethod("importAsync", async function(url) {
|
|
1028
|
+
if ((0, import_utils.isCssFile)(url)) {
|
|
1029
|
+
return this.loadCSS(url);
|
|
1039
1030
|
}
|
|
1040
|
-
|
|
1041
|
-
const g = globalThis;
|
|
1042
|
-
g.__nocobaseImportAsyncCache = g.__nocobaseImportAsyncCache || /* @__PURE__ */ new Map();
|
|
1043
|
-
const cache = g.__nocobaseImportAsyncCache;
|
|
1044
|
-
if (cache.has(u)) return cache.get(u);
|
|
1045
|
-
const nativeImport = /* @__PURE__ */ __name(() => import(
|
|
1046
|
-
/* @vite-ignore */
|
|
1047
|
-
/* webpackIgnore: true */
|
|
1048
|
-
u
|
|
1049
|
-
), "nativeImport");
|
|
1050
|
-
const evalImport = /* @__PURE__ */ __name(() => {
|
|
1051
|
-
const importer = (0, eval)("u => import(u)");
|
|
1052
|
-
return importer(u);
|
|
1053
|
-
}, "evalImport");
|
|
1054
|
-
const p = (async () => {
|
|
1055
|
-
try {
|
|
1056
|
-
return await nativeImport();
|
|
1057
|
-
} catch (err) {
|
|
1058
|
-
try {
|
|
1059
|
-
return await evalImport();
|
|
1060
|
-
} catch (err2) {
|
|
1061
|
-
throw err2 || err;
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
})();
|
|
1065
|
-
cache.set(u, p);
|
|
1066
|
-
return p;
|
|
1031
|
+
return await (0, import_runjsModuleLoader.runjsImportModule)(this, url, { importer: import_runjsModuleLoader.runjsImportAsync });
|
|
1067
1032
|
});
|
|
1068
1033
|
this.defineMethod("createJSRunner", async function(options) {
|
|
1069
1034
|
try {
|
|
@@ -1392,6 +1357,7 @@ const _FlowRunJSContext = class _FlowRunJSContext extends FlowContext {
|
|
|
1392
1357
|
return this.engine.reactView.createRoot(realContainer, options);
|
|
1393
1358
|
}, "createRoot")
|
|
1394
1359
|
};
|
|
1360
|
+
ReactDOMShim.__nbRunjsInternalShim = true;
|
|
1395
1361
|
this.defineProperty("ReactDOM", { value: ReactDOMShim });
|
|
1396
1362
|
(0, import_runjsLibs.setupRunJSLibs)(this);
|
|
1397
1363
|
this.defineMethod(
|
|
@@ -1403,39 +1369,64 @@ const _FlowRunJSContext = class _FlowRunJSContext extends FlowContext {
|
|
|
1403
1369
|
const globalRef = globalThis;
|
|
1404
1370
|
globalRef.__nbRunjsRoots = globalRef.__nbRunjsRoots || /* @__PURE__ */ new WeakMap();
|
|
1405
1371
|
const rootMap = globalRef.__nbRunjsRoots;
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
if (
|
|
1372
|
+
const disposeEntry = /* @__PURE__ */ __name((entry2) => {
|
|
1373
|
+
if (!entry2) return;
|
|
1374
|
+
if (entry2.disposeTheme && typeof entry2.disposeTheme === "function") {
|
|
1409
1375
|
try {
|
|
1410
|
-
|
|
1411
|
-
}
|
|
1412
|
-
rootMap.delete(containerEl);
|
|
1376
|
+
entry2.disposeTheme();
|
|
1377
|
+
} catch (_2) {
|
|
1413
1378
|
}
|
|
1379
|
+
entry2.disposeTheme = void 0;
|
|
1414
1380
|
}
|
|
1381
|
+
const root = entry2.root || entry2;
|
|
1382
|
+
if (root && typeof root.unmount === "function") {
|
|
1383
|
+
try {
|
|
1384
|
+
root.unmount();
|
|
1385
|
+
} catch (_2) {
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}, "disposeEntry");
|
|
1389
|
+
const unmountContainerRoot = /* @__PURE__ */ __name(() => {
|
|
1390
|
+
const existing = rootMap.get(containerEl);
|
|
1391
|
+
if (existing) {
|
|
1392
|
+
disposeEntry(existing);
|
|
1393
|
+
rootMap.delete(containerEl);
|
|
1394
|
+
}
|
|
1395
|
+
}, "unmountContainerRoot");
|
|
1396
|
+
if (typeof vnode === "string") {
|
|
1397
|
+
unmountContainerRoot();
|
|
1415
1398
|
const proxy = new import_ElementProxy.ElementProxy(containerEl);
|
|
1416
1399
|
proxy.innerHTML = String(vnode ?? "");
|
|
1417
1400
|
return null;
|
|
1418
1401
|
}
|
|
1419
1402
|
if (vnode && vnode.nodeType && (vnode.nodeType === 1 || vnode.nodeType === 3 || vnode.nodeType === 11)) {
|
|
1420
|
-
|
|
1421
|
-
if (existingRoot && typeof existingRoot.unmount === "function") {
|
|
1422
|
-
try {
|
|
1423
|
-
existingRoot.unmount();
|
|
1424
|
-
} finally {
|
|
1425
|
-
rootMap.delete(containerEl);
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1403
|
+
unmountContainerRoot();
|
|
1428
1404
|
while (containerEl.firstChild) containerEl.removeChild(containerEl.firstChild);
|
|
1429
1405
|
containerEl.appendChild(vnode);
|
|
1430
1406
|
return null;
|
|
1431
1407
|
}
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1408
|
+
const rendererKey = this.ReactDOM;
|
|
1409
|
+
const ownerKey = this;
|
|
1410
|
+
let entry = rootMap.get(containerEl);
|
|
1411
|
+
if (!entry || entry.rendererKey !== rendererKey || entry.ownerKey !== ownerKey) {
|
|
1412
|
+
if (entry) {
|
|
1413
|
+
disposeEntry(entry);
|
|
1414
|
+
rootMap.delete(containerEl);
|
|
1415
|
+
}
|
|
1416
|
+
const root = this.ReactDOM.createRoot(containerEl);
|
|
1417
|
+
entry = { rendererKey, ownerKey, root, disposeTheme: void 0, lastVnode: void 0 };
|
|
1418
|
+
rootMap.set(containerEl, entry);
|
|
1436
1419
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
1420
|
+
return (0, import_runjsLibs.externalReactRender)({
|
|
1421
|
+
ctx: this,
|
|
1422
|
+
entry,
|
|
1423
|
+
vnode,
|
|
1424
|
+
containerEl,
|
|
1425
|
+
rootMap,
|
|
1426
|
+
unmountContainerRoot,
|
|
1427
|
+
internalReact: import_react.default,
|
|
1428
|
+
internalAntd: antd
|
|
1429
|
+
});
|
|
1439
1430
|
}
|
|
1440
1431
|
);
|
|
1441
1432
|
}
|
package/lib/provider.js
CHANGED
|
@@ -79,17 +79,17 @@ const FlowEngineGlobalsContextProvider = /* @__PURE__ */ __name(({ children }) =
|
|
|
79
79
|
cache: false,
|
|
80
80
|
get: /* @__PURE__ */ __name((ctx) => new import_FlowView.FlowViewer(ctx, { drawer, embed, popover, dialog }), "get")
|
|
81
81
|
});
|
|
82
|
-
engine.context.defineProperty("themeToken", {
|
|
83
|
-
get: /* @__PURE__ */ __name(() => token, "get"),
|
|
84
|
-
observable: true,
|
|
85
|
-
cache: true
|
|
86
|
-
});
|
|
87
82
|
for (const item of Object.entries(context)) {
|
|
88
83
|
const [key, value] = item;
|
|
89
84
|
if (value) {
|
|
90
85
|
engine.context.defineProperty(key, { value });
|
|
91
86
|
}
|
|
92
87
|
}
|
|
88
|
+
engine.context.defineProperty("themeToken", {
|
|
89
|
+
get: /* @__PURE__ */ __name(() => token, "get"),
|
|
90
|
+
observable: true,
|
|
91
|
+
cache: true
|
|
92
|
+
});
|
|
93
93
|
engine.reactView.refresh();
|
|
94
94
|
}, [engine, drawer, modal, message, notification, config, popover, token, dialog, embed]);
|
|
95
95
|
return /* @__PURE__ */ import_react.default.createElement(import_antd.ConfigProvider, { ...config, locale: (_a = engine.context.locales) == null ? void 0 : _a.antd, popupMatchSelectWidth: false }, children, contextHolder, popoverContextHolder, pageContextHolder, dialogContextHolder);
|
package/lib/runjsLibs.d.ts
CHANGED
|
@@ -13,3 +13,16 @@ export declare function registerRunJSLib(name: string, loader: RunJSLibLoader, o
|
|
|
13
13
|
cache?: RunJSLibCache;
|
|
14
14
|
}): void;
|
|
15
15
|
export declare function setupRunJSLibs(ctx: FlowContext): void;
|
|
16
|
+
export declare function setRunJSLibOverride(ctx: FlowContext, name: string, value: unknown, options?: {
|
|
17
|
+
topLevelKey?: string | false;
|
|
18
|
+
}): void;
|
|
19
|
+
export declare function externalReactRender(options: {
|
|
20
|
+
ctx: any;
|
|
21
|
+
entry: any;
|
|
22
|
+
vnode: any;
|
|
23
|
+
containerEl: any;
|
|
24
|
+
rootMap: WeakMap<any, any>;
|
|
25
|
+
unmountContainerRoot: () => void;
|
|
26
|
+
internalReact: any;
|
|
27
|
+
internalAntd: any;
|
|
28
|
+
}): any;
|
package/lib/runjsLibs.js
CHANGED
|
@@ -37,15 +37,19 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
37
37
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
38
|
var runjsLibs_exports = {};
|
|
39
39
|
__export(runjsLibs_exports, {
|
|
40
|
+
externalReactRender: () => externalReactRender,
|
|
40
41
|
registerRunJSLib: () => registerRunJSLib,
|
|
42
|
+
setRunJSLibOverride: () => setRunJSLibOverride,
|
|
41
43
|
setupRunJSLibs: () => setupRunJSLibs
|
|
42
44
|
});
|
|
43
45
|
module.exports = __toCommonJS(runjsLibs_exports);
|
|
44
46
|
var antdIcons = __toESM(require("@ant-design/icons"));
|
|
47
|
+
var import_reactive = require("@formily/reactive");
|
|
45
48
|
const __runjsLibRegistry = /* @__PURE__ */ new Map();
|
|
46
49
|
const __runjsLibResolvedCache = /* @__PURE__ */ new Map();
|
|
47
50
|
const __runjsLibPendingCache = /* @__PURE__ */ new Map();
|
|
48
51
|
const __runjsLibPendingByCtx = /* @__PURE__ */ new WeakMap();
|
|
52
|
+
const __runjsErrorBoundaryByReact = /* @__PURE__ */ new WeakMap();
|
|
49
53
|
function __runjsGetPendingMapForCtx(ctx) {
|
|
50
54
|
let m = __runjsLibPendingByCtx.get(ctx);
|
|
51
55
|
if (!m) {
|
|
@@ -216,8 +220,313 @@ function setupRunJSLibs(ctx) {
|
|
|
216
220
|
setupRunJSLibAPIs(ctx);
|
|
217
221
|
}
|
|
218
222
|
__name(setupRunJSLibs, "setupRunJSLibs");
|
|
223
|
+
function setRunJSLibOverride(ctx, name, value, options) {
|
|
224
|
+
const topLevelKey = (options == null ? void 0 : options.topLevelKey) === false ? null : (options == null ? void 0 : options.topLevelKey) || name;
|
|
225
|
+
if (topLevelKey) {
|
|
226
|
+
ctx.defineProperty(topLevelKey, { value });
|
|
227
|
+
}
|
|
228
|
+
const libs = ctx.libs;
|
|
229
|
+
Object.defineProperty(libs, name, {
|
|
230
|
+
configurable: true,
|
|
231
|
+
enumerable: true,
|
|
232
|
+
writable: true,
|
|
233
|
+
value
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
__name(setRunJSLibOverride, "setRunJSLibOverride");
|
|
237
|
+
function buildMixedReactHint(options) {
|
|
238
|
+
var _a;
|
|
239
|
+
const { ctx, internalReact, internalAntd } = options;
|
|
240
|
+
const lines = [];
|
|
241
|
+
const externalReact = ctx.React && ctx.React !== internalReact;
|
|
242
|
+
const internalReactDOM = !!((_a = ctx.ReactDOM) == null ? void 0 : _a.__nbRunjsInternalShim);
|
|
243
|
+
const usingInternalAntd = ctx.antd === internalAntd;
|
|
244
|
+
const externalAntd = ctx.antd && ctx.antd !== internalAntd;
|
|
245
|
+
if (externalReact && internalReactDOM) {
|
|
246
|
+
const reactInfo = ctx.__runjsExternalReact;
|
|
247
|
+
const v = reactInfo == null ? void 0 : reactInfo.version;
|
|
248
|
+
const domHint = v ? `react-dom@${v}/client` : "react-dom/client";
|
|
249
|
+
lines.push(
|
|
250
|
+
`- You have imported external React, but you're still using the built-in ReactDOM Root; please also run: await ctx.importAsync("${domHint}")`
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
if (externalAntd && !externalReact) {
|
|
254
|
+
lines.push(
|
|
255
|
+
`- You have imported external antd, but you're still using the built-in React; please run: await ctx.importAsync("react@18.x")`
|
|
256
|
+
);
|
|
257
|
+
lines.push(`- And make sure ReactDOM matches: await ctx.importAsync("react-dom@18.x/client")`);
|
|
258
|
+
}
|
|
259
|
+
if (externalReact && usingInternalAntd) {
|
|
260
|
+
lines.push(
|
|
261
|
+
`- You have imported external React, but you're still using the built-in antd; please switch to: await ctx.importAsync("antd@5.x")`
|
|
262
|
+
);
|
|
263
|
+
lines.push(`- If you use icon components, also import: await ctx.importAsync("@ant-design/icons@5.x")`);
|
|
264
|
+
}
|
|
265
|
+
return lines.length ? `
|
|
266
|
+
|
|
267
|
+
[RunJS Hint]
|
|
268
|
+
${lines.join("\n")}` : "";
|
|
269
|
+
}
|
|
270
|
+
__name(buildMixedReactHint, "buildMixedReactHint");
|
|
271
|
+
function isReactHooksDispatcherNullError(err) {
|
|
272
|
+
const msg = String((err == null ? void 0 : err.message) || "");
|
|
273
|
+
if (!msg) return false;
|
|
274
|
+
if (!/Cannot read (?:properties|property) of (?:null|undefined) \(reading 'use[A-Za-z]+'\)/.test(msg)) return false;
|
|
275
|
+
const stack = String((err == null ? void 0 : err.stack) || "");
|
|
276
|
+
if (!stack) return false;
|
|
277
|
+
return /(?:^|\W)react@[^/\s)]+/i.test(stack) || /react\.mjs/i.test(stack) || /react\.(?:development|production)/i.test(stack);
|
|
278
|
+
}
|
|
279
|
+
__name(isReactHooksDispatcherNullError, "isReactHooksDispatcherNullError");
|
|
280
|
+
function extractReactVersionFromStack(err) {
|
|
281
|
+
var _a;
|
|
282
|
+
const stack = String((err == null ? void 0 : err.stack) || "");
|
|
283
|
+
if (!stack) return void 0;
|
|
284
|
+
const m = stack.match(/(?:^|\W)react@([^/\s)]+)/i);
|
|
285
|
+
const v = (_a = m == null ? void 0 : m[1]) == null ? void 0 : _a.trim();
|
|
286
|
+
return v || void 0;
|
|
287
|
+
}
|
|
288
|
+
__name(extractReactVersionFromStack, "extractReactVersionFromStack");
|
|
289
|
+
function buildReactDispatcherNullHint(options) {
|
|
290
|
+
const { ctx, internalReact, internalAntd, err } = options;
|
|
291
|
+
if (!isReactHooksDispatcherNullError(err)) return "";
|
|
292
|
+
const v = extractReactVersionFromStack(err);
|
|
293
|
+
const lines = [];
|
|
294
|
+
lines.push(`- This looks like a React Hooks crash caused by multiple React instances (hook dispatcher is null).`);
|
|
295
|
+
if (v) {
|
|
296
|
+
lines.push(`- Your stack trace includes external React: react@${v}.`);
|
|
297
|
+
lines.push(
|
|
298
|
+
`- Fix: import the same React BEFORE you read ctx.libs.React / call hooks / import React-based libs: await ctx.importAsync("react@${v}")`
|
|
299
|
+
);
|
|
300
|
+
} else {
|
|
301
|
+
lines.push(
|
|
302
|
+
`- Fix: import external React BEFORE you read ctx.libs.React / call hooks / import React-based libs (use the same version shown in the stack trace).`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
const usingInternalAntd = ctx.antd === internalAntd;
|
|
306
|
+
if (usingInternalAntd) {
|
|
307
|
+
lines.push(`- If you use antd components, also switch to external antd: await ctx.importAsync("antd@5.x")`);
|
|
308
|
+
lines.push(`- If you use icon components, also import: await ctx.importAsync("@ant-design/icons@5.x")`);
|
|
309
|
+
}
|
|
310
|
+
return lines.length ? `
|
|
311
|
+
|
|
312
|
+
[RunJS Hint]
|
|
313
|
+
${lines.join("\n")}` : "";
|
|
314
|
+
}
|
|
315
|
+
__name(buildReactDispatcherNullHint, "buildReactDispatcherNullHint");
|
|
316
|
+
function wrapErrorWithHint(err, messageWithHint) {
|
|
317
|
+
const e = new Error(messageWithHint);
|
|
318
|
+
e.cause = err;
|
|
319
|
+
try {
|
|
320
|
+
const name = typeof (err == null ? void 0 : err.name) === "string" ? err.name : "";
|
|
321
|
+
if (name) e.name = name;
|
|
322
|
+
} catch (_) {
|
|
323
|
+
}
|
|
324
|
+
try {
|
|
325
|
+
const stack = typeof (err == null ? void 0 : err.stack) === "string" ? err.stack : "";
|
|
326
|
+
if (stack) {
|
|
327
|
+
const lines = String(stack).split("\n");
|
|
328
|
+
if (lines.length) {
|
|
329
|
+
lines[0] = `${e.name}: ${messageWithHint}`;
|
|
330
|
+
e.stack = lines.join("\n");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
} catch (_) {
|
|
334
|
+
}
|
|
335
|
+
return e;
|
|
336
|
+
}
|
|
337
|
+
__name(wrapErrorWithHint, "wrapErrorWithHint");
|
|
338
|
+
function getRunjsErrorBoundary(ReactLike) {
|
|
339
|
+
if (!ReactLike) return null;
|
|
340
|
+
const cached = __runjsErrorBoundaryByReact.get(ReactLike);
|
|
341
|
+
if (cached) return cached;
|
|
342
|
+
if (typeof ReactLike.createElement !== "function") return null;
|
|
343
|
+
const Base = ReactLike.Component;
|
|
344
|
+
if (typeof Base !== "function") return null;
|
|
345
|
+
const _RunjsErrorBoundary = class _RunjsErrorBoundary extends Base {
|
|
346
|
+
static getDerivedStateFromError(error) {
|
|
347
|
+
return { error };
|
|
348
|
+
}
|
|
349
|
+
state = {};
|
|
350
|
+
componentDidCatch(error) {
|
|
351
|
+
var _a, _b, _c;
|
|
352
|
+
try {
|
|
353
|
+
const enhance = (_a = this.props) == null ? void 0 : _a.enhanceReactError;
|
|
354
|
+
const enhanced = typeof enhance === "function" ? enhance(error) : error;
|
|
355
|
+
const msg = String((enhanced == null ? void 0 : enhanced.message) || "");
|
|
356
|
+
if (msg && /\[RunJS Hint\]/.test(msg)) {
|
|
357
|
+
console.error(msg);
|
|
358
|
+
const logger = (_c = (_b = this.props) == null ? void 0 : _b.ctx) == null ? void 0 : _c.logger;
|
|
359
|
+
if (logger && typeof logger.error === "function") {
|
|
360
|
+
logger.error(msg);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
} catch (_) {
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
componentDidUpdate(prevProps) {
|
|
367
|
+
var _a, _b;
|
|
368
|
+
if ((prevProps == null ? void 0 : prevProps.resetKey) !== ((_a = this.props) == null ? void 0 : _a.resetKey) && ((_b = this.state) == null ? void 0 : _b.error)) {
|
|
369
|
+
this.setState({ error: void 0 });
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
render() {
|
|
373
|
+
var _a, _b;
|
|
374
|
+
const error = (_a = this.state) == null ? void 0 : _a.error;
|
|
375
|
+
if (!error) return this.props.children;
|
|
376
|
+
let msg = "";
|
|
377
|
+
try {
|
|
378
|
+
const enhance = (_b = this.props) == null ? void 0 : _b.enhanceReactError;
|
|
379
|
+
const enhanced = typeof enhance === "function" ? enhance(error) : error;
|
|
380
|
+
msg = String((enhanced == null ? void 0 : enhanced.message) || enhanced || (error == null ? void 0 : error.message) || error || "");
|
|
381
|
+
} catch (_) {
|
|
382
|
+
msg = String((error == null ? void 0 : error.message) || error || "");
|
|
383
|
+
}
|
|
384
|
+
const containerStyle = {
|
|
385
|
+
boxSizing: "border-box",
|
|
386
|
+
padding: 12,
|
|
387
|
+
borderRadius: 6,
|
|
388
|
+
border: "1px solid #ffccc7",
|
|
389
|
+
background: "#fff2f0",
|
|
390
|
+
color: "#a8071a",
|
|
391
|
+
fontSize: 12,
|
|
392
|
+
lineHeight: 1.5,
|
|
393
|
+
maxWidth: "100%",
|
|
394
|
+
overflow: "auto"
|
|
395
|
+
};
|
|
396
|
+
const preStyle = {
|
|
397
|
+
margin: 0,
|
|
398
|
+
whiteSpace: "pre-wrap",
|
|
399
|
+
wordBreak: "break-word",
|
|
400
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'
|
|
401
|
+
};
|
|
402
|
+
const titleStyle = { fontWeight: 600, marginBottom: 8 };
|
|
403
|
+
return ReactLike.createElement(
|
|
404
|
+
"div",
|
|
405
|
+
{ style: containerStyle },
|
|
406
|
+
ReactLike.createElement("div", { style: titleStyle }, "RunJS render error"),
|
|
407
|
+
ReactLike.createElement("pre", { style: preStyle }, msg)
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
__name(_RunjsErrorBoundary, "RunjsErrorBoundary");
|
|
412
|
+
let RunjsErrorBoundary = _RunjsErrorBoundary;
|
|
413
|
+
__runjsErrorBoundaryByReact.set(ReactLike, RunjsErrorBoundary);
|
|
414
|
+
return RunjsErrorBoundary;
|
|
415
|
+
}
|
|
416
|
+
__name(getRunjsErrorBoundary, "getRunjsErrorBoundary");
|
|
417
|
+
function wrapVnodeWithRunjsErrorBoundary(options) {
|
|
418
|
+
const { ctx, vnode, enhanceReactError, resetKey } = options;
|
|
419
|
+
const ReactLike = ctx == null ? void 0 : ctx.React;
|
|
420
|
+
const Boundary = getRunjsErrorBoundary(ReactLike);
|
|
421
|
+
if (!Boundary) return vnode;
|
|
422
|
+
return ReactLike.createElement(Boundary, { ctx, enhanceReactError, resetKey }, vnode);
|
|
423
|
+
}
|
|
424
|
+
__name(wrapVnodeWithRunjsErrorBoundary, "wrapVnodeWithRunjsErrorBoundary");
|
|
425
|
+
function tryRenderWithExternalAntdTheme(options) {
|
|
426
|
+
var _a;
|
|
427
|
+
const { ctx, entry, containerEl, rootMap, unmountContainerRoot, enhanceReactError, internalReact, internalAntd } = options;
|
|
428
|
+
const canUseExternalAntd = !((_a = ctx.ReactDOM) == null ? void 0 : _a.__nbRunjsInternalShim) && ctx.React && ctx.React !== internalReact && ctx.antd && ctx.antd !== internalAntd && typeof ctx.antd.ConfigProvider !== "undefined";
|
|
429
|
+
if (!canUseExternalAntd) {
|
|
430
|
+
if (entry.disposeTheme) {
|
|
431
|
+
try {
|
|
432
|
+
entry.disposeTheme();
|
|
433
|
+
} catch (_) {
|
|
434
|
+
}
|
|
435
|
+
entry.disposeTheme = void 0;
|
|
436
|
+
}
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
const renderWithExternalAntdTheme = /* @__PURE__ */ __name(() => {
|
|
440
|
+
var _a2, _b, _c, _d, _e, _f, _g;
|
|
441
|
+
const themeToken = (_b = (_a2 = ctx == null ? void 0 : ctx.engine) == null ? void 0 : _a2.context) == null ? void 0 : _b.themeToken;
|
|
442
|
+
const appConfig = (_d = (_c = ctx == null ? void 0 : ctx.engine) == null ? void 0 : _c.context) == null ? void 0 : _d.antdConfig;
|
|
443
|
+
const locale = ((_g = (_f = (_e = ctx == null ? void 0 : ctx.engine) == null ? void 0 : _e.context) == null ? void 0 : _f.locales) == null ? void 0 : _g.antd) || (appConfig == null ? void 0 : appConfig.locale);
|
|
444
|
+
const ConfigProvider = ctx.antd.ConfigProvider;
|
|
445
|
+
const App = ctx.antd.App;
|
|
446
|
+
const configProps = {
|
|
447
|
+
popupMatchSelectWidth: false,
|
|
448
|
+
locale: locale || {}
|
|
449
|
+
};
|
|
450
|
+
if (appConfig && typeof appConfig === "object") {
|
|
451
|
+
if (typeof appConfig.direction !== "undefined") configProps.direction = appConfig.direction;
|
|
452
|
+
if (typeof appConfig.prefixCls === "string") configProps.prefixCls = appConfig.prefixCls;
|
|
453
|
+
if (typeof appConfig.iconPrefixCls === "string") configProps.iconPrefixCls = appConfig.iconPrefixCls;
|
|
454
|
+
if (typeof appConfig.getPopupContainer === "function")
|
|
455
|
+
configProps.getPopupContainer = appConfig.getPopupContainer;
|
|
456
|
+
if (appConfig.theme && typeof appConfig.theme === "object") configProps.theme = appConfig.theme;
|
|
457
|
+
}
|
|
458
|
+
const child = entry.lastVnode;
|
|
459
|
+
const wrapped = App ? ctx.React.createElement(ConfigProvider, configProps, ctx.React.createElement(App, null, child)) : ctx.React.createElement(ConfigProvider, configProps, child);
|
|
460
|
+
entry.root.render(wrapped);
|
|
461
|
+
}, "renderWithExternalAntdTheme");
|
|
462
|
+
if (!entry.disposeTheme) {
|
|
463
|
+
entry.disposeTheme = (0, import_reactive.autorun)(() => {
|
|
464
|
+
try {
|
|
465
|
+
if (containerEl && containerEl.nodeType === 1 && typeof containerEl.isConnected === "boolean" && !containerEl.isConnected && entry.wasConnected) {
|
|
466
|
+
queueMicrotask(() => {
|
|
467
|
+
const cur = rootMap.get(containerEl);
|
|
468
|
+
if (cur === entry) unmountContainerRoot();
|
|
469
|
+
});
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
if (containerEl && containerEl.nodeType === 1 && typeof containerEl.isConnected === "boolean" && containerEl.isConnected) {
|
|
473
|
+
entry.wasConnected = true;
|
|
474
|
+
}
|
|
475
|
+
renderWithExternalAntdTheme();
|
|
476
|
+
} catch (e) {
|
|
477
|
+
throw enhanceReactError(e);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
} else {
|
|
481
|
+
renderWithExternalAntdTheme();
|
|
482
|
+
}
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
__name(tryRenderWithExternalAntdTheme, "tryRenderWithExternalAntdTheme");
|
|
486
|
+
function externalReactRender(options) {
|
|
487
|
+
const { ctx, entry, vnode, containerEl, rootMap, unmountContainerRoot, internalReact, internalAntd } = options;
|
|
488
|
+
const enhanceReactError = /* @__PURE__ */ __name((err) => {
|
|
489
|
+
const msg = String((err == null ? void 0 : err.message) || err || "");
|
|
490
|
+
if (!msg) return err;
|
|
491
|
+
if (/\[RunJS Hint\]/.test(msg)) return err;
|
|
492
|
+
const invalidHookCall = /invalid hook call/i.test(msg);
|
|
493
|
+
const dispatcherNull = isReactHooksDispatcherNullError(err);
|
|
494
|
+
if (!invalidHookCall && !dispatcherNull) return err;
|
|
495
|
+
const hint = buildMixedReactHint({ ctx, internalReact, internalAntd }) || buildReactDispatcherNullHint({ ctx, internalReact, internalAntd, err });
|
|
496
|
+
if (!hint) return err;
|
|
497
|
+
return wrapErrorWithHint(err, `${msg}${hint}`);
|
|
498
|
+
}, "enhanceReactError");
|
|
499
|
+
try {
|
|
500
|
+
entry.__nbRunjsRenderSeq = (entry.__nbRunjsRenderSeq || 0) + 1;
|
|
501
|
+
entry.lastVnode = wrapVnodeWithRunjsErrorBoundary({
|
|
502
|
+
ctx,
|
|
503
|
+
vnode,
|
|
504
|
+
enhanceReactError,
|
|
505
|
+
resetKey: entry.__nbRunjsRenderSeq
|
|
506
|
+
});
|
|
507
|
+
const renderedWithExternalAntdTheme = tryRenderWithExternalAntdTheme({
|
|
508
|
+
ctx,
|
|
509
|
+
entry,
|
|
510
|
+
containerEl,
|
|
511
|
+
rootMap,
|
|
512
|
+
unmountContainerRoot,
|
|
513
|
+
enhanceReactError,
|
|
514
|
+
internalReact,
|
|
515
|
+
internalAntd
|
|
516
|
+
});
|
|
517
|
+
if (!renderedWithExternalAntdTheme) {
|
|
518
|
+
entry.root.render(entry.lastVnode);
|
|
519
|
+
}
|
|
520
|
+
return entry.root;
|
|
521
|
+
} catch (e) {
|
|
522
|
+
throw enhanceReactError(e);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
__name(externalReactRender, "externalReactRender");
|
|
219
526
|
// Annotate the CommonJS export names for ESM import in node:
|
|
220
527
|
0 && (module.exports = {
|
|
528
|
+
externalReactRender,
|
|
221
529
|
registerRunJSLib,
|
|
530
|
+
setRunJSLibOverride,
|
|
222
531
|
setupRunJSLibs
|
|
223
532
|
});
|
package/lib/utils/index.d.ts
CHANGED
|
@@ -25,3 +25,4 @@ export { prepareRunJsCode, preprocessRunJsTemplates } from './runjsTemplateCompa
|
|
|
25
25
|
export { createEphemeralContext } from './createEphemeralContext';
|
|
26
26
|
export { pruneFilter } from './pruneFilter';
|
|
27
27
|
export { isBeforeRenderFlow } from './flows';
|
|
28
|
+
export { resolveModuleUrl, isCssFile } from './resolveModuleUrl';
|
package/lib/utils/index.js
CHANGED
|
@@ -55,6 +55,7 @@ __export(utils_exports, {
|
|
|
55
55
|
getT: () => import_translation.getT,
|
|
56
56
|
inferRecordRef: () => import_variablesParams.inferRecordRef,
|
|
57
57
|
isBeforeRenderFlow: () => import_flows.isBeforeRenderFlow,
|
|
58
|
+
isCssFile: () => import_resolveModuleUrl.isCssFile,
|
|
58
59
|
isInheritedFrom: () => import_inheritance.isInheritedFrom,
|
|
59
60
|
isVariableExpression: () => import_context.isVariableExpression,
|
|
60
61
|
parsePathnameToViewParams: () => import_parsePathnameToViewParams.parsePathnameToViewParams,
|
|
@@ -64,6 +65,7 @@ __export(utils_exports, {
|
|
|
64
65
|
resolveCreateModelOptions: () => import_params_resolvers.resolveCreateModelOptions,
|
|
65
66
|
resolveDefaultParams: () => import_params_resolvers.resolveDefaultParams,
|
|
66
67
|
resolveExpressions: () => import_params_resolvers.resolveExpressions,
|
|
68
|
+
resolveModuleUrl: () => import_resolveModuleUrl.resolveModuleUrl,
|
|
67
69
|
resolveStepUiSchema: () => import_schema_utils.resolveStepUiSchema,
|
|
68
70
|
resolveUiMode: () => import_schema_utils.resolveUiMode,
|
|
69
71
|
setAutoFlowError: () => import_autoFlowError.setAutoFlowError,
|
|
@@ -91,6 +93,7 @@ var import_runjsTemplateCompat = require("./runjsTemplateCompat");
|
|
|
91
93
|
var import_createEphemeralContext = require("./createEphemeralContext");
|
|
92
94
|
var import_pruneFilter = require("./pruneFilter");
|
|
93
95
|
var import_flows = require("./flows");
|
|
96
|
+
var import_resolveModuleUrl = require("./resolveModuleUrl");
|
|
94
97
|
// Annotate the CommonJS export names for ESM import in node:
|
|
95
98
|
0 && (module.exports = {
|
|
96
99
|
BLOCK_GROUP_CONFIGS,
|
|
@@ -122,6 +125,7 @@ var import_flows = require("./flows");
|
|
|
122
125
|
getT,
|
|
123
126
|
inferRecordRef,
|
|
124
127
|
isBeforeRenderFlow,
|
|
128
|
+
isCssFile,
|
|
125
129
|
isInheritedFrom,
|
|
126
130
|
isVariableExpression,
|
|
127
131
|
parsePathnameToViewParams,
|
|
@@ -131,6 +135,7 @@ var import_flows = require("./flows");
|
|
|
131
135
|
resolveCreateModelOptions,
|
|
132
136
|
resolveDefaultParams,
|
|
133
137
|
resolveExpressions,
|
|
138
|
+
resolveModuleUrl,
|
|
134
139
|
resolveStepUiSchema,
|
|
135
140
|
resolveUiMode,
|
|
136
141
|
setAutoFlowError,
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
/**
|
|
10
|
+
* 解析模块 URL,将相对路径转换为完整的 CDN URL
|
|
11
|
+
*
|
|
12
|
+
* @param url - 模块地址(支持相对路径或完整 URL)
|
|
13
|
+
* @param options - 可选配置
|
|
14
|
+
* @param options.addSuffix - 是否添加 ESM_CDN_SUFFIX 后缀(如 `+esm`),默认为 `true`
|
|
15
|
+
* @returns 解析后的完整 URL
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* // 相对路径会被拼接上 CDN 前缀和后缀(默认添加)
|
|
20
|
+
* // 如果使用 esm.sh(默认),不需要后缀
|
|
21
|
+
* resolveModuleUrl('vue@3.4.0')
|
|
22
|
+
* // => 'https://esm.sh/vue@3.4.0'
|
|
23
|
+
*
|
|
24
|
+
* // 如果使用 jsdelivr,需要配置 ESM_CDN_SUFFIX='/+esm'
|
|
25
|
+
* // resolveModuleUrl('vue@3.4.0') => 'https://cdn.jsdelivr.net/npm/vue@3.4.0/+esm'
|
|
26
|
+
*
|
|
27
|
+
* // 不添加后缀(适用于 UMD 库或 CSS 文件)
|
|
28
|
+
* resolveModuleUrl('vue@3.4.0', { addSuffix: false })
|
|
29
|
+
* // => 'https://esm.sh/vue@3.4.0' (即使配置了 suffix 也不会添加)
|
|
30
|
+
*
|
|
31
|
+
* // 原始 URL(适用于 UMD 库)
|
|
32
|
+
* resolveModuleUrl('lodash@4.17.21/lodash.js', { raw: true })
|
|
33
|
+
* // => 'https://esm.sh/lodash@4.17.21/lodash.js?raw' (即使配置了 suffix 也不会添加)
|
|
34
|
+
*
|
|
35
|
+
* // 完整 URL 保持不变
|
|
36
|
+
* resolveModuleUrl('https://cdn.jsdelivr.net/npm/vue@3.4.0')
|
|
37
|
+
* // => 'https://cdn.jsdelivr.net/npm/vue@3.4.0'
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveModuleUrl(url: string, options?: {
|
|
41
|
+
addSuffix?: boolean;
|
|
42
|
+
raw?: boolean;
|
|
43
|
+
}): string;
|
|
44
|
+
/**
|
|
45
|
+
* 判断 URL 是否为 CSS 文件
|
|
46
|
+
*
|
|
47
|
+
* @param url - 文件 URL(支持带 query 和 hash,如 `example.css?v=123`)
|
|
48
|
+
* @returns 如果是 CSS 文件返回 `true`,否则返回 `false`
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* isCssFile('style.css') // => true
|
|
53
|
+
* isCssFile('style.css?v=123') // => true
|
|
54
|
+
* isCssFile('style.css#section') // => true
|
|
55
|
+
* isCssFile('script.js') // => false
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function isCssFile(url: string): boolean;
|