@morojs/moro 1.3.0 → 1.5.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.
- package/README.md +61 -7
- package/dist/core/config/index.d.ts +0 -1
- package/dist/core/config/index.js +0 -4
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/config/loader.js +219 -226
- package/dist/core/config/loader.js.map +1 -1
- package/dist/core/config/schema.d.ts +30 -335
- package/dist/core/config/schema.js +133 -224
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/utils.d.ts +3 -2
- package/dist/core/config/utils.js.map +1 -1
- package/dist/core/config/validation.d.ts +17 -0
- package/dist/core/config/validation.js +129 -0
- package/dist/core/config/validation.js.map +1 -0
- package/dist/core/docs/index.js +1 -1
- package/dist/core/docs/index.js.map +1 -1
- package/dist/core/docs/openapi-generator.js +6 -6
- package/dist/core/docs/openapi-generator.js.map +1 -1
- package/dist/core/docs/schema-to-openapi.d.ts +7 -0
- package/dist/core/docs/schema-to-openapi.js +124 -0
- package/dist/core/docs/schema-to-openapi.js.map +1 -0
- package/dist/core/docs/simple-docs.js +5 -5
- package/dist/core/docs/zod-to-openapi.d.ts +4 -3
- package/dist/core/docs/zod-to-openapi.js +28 -0
- package/dist/core/docs/zod-to-openapi.js.map +1 -1
- package/dist/core/framework.d.ts +29 -6
- package/dist/core/framework.js +117 -18
- package/dist/core/framework.js.map +1 -1
- package/dist/core/networking/adapters/index.d.ts +3 -0
- package/dist/core/networking/adapters/index.js +10 -0
- package/dist/core/networking/adapters/index.js.map +1 -0
- package/dist/core/networking/adapters/socketio-adapter.d.ts +16 -0
- package/dist/core/networking/adapters/socketio-adapter.js +244 -0
- package/dist/core/networking/adapters/socketio-adapter.js.map +1 -0
- package/dist/core/networking/adapters/ws-adapter.d.ts +54 -0
- package/dist/core/networking/adapters/ws-adapter.js +383 -0
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -0
- package/dist/core/networking/websocket-adapter.d.ts +171 -0
- package/dist/core/networking/websocket-adapter.js +5 -0
- package/dist/core/networking/websocket-adapter.js.map +1 -0
- package/dist/core/networking/websocket-manager.d.ts +53 -17
- package/dist/core/networking/websocket-manager.js +184 -126
- package/dist/core/networking/websocket-manager.js.map +1 -1
- package/dist/core/routing/index.d.ts +13 -13
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/validation/adapters.d.ts +51 -0
- package/dist/core/validation/adapters.js +135 -0
- package/dist/core/validation/adapters.js.map +1 -0
- package/dist/core/validation/index.d.ts +12 -11
- package/dist/core/validation/index.js +32 -26
- package/dist/core/validation/index.js.map +1 -1
- package/dist/core/validation/schema-interface.d.ts +36 -0
- package/dist/core/validation/schema-interface.js +68 -0
- package/dist/core/validation/schema-interface.js.map +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +23 -4
- package/dist/index.js.map +1 -1
- package/dist/moro.js +24 -17
- package/dist/moro.js.map +1 -1
- package/dist/types/config.d.ts +146 -0
- package/dist/types/config.js +4 -0
- package/dist/types/config.js.map +1 -0
- package/package.json +30 -7
- package/src/core/config/index.ts +0 -3
- package/src/core/config/loader.ts +571 -247
- package/src/core/config/schema.ts +146 -279
- package/src/core/config/utils.ts +1 -2
- package/src/core/config/validation.ts +140 -0
- package/src/core/docs/index.ts +1 -1
- package/src/core/docs/openapi-generator.ts +7 -6
- package/src/core/docs/schema-to-openapi.ts +148 -0
- package/src/core/docs/simple-docs.ts +5 -5
- package/src/core/docs/zod-to-openapi.ts +52 -20
- package/src/core/framework.ts +121 -28
- package/src/core/networking/adapters/index.ts +16 -0
- package/src/core/networking/adapters/socketio-adapter.ts +252 -0
- package/src/core/networking/adapters/ws-adapter.ts +425 -0
- package/src/core/networking/websocket-adapter.ts +217 -0
- package/src/core/networking/websocket-manager.ts +201 -143
- package/src/core/routing/index.ts +13 -13
- package/src/core/validation/adapters.ts +147 -0
- package/src/core/validation/index.ts +54 -38
- package/src/core/validation/schema-interface.ts +100 -0
- package/src/index.ts +36 -3
- package/src/moro.ts +27 -17
- package/src/types/config.ts +157 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Native WebSocket Adapter for Moro Framework
|
|
3
|
+
// Implements the WebSocket adapter interface using the 'ws' library
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.WSAdapter = void 0;
|
|
39
|
+
/**
|
|
40
|
+
* Native WebSocket adapter using the 'ws' library
|
|
41
|
+
* Provides a lightweight, standards-compliant WebSocket implementation
|
|
42
|
+
*/
|
|
43
|
+
class WSAdapter {
|
|
44
|
+
constructor() {
|
|
45
|
+
this.namespaces = new Map();
|
|
46
|
+
this.connections = new Map();
|
|
47
|
+
this.connectionCounter = 0;
|
|
48
|
+
}
|
|
49
|
+
async initialize(httpServer, options = {}) {
|
|
50
|
+
try {
|
|
51
|
+
// Dynamic import to avoid requiring ws as a hard dependency
|
|
52
|
+
const { WebSocketServer } = await Promise.resolve().then(() => __importStar(require('ws')));
|
|
53
|
+
this.wss = new WebSocketServer({
|
|
54
|
+
server: httpServer,
|
|
55
|
+
path: options.path || '/ws',
|
|
56
|
+
maxPayload: options.maxPayloadLength || 100 * 1024 * 1024, // 100MB default
|
|
57
|
+
// Note: ws doesn't have built-in compression like socket.io
|
|
58
|
+
// but browsers handle compression at the transport level
|
|
59
|
+
});
|
|
60
|
+
// Setup connection handling
|
|
61
|
+
this.wss.on('connection', (ws, request) => {
|
|
62
|
+
this.handleConnection(ws, request);
|
|
63
|
+
});
|
|
64
|
+
// Setup default namespace
|
|
65
|
+
this.createNamespace('/');
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw new Error('ws library not found. Install it with: npm install ws @types/ws\n' +
|
|
69
|
+
'Or use a different WebSocket adapter.');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
handleConnection(ws, request) {
|
|
73
|
+
const id = this.generateId();
|
|
74
|
+
const connection = new WSConnectionWrapper(id, ws, request);
|
|
75
|
+
this.connections.set(id, connection);
|
|
76
|
+
// Parse namespace from URL path or default to '/'
|
|
77
|
+
const url = new URL(request.url || '/', `http://${request.headers.host}`);
|
|
78
|
+
const namespacePath = url.pathname === '/ws' ? '/' : url.pathname.replace('/ws', '') || '/';
|
|
79
|
+
const namespace = this.namespaces.get(namespacePath);
|
|
80
|
+
if (namespace) {
|
|
81
|
+
namespace.handleConnection(connection);
|
|
82
|
+
}
|
|
83
|
+
// Clean up on disconnect
|
|
84
|
+
ws.on('close', () => {
|
|
85
|
+
this.connections.delete(id);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
createNamespace(namespace) {
|
|
89
|
+
if (!this.namespaces.has(namespace)) {
|
|
90
|
+
const ns = new WSNamespaceWrapper(namespace, this);
|
|
91
|
+
this.namespaces.set(namespace, ns);
|
|
92
|
+
}
|
|
93
|
+
return this.namespaces.get(namespace);
|
|
94
|
+
}
|
|
95
|
+
getDefaultNamespace() {
|
|
96
|
+
return this.createNamespace('/');
|
|
97
|
+
}
|
|
98
|
+
async close() {
|
|
99
|
+
if (this.wss) {
|
|
100
|
+
return new Promise(resolve => {
|
|
101
|
+
this.wss.close(() => {
|
|
102
|
+
this.connections.clear();
|
|
103
|
+
this.namespaces.clear();
|
|
104
|
+
resolve();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
setCompression(enabled, _options = {}) {
|
|
110
|
+
// ws library handles compression at the browser level
|
|
111
|
+
// This is a no-op but kept for interface compatibility
|
|
112
|
+
if (enabled) {
|
|
113
|
+
console.warn('Compression is handled automatically by the ws library and browsers');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
setCustomIdGenerator(generator) {
|
|
117
|
+
this.customIdGenerator = generator;
|
|
118
|
+
}
|
|
119
|
+
getAdapterName() {
|
|
120
|
+
return 'ws';
|
|
121
|
+
}
|
|
122
|
+
getConnectionCount() {
|
|
123
|
+
return this.connections.size;
|
|
124
|
+
}
|
|
125
|
+
generateId() {
|
|
126
|
+
if (this.customIdGenerator) {
|
|
127
|
+
return this.customIdGenerator();
|
|
128
|
+
}
|
|
129
|
+
return `ws_${++this.connectionCounter}_${Date.now()}`;
|
|
130
|
+
}
|
|
131
|
+
addConnection(id, connection) {
|
|
132
|
+
this.connections.set(id, connection);
|
|
133
|
+
}
|
|
134
|
+
removeConnection(id) {
|
|
135
|
+
this.connections.delete(id);
|
|
136
|
+
}
|
|
137
|
+
getAllConnections() {
|
|
138
|
+
return this.connections;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.WSAdapter = WSAdapter;
|
|
142
|
+
/**
|
|
143
|
+
* WebSocket namespace wrapper
|
|
144
|
+
*/
|
|
145
|
+
class WSNamespaceWrapper {
|
|
146
|
+
constructor(namespacePath, adapter) {
|
|
147
|
+
this.namespacePath = namespacePath;
|
|
148
|
+
this.adapter = adapter;
|
|
149
|
+
this.connectionHandlers = [];
|
|
150
|
+
this.middlewares = [];
|
|
151
|
+
this.connections = new Map();
|
|
152
|
+
}
|
|
153
|
+
handleConnection(connection) {
|
|
154
|
+
this.connections.set(connection.id, connection);
|
|
155
|
+
// Run middlewares
|
|
156
|
+
this.runMiddlewares(connection, () => {
|
|
157
|
+
// Notify connection handlers
|
|
158
|
+
this.connectionHandlers.forEach(handler => handler(connection));
|
|
159
|
+
});
|
|
160
|
+
// Clean up on disconnect
|
|
161
|
+
connection.on('close', () => {
|
|
162
|
+
this.connections.delete(connection.id);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
runMiddlewares(connection, callback) {
|
|
166
|
+
let index = 0;
|
|
167
|
+
const next = (err) => {
|
|
168
|
+
if (err || index >= this.middlewares.length) {
|
|
169
|
+
if (!err)
|
|
170
|
+
callback();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const middleware = this.middlewares[index++];
|
|
174
|
+
middleware(connection, next);
|
|
175
|
+
};
|
|
176
|
+
next();
|
|
177
|
+
}
|
|
178
|
+
on(event, handler) {
|
|
179
|
+
this.connectionHandlers.push(handler);
|
|
180
|
+
}
|
|
181
|
+
emit(event, data) {
|
|
182
|
+
const message = JSON.stringify({ event, data });
|
|
183
|
+
for (const connection of this.connections.values()) {
|
|
184
|
+
if (connection.connected) {
|
|
185
|
+
connection.ws.send(message);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
to(room) {
|
|
190
|
+
return new WSEmitterWrapper(this.connections, room);
|
|
191
|
+
}
|
|
192
|
+
except(room) {
|
|
193
|
+
return new WSEmitterWrapper(this.connections, undefined, room);
|
|
194
|
+
}
|
|
195
|
+
getSockets() {
|
|
196
|
+
return Array.from(this.connections.values());
|
|
197
|
+
}
|
|
198
|
+
getConnectionCount() {
|
|
199
|
+
return this.connections.size;
|
|
200
|
+
}
|
|
201
|
+
use(middleware) {
|
|
202
|
+
this.middlewares.push(middleware);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* WebSocket connection wrapper
|
|
207
|
+
*/
|
|
208
|
+
class WSConnectionWrapper {
|
|
209
|
+
constructor(id, ws, request) {
|
|
210
|
+
this.id = id;
|
|
211
|
+
this.ws = ws;
|
|
212
|
+
this.request = request;
|
|
213
|
+
this.data = {};
|
|
214
|
+
this.eventHandlers = new Map();
|
|
215
|
+
this.anyHandlers = [];
|
|
216
|
+
this.rooms = new Set();
|
|
217
|
+
this._connected = true;
|
|
218
|
+
// Setup message handling
|
|
219
|
+
this.ws.on('message', (data) => {
|
|
220
|
+
this.handleMessage(data);
|
|
221
|
+
});
|
|
222
|
+
this.ws.on('close', () => {
|
|
223
|
+
this._connected = false;
|
|
224
|
+
this.emit('close');
|
|
225
|
+
});
|
|
226
|
+
this.ws.on('error', (error) => {
|
|
227
|
+
this.emit('error', error);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
get ip() {
|
|
231
|
+
return (this.request.socket?.remoteAddress || this.request.headers['x-forwarded-for']?.split(',')[0]);
|
|
232
|
+
}
|
|
233
|
+
get headers() {
|
|
234
|
+
return this.request.headers;
|
|
235
|
+
}
|
|
236
|
+
get connected() {
|
|
237
|
+
return this._connected && this.ws.readyState === 1; // WebSocket.OPEN
|
|
238
|
+
}
|
|
239
|
+
get broadcast() {
|
|
240
|
+
// Get all connections except this one
|
|
241
|
+
const allConnections = new Map();
|
|
242
|
+
// This would need access to adapter's connections
|
|
243
|
+
return new WSEmitterWrapper(allConnections, undefined, undefined, this.id);
|
|
244
|
+
}
|
|
245
|
+
on(event, handler) {
|
|
246
|
+
if (event === 'close' || event === 'error') {
|
|
247
|
+
// Special internal events
|
|
248
|
+
if (!this.eventHandlers.has(event)) {
|
|
249
|
+
this.eventHandlers.set(event, []);
|
|
250
|
+
}
|
|
251
|
+
this.eventHandlers.get(event).push(handler);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (!this.eventHandlers.has(event)) {
|
|
255
|
+
this.eventHandlers.set(event, []);
|
|
256
|
+
}
|
|
257
|
+
this.eventHandlers.get(event).push(handler);
|
|
258
|
+
}
|
|
259
|
+
onAny(handler) {
|
|
260
|
+
this.anyHandlers.push(handler);
|
|
261
|
+
}
|
|
262
|
+
emit(event, data) {
|
|
263
|
+
if (event === 'close' || event === 'error') {
|
|
264
|
+
// Internal events
|
|
265
|
+
const handlers = this.eventHandlers.get(event);
|
|
266
|
+
if (handlers) {
|
|
267
|
+
handlers.forEach(handler => handler(data));
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (this.connected) {
|
|
272
|
+
const message = JSON.stringify({ event, data });
|
|
273
|
+
this.ws.send(message);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
compressedEmit(event, data) {
|
|
277
|
+
// ws library handles compression automatically
|
|
278
|
+
this.emit(event, data);
|
|
279
|
+
}
|
|
280
|
+
join(room) {
|
|
281
|
+
if (Array.isArray(room)) {
|
|
282
|
+
room.forEach(r => this.rooms.add(r));
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
this.rooms.add(room);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
leave(room) {
|
|
289
|
+
if (Array.isArray(room)) {
|
|
290
|
+
room.forEach(r => this.rooms.delete(r));
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
this.rooms.delete(room);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
to(room) {
|
|
297
|
+
const connections = new Map([[this.id, this]]);
|
|
298
|
+
return new WSEmitterWrapper(connections, room);
|
|
299
|
+
}
|
|
300
|
+
getRooms() {
|
|
301
|
+
return new Set(this.rooms);
|
|
302
|
+
}
|
|
303
|
+
disconnect(close) {
|
|
304
|
+
if (close !== false && this.ws.readyState === 1) {
|
|
305
|
+
this.ws.close();
|
|
306
|
+
}
|
|
307
|
+
this._connected = false;
|
|
308
|
+
}
|
|
309
|
+
handleMessage(data) {
|
|
310
|
+
try {
|
|
311
|
+
const text = data.toString();
|
|
312
|
+
const parsed = JSON.parse(text);
|
|
313
|
+
const { event, data: messageData, callback: callbackId } = parsed;
|
|
314
|
+
// Create callback function if callback ID is provided
|
|
315
|
+
const callback = callbackId
|
|
316
|
+
? (response) => {
|
|
317
|
+
this.emit('callback', { id: callbackId, data: response });
|
|
318
|
+
}
|
|
319
|
+
: undefined;
|
|
320
|
+
// Call any handlers
|
|
321
|
+
this.anyHandlers.forEach(handler => handler(event, messageData));
|
|
322
|
+
// Call specific event handlers
|
|
323
|
+
const handlers = this.eventHandlers.get(event);
|
|
324
|
+
if (handlers) {
|
|
325
|
+
handlers.forEach(handler => handler(messageData, callback));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
// Invalid message format - ignore
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* WebSocket emitter wrapper
|
|
335
|
+
*/
|
|
336
|
+
class WSEmitterWrapper {
|
|
337
|
+
constructor(connections, targetRooms, excludeRooms, excludeId) {
|
|
338
|
+
this.connections = connections;
|
|
339
|
+
this.targetRooms = targetRooms;
|
|
340
|
+
this.excludeRooms = excludeRooms;
|
|
341
|
+
this.excludeId = excludeId;
|
|
342
|
+
}
|
|
343
|
+
emit(event, data) {
|
|
344
|
+
const message = JSON.stringify({ event, data });
|
|
345
|
+
for (const connection of this.connections.values()) {
|
|
346
|
+
if (this.excludeId && connection.id === this.excludeId) {
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
if (this.shouldIncludeConnection(connection) && connection.connected) {
|
|
350
|
+
connection.ws.send(message);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
to(room) {
|
|
355
|
+
return new WSEmitterWrapper(this.connections, room, this.excludeRooms, this.excludeId);
|
|
356
|
+
}
|
|
357
|
+
except(room) {
|
|
358
|
+
return new WSEmitterWrapper(this.connections, this.targetRooms, room, this.excludeId);
|
|
359
|
+
}
|
|
360
|
+
compress(_compress) {
|
|
361
|
+
// ws library handles compression automatically
|
|
362
|
+
return this;
|
|
363
|
+
}
|
|
364
|
+
shouldIncludeConnection(connection) {
|
|
365
|
+
const rooms = connection.getRooms();
|
|
366
|
+
// Check target rooms
|
|
367
|
+
if (this.targetRooms) {
|
|
368
|
+
const targets = Array.isArray(this.targetRooms) ? this.targetRooms : [this.targetRooms];
|
|
369
|
+
if (!targets.some(room => rooms.has(room))) {
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// Check exclude rooms
|
|
374
|
+
if (this.excludeRooms) {
|
|
375
|
+
const excludes = Array.isArray(this.excludeRooms) ? this.excludeRooms : [this.excludeRooms];
|
|
376
|
+
if (excludes.some(room => rooms.has(room))) {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
//# sourceMappingURL=ws-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-adapter.js","sourceRoot":"","sources":["../../../../src/core/networking/adapters/ws-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
export interface WebSocketAdapterOptions {
|
|
2
|
+
compression?: boolean;
|
|
3
|
+
cors?: {
|
|
4
|
+
origin?: string | string[] | boolean;
|
|
5
|
+
methods?: string[];
|
|
6
|
+
credentials?: boolean;
|
|
7
|
+
};
|
|
8
|
+
path?: string;
|
|
9
|
+
maxPayloadLength?: number;
|
|
10
|
+
idleTimeout?: number;
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Abstract WebSocket adapter interface
|
|
15
|
+
* Allows the framework to work with different WebSocket implementations
|
|
16
|
+
*/
|
|
17
|
+
export interface WebSocketAdapter {
|
|
18
|
+
/**
|
|
19
|
+
* Initialize the WebSocket server with the given HTTP server
|
|
20
|
+
*/
|
|
21
|
+
initialize(httpServer: any, options?: WebSocketAdapterOptions): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Create a namespace for organizing WebSocket connections
|
|
24
|
+
*/
|
|
25
|
+
createNamespace(namespace: string): WebSocketNamespace;
|
|
26
|
+
/**
|
|
27
|
+
* Get the default namespace (usually '/')
|
|
28
|
+
*/
|
|
29
|
+
getDefaultNamespace(): WebSocketNamespace;
|
|
30
|
+
/**
|
|
31
|
+
* Close the WebSocket server and all connections
|
|
32
|
+
*/
|
|
33
|
+
close(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Set compression configuration
|
|
36
|
+
*/
|
|
37
|
+
setCompression(enabled: boolean, options?: any): void;
|
|
38
|
+
/**
|
|
39
|
+
* Set custom ID generator for connections
|
|
40
|
+
*/
|
|
41
|
+
setCustomIdGenerator(generator: () => string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Get adapter name/type
|
|
44
|
+
*/
|
|
45
|
+
getAdapterName(): string;
|
|
46
|
+
/**
|
|
47
|
+
* Get connection count across all namespaces
|
|
48
|
+
*/
|
|
49
|
+
getConnectionCount(): number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* WebSocket namespace interface
|
|
53
|
+
* Represents a logical grouping of WebSocket connections
|
|
54
|
+
*/
|
|
55
|
+
export interface WebSocketNamespace {
|
|
56
|
+
/**
|
|
57
|
+
* Listen for connection events
|
|
58
|
+
*/
|
|
59
|
+
on(event: 'connection', handler: (socket: WebSocketConnection) => void): void;
|
|
60
|
+
/**
|
|
61
|
+
* Emit event to all connected sockets in this namespace
|
|
62
|
+
*/
|
|
63
|
+
emit(event: string, data: any): void;
|
|
64
|
+
/**
|
|
65
|
+
* Emit to specific room(s)
|
|
66
|
+
*/
|
|
67
|
+
to(room: string | string[]): WebSocketEmitter;
|
|
68
|
+
/**
|
|
69
|
+
* Emit to sockets except those in specified room(s)
|
|
70
|
+
*/
|
|
71
|
+
except(room: string | string[]): WebSocketEmitter;
|
|
72
|
+
/**
|
|
73
|
+
* Get all connected sockets
|
|
74
|
+
*/
|
|
75
|
+
getSockets(): WebSocketConnection[];
|
|
76
|
+
/**
|
|
77
|
+
* Get connection count for this namespace
|
|
78
|
+
*/
|
|
79
|
+
getConnectionCount(): number;
|
|
80
|
+
/**
|
|
81
|
+
* Use middleware for this namespace
|
|
82
|
+
*/
|
|
83
|
+
use(middleware: (socket: WebSocketConnection, next: (err?: Error) => void) => void): void;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* WebSocket connection interface
|
|
87
|
+
* Represents an individual client connection
|
|
88
|
+
*/
|
|
89
|
+
export interface WebSocketConnection {
|
|
90
|
+
/** Unique connection ID */
|
|
91
|
+
id: string;
|
|
92
|
+
/** Client IP address */
|
|
93
|
+
ip?: string;
|
|
94
|
+
/** Connection headers */
|
|
95
|
+
headers?: Record<string, string>;
|
|
96
|
+
/** Custom data storage */
|
|
97
|
+
data: Record<string, any>;
|
|
98
|
+
/**
|
|
99
|
+
* Listen for events from this socket
|
|
100
|
+
*/
|
|
101
|
+
on(event: string, handler: (data: any, callback?: (response?: any) => void) => void): void;
|
|
102
|
+
/**
|
|
103
|
+
* Listen for any event from this socket
|
|
104
|
+
*/
|
|
105
|
+
onAny(handler: (event: string, ...args: any[]) => void): void;
|
|
106
|
+
/**
|
|
107
|
+
* Emit event to this socket
|
|
108
|
+
*/
|
|
109
|
+
emit(event: string, data: any): void;
|
|
110
|
+
/**
|
|
111
|
+
* Emit with compression
|
|
112
|
+
*/
|
|
113
|
+
compressedEmit?(event: string, data: any): void;
|
|
114
|
+
/**
|
|
115
|
+
* Join a room
|
|
116
|
+
*/
|
|
117
|
+
join(room: string | string[]): void;
|
|
118
|
+
/**
|
|
119
|
+
* Leave a room
|
|
120
|
+
*/
|
|
121
|
+
leave(room: string | string[]): void;
|
|
122
|
+
/**
|
|
123
|
+
* Emit to specific room(s)
|
|
124
|
+
*/
|
|
125
|
+
to(room: string | string[]): WebSocketEmitter;
|
|
126
|
+
/**
|
|
127
|
+
* Emit to all sockets except this one
|
|
128
|
+
*/
|
|
129
|
+
broadcast: WebSocketEmitter;
|
|
130
|
+
/**
|
|
131
|
+
* Get rooms this socket has joined
|
|
132
|
+
*/
|
|
133
|
+
getRooms(): Set<string>;
|
|
134
|
+
/**
|
|
135
|
+
* Disconnect this socket
|
|
136
|
+
*/
|
|
137
|
+
disconnect(close?: boolean): void;
|
|
138
|
+
/**
|
|
139
|
+
* Check if socket is connected
|
|
140
|
+
*/
|
|
141
|
+
connected: boolean;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* WebSocket emitter interface for chaining operations
|
|
145
|
+
*/
|
|
146
|
+
export interface WebSocketEmitter {
|
|
147
|
+
/**
|
|
148
|
+
* Emit to target sockets
|
|
149
|
+
*/
|
|
150
|
+
emit(event: string, data: any): void;
|
|
151
|
+
/**
|
|
152
|
+
* Target specific room(s)
|
|
153
|
+
*/
|
|
154
|
+
to(room: string | string[]): WebSocketEmitter;
|
|
155
|
+
/**
|
|
156
|
+
* Exclude specific room(s)
|
|
157
|
+
*/
|
|
158
|
+
except(room: string | string[]): WebSocketEmitter;
|
|
159
|
+
/**
|
|
160
|
+
* Use compression for this emit
|
|
161
|
+
*/
|
|
162
|
+
compress(compress: boolean): WebSocketEmitter;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* WebSocket middleware function type
|
|
166
|
+
*/
|
|
167
|
+
export type WebSocketMiddleware = (socket: WebSocketConnection, next: (err?: Error) => void) => void;
|
|
168
|
+
/**
|
|
169
|
+
* WebSocket event handler type
|
|
170
|
+
*/
|
|
171
|
+
export type WebSocketEventHandler = (socket: WebSocketConnection, data: any, callback?: (response?: any) => void) => void | Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-adapter.js","sourceRoot":"","sources":["../../../src/core/networking/websocket-adapter.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,sEAAsE"}
|
|
@@ -1,27 +1,63 @@
|
|
|
1
|
-
import { Server as SocketIOServer, Namespace } from 'socket.io';
|
|
2
1
|
import { Container } from '../utilities';
|
|
3
2
|
import { ModuleConfig, WebSocketDefinition } from '../../types/module';
|
|
3
|
+
import { WebSocketAdapter, WebSocketNamespace } from './websocket-adapter';
|
|
4
4
|
export declare class WebSocketManager {
|
|
5
|
-
private
|
|
5
|
+
private adapter;
|
|
6
6
|
private container;
|
|
7
7
|
private circuitBreakers;
|
|
8
8
|
private rateLimiters;
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
private logger;
|
|
10
|
+
constructor(adapter: WebSocketAdapter, container: Container);
|
|
11
|
+
/**
|
|
12
|
+
* Set custom ID generator for the adapter
|
|
13
|
+
*/
|
|
13
14
|
setCustomIdGenerator(generator: () => string): void;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Enable compression for the adapter
|
|
17
|
+
*/
|
|
18
|
+
enableCompression(options?: any): void;
|
|
19
|
+
/**
|
|
20
|
+
* Get the underlying adapter
|
|
21
|
+
*/
|
|
22
|
+
getAdapter(): WebSocketAdapter;
|
|
23
|
+
/**
|
|
24
|
+
* Get connection count across all namespaces
|
|
25
|
+
*/
|
|
26
|
+
getConnectionCount(): number;
|
|
27
|
+
/**
|
|
28
|
+
* Create or get a namespace
|
|
29
|
+
*/
|
|
30
|
+
getNamespace(namespace: string): WebSocketNamespace;
|
|
31
|
+
/**
|
|
32
|
+
* Register WebSocket handlers for a module
|
|
33
|
+
*/
|
|
34
|
+
registerHandler(namespace: WebSocketNamespace, wsConfig: WebSocketDefinition, moduleConfig: ModuleConfig): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Setup socket-specific middleware
|
|
37
|
+
*/
|
|
23
38
|
private setupSocketMiddleware;
|
|
24
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Setup handlers for a specific WebSocket configuration
|
|
41
|
+
*/
|
|
42
|
+
private setupSocketHandlers;
|
|
43
|
+
/**
|
|
44
|
+
* Get or create circuit breaker for handler
|
|
45
|
+
*/
|
|
25
46
|
private getCircuitBreaker;
|
|
26
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Check rate limit for socket and handler
|
|
49
|
+
*/
|
|
50
|
+
private checkRateLimit;
|
|
51
|
+
/**
|
|
52
|
+
* Process binary data efficiently
|
|
53
|
+
*/
|
|
54
|
+
private processBinaryData;
|
|
55
|
+
/**
|
|
56
|
+
* Check if data should be compressed
|
|
57
|
+
*/
|
|
58
|
+
private shouldCompress;
|
|
59
|
+
/**
|
|
60
|
+
* Close the WebSocket manager and underlying adapter
|
|
61
|
+
*/
|
|
62
|
+
close(): Promise<void>;
|
|
27
63
|
}
|