@nocobase/server 1.6.0-alpha.9 → 1.6.0-beta.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.
@@ -0,0 +1,20 @@
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 Application from './application';
11
+ export declare class AesEncryptor {
12
+ private key;
13
+ constructor(key: Buffer);
14
+ encrypt(text: string): Promise<string>;
15
+ decrypt(encryptedText: string): Promise<string>;
16
+ static getOrGenerateKey(keyFilePath: string): Promise<Buffer>;
17
+ static getKeyPath(appName: string): Promise<string>;
18
+ static create(app: Application): Promise<AesEncryptor>;
19
+ }
20
+ export default AesEncryptor;
@@ -0,0 +1,126 @@
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 aes_encryptor_exports = {};
39
+ __export(aes_encryptor_exports, {
40
+ AesEncryptor: () => AesEncryptor,
41
+ default: () => aes_encryptor_default
42
+ });
43
+ module.exports = __toCommonJS(aes_encryptor_exports);
44
+ var import_crypto = __toESM(require("crypto"));
45
+ var import_fs_extra = __toESM(require("fs-extra"));
46
+ var import_path = __toESM(require("path"));
47
+ const _AesEncryptor = class _AesEncryptor {
48
+ key;
49
+ constructor(key) {
50
+ if (key.length !== 32) {
51
+ throw new Error("Key must be 32 bytes for AES-256 encryption.");
52
+ }
53
+ this.key = key;
54
+ }
55
+ async encrypt(text) {
56
+ return new Promise((resolve, reject) => {
57
+ try {
58
+ const iv = import_crypto.default.randomBytes(16);
59
+ const cipher = import_crypto.default.createCipheriv("aes-256-cbc", this.key, iv);
60
+ const encrypted = Buffer.concat([cipher.update(Buffer.from(text, "utf8")), cipher.final()]);
61
+ resolve(iv.toString("hex") + encrypted.toString("hex"));
62
+ } catch (error) {
63
+ reject(error);
64
+ }
65
+ });
66
+ }
67
+ async decrypt(encryptedText) {
68
+ return new Promise((resolve, reject) => {
69
+ try {
70
+ const iv = Buffer.from(encryptedText.slice(0, 32), "hex");
71
+ const encrypted = Buffer.from(encryptedText.slice(32), "hex");
72
+ const decipher = import_crypto.default.createDecipheriv("aes-256-cbc", this.key, iv);
73
+ const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
74
+ resolve(decrypted.toString("utf8"));
75
+ } catch (error) {
76
+ reject(error);
77
+ }
78
+ });
79
+ }
80
+ static async getOrGenerateKey(keyFilePath) {
81
+ try {
82
+ const key = await import_fs_extra.default.readFile(keyFilePath);
83
+ if (key.length !== 32) {
84
+ throw new Error("Invalid key length in file.");
85
+ }
86
+ return key;
87
+ } catch (error) {
88
+ if (error.code === "ENOENT") {
89
+ const key = import_crypto.default.randomBytes(32);
90
+ await import_fs_extra.default.mkdir(import_path.default.dirname(keyFilePath), { recursive: true });
91
+ await import_fs_extra.default.writeFile(keyFilePath, key);
92
+ return key;
93
+ } else {
94
+ throw new Error(`Failed to load key: ${error.message}`);
95
+ }
96
+ }
97
+ }
98
+ static async getKeyPath(appName) {
99
+ const appKeyPath = import_path.default.resolve(process.cwd(), "storage", "apps", appName, "aes_key.dat");
100
+ const appKeyExists = await import_fs_extra.default.exists(appKeyPath);
101
+ if (appKeyExists) {
102
+ return appKeyPath;
103
+ }
104
+ const envKeyPath = import_path.default.resolve(process.cwd(), "storage", "environment-variables", appName, "aes_key.dat");
105
+ const envKeyExists = await import_fs_extra.default.exists(envKeyPath);
106
+ if (envKeyExists) {
107
+ return envKeyPath;
108
+ }
109
+ return appKeyPath;
110
+ }
111
+ static async create(app) {
112
+ let key = process.env.APP_AES_SECRET_KEY;
113
+ if (!key) {
114
+ const keyPath = await this.getKeyPath(app.name);
115
+ key = await _AesEncryptor.getOrGenerateKey(keyPath);
116
+ }
117
+ return new _AesEncryptor(key);
118
+ }
119
+ };
120
+ __name(_AesEncryptor, "AesEncryptor");
121
+ let AesEncryptor = _AesEncryptor;
122
+ var aes_encryptor_default = AesEncryptor;
123
+ // Annotate the CommonJS export names for ESM import in node:
124
+ 0 && (module.exports = {
125
+ AesEncryptor
126
+ });
@@ -31,8 +31,10 @@ import { Plugin } from './plugin';
31
31
  import { InstallOptions, PluginManager } from './plugin-manager';
