@nocobase/server 2.1.0-beta.8 → 2.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/lib/acl/available-action.js +1 -1
  2. package/lib/aes-encryptor.js +3 -2
  3. package/lib/app-supervisor/app-options-factory.d.ts +1 -0
  4. package/lib/app-supervisor/index.d.ts +13 -5
  5. package/lib/app-supervisor/index.js +48 -13
  6. package/lib/app-supervisor/main-only-adapter.d.ts +3 -0
  7. package/lib/app-supervisor/main-only-adapter.js +7 -0
  8. package/lib/app-supervisor/types.d.ts +18 -3
  9. package/lib/application.d.ts +1 -2
  10. package/lib/application.js +3 -24
  11. package/lib/audit-manager/index.d.ts +2 -0
  12. package/lib/audit-manager/index.js +5 -2
  13. package/lib/commands/ai.js +1 -6
  14. package/lib/commands/create-migration.js +1 -1
  15. package/lib/commands/install.js +0 -4
  16. package/lib/commands/pm.js +7 -0
  17. package/lib/commands/start.js +2 -5
  18. package/lib/commands/upgrade.js +0 -4
  19. package/lib/{ai/create-docs-index.d.ts → constants.d.ts} +1 -5
  20. package/lib/constants.js +36 -0
  21. package/lib/event-queue.js +1 -1
  22. package/lib/gateway/index.d.ts +15 -3
  23. package/lib/gateway/index.js +180 -20
  24. package/lib/gateway/static-file-security.d.ts +10 -0
  25. package/lib/gateway/static-file-security.js +69 -0
  26. package/lib/gateway/utils.d.ts +19 -0
  27. package/lib/gateway/utils.js +128 -0
  28. package/lib/helpers/application-version.js +1 -0
  29. package/lib/index.d.ts +3 -1
  30. package/lib/index.js +5 -4
  31. package/lib/locale/locale.d.ts +24 -0
  32. package/lib/locale/locale.js +29 -5
  33. package/lib/main-data-source.js +12 -5
  34. package/lib/plugin-manager/constants.js +1 -1
  35. package/lib/plugin-manager/deps.js +3 -2
  36. package/lib/plugin-manager/findPackageNames.d.ts +5 -5
  37. package/lib/plugin-manager/findPackageNames.js +35 -58
  38. package/lib/plugin-manager/options/collection.js +1 -0
  39. package/lib/plugin-manager/options/resource.d.ts +12 -1
  40. package/lib/plugin-manager/options/resource.js +210 -65
  41. package/lib/plugin-manager/plugin-manager.d.ts +7 -2
  42. package/lib/plugin-manager/plugin-manager.js +59 -81
  43. package/lib/plugin-manager/utils.d.ts +9 -1
  44. package/lib/plugin-manager/utils.js +67 -9
  45. package/lib/plugin.js +33 -2
  46. package/lib/pub-sub-manager/handler-manager.d.ts +1 -0
  47. package/lib/pub-sub-manager/handler-manager.js +11 -0
  48. package/lib/pub-sub-manager/pub-sub-manager.js +2 -1
  49. package/lib/swagger/app.d.ts +102 -0
  50. package/lib/swagger/app.js +124 -0
  51. package/lib/swagger/base.d.ts +244 -0
  52. package/lib/swagger/base.js +292 -0
  53. package/lib/swagger/collections.d.ts +996 -0
  54. package/lib/swagger/collections.js +1264 -0
  55. package/lib/swagger/index.d.ts +1774 -0
  56. package/lib/swagger/index.js +70 -0
  57. package/lib/swagger/pm.d.ts +462 -0
  58. package/lib/swagger/pm.js +422 -0
  59. package/lib/sync-message-manager.js +8 -1
  60. package/lib/worker-mode.d.ts +19 -0
  61. package/lib/worker-mode.js +67 -0
  62. package/package.json +18 -18
  63. package/lib/ai/create-docs-index.js +0 -892
  64. package/lib/swagger/index.json +0 -1569
@@ -39,7 +39,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
39
39
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
40
40
  var gateway_exports = {};
41
41
  __export(gateway_exports, {
42
- Gateway: () => Gateway
42
+ Gateway: () => Gateway,
43
+ getHost: () => import_utils4.getHost,
44
+ getHostname: () => import_utils4.getHostname
43
45
  });
