redux-cluster 1.9.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +345 -471
  3. package/dist/cjs/core/backup.d.ts +10 -0
  4. package/dist/cjs/core/backup.d.ts.map +1 -0
  5. package/dist/cjs/core/backup.js +166 -0
  6. package/dist/cjs/core/redux-cluster.d.ts +47 -0
  7. package/dist/cjs/core/redux-cluster.d.ts.map +1 -0
  8. package/dist/cjs/core/redux-cluster.js +367 -0
  9. package/dist/cjs/index.d.ts +22 -0
  10. package/dist/cjs/index.d.ts.map +1 -0
  11. package/dist/cjs/index.js +43 -0
  12. package/dist/cjs/network/client.d.ts +23 -0
  13. package/dist/cjs/network/client.d.ts.map +1 -0
  14. package/dist/cjs/network/client.js +251 -0
  15. package/dist/cjs/network/server.d.ts +39 -0
  16. package/dist/cjs/network/server.d.ts.map +1 -0
  17. package/dist/cjs/network/server.js +439 -0
  18. package/dist/cjs/package.json +1 -0
  19. package/dist/cjs/types/index.d.ts +125 -0
  20. package/dist/cjs/types/index.d.ts.map +1 -0
  21. package/dist/cjs/types/index.js +20 -0
  22. package/dist/cjs/utils/crypto.d.ts +22 -0
  23. package/dist/cjs/utils/crypto.d.ts.map +1 -0
  24. package/dist/cjs/utils/crypto.js +404 -0
  25. package/dist/esm/core/backup.d.ts +10 -0
  26. package/dist/esm/core/backup.d.ts.map +1 -0
  27. package/dist/esm/core/backup.js +134 -0
  28. package/dist/esm/core/redux-cluster.d.ts +47 -0
  29. package/dist/esm/core/redux-cluster.d.ts.map +1 -0
  30. package/dist/esm/core/redux-cluster.js +376 -0
  31. package/dist/esm/index.d.ts +22 -0
  32. package/dist/esm/index.d.ts.map +1 -0
  33. package/dist/esm/index.js +25 -0
  34. package/dist/esm/network/client.d.ts +23 -0
  35. package/dist/esm/network/client.d.ts.map +1 -0
  36. package/dist/esm/network/client.js +221 -0
  37. package/dist/esm/network/server.d.ts +39 -0
  38. package/dist/esm/network/server.d.ts.map +1 -0
  39. package/dist/esm/network/server.js +408 -0
  40. package/dist/esm/package.json +1 -0
  41. package/dist/esm/types/index.d.ts +125 -0
  42. package/dist/esm/types/index.d.ts.map +1 -0
  43. package/dist/esm/types/index.js +17 -0
  44. package/dist/esm/utils/crypto.d.ts +22 -0
  45. package/dist/esm/utils/crypto.d.ts.map +1 -0
  46. package/dist/esm/utils/crypto.js +351 -0
  47. package/package.json +115 -42
  48. package/index.js +0 -678
  49. package/test.auto.js +0 -94
  50. package/test.auto.proc1.js +0 -97
  51. package/test.auto.proc2.js +0 -85
  52. package/test.visual.client.highload.js +0 -102
  53. package/test.visual.client.js +0 -103
  54. package/test.visual.error.js +0 -45
  55. package/test.visual.js +0 -97
  56. package/test.visual.server.highload.js +0 -102
  57. package/test.visual.server.js +0 -103