32
32
  import { PubSubManager, PubSubManagerOptions } from './pub-sub-manager';
33
33
  import { SyncMessageManager } from './sync-message-manager';
34
- import { ServiceContainer } from './service-container';
34
+ import AesEncryptor from './aes-encryptor';
35
35
  import { AuditManager } from './audit-manager';
36
+ import { Environment } from './environment';
37
+ import { ServiceContainer } from './service-container';
36
38
  export type PluginType = string | typeof Plugin;
37
39
  export type PluginConfiguration = PluginType | [PluginType, any];
38
40
  export interface ResourceManagerOptions {
@@ -195,6 +197,8 @@ export declare class Application<StateT = DefaultState, ContextT = DefaultContex
195
197
  * @internal
196
198
  */
197
199
  get maintainingMessage(): string;
200
+ private _env;
201
+ get environment(): Environment;
198
202
  protected _cronJobManager: CronJobManager;
199
203
  get cronJobManager(): CronJobManager;
200
204
  get mainDataSource(): SequelizeDataSource;
@@ -240,6 +244,8 @@ export declare class Application<StateT = DefaultState, ContextT = DefaultContex
240
244
  get name(): string;
241
245
  protected _dataSourceManager: DataSourceManager;
242
246
  get dataSourceManager(): DataSourceManager;
247
+ protected _aesEncryptor: AesEncryptor;
248
+ get aesEncryptor(): AesEncryptor;
243
249
  /**
244
250
  * @internal
245
251
  */
@@ -76,9 +76,11 @@ var import_plugin_manager = require("./plugin-manager");
76
76
  var import_pub_sub_manager = require("./pub-sub-manager");
77
77
  var import_sync_message_manager = require("./sync-message-manager");
78
78
  var import_package = __toESM(require("../package.json"));
79
- var import_service_container = require("./service-container");
80
79
  var import_available_action = require("./acl/available-action");
80
+ var import_aes_encryptor = __toESM(require("./aes-encryptor"));
81
81
  var import_audit_manager = require("./audit-manager");
82
+ var import_environment = require("./environment");
83
+ var import_service_container = require("./service-container");
82
84
  const _Application = class _Application extends import_koa.default {
83
85
  constructor(options) {
84
86
  super();
@@ -164,6 +166,10 @@ const _Application = class _Application extends import_koa.default {
164
166
  get maintainingMessage() {
165
167
  return this._maintainingMessage;
166
168
  }
169
+ _env;
170
+ get environment() {
171
+ return this._env;
172
+ }
167
173
  _cronJobManager;
168
174
  get cronJobManager() {
169
175
  return this._cronJobManager;
@@ -253,6 +259,10 @@ const _Application = class _Application extends import_koa.default {
253
259
  get dataSourceManager() {
254
260
  return this._dataSourceManager;
255
261
  }
262
+ _aesEncryptor;
263
+ get aesEncryptor() {
264
+ return this._aesEncryptor;
265
+ }
256
266
  /**
257
267
  * @internal
258
268
  */
@@ -399,6 +409,7 @@ const _Application = class _Application extends import_koa.default {
399
409
  await oldDb.close();
400
410
  }
401
411
  }
412
+ this._aesEncryptor = await import_aes_encryptor.default.create(this);
402
413
  if (this.cacheManager) {
403
414
  await this.cacheManager.close();
404
415
  }
@@ -836,6 +847,7 @@ const _Application = class _Application extends import_koa.default {
836
847
  }
837
848
  this.createMainDataSource(options);
838
849
  this._cronJobManager = new import_cron_job_manager.CronJobManager(this);
850
+ this._env = new import_environment.Environment();
839
851
  this._cli = this.createCLI();
840
852
  this._i18n = (0, import_helper.createI18n)(options);
841
853
  this.pubSubManager = (0, import_pub_sub_manager.createPubSubManager)(this, options.pubSubManager);
@@ -935,6 +947,7 @@ const _Application = class _Application extends import_koa.default {
935
947
  },
936
948
  logger: this._logger.child({ module: "database" })
937
949
  });
950
+ db.setMaxListeners(100);
938
951
  return db;
939
952
  }
940
953
  };
@@ -0,0 +1,18 @@
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 class Environment {
10
+ private vars;
11
+ setVariable(key: string, value: string): void;
12
+ removeVariable(key: string): void;
13
+ getVariablesAndSecrets(): {};
14
+ getVariables(): {};
15
+ renderJsonTemplate(template: any, options?: {
16
+ omit?: string[];
17
+ }): any;
18
+ }
@@ -0,0 +1,80 @@
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 environment_exports = {};
39
+ __export(environment_exports, {
40
+ Environment: () => Environment
41
+ });
42
+ module.exports = __toCommonJS(environment_exports);
43
+ var import_utils = require("@nocobase/utils");
44
+ var import_lodash = __toESM(require("lodash"));
45
+ const _Environment = class _Environment {
46
+ vars = {};
47
+ setVariable(key, value) {
48
+ this.vars[key] = value;
49
+ }
50
+ removeVariable(key) {
51
+ delete this.vars[key];
52
+ }
53
+ getVariablesAndSecrets() {
54
+ return this.vars;
55
+ }
56
+ getVariables() {
57
+ return this.vars;
58
+ }
59
+ renderJsonTemplate(template, options) {
60
+ if (options == null ? void 0 : options.omit) {
61
+ const omitTemplate = import_lodash.default.omit(template, options.omit);
62
+ const parsed = (0, import_utils.parse)(omitTemplate)({
63
+ $env: this.vars
64
+ });
65
+ for (const key of options.omit) {
66
+ import_lodash.default.set(parsed, key, import_lodash.default.get(template, key));
67
+ }
68
+ return parsed;
69
+ }
70
+ return (0, import_utils.parse)(template)({
71
+ $env: this.vars
72
+ });
73
+ }
74
+ };
75
+ __name(_Environment, "Environment");
76
+ let Environment = _Environment;
77
+ // Annotate the CommonJS export names for ESM import in node:
78
+ 0 && (module.exports = {
79
+ Environment
80
+ });
@@ -66,6 +66,14 @@ var import_ws_server = require("./ws-server");
66
66
  var import_node_worker_threads = require("node:worker_threads");
67
67
  var import_node_process = __toESM(require("node:process"));
68
68
  const compress = (0, import_node_util.promisify)((0, import_compression.default)());
69
+ function getSocketPath() {
70
+ const { SOCKET_PATH } = import_node_process.default.env;
71
+ if ((0, import_path.isAbsolute)(SOCKET_PATH)) {
72
+ return SOCKET_PATH;
73
+ }
74
+ return (0, import_path.resolve)(import_node_process.default.cwd(), SOCKET_PATH);
75
+ }
76
+ __name(getSocketPath, "getSocketPath");
69
77
  const _Gateway = class _Gateway extends import_events.EventEmitter {
70
78
  /**
71
79
  * use main app as default app to handle request
@@ -81,9 +89,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
81
89
  constructor() {
82
90
  super();
83
91
  this.reset();
84
- if (import_node_process.default.env.SOCKET_PATH) {
85
- this.socketPath = (0, import_path.resolve)(import_node_process.default.cwd(), import_node_process.default.env.SOCKET_PATH);
86
- }
92
+ this.socketPath = getSocketPath();
87
93
  }
88
94
  static getInstance(options = {}) {
89
95
  if (!_Gateway.instance) {
@@ -92,7 +98,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
92
98
  return _Gateway.instance;
93
99
  }
94
100
  static async getIPCSocketClient() {
95
- const socketPath = (0, import_path.resolve)(import_node_process.default.cwd(), import_node_process.default.env.SOCKET_PATH || "storage/gateway.sock");
101
+ const socketPath = getSocketPath();
96
102
  try {
97
103
  return await import_ipc_socket_client.IPCSocketClient.getConnection(socketPath);
98
104
  } catch (error) {
@@ -302,6 +308,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
302
308
  await (0, import_plugin_symlink.createStoragePluginsSymlink)();
303
309
  }
304
310
  const mainApp = import_app_supervisor.AppSupervisor.getInstance().bootMainApp(options.mainAppOptions);
311
+ mainApp.setMaxListeners(50);
305
312
  let runArgs = [import_node_process.default.argv, { throwError: true, from: "node" }];
306
313
  if (!import_node_worker_threads.isMainThread) {
307
314
  runArgs = [import_node_worker_threads.workerData.argv, { throwError: true, from: "user" }];
@@ -355,51 +362,6 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
355
362
  }
356
363
  this.server = import_http.default.createServer(this.getCallback());
357
364
  this.wsServer = new import_ws_server.WSServer();
358
- this.wsServer.on("message", async ({ client, message }) => {
359
- const app = await import_app_supervisor.AppSupervisor.getInstance().getApp(client.app);
360
- if (!app) {
361
- return;
362
- }
363
- const parsedMessage = JSON.parse(message.toString());
364
- if (!parsedMessage.type) {
365
- return;
366
- }
367
- if (!app.listenerCount(`ws:setTag`)) {
368
- app.on("ws:setTag", ({ clientId, tagKey, tagValue }) => {
369
- this.wsServer.setClientTag(clientId, tagKey, tagValue);
370
- });
371
- app.on("ws:removeTag", ({ clientId, tagKey }) => {
372
- this.wsServer.removeClientTag(clientId, tagKey);
373
- });
374
- app.on("ws:sendToTag", ({ tagKey, tagValue, message: message2 }) => {
375
- this.wsServer.sendToConnectionsByTags(
376
- [
377
- { tagName: tagKey, tagValue },
378
- { tagName: "app", tagValue: app.name }
379
- ],
380
- message2
381
- );
382
- });
383
- app.on("ws:sendToTags", ({ tags, message: message2 }) => {
384
- this.wsServer.sendToConnectionsByTags(tags, message2);
385
- });
386
- app.on("ws:authorized", ({ clientId, userId }) => {
387
- this.wsServer.sendToConnectionsByTags(
388
- [
389
- { tagName: "userId", tagValue: userId },
390
- { tagName: "app", tagValue: app.name }
391
- ],
392
- { type: "authorized" }
393
- );
394
- });
395
- }
396
- const eventName = `ws:message:${parsedMessage.type}`;
397
- app.emit(eventName, {
398
- clientId: client.id,
399
- tags: [...client.tags],
400
- payload: parsedMessage.payload
401
- });
402
- });
403
365
  this.server.on("upgrade", (request, socket, head) => {
404
366
  const { pathname } = (0, import_url.parse)(request.url);
405
367
  if (pathname === import_node_process.default.env.WS_PATH) {
@@ -28,6 +28,7 @@ export declare class WSServer extends EventEmitter {
28
28
  webSocketClients: Map<string, WebSocketClient>;
29
29
  logger: Logger;
30
30
  constructor();
31
+ bindAppWSEvents(app: any): void;
31
32
  addNewConnection(ws: WebSocketWithId, request: IncomingMessage): WebSocketClient;
32
33
  setClientTag(clientId: string, tagKey: string, tagValue: string): void;
33
34
  removeClientTag(clientId: string, tagKey: string): void;
@@ -44,6 +45,7 @@ export declare class WSServer extends EventEmitter {
44
45
  tagName: string;
45
46
  tagValue: string;
46
47
  }>, sendMessage: object): void;
48
+ sendToClient(clientId: string, sendMessage: object): void;
47
49
  loopThroughConnections(callback: (client: WebSocketClient) => void): void;
48
50
  close(): void;
49
51
  }
@@ -133,6 +133,57 @@ const _WSServer = class _WSServer extends import_events.default {
133
133
  }
134
134
  });
135
135
  });
136
+ import_app_supervisor.AppSupervisor.getInstance().on("afterAppAdded", (app) => {
137
+ this.bindAppWSEvents(app);
138
+ });
139
+ this.on("message", async ({ client, message }) => {
140
+ const app = await import_app_supervisor.AppSupervisor.getInstance().getApp(client.app);
141
+ if (!app) {
142
+ return;
143
+ }
144
+ const parsedMessage = JSON.parse(message.toString());
145
+ if (!parsedMessage.type) {
146
+ return;
147
+ }
148
+ const eventName = `ws:message:${parsedMessage.type}`;
149
+ app.emit(eventName, {
150
+ clientId: client.id,
151
+ tags: [...client.tags],
152
+ payload: parsedMessage.payload
153
+ });
154
+ });
155
+ }
156
+ bindAppWSEvents(app) {
157
+ if (app.listenerCount("ws:setTag") > 0) {
158
+ return;
159
+ }
160
+ app.on("ws:setTag", ({ clientId, tagKey, tagValue }) => {
161
+ this.setClientTag(clientId, tagKey, tagValue);
162
+ });
163
+ app.on("ws:removeTag", ({ clientId, tagKey }) => {
164
+ this.removeClientTag(clientId, tagKey);
165
+ });
166
+ app.on("ws:sendToTag", ({ tagKey, tagValue, message }) => {
167
+ this.sendToConnectionsByTags(
168
+ [
169
+ { tagName: tagKey, tagValue },
170
+ { tagName: "app", tagValue: app.name }
171
+ ],
172
+ message
173
+ );
174
+ });
175
+ app.on("ws:sendToClient", ({ clientId, message }) => {
176
+ this.sendToClient(clientId, message);
177
+ });
178
+ app.on("ws:sendToCurrentApp", ({ message }) => {
179
+ this.sendToConnectionsByTag("app", app.name, message);
180
+ });
181
+ app.on("ws:sendToTags", ({ tags, message }) => {
182
+ this.sendToConnectionsByTags(tags, message);
183
+ });
184
+ app.on("ws:authorized", ({ clientId, userId }) => {
185
+ this.sendToClient(clientId, { type: "authorized" });
186
+ });
136
187
  }
137
188
  addNewConnection(ws, request) {
138
189
  const id = (0, import_nanoid.nanoid)();
@@ -149,6 +200,9 @@ const _WSServer = class _WSServer extends import_events.default {
149
200
  }
150
201
  setClientTag(clientId, tagKey, tagValue) {
151
202
  const client = this.webSocketClients.get(clientId);
203
+ if (!client) {
204
+ return;
205
+ }
152
206
  client.tags.add(`${tagKey}#${tagValue}`);
153
207
  console.log(`client tags: ${Array.from(client.tags)}`);
154
208
  }
@@ -173,26 +227,6 @@ const _WSServer = class _WSServer extends import_events.default {
173
227
  if (!hasApp) {
174
228
  import_app_supervisor.AppSupervisor.getInstance().bootStrapApp(handleAppName);
175
229
  }
176
- const appStatus = import_app_supervisor.AppSupervisor.getInstance().getAppStatus(handleAppName, "initializing");
177
- if (appStatus === "not_found") {
178
- this.sendMessageToConnection(client, {
179
- type: "maintaining",
180
- payload: getPayloadByErrorCode("APP_NOT_FOUND", { appName: handleAppName })
181
- });
182
- return;
183
- }
184
- if (appStatus === "initializing") {
185
- this.sendMessageToConnection(client, {
186
- type: "maintaining",
187
- payload: getPayloadByErrorCode("APP_INITIALIZING", { appName: handleAppName })
188
- });
189
- return;
190
- }
191
- const app = await import_app_supervisor.AppSupervisor.getInstance().getApp(handleAppName);
192
- this.sendMessageToConnection(client, {
193
- type: "maintaining",
194
- payload: getPayloadByErrorCode(appStatus, { app })
195
- });
196
230
  }
197
231
  removeConnection(id) {
198
232
  console.log(`client disconnected ${id}`);
@@ -217,6 +251,12 @@ const _WSServer = class _WSServer extends import_events.default {
217
251
  }
218
252
  });
219
253
  }
254
+ sendToClient(clientId, sendMessage) {
255
+ const client = this.webSocketClients.get(clientId);
256
+ if (client) {
257
+ this.sendMessageToConnection(client, sendMessage);
258
+ }
259
+ }
220
260
  loopThroughConnections(callback) {
221
261
  this.webSocketClients.forEach((client) => {
222
262
  callback(client);
package/lib/helper.js CHANGED
@@ -56,6 +56,7 @@ var import_i18next = __toESM(require("i18next"));
56
56
  var import_koa_bodyparser = __toESM(require("koa-bodyparser"));
57
57
  var import_perf_hooks = require("perf_hooks");
58
58
  var import_data_wrapping = require("./middlewares/data-wrapping");
59
+ var import_extract_client_ip = require("./middlewares/extract-client-ip");
59
60
  var import_i18n = require("./middlewares/i18n");
60
61
  function createI18n(options) {
61
62
  const instance = import_i18next.default.createInstance();
@@ -121,6 +122,7 @@ function registerMiddlewares(app, options) {
121
122
  app.use((0, import_data_wrapping.dataWrapping)(), { tag: "dataWrapping", after: "cors" });
122
123
  }
123
124
  app.use(app.dataSourceManager.middleware(), { tag: "dataSource", after: "dataWrapping" });
125
+ app.use((0, import_extract_client_ip.extractClientIp)(), { tag: "extractClientIp", before: "cors" });
124
126
  }
125
127
  __name(registerMiddlewares, "registerMiddlewares");
126
128
  const createAppProxy = /* @__PURE__ */ __name((app) => {
@@ -49,6 +49,7 @@ const _ApplicationVersion = class _ApplicationVersion {
49
49
  app.db.collection({
50
50
  origin: "@nocobase/server",
51
51
  name: "applicationVersion",
52
+ migrationRules: ["schema-only"],
52
53
  dataType: "meta",
53
54
  timestamps: false,
54
55
  dumpRules: "required",
package/lib/index.d.ts CHANGED
@@ -6,15 +6,16 @@
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 * from './aes-encryptor';
9
10
  export * from './app-supervisor';
10
11
  export * from './application';
11
12
  export { Application as default } from './application';
13
+ export * from './audit-manager';
12
14
  export * from './gateway';
13
15
  export * as middlewares from './middlewares';
14
16
  export * from './migration';
15
17
  export * from './plugin';
16
18
  export * from './plugin-manager';
17
- export * from './audit-manager';
18
19
  export * from './pub-sub-manager';
19
20
  export declare const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
20
21
  export { appendToBuiltInPlugins, findAllPlugins, findBuiltInPlugins, findLocalPlugins, packageNameTrim, } from './plugin-manager/findPackageNames';
package/lib/index.js CHANGED
@@ -48,15 +48,16 @@ __export(src_exports, {
48
48
  runPluginStaticImports: () => import_run_plugin_static_imports.runPluginStaticImports
49
49
  });
50
50
  module.exports = __toCommonJS(src_exports);
51
+ __reExport(src_exports, require("./aes-encryptor"), module.exports);
51
52
  __reExport(src_exports, require("./app-supervisor"), module.exports);
52
53
  __reExport(src_exports, require("./application"), module.exports);
53
54
  var import_application = require("./application");
55
+ __reExport(src_exports, require("./audit-manager"), module.exports);
54
56
  __reExport(src_exports, require("./gateway"), module.exports);
55
57
  var middlewares = __toESM(require("./middlewares"));
56
58
  __reExport(src_exports, require("./migration"), module.exports);
57
59
  __reExport(src_exports, require("./plugin"), module.exports);
58
60
  __reExport(src_exports, require("./plugin-manager"), module.exports);
59
- __reExport(src_exports, require("./audit-manager"), module.exports);
60
61
  __reExport(src_exports, require("./pub-sub-manager"), module.exports);
61
62
  var import_findPackageNames = require("./plugin-manager/findPackageNames");
62
63
  var import_run_plugin_static_imports = require("./run-plugin-static-imports");
@@ -71,12 +72,13 @@ const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
71
72
  middlewares,
72
73
  packageNameTrim,
73
74
  runPluginStaticImports,
75
+ ...require("./aes-encryptor"),
74
76
  ...require("./app-supervisor"),
75
77
  ...require("./application"),
78
+ ...require("./audit-manager"),
76
79
  ...require("./gateway"),
77
80
  ...require("./migration"),
78
81
  ...require("./plugin"),
79
82
  ...require("./plugin-manager"),
80
- ...require("./audit-manager"),
81
83
  ...require("./pub-sub-manager")
82
84
  });
@@ -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
+ import { Context, Next } from '@nocobase/actions';
10
+ export declare function extractClientIp(): (ctx: Context, next: Next) => Promise<void>;
@@ -0,0 +1,46 @@
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 extract_client_ip_exports = {};
29
+ __export(extract_client_ip_exports, {
30
+ extractClientIp: () => extractClientIp
31
+ });
32
+ module.exports = __toCommonJS(extract_client_ip_exports);
33
+ function extractClientIp() {
34
+ return /* @__PURE__ */ __name(async function extractClientIp2(ctx, next) {
35
+ const forwardedFor = ctx.get("X-Forwarded-For");
36
+ const ipArray = forwardedFor ? forwardedFor.split(",") : [];
37
+ const clientIp = ipArray.length > 0 ? ipArray[0].trim() : ctx.request.ip;
38
+ ctx.state.clientIp = clientIp;
39
+ await next();
40
+ }, "extractClientIp");
41
+ }
42
+ __name(extractClientIp, "extractClientIp");
43
+ // Annotate the CommonJS export names for ESM import in node:
44
+ 0 && (module.exports = {
45
+ extractClientIp
46
+ });
@@ -7,4 +7,5 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
  export * from './data-wrapping';
10
+ export * from './extract-client-ip';
10
11
  export { parseVariables } from './parse-variables';
@@ -31,9 +31,11 @@ __export(middlewares_exports, {
31
31
  });
32
32
  module.exports = __toCommonJS(middlewares_exports);
33
33
  __reExport(middlewares_exports, require("./data-wrapping"), module.exports);
34
+ __reExport(middlewares_exports, require("./extract-client-ip"), module.exports);
34
35
  var import_parse_variables = require("./parse-variables");
35
36
  // Annotate the CommonJS export names for ESM import in node:
36
37
  0 && (module.exports = {
37
38
  parseVariables,
38
- ...require("./data-wrapping")
39
+ ...require("./data-wrapping"),
40
+ ...require("./extract-client-ip")
39
41
  });
@@ -33,6 +33,7 @@ var import_database = require("@nocobase/database");
33
33
  var collection_default = (0, import_database.defineCollection)({
34
34
  name: "applicationPlugins",
35
35
  dumpRules: "required",
36
+ migrationRules: ["overwrite", "schema-only"],
36
37
  repository: "PluginManagerRepository",
37
38
  origin: "@nocobase/server",
38
39
  fields: [
@@ -89,9 +89,9 @@ export declare class PluginManager {
89
89
  addPreset(plugin: string | typeof Plugin, options?: any): void;
90
90
  getPlugins(): Map<typeof Plugin, Plugin<any>>;
91
91
  getAliases(): IterableIterator<string>;
92
- get(name: string | typeof Plugin): Plugin<any>;
92
+ get<T extends Plugin>(name: string | typeof Plugin | (new () => T)): T;
93
93
  has(name: string | typeof Plugin): boolean;
94
- del(name: string | typeof Plugin): void;
94
+ del(name: any): void;
95
95
  create(pluginName: string, options?: {
96
96
  forceRecreate?: boolean;
97
97
  }): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/server",
3
- "version": "1.6.0-alpha.9",
3
+ "version": "1.6.0-beta.10",
4
4
  "main": "lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "license": "AGPL-3.0",
@@ -10,19 +10,19 @@
10
10
  "@koa/cors": "^3.1.0",
11
11
  "@koa/multer": "^3.0.2",
12
12
  "@koa/router": "^9.4.0",
13
- "@nocobase/acl": "1.6.0-alpha.9",
14
- "@nocobase/actions": "1.6.0-alpha.9",
15
- "@nocobase/auth": "1.6.0-alpha.9",
16
- "@nocobase/cache": "1.6.0-alpha.9",
17
- "@nocobase/data-source-manager": "1.6.0-alpha.9",
18
- "@nocobase/database": "1.6.0-alpha.9",
19
- "@nocobase/evaluators": "1.6.0-alpha.9",
20
- "@nocobase/lock-manager": "1.6.0-alpha.9",
21
- "@nocobase/logger": "1.6.0-alpha.9",
22
- "@nocobase/resourcer": "1.6.0-alpha.9",
23
- "@nocobase/sdk": "1.6.0-alpha.9",
24
- "@nocobase/telemetry": "1.6.0-alpha.9",
25
- "@nocobase/utils": "1.6.0-alpha.9",
13
+ "@nocobase/acl": "1.6.0-beta.10",
14
+ "@nocobase/actions": "1.6.0-beta.10",
15
+ "@nocobase/auth": "1.6.0-beta.10",
16
+ "@nocobase/cache": "1.6.0-beta.10",
17
+ "@nocobase/data-source-manager": "1.6.0-beta.10",
18
+ "@nocobase/database": "1.6.0-beta.10",
19
+ "@nocobase/evaluators": "1.6.0-beta.10",
20
+ "@nocobase/lock-manager": "1.6.0-beta.10",
21
+ "@nocobase/logger": "1.6.0-beta.10",
22
+ "@nocobase/resourcer": "1.6.0-beta.10",
23
+ "@nocobase/sdk": "1.6.0-beta.10",
24
+ "@nocobase/telemetry": "1.6.0-beta.10",
25
+ "@nocobase/utils": "1.6.0-beta.10",
26
26
  "@types/decompress": "4.2.7",
27
27
  "@types/ini": "^1.3.31",
28
28
  "@types/koa-send": "^4.1.3",
@@ -56,5 +56,5 @@
56
56
  "@types/serve-handler": "^6.1.1",
57
57
  "@types/ws": "^8.5.5"
58
58
  },
59
- "gitHead": "c6136fc6c9a2daab33fb1a20716cd9768e9a147f"
59
+ "gitHead": "72684ad7261e46b67969ecc4db0f1bcbea545a8d"
60
60
  }