@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.
- package/lib/gateway/index.d.ts +10 -0
- package/lib/gateway/index.js +117 -3
- package/lib/gateway/utils.d.ts +12 -0
- package/lib/gateway/utils.js +79 -0
- package/package.json +17 -17
package/lib/gateway/index.d.ts
CHANGED
|
@@ -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>;
|
package/lib/gateway/index.js
CHANGED
|
@@ -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
|
|
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
|
|
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.
|
|
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.
|
|
14
|
-
"@nocobase/actions": "2.0.
|
|
15
|
-
"@nocobase/ai": "2.0.
|
|
16
|
-
"@nocobase/auth": "2.0.
|
|
17
|
-
"@nocobase/cache": "2.0.
|
|
18
|
-
"@nocobase/data-source-manager": "2.0.
|
|
19
|
-
"@nocobase/database": "2.0.
|
|
20
|
-
"@nocobase/evaluators": "2.0.
|
|
21
|
-
"@nocobase/lock-manager": "2.0.
|
|
22
|
-
"@nocobase/logger": "2.0.
|
|
23
|
-
"@nocobase/resourcer": "2.0.
|
|
24
|
-
"@nocobase/sdk": "2.0.
|
|
25
|
-
"@nocobase/snowflake-id": "2.0.
|
|
26
|
-
"@nocobase/telemetry": "2.0.
|
|
27
|
-
"@nocobase/utils": "2.0.
|
|
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": "
|
|
64
|
+
"gitHead": "ce790d46c0a5768ca9618c7d0d77ab8300de75c8"
|
|
65
65
|
}
|