44
46
  module.exports = __toCommonJS(gateway_exports);
45
47
  var import_logger = require("@nocobase/logger");
@@ -54,6 +56,7 @@ var import_fs = __toESM(require("fs"));
54
56
  var import_http = __toESM(require("http"));
55
57
  var import_koa_compose = __toESM(require("koa-compose"));
56
58
  var import_node_util = require("node:util");
59
+ var import_node_os = require("node:os");
57
60
  var import_path = require("path");
58
61
  var import_qs = __toESM(require("qs"));
59
62
  var import_serve_handler = __toESM(require("serve-handler"));
@@ -63,16 +66,27 @@ var import_plugin_manager = require("../plugin-manager");
63
66
  var import_errors = require("./errors");
64
67
  var import_ipc_socket_client = require("./ipc-socket-client");
65
68
  var import_ipc_socket_server = require("./ipc-socket-server");
69
+ var import_static_file_security = require("./static-file-security");
70
+ var import_utils3 = require("./utils");
66
71
  var import_ws_server = require("./ws-server");
67
72
  var import_node_worker_threads = require("node:worker_threads");
68
73
  var import_node_process = __toESM(require("node:process"));
74
+ var import_utils4 = require("./utils");
69
75
  const compress = (0, import_node_util.promisify)((0, import_compression.default)());