@@ -0,0 +1,39 @@
1
+ import { ServerSettings, ReduxClusterStore, ClusterMessage, ClusterSocket } from "../types";
2
+ export declare class ClusterServer {
3
+ private store;
4
+ private settings;
5
+ readonly uid: string;
6
+ readonly sockets: Record<string, ClusterSocket>;
7
+ readonly database: Record<string, string>;
8
+ readonly ip2ban: Record<string, {
9
+ time: number;
10
+ count: number;
11
+ }>;
12
+ private readonly ip2banTimeout;
13
+ private readonly ip2banGC;
14
+ private server;
15
+ private unsubscribe?;
16
+ private shouldAutoRestart;
17
+ constructor(store: ReduxClusterStore, settings?: ServerSettings);
18
+ private setupDatabase;
19
+ private setupBanSystem;
20
+ private cleanupBannedIPs;
21
+ private setupServer;
22
+ private getListenOptions;
23
+ private startListening;
24
+ private handleNewConnection;
25
+ private isIPBanned;
26
+ private rejectConnection;
27
+ private setupSocket;
28
+ private setupSocketPipeline;
29
+ private handleSocketMessage;
30
+ private handleAuthentication;
31
+ private recordFailedLogin;
32
+ private closeSocket;
33
+ private setupStoreIntegration;
34
+ sendtoall(message?: ClusterMessage): void;
35
+ ip2banGCStop(): void;
36
+ private cleanup;
37
+ close(): Promise<void>;
38
+ }
39
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/network/server.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,cAAc,EAEd,aAAa,EACd,MAAM,UAAU,CAAC;AAGlB,qBAAa,aAAa;IAatB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAblB,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAM;IAC5D,SAAgB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IACtD,SAAgB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAM;IAE7E,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAY;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,WAAW,CAAC,CAAa;IACjC,OAAO,CAAC,iBAAiB,CAAiB;gBAGhC,KAAK,EAAE,iBAAiB,EACxB,QAAQ,GAAE,cAAmB;IAavC,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,WAAW;IA8CnB,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,mBAAmB;IAmB3B,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,WAAW;IAyBnB,OAAO,CAAC,mBAAmB;IA2D3B,OAAO,CAAC,mBAAmB;IA0C3B,OAAO,CAAC,oBAAoB;IAyD5B,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,qBAAqB;IActB,SAAS,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI;IAezC,YAAY,IAAI,IAAI;IAI3B,OAAO,CAAC,OAAO;IAQR,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAiD9B"}
@@ -0,0 +1,408 @@
1
+ import * as net from "net";
2
+ import * as os from "os";
3
+ import * as path from "path";
4
+ import * as fs from "fs";
5
+ import * as zlib from "zlib";
6
+ import * as stream from "stream";
7
+ import * as crypto from "crypto";
8
+ import { MessageType, } from "../types";
9
+ import { hasher } from "../utils/crypto";
10
+ export class ClusterServer {
11
+ store;
12
+ settings;
13
+ uid;
14
+ sockets = {};
15
+ database = {};
16
+ ip2ban = {};
17
+ ip2banTimeout = 10800000; // 3 hours
18
+ ip2banGC;
19
+ server;
20
+ unsubscribe;
21
+ shouldAutoRestart = true;
22
+ constructor(store, settings = {}) {
23
+ this.store = store;
24
+ this.settings = settings;
25
+ this.uid = crypto.randomUUID();
26
+ this.setupDatabase();
27
+ this.setupBanSystem();
28
+ this.setupServer();
29
+ this.setupStoreIntegration();
30
+ this.ip2banGC = setInterval(() => {
31
+ this.cleanupBannedIPs();
32
+ }, 60000);
33
+ }
34
+ setupDatabase() {
35
+ if (this.settings.logins) {
36
+ for (const login in this.settings.logins) {
37
+ const hashedLogin = hasher(`REDUX_CLUSTER${login}`);
38
+ const hashedPassword = hasher(`REDUX_CLUSTER${this.settings.logins[login]}`);
39
+ if (hashedLogin && hashedPassword) {
40
+ this.database[hashedLogin] = hashedPassword;
41
+ }
42
+ }
43
+ }
44
+ }
45
+ setupBanSystem() {
46
+ // IP ban system is initialized in constructor
47
+ }
48
+ cleanupBannedIPs() {
49
+ const now = Date.now();
50
+ for (const key in this.ip2ban) {
51
+ if (this.ip2ban[key].time + this.ip2banTimeout < now) {
52
+ delete this.ip2ban[key];
53
+ }
54
+ }
55
+ }
56
+ setupServer() {
57
+ const listenOptions = this.getListenOptions();
58
+ this.server = net.createServer((socket) => {
59
+ this.handleNewConnection(socket);
60
+ });
61
+ this.server.on("listening", () => {
62
+ this.store.connected = true;
63
+ this.store.sendtoall({
64
+ _msg: MessageType.CONN_STATUS,
65
+ _hash: this.store.RCHash,
66
+ _connected: true,
67
+ });
68
+ });
69
+ this.server.on("close", () => {
70
+ this.store.connected = false;
71
+ this.store.sendtoall({
72
+ _msg: MessageType.CONN_STATUS,
73
+ _hash: this.store.RCHash,
74
+ _connected: false,
75
+ });
76
+ this.cleanup();
77
+ // Auto-restart server after 10 seconds
78
+ if (this.shouldAutoRestart) {
79
+ setTimeout(() => {
80
+ new ClusterServer(this.store, this.settings);
81
+ }, 10000);
82
+ }
83
+ });
84
+ this.server.on("error", (err) => {
85
+ this.store.stderr(`ReduxCluster.createServer socket error: ${err.message}`);
86
+ if (typeof this.server.close === "function") {
87
+ this.server.close();
88
+ }
89
+ });
90
+ this.startListening(listenOptions);
91
+ }
92
+ getListenOptions() {
93
+ const defaultOptions = { port: 10001 };
94
+ if (typeof this.settings.path === "string") {
95
+ switch (os.platform()) {
96
+ case "win32":
97
+ return { path: path.join("\\\\?\\pipe", this.settings.path) };
98
+ default:
99
+ return { path: path.join(this.settings.path) };
100
+ }
101
+ }
102
+ const options = { ...defaultOptions };
103
+ if (typeof this.settings.host === "string") {
104
+ options.host = this.settings.host;
105
+ }
106
+ if (typeof this.settings.port === "number") {
107
+ options.port = this.settings.port;
108
+ }
109
+ return options;
110
+ }
111
+ startListening(options) {
112
+ if (typeof options.path === "string") {
113
+ // Remove existing socket file
114
+ fs.unlink(options.path, (err) => {
115
+ if (err &&
116
+ !err.message.toLowerCase().includes("no such file or directory")) {
117
+ this.store.stderr(`ReduxCluster.createServer socket error: ${err.message}`);
118
+ }
119
+ this.server.listen(options);
120
+ });
121
+ }
122
+ else {
123
+ this.server.listen(options);
124
+ }
125
+ }
126
+ handleNewConnection(socket) {
127
+ // Hash IP address for security using hasher function
128
+ const clientIP = socket.remoteAddress
129
+ ? hasher(socket.remoteAddress)
130
+ : "";
131
+ const uid = crypto.randomUUID();
132
+ const clusterSocket = socket;
133
+ clusterSocket.uid = uid;
134
+ // Check if IP is banned
135
+ if (this.isIPBanned(clientIP)) {
136
+ this.rejectConnection(clusterSocket, true);
137
+ return;
138
+ }
139
+ this.setupSocket(clusterSocket, clientIP);
140
+ }
141
+ isIPBanned(ip) {
142
+ if (!ip || !this.ip2ban[ip])
143
+ return false;
144
+ const banInfo = this.ip2ban[ip];
145
+ const now = Date.now();
146
+ return banInfo.count >= 5 && banInfo.time + this.ip2banTimeout > now;
147
+ }
148
+ rejectConnection(socket, banned = false) {
149
+ // Create rejection message
150
+ const rejectionMessage = {
151
+ _msg: MessageType.SOCKET_AUTH_STATE,
152
+ _hash: this.store.RCHash,
153
+ _value: false,
154
+ ...(banned && { _banned: true }),
155
+ };
156
+ // Manually serialize and compress since custom write is not set up yet
157
+ try {
158
+ const compressed = zlib.gzipSync(Buffer.from(JSON.stringify(rejectionMessage)));
159
+ // Use the native write method directly, not the overridden one
160
+ const originalWrite = socket.writeNEW || socket.write.bind(socket);
161
+ originalWrite(compressed);
162
+ }
163
+ catch (err) {
164
+ this.store.stderr(`ReduxCluster.rejectConnection error: ${err.message}`);
165
+ }
166
+ this.closeSocket(socket);
167
+ }
168
+ setupSocket(socket, clientIP) {
169
+ // Override write method for object mode + compression
170
+ socket.writeNEW = socket.write;
171
+ socket.write = (data) => {
172
+ try {
173
+ const compressed = zlib.gzipSync(Buffer.from(JSON.stringify(data)));
174
+ return socket.writeNEW(compressed);
175
+ }
176
+ catch (err) {
177
+ this.store.stderr(`ReduxCluster.createServer write error: ${err.message}`);
178
+ return false;
179
+ }
180
+ };
181
+ socket.on("error", (err) => {
182
+ this.store.stderr(`ReduxCluster.createServer client error: ${err.message}`);
183
+ this.closeSocket(socket);
184
+ });
185
+ this.setupSocketPipeline(socket, clientIP);
186
+ }
187
+ setupSocketPipeline(socket, clientIP) {
188
+ // Create processing pipeline
189
+ const mbstring = new stream.Transform({
190
+ transform(buffer, encoding, callback) {
191
+ this.push(buffer);
192
+ callback();
193
+ },
194
+ });
195
+ mbstring.setEncoding("utf8");
196
+ const gunzipper = zlib.createGunzip();
197
+ // For now, we'll create a simple parser instead of using external library
198
+ const parser = new stream.Transform({
199
+ transform(chunk, encoding, callback) {
200
+ try {
201
+ const data = JSON.parse(chunk.toString());
202
+ this.push(data);
203
+ }
204
+ catch {
205
+ // Invalid JSON, ignore
206
+ }
207
+ callback();
208
+ },
209
+ objectMode: true,
210
+ });
211
+ const eventHandler = new stream.Writable({
212
+ write: (data, encoding, callback) => {
213
+ this.handleSocketMessage(data, socket, clientIP);
214
+ callback();
215
+ },
216
+ objectMode: true,
217
+ });
218
+ // Setup error handlers
219
+ [gunzipper, mbstring, parser, eventHandler].forEach((stream) => {
220
+ stream.on("error", (err) => {
221
+ this.store.stderr(`ReduxCluster.createServer stream error: ${err.message}`);
222
+ });
223
+ });
224
+ // Connect pipeline
225
+ socket.pipe(gunzipper).pipe(mbstring).pipe(parser).pipe(eventHandler);
226
+ }
227
+ handleSocketMessage(data, socket, clientIP) {
228
+ if (data._hash !== this.store.RCHash)
229
+ return;
230
+ switch (data._msg) {
231
+ case MessageType.MSG_TO_MASTER:
232
+ if (this.sockets[socket.uid]) {
233
+ if (data._action.type === MessageType.SYNC) {
234
+ throw new Error("Please don't use REDUX_CLUSTER_SYNC action type!");
235
+ }
236
+ // Apply action to server state
237
+ // This will automatically trigger sendActionsToNodes via reducer
238
+ this.store.dispatch(data._action);
239
+ }
240
+ break;
241
+ case MessageType.START:
242
+ if (this.sockets[socket.uid]) {
243
+ socket.write({
244
+ _msg: MessageType.MSG_TO_WORKER,
245
+ _hash: this.store.RCHash,
246
+ _action: {
247
+ type: MessageType.SYNC,
248
+ payload: this.store.getState(),
249
+ },
250
+ });
251
+ }
252
+ break;
253
+ case MessageType.SOCKET_AUTH:
254
+ this.handleAuthentication(data, socket, clientIP);
255
+ break;
256
+ default:
257
+ // Ignore unknown message types
258
+ break;
259
+ }
260
+ }
261
+ handleAuthentication(data, socket, clientIP) {
262
+ const { _login, _password } = data;
263
+ // If no authentication is configured (empty database), allow all connections
264
+ if (Object.keys(this.database).length === 0) {
265
+ // No authentication required
266
+ this.sockets[socket.uid] = socket;
267
+ socket.write({
268
+ _msg: MessageType.SOCKET_AUTH_STATE,
269
+ _hash: this.store.RCHash,
270
+ _value: true,
271
+ });
272
+ return;
273
+ }
274
+ if (typeof _login !== "undefined" &&
275
+ typeof _password !== "undefined" &&
276
+ typeof this.database[_login] !== "undefined" &&
277
+ this.database[_login] === _password) {
278
+ // Successful authentication
279
+ this.sockets[socket.uid] = socket;
280
+ // Clear ban if exists
281
+ if (clientIP && this.ip2ban[clientIP]) {
282
+ delete this.ip2ban[clientIP];
283
+ }
284
+ // Use the custom write method that should be set up by now
285
+ socket.write({
286
+ _msg: MessageType.SOCKET_AUTH_STATE,
287
+ _hash: this.store.RCHash,
288
+ _value: true,
289
+ });
290
+ }
291
+ else {
292
+ // Failed authentication
293
+ if (clientIP) {
294
+ this.recordFailedLogin(clientIP);
295
+ }
296
+ // Use the custom write method that should be set up by now
297
+ socket.write({
298
+ _msg: MessageType.SOCKET_AUTH_STATE,
299
+ _hash: this.store.RCHash,
300
+ _value: false,
301
+ });
302
+ this.closeSocket(socket);
303
+ }
304
+ }
305
+ recordFailedLogin(ip) {
306
+ let count = 0;
307
+ if (this.ip2ban[ip]) {
308
+ count = this.ip2ban[ip].count;
309
+ if (count >= 5)
310
+ count = 0; // Reset on timeout
311
+ }
312
+ this.ip2ban[ip] = {
313
+ time: Date.now(),
314
+ count: count + 1,
315
+ };
316
+ }
317
+ closeSocket(socket) {
318
+ if (typeof socket.end === "function") {
319
+ socket.end();
320
+ }
321
+ if (socket.uid && this.sockets[socket.uid]) {
322
+ delete this.sockets[socket.uid];
323
+ }
324
+ }
325
+ setupStoreIntegration() {
326
+ // Register with store if in action mode
327
+ if (this.store.mode === "action") {
328
+ this.store.allsock[this.uid] = this;
329
+ }
330
+ // Subscribe to store changes in snapshot mode
331
+ this.unsubscribe = this.store.subscribe(() => {
332
+ if (this.store.mode === "snapshot") {
333
+ this.sendtoall();
334
+ }
335
+ });
336
+ }
337
+ sendtoall(message) {
338
+ const msg = message || {
339
+ _msg: MessageType.MSG_TO_WORKER,
340
+ _hash: this.store.RCHash,
341
+ _action: {
342
+ type: MessageType.SYNC,
343
+ payload: this.store.getState(),
344
+ },
345
+ };
346
+ for (const uid in this.sockets) {
347
+ this.sockets[uid].write(msg);
348
+ }
349
+ }
350
+ ip2banGCStop() {
351
+ clearInterval(this.ip2banGC);
352
+ }
353
+ cleanup() {
354
+ if (this.unsubscribe) {
355
+ this.unsubscribe();
356
+ }
357
+ this.ip2banGCStop();
358
+ delete this.store.allsock[this.uid];
359
+ }
360
+ close() {
361
+ return new Promise((resolve) => {
362
+ // Prevent the automatic restart handler from creating a new server
363
+ this.shouldAutoRestart = false;
364
+ // Close all connected sockets first
365
+ Object.values(this.sockets).forEach((socket) => {
366
+ if (socket) {
367
+ try {
368
+ this.closeSocket(socket);
369
+ }
370
+ catch {
371
+ // ignore
372
+ }
373
+ }
374
+ });
375
+ // Clear sockets registry
376
+ Object.keys(this.sockets).forEach((key) => {
377
+ delete this.sockets[key];
378
+ });
379
+ // Stop IP ban garbage collector
380
+ if (this.ip2banGC) {
381
+ clearInterval(this.ip2banGC);
382
+ }
383
+ // Unsubscribe from store updates
384
+ if (this.unsubscribe) {
385
+ try {
386
+ this.unsubscribe();
387
+ }
388
+ catch {
389
+ // ignore
390
+ }
391
+ this.unsubscribe = undefined;
392
+ }
393
+ // Finally close the server and resolve when closed
394
+ if (this.server && typeof this.server.close === "function") {
395
+ try {
396
+ this.server.close(() => resolve());
397
+ }
398
+ catch {
399
+ // fallback resolve
400
+ resolve();
401
+ }
402
+ }
403
+ else {
404
+ resolve();
405
+ }
406
+ });
407
+ }
408
+ }
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,125 @@
1
+ import { Store, Action } from "redux";
2
+ export declare enum SerializationMode {
3
+ JSON = "json",
4
+ PROTOOBJECT = "protoobject"
5
+ }
6
+ export interface ReduxClusterConfig {
7
+ serializationMode?: SerializationMode;
8
+ debug?: boolean;
9
+ mode?: SyncMode;
10
+ syncMode?: "ipc" | "tcp";
11
+ role?: Role[];
12
+ server?: ServerSettings;
13
+ client?: ClientSettings;
14
+ backup?: BackupSettings;
15
+ stderr?: ErrorHandler;
16
+ resync?: number;
17
+ }
18
+ export type ProtoObjectState = any;
19
+ export declare enum MessageType {
20
+ CONN_STATUS = "REDUX_CLUSTER_CONNSTATUS",
21
+ MSG_TO_WORKER = "REDUX_CLUSTER_MSGTOWORKER",
22
+ MSG_TO_MASTER = "REDUX_CLUSTER_MSGTOMASTER",
23
+ SOCKET_AUTH = "REDUX_CLUSTER_SOCKET_AUTH",
24
+ SOCKET_AUTH_STATE = "REDUX_CLUSTER_SOCKET_AUTHSTATE",
25
+ START = "REDUX_CLUSTER_START",
26
+ SYNC = "REDUX_CLUSTER_SYNC"
27
+ }
28
+ export interface BaseMessage {
29
+ _msg: MessageType;
30
+ _hash: string;
31
+ }
32
+ export interface ConnectionStatusMessage extends BaseMessage {
33
+ _msg: MessageType.CONN_STATUS;
34
+ _connected: boolean;
35
+ }
36
+ export interface ActionToWorkerMessage extends BaseMessage {
37
+ _msg: MessageType.MSG_TO_WORKER;
38
+ _action: Action;
39
+ }
40
+ export interface ActionToMasterMessage extends BaseMessage {
41
+ _msg: MessageType.MSG_TO_MASTER;
42
+ _action: Action;
43
+ }
44
+ export interface SocketAuthMessage extends BaseMessage {
45
+ _msg: MessageType.SOCKET_AUTH;
46
+ _login: string;
47
+ _password: string;
48
+ }
49
+ export interface SocketAuthStateMessage extends BaseMessage {
50
+ _msg: MessageType.SOCKET_AUTH_STATE;
51
+ _value: boolean;
52
+ _banned?: boolean;
53
+ }
54
+ export interface StartMessage extends BaseMessage {
55
+ _msg: MessageType.START;
56
+ }
57
+ export type ClusterMessage = ConnectionStatusMessage | ActionToWorkerMessage | ActionToMasterMessage | SocketAuthMessage | SocketAuthStateMessage | StartMessage;
58
+ export type SyncMode = "action" | "snapshot";
59
+ export type Role = "master" | "worker" | "server" | "client";
60
+ export interface ServerSettings {
61
+ host?: string;
62
+ port?: number;
63
+ path?: string;
64
+ logins?: Record<string, string>;
65
+ }
66
+ export interface ClientSettings {
67
+ host?: string;
68
+ port?: number;
69
+ path?: string;
70
+ login?: string;
71
+ password?: string;
72
+ }
73
+ export interface BackupSettings {
74
+ path: string;
75
+ key?: string;
76
+ timeout?: number;
77
+ count?: number;
78
+ }
79
+ export interface ReduxClusterStore<S = any, A extends Action = Action> extends Store<S, A> {
80
+ readonly RCHash: string;
81
+ readonly version: string;
82
+ readonly homepage: string;
83
+ readonly role: Role[];
84
+ connected: boolean;
85
+ mode: SyncMode;
86
+ resync: number;
87
+ stderr: (message: string) => void;
88
+ readonly config: ReduxClusterConfig;
89
+ createServer(settings?: ServerSettings): ClusterServer;
90
+ createClient(settings?: ClientSettings): ClusterClient;
91
+ backup(settings: BackupSettings): Promise<boolean>;
92
+ sendtoall(message?: ClusterMessage): void;
93
+ sendtoallsock(message?: ClusterMessage): void;
94
+ registerClass?(name: string, classConstructor: any): void;
95
+ getRegisteredClasses?(): string[];
96
+ }
97
+ export interface ClusterServer {
98
+ readonly uid: string;
99
+ readonly sockets: Record<string, any>;
100
+ readonly database: Record<string, string>;
101
+ readonly ip2ban: Record<string, {
102
+ time: number;
103
+ count: number;
104
+ }>;
105
+ sendtoall(message?: ClusterMessage): void;
106
+ ip2banGCStop(): void;
107
+ }
108
+ export interface ClusterClient {
109
+ login?: string;
110
+ password?: string;
111
+ }
112
+ export interface ClusterSocket {
113
+ uid: string;
114
+ writeNEW: (data: any) => boolean;
115
+ write(data: any): boolean;
116
+ on(event: string, listener: (...args: any[]) => void): any;
117
+ pipe(...args: any[]): any;
118
+ end(): void;
119
+ remoteAddress?: string;
120
+ }
121
+ export type HasherFunction = (data: string, algorithm?: string) => string | undefined;
122
+ export type EncrypterFunction = (data: string, pass: string) => string;
123
+ export type DecrypterFunction = (data: string, pass: string) => string;
124
+ export type ErrorHandler = (message: string) => void;
125
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ // Serialization modes
2
+ export var SerializationMode;
3
+ (function (SerializationMode) {
4
+ SerializationMode["JSON"] = "json";
5
+ SerializationMode["PROTOOBJECT"] = "protoobject";
6
+ })(SerializationMode || (SerializationMode = {}));
7
+ // Message types for IPC communication
8
+ export var MessageType;
9
+ (function (MessageType) {
10
+ MessageType["CONN_STATUS"] = "REDUX_CLUSTER_CONNSTATUS";
11
+ MessageType["MSG_TO_WORKER"] = "REDUX_CLUSTER_MSGTOWORKER";
12
+ MessageType["MSG_TO_MASTER"] = "REDUX_CLUSTER_MSGTOMASTER";
13
+ MessageType["SOCKET_AUTH"] = "REDUX_CLUSTER_SOCKET_AUTH";
14
+ MessageType["SOCKET_AUTH_STATE"] = "REDUX_CLUSTER_SOCKET_AUTHSTATE";
15
+ MessageType["START"] = "REDUX_CLUSTER_START";
16
+ MessageType["SYNC"] = "REDUX_CLUSTER_SYNC";
17
+ })(MessageType || (MessageType = {}));
@@ -0,0 +1,22 @@
1
+ import * as crypto from "crypto";
2
+ import { Transform } from "stream";
3
+ import { SerializationMode } from "../types";
4
+ export declare function hasher(input: string): string;
5
+ export declare function createCipher(key: string): crypto.Cipher;
6
+ export declare function createDecipher(key: string, iv: Buffer): crypto.Decipher;
7
+ export declare function encrypter(data: string, password: string): string;
8
+ export declare function decrypter(encryptedData: string, password: string): string;
9
+ export declare function deepClone(obj: any): any;
10
+ export declare function universalClone(obj: any, mode: SerializationMode, _classRegistry?: Map<string, any>): any;
11
+ export declare function protoObjectClone(obj: any): any;
12
+ export declare function universalSerialize(obj: any, mode: SerializationMode, classRegistry?: Map<string, any>): string;
13
+ export declare function universalDeserialize(str: string, mode: SerializationMode, classRegistry?: Map<string, any>): any;
14
+ export declare function serializeProtoObject(obj: any, classRegistry?: Map<string, any>): string;
15
+ export declare function deserializeProtoObject(str: string, classRegistry?: Map<string, any>): any;
16
+ export declare function createClassRegistry(): Map<string, any>;
17
+ export declare function createObjectStreamParser(): Transform | null;
18
+ export declare function createObjectStreamStringifier(): Transform | null;
19
+ export declare function createObjectStream(): Transform | null;
20
+ export declare function createDeserializationStream(mode: SerializationMode, classRegistry?: Map<string, any>): Transform;
21
+ export declare function createSerializationStream(mode: SerializationMode, classRegistry?: Map<string, any>): Transform;
22
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../../src/utils/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAoD7C,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5C;AAGD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAGvD;AAGD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,QAAQ,CAEvE;AAGD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAShE;AAGD,wBAAgB,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWzE;AAGD,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAKvC;AAGD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,iBAAiB,EACvB,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAChC,GAAG,CAKL;AAGD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAsC9C;AAGD,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,iBAAiB,EACvB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAC/B,MAAM,CAMR;AAGD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,iBAAiB,EACvB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAC/B,GAAG,CAML;AAGD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,GAAG,EACR,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAC/B,MAAM,CAmCR;AAGD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAC/B,GAAG,CAqCL;AAGD,wBAAgB,mBAAmB,IAAI,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAEtD;AAKD,wBAAgB,wBAAwB,IAAI,SAAS,GAAG,IAAI,CAK3D;AAGD,wBAAgB,6BAA6B,IAAI,SAAS,GAAG,IAAI,CAKhE;AAGD,wBAAgB,kBAAkB,IAAI,SAAS,GAAG,IAAI,CAErD;AAGD,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,iBAAiB,EACvB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAC/B,SAAS,CAuBX;AAGD,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,iBAAiB,EACvB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAC/B,SAAS,CAuBX"}