@nocobase/server 2.1.0-alpha.1 → 2.1.0-alpha.11

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 (53) hide show
  1. package/LICENSE +201 -661
  2. package/README.md +79 -10
  3. package/lib/aes-encryptor.d.ts +1 -0
  4. package/lib/aes-encryptor.js +8 -5
  5. package/lib/ai/create-docs-index.d.ts +13 -0
  6. package/lib/ai/create-docs-index.js +892 -0
  7. package/lib/app-supervisor/app-options-factory.d.ts +80 -0
  8. package/lib/app-supervisor/app-options-factory.js +91 -0
  9. package/lib/app-supervisor/condition-registry.d.ts +18 -0
  10. package/lib/app-supervisor/condition-registry.js +60 -0
  11. package/lib/app-supervisor/db-creator.d.ts +16 -0
  12. package/lib/app-supervisor/db-creator.js +163 -0
  13. package/lib/app-supervisor/db-drivers.d.ts +11 -0
  14. package/lib/app-supervisor/db-drivers.js +52 -0
  15. package/lib/app-supervisor/index.d.ts +161 -0
  16. package/lib/app-supervisor/index.js +693 -0
  17. package/lib/app-supervisor/main-only-adapter.d.ts +37 -0
  18. package/lib/app-supervisor/main-only-adapter.js +161 -0
  19. package/lib/app-supervisor/types.d.ts +161 -0
  20. package/lib/app-supervisor/types.js +24 -0
  21. package/lib/application.d.ts +3 -1
  22. package/lib/application.js +10 -6
  23. package/lib/commands/ai.d.ts +11 -0
  24. package/lib/commands/ai.js +40 -0
  25. package/lib/commands/console.js +1 -1
  26. package/lib/commands/index.js +2 -0
  27. package/lib/commands/install.js +4 -0
  28. package/lib/commands/start.js +3 -0
  29. package/lib/commands/upgrade.js +4 -0
  30. package/lib/event-queue.d.ts +1 -0
  31. package/lib/event-queue.js +2 -1
  32. package/lib/gateway/errors.js +1 -1
  33. package/lib/gateway/index.d.ts +10 -0
  34. package/lib/gateway/index.js +181 -18
  35. package/lib/gateway/ipc-socket-server.js +1 -1
  36. package/lib/gateway/utils.d.ts +12 -0
  37. package/lib/gateway/utils.js +84 -0
  38. package/lib/gateway/ws-server.js +3 -2
  39. package/lib/helper.js +53 -4
  40. package/lib/plugin-manager/deps.js +1 -1
  41. package/lib/plugin-manager/options/resource.d.ts +10 -0
  42. package/lib/plugin-manager/options/resource.js +90 -36
  43. package/lib/plugin-manager/plugin-manager.d.ts +1 -0
  44. package/lib/plugin-manager/plugin-manager.js +37 -40
  45. package/lib/plugin-manager/utils.js +1 -1
  46. package/lib/plugin.d.ts +5 -0
  47. package/lib/plugin.js +66 -1
  48. package/lib/pub-sub-manager/pub-sub-manager.js +1 -1
  49. package/lib/redis-connection-manager.d.ts +15 -5
  50. package/lib/redis-connection-manager.js +117 -24
  51. package/package.json +19 -18
  52. package/lib/app-supervisor.d.ts +0 -74
  53. package/lib/app-supervisor.js +0 -338
@@ -57,6 +57,7 @@ export declare class Gateway extends EventEmitter {
57
57
  private port;
58
58
  private host;
59
59
  private socketPath;
60
+ private v2IndexTemplateCache;
60
61
  private terminating;
61
62
  private onTerminate;
62
63
  private constructor();
@@ -74,6 +75,15 @@ export declare class Gateway extends EventEmitter {
74
75
  code: string;
75
76
  }): void;
76
77
  responseErrorWithCode(code: any, res: any, options: any): void;
