@nocobase/server 2.0.22 → 2.1.0-alpha.10

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.
@@ -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>;
@@ -63,10 +63,16 @@ var import_plugin_manager = require("../plugin-manager");
63
63
  var import_errors = require("./errors");
64
64
  var import_ipc_socket_client = require("./ipc-socket-client");
65
65
  var import_ipc_socket_server = require("./ipc-socket-server");
66
+ var import_utils3 = require("./utils");
66
67
  var import_ws_server = require("./ws-server");
67
68
  var import_node_worker_threads = require("node:worker_threads");
68
69
  var import_node_process = __toESM(require("node:process"));
69
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");
70
76
  function getSocketPath() {
71
77
  const { SOCKET_PATH } = import_node_process.default.env;
72
78
  if ((0, import_path.isAbsolute)(SOCKET_PATH)) {
@@ -88,6 +94,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
88
94
  port = import_node_process.default.env.APP_PORT ? parseInt(import_node_process.default.env.APP_PORT) : null;
89
95
  host = "0.0.0.0";
90
96
  socketPath = (0, import_path.resolve)(import_node_process.default.cwd(), "storage", "gateway.sock");
97
+ v2IndexTemplateCache = null;
91
98
  terminating = false;
92
99
  onTerminate = /* @__PURE__ */ __name(async (signal) => {
93
100
  var _a;
@@ -151,15 +158,31 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
151
158
  this.selectorMiddlewares = new import_utils.Toposort();
152
159
  this.addAppSelectorMiddleware(
153
160
  async (ctx, next) => {
154
- var _a;
161
+ var _a, _b;
155
162
  const { req } = ctx;
156
- 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/`;
157
167
  if (appName) {
158
168
  ctx.resolvedAppName = appName;
159
169
  }
160
170
  if (req.headers["x-app"]) {
161
171
  ctx.resolvedAppName = req.headers["x-app"];
162
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
+ }
163
186
  await next();
164
187
  },
165
188
  {
@@ -222,9 +245,79 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
222
245
  });
223
246
  this.responseError(res, error);
224
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
+ }
225
317
  async requestHandler(req, res) {
226
318
  const { pathname } = (0, import_url.parse)(req.url);
227
- 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();
228
321
  if (pathname.endsWith("/__umi/api/bundle-status")) {
229
322
  res.statusCode = 200;
230
323
  res.end("ok");
@@ -275,6 +368,27 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
275
368
  });
276
369
  }
277
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
+ }
278
392
  if (handleApp !== "main") {
279
393
  const isProxy = await supervisor.proxyWeb(handleApp, req, res);
280
394
  if (isProxy) {
@@ -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,79 @@
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 moduleScriptMatch = html.match(/<script\b[^>]*type=["']module["'][^>]*>/i);
61
+ if (moduleScriptMatch == null ? void 0 : moduleScriptMatch[0]) {
62
+ return html.replace(moduleScriptMatch[0], `${runtimeScript}
63
+ ${moduleScriptMatch[0]}`);
64
+ }
65
+ if (html.includes("</head>")) {
66
+ return html.replace("</head>", `${runtimeScript}
67
+ </head>`);
68
+ }
69
+ return `${runtimeScript}
70
+ ${html}`;
71
+ }
72
+ __name(injectRuntimeScript, "injectRuntimeScript");
73
+ // Annotate the CommonJS export names for ESM import in node:
74
+ 0 && (module.exports = {
75
+ injectRuntimeScript,
76
+ resolvePublicPath,
77
+ resolveV2PublicPath,
78
+ rewriteV2AssetPublicPath
79
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/server",
3
- "version": "2.0.22",
3
+ "version": "2.1.0-alpha.10",
4
4
  "main": "lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -10,21 +10,21 @@
10
10
  "@koa/cors": "^5.0.0",
11
11
  "@koa/multer": "^3.1.0",
12
12
  "@koa/router": "^13.1.0",
13
- "@nocobase/acl": "2.0.22",
14
- "@nocobase/actions": "2.0.22",
15
- "@nocobase/ai": "2.0.22",
16
- "@nocobase/auth": "2.0.22",
17
- "@nocobase/cache": "2.0.22",
18
- "@nocobase/data-source-manager": "2.0.22",
19
- "@nocobase/database": "2.0.22",
20
- "@nocobase/evaluators": "2.0.22",
21
- "@nocobase/lock-manager": "2.0.22",
22
- "@nocobase/logger": "2.0.22",
23
- "@nocobase/resourcer": "2.0.22",
24
- "@nocobase/sdk": "2.0.22",
25
- "@nocobase/snowflake-id": "2.0.22",
26
- "@nocobase/telemetry": "2.0.22",
27
- "@nocobase/utils": "2.0.22",
13
+ "@nocobase/acl": "2.1.0-alpha.10",
14
+ "@nocobase/actions": "2.1.0-alpha.10",
15
+ "@nocobase/ai": "2.1.0-alpha.10",
16
+ "@nocobase/auth": "2.1.0-alpha.10",
17
+ "@nocobase/cache": "2.1.0-alpha.10",
18
+ "@nocobase/data-source-manager": "2.1.0-alpha.10",
19
+ "@nocobase/database": "2.1.0-alpha.10",
20
+ "@nocobase/evaluators": "2.1.0-alpha.10",
21
+ "@nocobase/lock-manager": "2.1.0-alpha.10",
22
+ "@nocobase/logger": "2.1.0-alpha.10",
23
+ "@nocobase/resourcer": "2.1.0-alpha.10",
24
+ "@nocobase/sdk": "2.1.0-alpha.10",
25
+ "@nocobase/snowflake-id": "2.1.0-alpha.10",
26
+ "@nocobase/telemetry": "2.1.0-alpha.10",
27
+ "@nocobase/utils": "2.1.0-alpha.10",
28
28
  "@types/decompress": "4.2.7",
29
29
  "@types/ini": "^1.3.31",
30
30
  "@types/koa-send": "^4.1.3",
@@ -61,5 +61,5 @@
61
61
  "@types/serve-handler": "^6.1.1",
62
62
  "@types/ws": "^8.5.5"
63
63
  },
64
- "gitHead": "7b703580c4bb60f1e5e44c8fd685141bb8b3a47c"
64
+ "gitHead": "ce790d46c0a5768ca9618c7d0d77ab8300de75c8"
65
65
  }