@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.
- package/LICENSE +201 -661
- package/README.md +79 -10
- package/lib/aes-encryptor.d.ts +1 -0
- package/lib/aes-encryptor.js +8 -5
- package/lib/ai/create-docs-index.d.ts +13 -0
- package/lib/ai/create-docs-index.js +892 -0
- package/lib/app-supervisor/app-options-factory.d.ts +80 -0
- package/lib/app-supervisor/app-options-factory.js +91 -0
- package/lib/app-supervisor/condition-registry.d.ts +18 -0
- package/lib/app-supervisor/condition-registry.js +60 -0
- package/lib/app-supervisor/db-creator.d.ts +16 -0
- package/lib/app-supervisor/db-creator.js +163 -0
- package/lib/app-supervisor/db-drivers.d.ts +11 -0
- package/lib/app-supervisor/db-drivers.js +52 -0
- package/lib/app-supervisor/index.d.ts +161 -0
- package/lib/app-supervisor/index.js +693 -0
- package/lib/app-supervisor/main-only-adapter.d.ts +37 -0
- package/lib/app-supervisor/main-only-adapter.js +161 -0
- package/lib/app-supervisor/types.d.ts +161 -0
- package/lib/app-supervisor/types.js +24 -0
- package/lib/application.d.ts +3 -1
- package/lib/application.js +10 -6
- package/lib/commands/ai.d.ts +11 -0
- package/lib/commands/ai.js +40 -0
- package/lib/commands/console.js +1 -1
- package/lib/commands/index.js +2 -0
- package/lib/commands/install.js +4 -0
- package/lib/commands/start.js +3 -0
- package/lib/commands/upgrade.js +4 -0
- package/lib/event-queue.d.ts +1 -0
- package/lib/event-queue.js +2 -1
- package/lib/gateway/errors.js +1 -1
- package/lib/gateway/index.d.ts +10 -0
- package/lib/gateway/index.js +181 -18
- package/lib/gateway/ipc-socket-server.js +1 -1
- package/lib/gateway/utils.d.ts +12 -0
- package/lib/gateway/utils.js +84 -0
- package/lib/gateway/ws-server.js +3 -2
- package/lib/helper.js +53 -4
- package/lib/plugin-manager/deps.js +1 -1
- package/lib/plugin-manager/options/resource.d.ts +10 -0
- package/lib/plugin-manager/options/resource.js +90 -36
- package/lib/plugin-manager/plugin-manager.d.ts +1 -0
- package/lib/plugin-manager/plugin-manager.js +37 -40
- package/lib/plugin-manager/utils.js +1 -1
- package/lib/plugin.d.ts +5 -0
- package/lib/plugin.js +66 -1
- package/lib/pub-sub-manager/pub-sub-manager.js +1 -1
- package/lib/redis-connection-manager.d.ts +15 -5
- package/lib/redis-connection-manager.js +117 -24
- package/package.json +19 -18
- package/lib/app-supervisor.d.ts +0 -74
- package/lib/app-supervisor.js +0 -338
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
|
@@ -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
|
|
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
|
|
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
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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 =
|
|
411
|
+
const hasApp = supervisor.hasApp(handleApp);
|
|
269
412
|
if (!hasApp) {
|
|
270
|
-
void
|
|
413
|
+
void supervisor.bootstrapApp(handleApp);
|
|
271
414
|
}
|
|
272
|
-
let appStatus =
|
|
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
|
|
287
|
-
appInstance
|
|
288
|
-
|
|
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
|
-
|
|
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
|
+
});
|
package/lib/gateway/ws-server.js
CHANGED
|
@@ -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().
|
|
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().
|
|
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
|
|
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: {
|
|
@@ -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
|
};
|