76
+ function normalizeBasePath(path = "") {
77
+ const normalized = path.replace(/\/+/g, "/").replace(/\/$/, "");
78
+ return normalized || "/";
79
+ }
80
+ __name(normalizeBasePath, "normalizeBasePath");
70
81
  function getSocketPath() {
71
- const { SOCKET_PATH } = import_node_process.default.env;
72
- if ((0, import_path.isAbsolute)(SOCKET_PATH)) {
73
- return SOCKET_PATH;
82
+ const socketPath = import_node_process.default.env.SOCKET_PATH;
83
+ if (socketPath) {
84
+ return (0, import_path.isAbsolute)(socketPath) ? socketPath : (0, import_path.resolve)(import_node_process.default.cwd(), socketPath);
85
+ }
86
+ if (import_node_process.default.env.NOCOBASE_RUNNING_IN_DOCKER === "true") {
87
+ return (0, import_path.resolve)((0, import_node_os.homedir)(), ".nocobase", "gateway.sock");
74
88
  }
75
- return (0, import_path.resolve)(import_node_process.default.cwd(), SOCKET_PATH);
89
+ return (0, import_utils.storagePathJoin)("gateway.sock");
76
90
  }
77
91
  __name(getSocketPath, "getSocketPath");
78
92
  const _Gateway = class _Gateway extends import_events.EventEmitter {
@@ -87,8 +101,21 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
87
101
  loggers = new import_utils.Registry();
88
102
  port = import_node_process.default.env.APP_PORT ? parseInt(import_node_process.default.env.APP_PORT) : null;
89
103
  host = "0.0.0.0";
90
- socketPath = (0, import_path.resolve)(import_node_process.default.cwd(), "storage", "gateway.sock");
104
+ socketPath = getSocketPath();
105
+ v2IndexTemplateCache = null;
91
106
  terminating = false;
107
+ getOriginalRequestUrl(req) {
108
+ return req.originalUrl || req.url;
109
+ }
110
+ async proxyRequestToSubApp(supervisor, appName, req, res) {
111
+ const internalUrl = req.url;
112
+ req.url = this.getOriginalRequestUrl(req);
113
+ try {
114
+ return await supervisor.proxyWeb(appName, req, res);
115
+ } finally {
116
+ req.url = internalUrl;
117
+ }
118
+ }
92
119
  onTerminate = /* @__PURE__ */ __name(async (signal) => {
93
120
  var _a;
94
121
  if (this.terminating) {
@@ -119,7 +146,6 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
119
146
  constructor() {
120
147
  super();
121
148
  this.reset();
122
- this.socketPath = getSocketPath();
123
149
  import_node_process.default.once("SIGTERM", this.onTerminate);
124
150
  import_node_process.default.once("SIGINT", this.onTerminate);
125
151
  }
@@ -151,14 +177,30 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
151
177
  this.selectorMiddlewares = new import_utils.Toposort();
152
178
  this.addAppSelectorMiddleware(
153
179
  async (ctx, next) => {
154
- var _a;
180
+ var _a, _b;
155
181
  const { req } = ctx;
156
- const appName = (_a = import_qs.default.parse((0, import_url.parse)(req.url).query)) == null ? void 0 : _a.__appName;
182
+ const parsedUrl = (0, import_url.parse)(req.url);
183
+ const appName = (_a = import_qs.default.parse(parsedUrl.query)) == null ? void 0 : _a.__appName;
184
+ const apiBasePath = normalizeBasePath(import_node_process.default.env.API_BASE_PATH || "/api");
185
+ const appPathPrefix = `${apiBasePath}/__app/`;
186
+ if (req.headers["x-app"]) {
187
+ ctx.resolvedAppName = req.headers["x-app"];
188
+ }
157
189
  if (appName) {
158
190
  ctx.resolvedAppName = appName;
159
191
  }
160
- if (req.headers["x-app"]) {
161
- ctx.resolvedAppName = req.headers["x-app"];
192
+ if ((_b = parsedUrl.pathname) == null ? void 0 : _b.startsWith(appPathPrefix)) {
193
+ const restPath = parsedUrl.pathname.slice(appPathPrefix.length);
194
+ const [pathAppName, ...segments] = restPath.split("/");
195
+ if (pathAppName) {
196
+ ctx.resolvedAppName = pathAppName;
197
+ const rewrittenPath = `${apiBasePath}${segments.length ? `/${segments.join("/")}` : ""}`;
198
+ const rewrittenUrl = `${rewrittenPath}${parsedUrl.search || ""}`;
199
+ if (!req.originalUrl) {
200
+ req.originalUrl = req.url;
201
+ }
202
+ req.url = rewrittenUrl;
203
+ }
162
204
  }
163
205
  await next();
164
206
  },
@@ -222,9 +264,82 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
222
264
  });
223
265
  this.responseError(res, error);
224
266
  }
267
+ getV2PublicPath() {
268
+ return (0, import_utils3.resolveV2PublicPath)(import_node_process.default.env.APP_PUBLIC_PATH || "/");
269
+ }
270
+ getAppPublicPath() {
271
+ return (0, import_utils3.resolvePublicPath)(import_node_process.default.env.APP_PUBLIC_PATH || "/");
272
+ }
273
+ isV2Request(pathname) {
274
+ const v2PublicPath = this.getV2PublicPath();
275
+ return pathname === v2PublicPath.slice(0, -1) || pathname.startsWith(v2PublicPath);
276
+ }
277
+ isV2IndexRequest(pathname) {
278
+ if (!this.isV2Request(pathname)) {
279
+ return false;
280
+ }
281
+ const v2PublicPath = this.getV2PublicPath();
282
+ if (pathname === v2PublicPath || pathname === v2PublicPath.slice(0, -1) || pathname === `${v2PublicPath}index.html`) {
283
+ return true;
284
+ }
285
+ return !(0, import_path.extname)(pathname);
286
+ }
287
+ getV2RuntimeConfig() {
288
+ return {
289
+ __nocobase_public_path__: this.getV2PublicPath(),
290
+ __nocobase_modern_client_prefix__: (0, import_utils3.normalizeModernClientPrefix)(import_node_process.default.env.APP_MODERN_CLIENT_PREFIX),
291
+ __webpack_public_path__: import_node_process.default.env.CDN_BASE_URL ? `${import_node_process.default.env.CDN_BASE_URL.replace(/\/+$/, "")}/` : "",
292
+ __nocobase_api_base_url__: import_node_process.default.env.API_BASE_URL || import_node_process.default.env.API_BASE_PATH,
293
+ __nocobase_api_client_storage_prefix__: import_node_process.default.env.API_CLIENT_STORAGE_PREFIX,
294
+ __nocobase_api_client_storage_type__: import_node_process.default.env.API_CLIENT_STORAGE_TYPE,
295
+ __nocobase_api_client_share_token__: import_node_process.default.env.API_CLIENT_SHARE_TOKEN === "true",
296
+ __nocobase_ws_url__: import_node_process.default.env.WEBSOCKET_URL || "",
297
+ __nocobase_ws_path__: import_node_process.default.env.WS_PATH,
298
+ __nocobase_app_dev__: import_node_process.default.env.NOCOBASE_APP_DEV === "true",
299
+ __esm_cdn_base_url__: import_node_process.default.env.ESM_CDN_BASE_URL || "https://esm.sh",
300
+ __esm_cdn_suffix__: import_node_process.default.env.ESM_CDN_SUFFIX || ""
301
+ };
302
+ }
303
+ getV2RuntimeConfigScript() {
304
+ const runtimeConfig = this.getV2RuntimeConfig();
305
+ const scriptContent = Object.entries(runtimeConfig).map(([key, value]) => `window['${key}'] = ${JSON.stringify(value)};`).join("\n");
306
+ return `<script>${scriptContent}</script>`;
307
+ }
308
+ getV2AssetPublicPath() {
309
+ if (import_node_process.default.env.CDN_BASE_URL) {
310
+ return `${import_node_process.default.env.CDN_BASE_URL.replace(/\/+$/, "")}/${import_utils3.MODERN_CLIENT_DIST_DIR}/`;
311
+ }
312
+ return this.getV2PublicPath();
313
+ }
314
+ getV2IndexTemplate() {
315
+ const file = `${import_node_process.default.env.APP_PACKAGE_ROOT}/dist/client/${import_utils3.MODERN_CLIENT_DIST_DIR}/index.html`;
316
+ if (!import_fs.default.existsSync(file)) {
317
+ return null;
318
+ }
319
+ const stat = import_fs.default.statSync(file);
320
+ if (this.v2IndexTemplateCache && this.v2IndexTemplateCache.file === file && this.v2IndexTemplateCache.mtimeMs === stat.mtimeMs) {
321
+ return this.v2IndexTemplateCache.html;
322
+ }
323
+ const html = import_fs.default.readFileSync(file, "utf-8");
324
+ this.v2IndexTemplateCache = {
325
+ file,
326
+ mtimeMs: stat.mtimeMs,
327
+ html
328
+ };
329
+ return html;
330
+ }
331
+ renderV2IndexHtml() {
332
+ const template = this.getV2IndexTemplate();
333
+ if (!template) {
334
+ return null;
335
+ }
336
+ const html = (0, import_utils3.rewriteV2AssetPublicPath)(template, this.getV2AssetPublicPath());
337
+ return (0, import_utils3.injectRuntimeScript)(html, this.getV2RuntimeConfigScript());
338
+ }
225
339
  async requestHandler(req, res) {
226
340
  const { pathname } = (0, import_url.parse)(req.url);
227
- const { PLUGIN_STATICS_PATH, APP_PUBLIC_PATH } = import_node_process.default.env;
341
+ const { PLUGIN_STATICS_PATH } = import_node_process.default.env;
342
+ const APP_PUBLIC_PATH = this.getAppPublicPath();
228
343
  if (pathname.endsWith("/__umi/api/bundle-status")) {
229
344
  res.statusCode = 200;
230
345
  res.end("ok");
@@ -241,21 +356,39 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
241
356
  }
242
357
  if (pathname.startsWith(APP_PUBLIC_PATH + "storage/uploads/")) {
243
358
  if (handleApp !== "main") {
244
- const isProxy = await supervisor.proxyWeb(handleApp, req, res);
359
+ const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
245
360
  if (isProxy) {
246
361
  return;
247
362
  }
248
363
  }
249
- req.url = req.url.substring(APP_PUBLIC_PATH.length - 1);
364
+ const headers = (0, import_static_file_security.getStorageUploadSecurityHeaders)(pathname);
365
+ for (const [key, value] of Object.entries(headers)) {
366
+ res.setHeader(key, value);
367
+ }
368
+ req.url = req.url.substring(APP_PUBLIC_PATH.length + "storage".length);
369
+ await compress(req, res);
370
+ return (0, import_serve_handler.default)(req, res, {
371
+ public: (0, import_utils.resolveStorageRoot)(),
372
+ directoryListing: false
373
+ });
374
+ }
375
+ if (pathname.startsWith(APP_PUBLIC_PATH + "dist/")) {
376
+ if (handleApp !== "main") {
377
+ const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
378
+ if (isProxy) {
379
+ return;
380
+ }
381
+ }
382
+ req.url = req.url.substring(APP_PUBLIC_PATH.length + "dist".length);
250
383
  await compress(req, res);
251
384
  return (0, import_serve_handler.default)(req, res, {
252
- public: (0, import_path.resolve)(import_node_process.default.cwd()),
385
+ public: (0, import_utils.storagePathJoin)("dist-client"),
253
386
  directoryListing: false
254
387
  });
255
388
  }
256
389
  if (pathname.startsWith(PLUGIN_STATICS_PATH) && !pathname.includes("/server/")) {
257
390
  if (handleApp !== "main") {
258
- const isProxy = await supervisor.proxyWeb(handleApp, req, res);
391
+ const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
259
392
  if (isProxy) {
260
393
  return;
261
394
  }
@@ -275,8 +408,33 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
275
408
  });
276
409
  }
277
410
  if (!pathname.startsWith(import_node_process.default.env.API_BASE_PATH)) {
411
+ if (this.isV2Request(pathname)) {
412
+ if (handleApp !== "main") {
413
+ const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
414
+ if (isProxy) {
415
+ return;
416
+ }
417
+ }
418
+ if (this.isV2IndexRequest(pathname)) {
419
+ const v2Html = this.renderV2IndexHtml();
420
+ if (v2Html) {
421
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
422
+ res.end(v2Html);
423
+ return;
424
+ }
425
+ }
426
+ req.url = req.url.substring(APP_PUBLIC_PATH.length - 1);
427
+ const modernPrefix = (0, import_utils3.normalizeModernClientPrefix)(import_node_process.default.env.APP_MODERN_CLIENT_PREFIX);
428
+ if (modernPrefix !== import_utils3.MODERN_CLIENT_DIST_DIR && req.url.startsWith(`/${modernPrefix}/`)) {
429
+ req.url = `/${import_utils3.MODERN_CLIENT_DIST_DIR}/${req.url.slice(modernPrefix.length + 2)}`;
430
+ }
431
+ await compress(req, res);
432
+ return (0, import_serve_handler.default)(req, res, {
433
+ public: `${import_node_process.default.env.APP_PACKAGE_ROOT}/dist/client`
434
+ });
435
+ }
278
436
  if (handleApp !== "main") {
279
- const isProxy = await supervisor.proxyWeb(handleApp, req, res);
437
+ const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
280
438
  if (isProxy) {
281
439
  return;
282
440
  }
@@ -289,7 +447,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
289
447
  });
290
448
  }
291
449
  if (handleApp !== "main") {
292
- const isProxy = await supervisor.proxyWeb(handleApp, req, res);
450
+ const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
293
451
  if (isProxy) {
294
452
  return;
295
453
  }
@@ -399,7 +557,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
399
557
  }
400
558
  }
401
559
  if (isStart || !ipcClient) {
402
- await (0, import_plugin_symlink.createStoragePluginsSymlink)();
560
+ await (0, import_plugin_symlink.syncPluginSymlinks)();
403
561
  }
404
562
  const mainApp = import_app_supervisor.AppSupervisor.getInstance().bootMainApp(options.mainAppOptions);
405
563
  mainApp.setMaxListeners(50);
@@ -541,5 +699,7 @@ __publicField(_Gateway, "wsServers", []);
541
699
  let Gateway = _Gateway;
542
700
  // Annotate the CommonJS export names for ESM import in node:
543
701
  0 && (module.exports = {
544
- Gateway
702
+ Gateway,
703
+ getHost,
704
+ getHostname
545
705
  });
@@ -0,0 +1,10 @@
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 hasActiveContentExtension(pathname?: string): boolean;
10
+ export declare function getStorageUploadSecurityHeaders(pathname?: string): Record<string, string>;
@@ -0,0 +1,69 @@
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 __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
17
+ var __export = (target, all) => {
18
+ for (var name in all)
19
+ __defProp(target, name, { get: all[name], enumerable: true });
20
+ };
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") {
23
+ for (let key of __getOwnPropNames(from))
24
+ if (!__hasOwnProp.call(to, key) && key !== except)
25
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
26
+ }
27
+ return to;
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
+ ));
37
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
+ var static_file_security_exports = {};
39
+ __export(static_file_security_exports, {
40
+ getStorageUploadSecurityHeaders: () => getStorageUploadSecurityHeaders,
41
+ hasActiveContentExtension: () => hasActiveContentExtension
42
+ });
43
+ module.exports = __toCommonJS(static_file_security_exports);
44
+ var import_node_path = __toESM(require("node:path"));
45
+ const ACTIVE_CONTENT_EXTENSIONS = /* @__PURE__ */ new Set([".htm", ".html", ".pdf", ".svg", ".svgz", ".xhtml"]);
46
+ function stripQueryAndHash(pathname = "") {
47
+ return pathname.split("?")[0].split("#")[0];
48
+ }
49
+ __name(stripQueryAndHash, "stripQueryAndHash");
50
+ function hasActiveContentExtension(pathname = "") {
51
+ const ext = import_node_path.default.extname(stripQueryAndHash(pathname)).toLowerCase();
52
+ return ACTIVE_CONTENT_EXTENSIONS.has(ext);
53
+ }
54
+ __name(hasActiveContentExtension, "hasActiveContentExtension");
55
+ function getStorageUploadSecurityHeaders(pathname = "") {
56
+ const headers = {
57
+ "X-Content-Type-Options": "nosniff"
58
+ };
59
+ if (hasActiveContentExtension(pathname)) {
60
+ headers["Content-Disposition"] = "attachment";
61
+ }
62
+ return headers;
63
+ }
64
+ __name(getStorageUploadSecurityHeaders, "getStorageUploadSecurityHeaders");
65
+ // Annotate the CommonJS export names for ESM import in node:
66
+ 0 && (module.exports = {
67
+ getStorageUploadSecurityHeaders,
68
+ hasActiveContentExtension
69
+ });
@@ -0,0 +1,19 @@
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
+ /// <reference types="node" />
10
+ import { IncomingMessage } from 'http';
11
+ import { IncomingRequest } from '.';
12
+ export declare const MODERN_CLIENT_DIST_DIR = "v";
13
+ export declare function resolvePublicPath(appPublicPath?: string): string;
14
+ export declare function normalizeModernClientPrefix(value?: string): string;
15
+ export declare function resolveV2PublicPath(appPublicPath?: string): string;
16
+ export declare function rewriteV2AssetPublicPath(html: string, assetPublicPath: string): string;
17
+ export declare function injectRuntimeScript(html: string, runtimeScript: string): string;
18
+ export declare function getHost(req: IncomingMessage | IncomingRequest): any;
19
+ export declare function getHostname(req: IncomingMessage | IncomingRequest): any;
@@ -0,0 +1,128 @@
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
+ MODERN_CLIENT_DIST_DIR: () => MODERN_CLIENT_DIST_DIR,
31
+ getHost: () => getHost,
32
+ getHostname: () => getHostname,
33
+ injectRuntimeScript: () => injectRuntimeScript,
34
+ normalizeModernClientPrefix: () => normalizeModernClientPrefix,
35
+ resolvePublicPath: () => resolvePublicPath,
36
+ resolveV2PublicPath: () => resolveV2PublicPath,
37
+ rewriteV2AssetPublicPath: () => rewriteV2AssetPublicPath
38
+ });
39
+ module.exports = __toCommonJS(utils_exports);
40
+ const MODERN_CLIENT_DIST_DIR = "v";
41
+ function resolvePublicPath(appPublicPath = "/") {
42
+ const normalized = String(appPublicPath || "/").trim() || "/";
43
+ const withLeadingSlash = normalized.startsWith("/") ? normalized : `/${normalized}`;
44
+ return withLeadingSlash.endsWith("/") ? withLeadingSlash : `${withLeadingSlash}/`;
45
+ }
46
+ __name(resolvePublicPath, "resolvePublicPath");
47
+ function normalizeModernClientPrefix(value) {
48
+ const segment = String(value || "").trim().replace(/^\/+|\/+$/g, "");
49
+ return segment || MODERN_CLIENT_DIST_DIR;
50
+ }
51
+ __name(normalizeModernClientPrefix, "normalizeModernClientPrefix");
52
+ function resolveV2PublicPath(appPublicPath = "/") {
53
+ const publicPath = resolvePublicPath(appPublicPath);
54
+ const prefix = normalizeModernClientPrefix(process.env.APP_MODERN_CLIENT_PREFIX);
55
+ return `${publicPath.replace(/\/$/, "")}/${prefix}/`;
56
+ }
57
+ __name(resolveV2PublicPath, "resolveV2PublicPath");
58
+ function ensureTrailingSlash(value) {
59
+ return value.endsWith("/") ? value : `${value}/`;
60
+ }
61
+ __name(ensureTrailingSlash, "ensureTrailingSlash");
62
+ function rewriteV2AssetPublicPath(html, assetPublicPath) {
63
+ const normalizedAssetPublicPath = ensureTrailingSlash(assetPublicPath);
64
+ const sentinel = `/${MODERN_CLIENT_DIST_DIR}/`;
65
+ if (normalizedAssetPublicPath === sentinel) {
66
+ return html;
67
+ }
68
+ const sentinelPattern = new RegExp(`((?:src|href)=["'])${sentinel.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, "g");
69
+ return html.replace(sentinelPattern, `$1${normalizedAssetPublicPath}`);
70
+ }
71
+ __name(rewriteV2AssetPublicPath, "rewriteV2AssetPublicPath");
72
+ function injectRuntimeScript(html, runtimeScript) {
73
+ const browserCheckerScriptMatch = html.match(/<script\b[^>]*browser-checker\.js[^>]*><\/script>/i);
74
+ if (browserCheckerScriptMatch == null ? void 0 : browserCheckerScriptMatch[0]) {
75
+ return html.replace(browserCheckerScriptMatch[0], `${runtimeScript}
76
+ ${browserCheckerScriptMatch[0]}`);
77
+ }
78
+ const moduleScriptMatch = html.match(/<script\b[^>]*type=["']module["'][^>]*>/i);
79
+ if (moduleScriptMatch == null ? void 0 : moduleScriptMatch[0]) {
80
+ return html.replace(moduleScriptMatch[0], `${runtimeScript}
81
+ ${moduleScriptMatch[0]}`);
82
+ }
83
+ if (html.includes("</head>")) {
84
+ return html.replace("</head>", `${runtimeScript}
85
+ </head>`);
86
+ }
87
+ return `${runtimeScript}
88
+ ${html}`;
89
+ }
90
+ __name(injectRuntimeScript, "injectRuntimeScript");
91
+ function splitCommaSeparatedValues(value, limit) {
92
+ return value.split(",", limit).map((v) => v.trim());
93
+ }
94
+ __name(splitCommaSeparatedValues, "splitCommaSeparatedValues");
95
+ function getHost(req) {
96
+ let host = req.headers["x-forwarded-host"];
97
+ if (!host) {
98
+ host = req.headers[":authority"] || req.headers["host"];
99
+ }
100
+ if (!host) return "";
101
+ host = splitCommaSeparatedValues(host, 1)[0];
102
+ if (host.includes("@")) {
103
+ try {
104
+ host = new URL(`http://${host}`).host;
105
+ } catch (e) {
106
+ return "";
107
+ }
108
+ }
109
+ return host;
110
+ }
111
+ __name(getHost, "getHost");
112
+ function getHostname(req) {
113
+ const host = getHost(req);
114
+ if (!host) return "";
115
+ return host.split(":", 1)[0];
116
+ }
117
+ __name(getHostname, "getHostname");
118
+ // Annotate the CommonJS export names for ESM import in node:
119
+ 0 && (module.exports = {
120
+ MODERN_CLIENT_DIST_DIR,
121
+ getHost,
122
+ getHostname,
123
+ injectRuntimeScript,
124
+ normalizeModernClientPrefix,
125
+ resolvePublicPath,
126
+ resolveV2PublicPath,
127
+ rewriteV2AssetPublicPath
128
+ });
@@ -49,6 +49,7 @@ const _ApplicationVersion = class _ApplicationVersion {
49
49
  app.db.collection({
50
50
  origin: "@nocobase/server",
51
51
  name: "applicationVersion",
52
+ dataCategory: "system",
52
53
  migrationRules: ["schema-only"],
53
54
  dataType: "meta",
54
55
  timestamps: false,
package/lib/index.d.ts CHANGED
@@ -20,9 +20,11 @@ export * from './plugin-manager';
20
20
  export * from './pub-sub-manager';
21
21
  export * from './event-queue';
22
22
  export * from './worker-id-allocator';
23
+ export * from './worker-mode';
23
24
  export * from './redis-connection-manager';
24
25
  export * from './main-data-source';
25
- export declare const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
26
+ export * from './constants';
27
+ export type { LocaleSource, LocaleSourceText } from './locale';
26
28
  export { appendToBuiltInPlugins, findAllPlugins, findBuiltInPlugins, findLocalPlugins, packageNameTrim, } from './plugin-manager/findPackageNames';
27
29
  export { runPluginStaticImports } from './run-plugin-static-imports';
28
30
  export { createContextVariablesScope } from './helper';
package/lib/index.js CHANGED
@@ -37,7 +37,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
37
37
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
38
  var src_exports = {};
39
39
  __export(src_exports, {
40
- OFFICIAL_PLUGIN_PREFIX: () => OFFICIAL_PLUGIN_PREFIX,
41
40
  appendToBuiltInPlugins: () => import_findPackageNames.appendToBuiltInPlugins,
42
41
  createContextVariablesScope: () => import_helper.createContextVariablesScope,
43
42
  default: () => import_application.Application,
@@ -63,15 +62,15 @@ __reExport(src_exports, require("./plugin-manager"), module.exports);
63
62
  __reExport(src_exports, require("./pub-sub-manager"), module.exports);
64
63
  __reExport(src_exports, require("./event-queue"), module.exports);
65
64
  __reExport(src_exports, require("./worker-id-allocator"), module.exports);
65
+ __reExport(src_exports, require("./worker-mode"), module.exports);
66
66
  __reExport(src_exports, require("./redis-connection-manager"), module.exports);
67
67
  __reExport(src_exports, require("./main-data-source"), module.exports);
68
+ __reExport(src_exports, require("./constants"), module.exports);
68
69
  var import_findPackageNames = require("./plugin-manager/findPackageNames");
69
70
  var import_run_plugin_static_imports = require("./run-plugin-static-imports");
70
71
  var import_helper = require("./helper");
71
- const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
72
72
  // Annotate the CommonJS export names for ESM import in node:
73
73
  0 && (module.exports = {
74
- OFFICIAL_PLUGIN_PREFIX,
75
74
  appendToBuiltInPlugins,
76
75
  createContextVariablesScope,
77
76
  findAllPlugins,
@@ -92,6 +91,8 @@ const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
92
91
  ...require("./pub-sub-manager"),
93
92
  ...require("./event-queue"),
94
93
  ...require("./worker-id-allocator"),
94
+ ...require("./worker-mode"),
95
95
  ...require("./redis-connection-manager"),
96
- ...require("./main-data-source")
96
+ ...require("./main-data-source"),
97
+ ...require("./constants")
97
98
  });
@@ -15,6 +15,24 @@ export interface ResourceStorer {
15
15
  }>;
16
16
  reset?: () => Promise<void>;
17
17
  }
18
+ export type LocaleSourceText = {
19
+ text: string;
20
+ module: string;
21
+ };
22
+ export type LocaleSource = {
23
+ title: string;
24
+ sync?: (ctx: any) => Promise<{
25
+ [module: string]: {
26
+ [text: string]: string;
27
+ };
28
+ }>;
29
+ namespace?: string;
30
+ collections?: {
31
+ collection: string;
32
+ fields?: string[];
33
+ getTexts?: (instance: any, options?: any) => LocaleSourceText[] | Promise<LocaleSourceText[]>;
34
+ }[];
35
+ };
18
36
  export declare class Locale {
19
37
  app: Application;
20
38
  cache: Cache;
@@ -23,18 +41,24 @@ export declare class Locale {
23
41
  resourceCached: Map<any, any>;
24
42
  i18nInstances: Map<any, any>;
25
43
  resourceStorers: Registry<ResourceStorer>;
44
+ sources: Registry<LocaleSource>;
26
45
  constructor(app: Application);
27
46
  load(): Promise<void>;
28
47
  reset(): Promise<void>;
29
48
  reload(): Promise<void>;
30
49
  setLocaleFn(name: string, fn: (lang: string) => Promise<any>): void;
31
50
  registerResourceStorer(name: string, storer: ResourceStorer): void;
51
+ registerSource(name: string, source: LocaleSource): void;
52
+ syncSources(ctx: any, types: string[]): Promise<{
53
+ [module: string]: any;
54
+ }>;
32
55
  get(lang: string): Promise<{
33
56
  resources: any;
34
57
  }>;
35
58
  wrapCache(key: string, fn: () => any): Promise<any>;
36
59
  loadResourcesByLang(lang: string): Promise<void>;
37
60
  getCacheResources(lang: string): Promise<any>;
61
+ getBuiltInResources(lang: string): Promise<{}>;
38
62
  getResources(lang: string): Promise<{}>;
39
63
  getI18nInstance(lang: string): Promise<any>;
40
64
  }