78
+ private getV2PublicPath;
79
+ private getAppPublicPath;
80
+ private isV2Request;
81
+ private isV2IndexRequest;
82
+ private getV2RuntimeConfig;
83
+ private getV2RuntimeConfigScript;
84
+ private getV2AssetPublicPath;
85
+ private getV2IndexTemplate;
86
+ private renderV2IndexHtml;
77
87
  requestHandler(req: IncomingMessage, res: ServerResponse): Promise<void>;
78
88
  getAppSelectorMiddlewares(): Toposort<AppSelectorMiddleware>;
79
89
  getRequestHandleAppName(req: IncomingRequest): Promise<string>;
@@ -44,6 +44,7 @@ __export(gateway_exports, {
44
44
  module.exports = __toCommonJS(gateway_exports);
45
45
  var import_logger = require("@nocobase/logger");
46
46
  var import_utils = require("@nocobase/utils");
47
+ var import_utils2 = require("@nocobase/utils");
47
48
  var import_plugin_symlink = require("@nocobase/utils/plugin-symlink");
48
49
  var import_commander = require("commander");
49
50
  var import_compression = __toESM(require("compression"));
@@ -62,10 +63,16 @@ var import_plugin_manager = require("../plugin-manager");
62
63
  var import_errors = require("./errors");
63
64
  var import_ipc_socket_client = require("./ipc-socket-client");
64
65
  var import_ipc_socket_server = require("./ipc-socket-server");
66
+ var import_utils3 = require("./utils");
65
67
  var import_ws_server = require("./ws-server");
66
68
  var import_node_worker_threads = require("node:worker_threads");
67
69
  var import_node_process = __toESM(require("node:process"));
68
70
  const compress = (0, import_node_util.promisify)((0, import_compression.default)());
71
+ function normalizeBasePath(path = "") {
72
+ const normalized = path.replace(/\/+/g, "/").replace(/\/$/, "");
73
+ return normalized || "/";
74
+ }
75
+ __name(normalizeBasePath, "normalizeBasePath");
69
76
  function getSocketPath() {
70
77
  const { SOCKET_PATH } = import_node_process.default.env;
71
78
  if ((0, import_path.isAbsolute)(SOCKET_PATH)) {
@@ -87,6 +94,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
87
94
  port = import_node_process.default.env.APP_PORT ? parseInt(import_node_process.default.env.APP_PORT) : null;
88
95
  host = "0.0.0.0";
89
96
  socketPath = (0, import_path.resolve)(import_node_process.default.cwd(), "storage", "gateway.sock");
97
+ v2IndexTemplateCache = null;
90
98
  terminating = false;
91
99
  onTerminate = /* @__PURE__ */ __name(async (signal) => {
92
100
  var _a;
@@ -99,6 +107,9 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
99
107
  try {
100
108
  for (const app of apps) {
101
109
  try {
110
+ if (!app) {
111
+ continue;
112
+ }
102
113
  await app.destroy({ signal });
103
114
  } catch (error) {
104
115
  const logger = (app == null ? void 0 : app.log) ?? console;
@@ -147,15 +158,31 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
147
158
  this.selectorMiddlewares = new import_utils.Toposort();
148
159
  this.addAppSelectorMiddleware(
149
160
  async (ctx, next) => {
150
- var _a;
161
+ var _a, _b;
151
162
  const { req } = ctx;
152
- const appName = (_a = import_qs.default.parse((0, import_url.parse)(req.url).query)) == null ? void 0 : _a.__appName;
163
+ const parsedUrl = (0, import_url.parse)(req.url);
164
+ const appName = (_a = import_qs.default.parse(parsedUrl.query)) == null ? void 0 : _a.__appName;
165
+ const apiBasePath = normalizeBasePath(import_node_process.default.env.API_BASE_PATH || "/api");
166
+ const appPathPrefix = `${apiBasePath}/__app/`;
153
167
  if (appName) {
154
168
  ctx.resolvedAppName = appName;
155
169
  }
156
170
  if (req.headers["x-app"]) {
157
171
  ctx.resolvedAppName = req.headers["x-app"];
158
172
  }
173
+ if ((_b = parsedUrl.pathname) == null ? void 0 : _b.startsWith(appPathPrefix)) {
174
+ const restPath = parsedUrl.pathname.slice(appPathPrefix.length);
175
+ const [pathAppName, ...segments] = restPath.split("/");
176
+ if (pathAppName) {
177
+ ctx.resolvedAppName = pathAppName;
178
+ const rewrittenPath = `${apiBasePath}${segments.length ? `/${segments.join("/")}` : ""}`;
179
+ const rewrittenUrl = `${rewrittenPath}${parsedUrl.search || ""}`;
180
+ if (!req.originalUrl) {
181
+ req.originalUrl = req.url;
182
+ }
183
+ req.url = rewrittenUrl;
184
+ }
185
+ }
159
186
  await next();
160
187
  },
161
188
  {
@@ -218,15 +245,100 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
218
245
  });
219
246
  this.responseError(res, error);
220
247
  }
248
+ getV2PublicPath() {
249
+ return (0, import_utils3.resolveV2PublicPath)(import_node_process.default.env.APP_PUBLIC_PATH || "/");
250
+ }
251
+ getAppPublicPath() {
252
+ return (0, import_utils3.resolvePublicPath)(import_node_process.default.env.APP_PUBLIC_PATH || "/");
253
+ }
254
+ isV2Request(pathname) {
255
+ const v2PublicPath = this.getV2PublicPath();
256
+ return pathname === v2PublicPath.slice(0, -1) || pathname.startsWith(v2PublicPath);
257
+ }
258
+ isV2IndexRequest(pathname) {
259
+ if (!this.isV2Request(pathname)) {
260
+ return false;
261
+ }
262
+ const v2PublicPath = this.getV2PublicPath();
263
+ if (pathname === v2PublicPath || pathname === v2PublicPath.slice(0, -1) || pathname === `${v2PublicPath}index.html`) {
264
+ return true;
265
+ }
266
+ return !(0, import_path.extname)(pathname);
267
+ }
268
+ getV2RuntimeConfig() {
269
+ return {
270
+ __nocobase_public_path__: this.getV2PublicPath(),
271
+ __nocobase_api_base_url__: import_node_process.default.env.API_BASE_URL || import_node_process.default.env.API_BASE_PATH,
272
+ __nocobase_api_client_storage_prefix__: import_node_process.default.env.API_CLIENT_STORAGE_PREFIX,
273
+ __nocobase_api_client_storage_type__: import_node_process.default.env.API_CLIENT_STORAGE_TYPE,
274
+ __nocobase_api_client_share_token__: import_node_process.default.env.API_CLIENT_SHARE_TOKEN === "true",
275
+ __nocobase_ws_url__: import_node_process.default.env.WEBSOCKET_URL || "",
276
+ __nocobase_ws_path__: import_node_process.default.env.WS_PATH,
277
+ __esm_cdn_base_url__: import_node_process.default.env.ESM_CDN_BASE_URL || "https://esm.sh",
278
+ __esm_cdn_suffix__: import_node_process.default.env.ESM_CDN_SUFFIX || ""
279
+ };
280
+ }
281
+ getV2RuntimeConfigScript() {
282
+ const runtimeConfig = this.getV2RuntimeConfig();
283
+ const scriptContent = Object.entries(runtimeConfig).map(([key, value]) => `window['${key}'] = ${JSON.stringify(value)};`).join("\n");
284
+ return `<script>${scriptContent}</script>`;
285
+ }
286
+ getV2AssetPublicPath() {
287
+ if (import_node_process.default.env.CDN_BASE_URL) {
288
+ return `${import_node_process.default.env.CDN_BASE_URL.replace(/\/+$/, "")}/v2/`;
289
+ }
290
+ return this.getV2PublicPath();
291
+ }
292
+ getV2IndexTemplate() {
293
+ const file = `${import_node_process.default.env.APP_PACKAGE_ROOT}/dist/client/v2/index.html`;
294
+ if (!import_fs.default.existsSync(file)) {
295
+ return null;
296
+ }
297
+ const stat = import_fs.default.statSync(file);
298
+ if (this.v2IndexTemplateCache && this.v2IndexTemplateCache.file === file && this.v2IndexTemplateCache.mtimeMs === stat.mtimeMs) {
299
+ return this.v2IndexTemplateCache.html;
300
+ }
301
+ const html = import_fs.default.readFileSync(file, "utf-8");
302
+ this.v2IndexTemplateCache = {
303
+ file,
304
+ mtimeMs: stat.mtimeMs,
305
+ html
306
+ };
307
+ return html;
308
+ }
309
+ renderV2IndexHtml() {
310
+ const template = this.getV2IndexTemplate();
311
+ if (!template) {
312
+ return null;
313
+ }
314
+ const html = (0, import_utils3.rewriteV2AssetPublicPath)(template, this.getV2AssetPublicPath());
315
+ return (0, import_utils3.injectRuntimeScript)(html, this.getV2RuntimeConfigScript());
316
+ }
221
317
  async requestHandler(req, res) {
222
318
  const { pathname } = (0, import_url.parse)(req.url);
223
- const { PLUGIN_STATICS_PATH, APP_PUBLIC_PATH } = import_node_process.default.env;
319
+ const { PLUGIN_STATICS_PATH } = import_node_process.default.env;
320
+ const APP_PUBLIC_PATH = this.getAppPublicPath();
224
321
  if (pathname.endsWith("/__umi/api/bundle-status")) {
225
322
  res.statusCode = 200;
226
323
  res.end("ok");
227
324
  return;
228
325
  }
326
+ const supervisor = import_app_supervisor.AppSupervisor.getInstance();
327
+ let handleApp = "main";
328
+ try {
329
+ handleApp = await this.getRequestHandleAppName(req);
330
+ } catch (error) {
331
+ this.getLogger("main", res).error("Failed to get handle app name", { error });
332
+ this.responseErrorWithCode("APP_INITIALIZING", res, { appName: handleApp });
333
+ return;
334
+ }
229
335
  if (pathname.startsWith(APP_PUBLIC_PATH + "storage/uploads/")) {
336
+ if (handleApp !== "main") {
337
+ const isProxy = await supervisor.proxyWeb(handleApp, req, res);
338
+ if (isProxy) {
339
+ return;
340
+ }
341
+ }
230
342
  req.url = req.url.substring(APP_PUBLIC_PATH.length - 1);
231
343
  await compress(req, res);
232
344
  return (0, import_serve_handler.default)(req, res, {
@@ -235,6 +347,12 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
235
347
  });
236
348
  }
237
349
  if (pathname.startsWith(PLUGIN_STATICS_PATH) && !pathname.includes("/server/")) {
350
+ if (handleApp !== "main") {
351
+ const isProxy = await supervisor.proxyWeb(handleApp, req, res);
352
+ if (isProxy) {
353
+ return;
354
+ }
355
+ }
238
356
  await compress(req, res);
239
357
  const packageName = (0, import_plugin_manager.getPackageNameByExposeUrl)(pathname);
240
358
  const publicDir = (0, import_plugin_manager.getPackageDirByExposeUrl)(pathname);
@@ -250,6 +368,33 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
250
368
  });
251
369
  }
252
370
  if (!pathname.startsWith(import_node_process.default.env.API_BASE_PATH)) {
371
+ if (this.isV2Request(pathname)) {
372
+ if (handleApp !== "main") {
373
+ const isProxy = await supervisor.proxyWeb(handleApp, req, res);
374
+ if (isProxy) {
375
+ return;
376
+ }
377
+ }
378
+ if (this.isV2IndexRequest(pathname)) {
379
+ const v2Html = this.renderV2IndexHtml();
380
+ if (v2Html) {
381
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
382
+ res.end(v2Html);
383
+ return;
384
+ }
385
+ }
386
+ req.url = req.url.substring(APP_PUBLIC_PATH.length - 1);
387
+ await compress(req, res);
388
+ return (0, import_serve_handler.default)(req, res, {
389
+ public: `${import_node_process.default.env.APP_PACKAGE_ROOT}/dist/client`
390
+ });
391
+ }
392
+ if (handleApp !== "main") {
393
+ const isProxy = await supervisor.proxyWeb(handleApp, req, res);
394
+ if (isProxy) {
395
+ return;
396
+ }
397
+ }
253
398
  req.url = req.url.substring(APP_PUBLIC_PATH.length - 1);
254
399
  await compress(req, res);
255
400
  return (0, import_serve_handler.default)(req, res, {
@@ -257,19 +402,17 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
257
402
  rewrites: [{ source: "/**", destination: "/index.html" }]
258
403
  });
259
404
  }
260
- let handleApp = "main";
261
- try {
262
- handleApp = await this.getRequestHandleAppName(req);
263
- } catch (error) {
264
- console.log(error);
265
- this.responseErrorWithCode("APP_INITIALIZING", res, { appName: handleApp });
266
- return;
405
+ if (handleApp !== "main") {
406
+ const isProxy = await supervisor.proxyWeb(handleApp, req, res);
407
+ if (isProxy) {
408
+ return;
409
+ }
267
410
  }
268
- const hasApp = import_app_supervisor.AppSupervisor.getInstance().hasApp(handleApp);
411
+ const hasApp = supervisor.hasApp(handleApp);
269
412
  if (!hasApp) {
270
- void import_app_supervisor.AppSupervisor.getInstance().bootStrapApp(handleApp);
413
+ void supervisor.bootstrapApp(handleApp);
271
414
  }
272
- let appStatus = import_app_supervisor.AppSupervisor.getInstance().getAppStatus(handleApp, "preparing");
415
+ let appStatus = await supervisor.getAppStatus(handleApp, "preparing");
273
416
  if (appStatus === "not_found") {
274
417
  this.responseErrorWithCode("APP_NOT_FOUND", res, { appName: handleApp });
275
418
  return;
@@ -283,11 +426,19 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
283
426
  return;
284
427
  }
285
428
  if (appStatus === "initialized") {
286
- const appInstance = await import_app_supervisor.AppSupervisor.getInstance().getApp(handleApp);
287
- appInstance.runCommand("start", "--quickstart");
288
- appStatus = import_app_supervisor.AppSupervisor.getInstance().getAppStatus(handleApp);
429
+ const appInstance = await supervisor.getApp(handleApp);
430
+ if (!appInstance) {
431
+ this.responseErrorWithCode("APP_NOT_FOUND", res, { appName: handleApp });
432
+ return;
433
+ }
434
+ supervisor.startApp(handleApp);
435
+ appStatus = await supervisor.getAppStatus(handleApp);
436
+ }
437
+ const app = await supervisor.getApp(handleApp);
438
+ if (!app) {
439
+ this.responseErrorWithCode("APP_NOT_FOUND", res, { appName: handleApp });
440
+ return;
289
441
  }
290
- const app = await import_app_supervisor.AppSupervisor.getInstance().getApp(handleApp);
291
442
  if (appStatus !== "running") {
292
443
  this.responseErrorWithCode(`${appStatus}`, res, { app, appName: handleApp });
293
444
  return;
@@ -298,7 +449,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
298
449
  return;
299
450
  }
300
451
  if (handleApp !== "main") {
301
- import_app_supervisor.AppSupervisor.getInstance().touchApp(handleApp);
452
+ await supervisor.setAppLastSeenAt(handleApp);
302
453
  }
303
454
  const ctx = { req, res, appName: handleApp };
304
455
  const fn = (0, import_koa_compose.default)([
@@ -366,6 +517,14 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
366
517
  }
367
518
  const mainApp = import_app_supervisor.AppSupervisor.getInstance().bootMainApp(options.mainAppOptions);
368
519
  mainApp.setMaxListeners(50);
520
+ mainApp.once("afterStart", () => {
521
+ (0, import_utils2.lockdownSes)({
522
+ consoleTaming: "unsafe",
523
+ errorTaming: "unsafe",
524
+ overrideTaming: "moderate",
525
+ stackFiltering: "verbose"
526
+ });
527
+ });
369
528
  let runArgs = [import_node_process.default.argv, { throwError: true, from: "node" }];
370
529
  if (!import_node_worker_threads.isMainThread) {
371
530
  runArgs = [import_node_worker_threads.workerData.argv, { throwError: true, from: "user" }];
@@ -433,6 +592,10 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
433
592
  });
434
593
  this.wsServer = new import_ws_server.WSServer();
435
594
  this.server.on("upgrade", async (request, socket, head) => {
595
+ const isProxy = await import_app_supervisor.AppSupervisor.getInstance().proxyWs(request, socket, head);
596
+ if (isProxy) {
597
+ return;
598
+ }
436
599
  const appInstance = await import_app_supervisor.AppSupervisor.getInstance().getApp("main");
437
600
  for (const handle of _Gateway.wsServers) {
438
601
  const result = await handle(request, socket, head, appInstance);
@@ -104,7 +104,7 @@ const _IPCSocketServer = class _IPCSocketServer {
104
104
  const max = 300;
105
105
  let count = 0;
106
106
  const timer = setInterval(async () => {
107
- status2 = import_app_supervisor.AppSupervisor.getInstance().getAppStatus("main");
107
+ status2 = await import_app_supervisor.AppSupervisor.getInstance().getAppStatus("main");
108
108
  if (status2 === "running") {
109
109
  clearInterval(timer);
110
110
  resolve(status2);
@@ -0,0 +1,12 @@
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
+ export declare function resolvePublicPath(appPublicPath?: string): string;
10
+ export declare function resolveV2PublicPath(appPublicPath?: string): string;
11
+ export declare function rewriteV2AssetPublicPath(html: string, assetPublicPath: string): string;
12
+ export declare function injectRuntimeScript(html: string, runtimeScript: string): string;
@@ -0,0 +1,84 @@
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
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
18
+ };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
+ }
25
+ return to;
26
+ };
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var utils_exports = {};
29
+ __export(utils_exports, {
30
+ injectRuntimeScript: () => injectRuntimeScript,
31
+ resolvePublicPath: () => resolvePublicPath,
32
+ resolveV2PublicPath: () => resolveV2PublicPath,
33
+ rewriteV2AssetPublicPath: () => rewriteV2AssetPublicPath
34
+ });
35
+ module.exports = __toCommonJS(utils_exports);
36
+ function resolvePublicPath(appPublicPath = "/") {
37
+ const normalized = String(appPublicPath || "/").trim() || "/";
38
+ const withLeadingSlash = normalized.startsWith("/") ? normalized : `/${normalized}`;
39
+ return withLeadingSlash.endsWith("/") ? withLeadingSlash : `${withLeadingSlash}/`;
40
+ }
41
+ __name(resolvePublicPath, "resolvePublicPath");
42
+ function resolveV2PublicPath(appPublicPath = "/") {
43
+ const publicPath = resolvePublicPath(appPublicPath);
44
+ return `${publicPath.replace(/\/$/, "")}/v2/`;
45
+ }
46
+ __name(resolveV2PublicPath, "resolveV2PublicPath");
47
+ function ensureTrailingSlash(value) {
48
+ return value.endsWith("/") ? value : `${value}/`;
49
+ }
50
+ __name(ensureTrailingSlash, "ensureTrailingSlash");
51
+ function rewriteV2AssetPublicPath(html, assetPublicPath) {
52
+ const normalizedAssetPublicPath = ensureTrailingSlash(assetPublicPath);
53
+ if (normalizedAssetPublicPath === "/v2/") {
54
+ return html;
55
+ }
56
+ return html.replace(/((?:src|href)=["'])\/v2\//g, `$1${normalizedAssetPublicPath}`);
57
+ }
58
+ __name(rewriteV2AssetPublicPath, "rewriteV2AssetPublicPath");
59
+ function injectRuntimeScript(html, runtimeScript) {
60
+ const browserCheckerScriptMatch = html.match(/<script\b[^>]*browser-checker\.js[^>]*><\/script>/i);
61
+ if (browserCheckerScriptMatch == null ? void 0 : browserCheckerScriptMatch[0]) {
62
+ return html.replace(browserCheckerScriptMatch[0], `${runtimeScript}
63
+ ${browserCheckerScriptMatch[0]}`);
64
+ }
65
+ const moduleScriptMatch = html.match(/<script\b[^>]*type=["']module["'][^>]*>/i);
66
+ if (moduleScriptMatch == null ? void 0 : moduleScriptMatch[0]) {
67
+ return html.replace(moduleScriptMatch[0], `${runtimeScript}
68
+ ${moduleScriptMatch[0]}`);
69
+ }
70
+ if (html.includes("</head>")) {
71
+ return html.replace("</head>", `${runtimeScript}
72
+ </head>`);
73
+ }
74
+ return `${runtimeScript}
75
+ ${html}`;
76
+ }
77
+ __name(injectRuntimeScript, "injectRuntimeScript");
78
+ // Annotate the CommonJS export names for ESM import in node:
79
+ 0 && (module.exports = {
80
+ injectRuntimeScript,
81
+ resolvePublicPath,
82
+ resolveV2PublicPath,
83
+ rewriteV2AssetPublicPath
84
+ });
@@ -90,7 +90,7 @@ const _WSServer = class _WSServer extends import_events.default {
90
90
  }
91
91
  }
92
92
  client.tags.add(`app#${handleAppName}`);
93
- import_app_supervisor.AppSupervisor.getInstance().bootStrapApp(handleAppName);
93
+ import_app_supervisor.AppSupervisor.getInstance().bootstrapApp(handleAppName);
94
94
  });
95
95
  });
96
96
  import_app_supervisor.AppSupervisor.getInstance().on("appError", async ({ appName, error }) => {
@@ -112,6 +112,7 @@ const _WSServer = class _WSServer extends import_events.default {
112
112
  });
113
113
  const payload = getPayloadByErrorCode(status, {
114
114
  app,
115
+ appName,
115
116
  message,
116
117
  command
117
118
  });
@@ -248,7 +249,7 @@ const _WSServer = class _WSServer extends import_events.default {
248
249
  client.tags.add(`app#${handleAppName}`);
249
250
  const hasApp = import_app_supervisor.AppSupervisor.getInstance().hasApp(handleAppName);
250
251
  if (!hasApp) {
251
- import_app_supervisor.AppSupervisor.getInstance().bootStrapApp(handleAppName);
252
+ import_app_supervisor.AppSupervisor.getInstance().bootstrapApp(handleAppName);
252
253
  }
253
254
  }
254
255
  removeConnection(id) {
package/lib/helper.js CHANGED
@@ -76,6 +76,25 @@ function createResourcer(options) {
76
76
  return new import_resourcer.Resourcer({ ...options.resourcer });
77
77
  }
78
78
  __name(createResourcer, "createResourcer");
79
+ function resolveCorsOrigin(ctx) {
80
+ const origin = ctx.get("origin");
81
+ const disallowNoOrigin = process.env.CORS_DISALLOW_NO_ORIGIN === "true";
82
+ const whitelistString = process.env.CORS_ORIGIN_WHITELIST;
83
+ if (!origin && disallowNoOrigin) {
84
+ return false;
85
+ }
86
+ if (!whitelistString) {
87
+ return origin;
88
+ }
89
+ const whitelist = new Set(
90
+ whitelistString.split(",").map((item) => item.trim()).filter(Boolean)
91
+ );
92
+ if (whitelist.has(origin)) {
93
+ return origin;
94
+ }
95
+ return false;
96
+ }
97
+ __name(resolveCorsOrigin, "resolveCorsOrigin");
79
98
  function registerMiddlewares(app, options) {
80
99
  var _a;
81
100
  app.use(
@@ -90,9 +109,7 @@ function registerMiddlewares(app, options) {
90
109
  app.use(
91
110
  (0, import_cors.default)({
92
111
  exposeHeaders: ["content-disposition"],
93
- origin(ctx) {
94
- return ctx.get("origin");
95
- },
112
+ origin: resolveCorsOrigin,
96
113
  ...options.cors
97
114
  }),
98
115
  {
@@ -222,14 +239,46 @@ function isNumeric(str) {
222
239
  return !isNaN(str) && !isNaN(parseFloat(str));
223
240
  }
224
241
  __name(isNumeric, "isNumeric");
242
+ function getFieldFromCollectionManager(ctx, resourceName, fieldPath) {
243
+ var _a;
244
+ const collectionManager = (_a = ctx.dataSource) == null ? void 0 : _a.collectionManager;
245
+ if (!(collectionManager == null ? void 0 : collectionManager.getCollection)) {
246
+ return;
247
+ }
248
+ const collection = collectionManager.getCollection(resourceName);
249
+ if (!(collection == null ? void 0 : collection.getField)) {
250
+ return;
251
+ }
252
+ const [firstName, ...others] = fieldPath.split(".");
253
+ let field = collection.getField(firstName);
254
+ if (!field || !others.length) {
255
+ return field;
256
+ }
257
+ let currentCollection = typeof field.targetCollection === "function" ? field.targetCollection() : field.targetCollection;
258
+ for (const name of others) {
259
+ if (!(currentCollection == null ? void 0 : currentCollection.getField)) {
260
+ return;
261
+ }
262
+ field = currentCollection.getField(name);
263
+ if (!field) {
264
+ return;
265
+ }
266
+ currentCollection = typeof field.targetCollection === "function" ? field.targetCollection() : field.targetCollection;
267
+ }
268
+ return field;
269
+ }
270
+ __name(getFieldFromCollectionManager, "getFieldFromCollectionManager");
225
271
  function createContextVariablesScope(ctx) {
226
272
  const state = JSON.parse(JSON.stringify(ctx.state));
227
273
  return {
228
274
  timezone: ctx.get("x-timezone"),
229
275
  now: (/* @__PURE__ */ new Date()).toISOString(),
230
276
  getField: /* @__PURE__ */ __name((path) => {
231
- const fieldPath = path.split(".").filter((p) => !p.startsWith("$") && !isNumeric(p)).join(".");
232
277
  const { resourceName } = ctx.action;
278
+ const fieldPath = path.split(".").filter((p) => !p.startsWith("$") && !isNumeric(p)).join(".");
279
+ if (!ctx.database) {
280
+ return getFieldFromCollectionManager(ctx, resourceName, fieldPath);
281
+ }
233
282
  return ctx.database.getFieldByPath(`${resourceName}.${fieldPath}`);
234
283
  }, "getField"),
235
284
  vars: {
@@ -41,7 +41,7 @@ const deps = {
41
41
  umzug: "3.x",
42
42
  "async-mutex": "0.5.x",
43
43
  "@formulajs/formulajs": "4.x",
44
- mathjs: "10.x",
44
+ mathjs: "15.x",
45
45
  winston: "3.x",
46
46
  "winston-daily-rotate-file": "4.x",
47
47
  koa: "2.x",
@@ -6,6 +6,15 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
+ export type PluginClientLane = 'client' | 'client-v2';
10
+ export declare class PackageUrls {
11
+ static items: Record<string, string | undefined>;
12
+ static clear(): void;
13
+ static getCacheKey(packageName: string, lane: PluginClientLane): string;
14
+ static get(packageName: string, lane?: PluginClientLane): Promise<string>;
15
+ static hasClientEntry(packageName: string, lane: PluginClientLane): Promise<boolean>;
16
+ static fetch(packageName: string, lane?: PluginClientLane): Promise<string>;
17
+ }
9
18
  declare const _default: {
10
19
  name: string;
11
20
  actions: {
@@ -17,6 +26,7 @@ declare const _default: {
17
26
  remove(ctx: any, next: any): Promise<void>;
18
27
  list(ctx: any, next: any): Promise<void>;
19
28
  listEnabled(ctx: any, next: any): Promise<void>;
29
+ listEnabledV2(ctx: any, next: any): Promise<void>;
20
30
  get(ctx: any, next: any): Promise<void>;
21
31
  };
22
32
  };