@hazeljs/websocket 0.2.0-beta.1
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 +530 -0
- package/dist/decorators/realtime.decorator.d.ts +113 -0
- package/dist/decorators/realtime.decorator.d.ts.map +1 -0
- package/dist/decorators/realtime.decorator.js +202 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/room/room.manager.d.ts +81 -0
- package/dist/room/room.manager.d.ts.map +1 -0
- package/dist/room/room.manager.js +209 -0
- package/dist/src/decorators/realtime.decorator.d.ts +113 -0
- package/dist/src/decorators/realtime.decorator.d.ts.map +1 -0
- package/dist/src/decorators/realtime.decorator.js +202 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +32 -0
- package/dist/src/room/room.manager.d.ts +81 -0
- package/dist/src/room/room.manager.d.ts.map +1 -0
- package/dist/src/room/room.manager.js +209 -0
- package/dist/src/sse/sse.handler.d.ts +61 -0
- package/dist/src/sse/sse.handler.d.ts.map +1 -0
- package/dist/src/sse/sse.handler.js +209 -0
- package/dist/src/websocket.gateway.d.ts +94 -0
- package/dist/src/websocket.gateway.d.ts.map +1 -0
- package/dist/src/websocket.gateway.js +309 -0
- package/dist/src/websocket.module.d.ts +57 -0
- package/dist/src/websocket.module.d.ts.map +1 -0
- package/dist/src/websocket.module.js +88 -0
- package/dist/src/websocket.types.d.ts +258 -0
- package/dist/src/websocket.types.d.ts.map +1 -0
- package/dist/src/websocket.types.js +2 -0
- package/dist/sse/sse.handler.d.ts +61 -0
- package/dist/sse/sse.handler.d.ts.map +1 -0
- package/dist/sse/sse.handler.js +209 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/websocket.gateway.d.ts +79 -0
- package/dist/websocket.gateway.d.ts.map +1 -0
- package/dist/websocket.gateway.js +214 -0
- package/dist/websocket.module.d.ts +57 -0
- package/dist/websocket.module.d.ts.map +1 -0
- package/dist/websocket.module.js +88 -0
- package/dist/websocket.types.d.ts +258 -0
- package/dist/websocket.types.d.ts.map +1 -0
- package/dist/websocket.types.js +2 -0
- package/package.json +48 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Realtime = Realtime;
|
|
7
|
+
exports.getRealtimeMetadata = getRealtimeMetadata;
|
|
8
|
+
exports.isRealtimeGateway = isRealtimeGateway;
|
|
9
|
+
exports.Subscribe = Subscribe;
|
|
10
|
+
exports.getSubscribeMetadata = getSubscribeMetadata;
|
|
11
|
+
exports.OnConnect = OnConnect;
|
|
12
|
+
exports.getOnConnectMetadata = getOnConnectMetadata;
|
|
13
|
+
exports.OnDisconnect = OnDisconnect;
|
|
14
|
+
exports.getOnDisconnectMetadata = getOnDisconnectMetadata;
|
|
15
|
+
exports.OnMessage = OnMessage;
|
|
16
|
+
exports.getOnMessageMetadata = getOnMessageMetadata;
|
|
17
|
+
exports.Client = Client;
|
|
18
|
+
exports.Data = Data;
|
|
19
|
+
exports.getParameterMetadata = getParameterMetadata;
|
|
20
|
+
require("reflect-metadata");
|
|
21
|
+
const core_1 = __importDefault(require("@hazeljs/core"));
|
|
22
|
+
const REALTIME_METADATA_KEY = 'hazel:realtime';
|
|
23
|
+
const SUBSCRIBE_METADATA_KEY = 'hazel:subscribe';
|
|
24
|
+
const ON_CONNECT_METADATA_KEY = 'hazel:onconnect';
|
|
25
|
+
const ON_DISCONNECT_METADATA_KEY = 'hazel:ondisconnect';
|
|
26
|
+
const ON_MESSAGE_METADATA_KEY = 'hazel:onmessage';
|
|
27
|
+
/**
|
|
28
|
+
* Realtime decorator for WebSocket gateways
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* @Realtime('/notifications')
|
|
33
|
+
* export class NotificationGateway {
|
|
34
|
+
* // Gateway methods
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function Realtime(pathOrOptions) {
|
|
39
|
+
return (target) => {
|
|
40
|
+
const options = typeof pathOrOptions === 'string' ? { path: pathOrOptions } : pathOrOptions || {};
|
|
41
|
+
const defaults = {
|
|
42
|
+
path: '/',
|
|
43
|
+
namespace: '/',
|
|
44
|
+
auth: false,
|
|
45
|
+
pingInterval: 25000,
|
|
46
|
+
pingTimeout: 5000,
|
|
47
|
+
maxPayload: 1048576, // 1MB
|
|
48
|
+
...options,
|
|
49
|
+
};
|
|
50
|
+
const targetName = typeof target === 'function' ? target.name : 'unknown';
|
|
51
|
+
core_1.default.debug(`Marking ${targetName} as realtime gateway with path: ${defaults.path}`);
|
|
52
|
+
Reflect.defineMetadata(REALTIME_METADATA_KEY, defaults, target);
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get realtime metadata from a class
|
|
57
|
+
*/
|
|
58
|
+
function getRealtimeMetadata(target) {
|
|
59
|
+
return Reflect.getMetadata(REALTIME_METADATA_KEY, target);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if a class is a realtime gateway
|
|
63
|
+
*/
|
|
64
|
+
function isRealtimeGateway(target) {
|
|
65
|
+
return Reflect.hasMetadata(REALTIME_METADATA_KEY, target);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Subscribe decorator for event handlers
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* @Subscribe('user-{userId}')
|
|
73
|
+
* onUserEvent(@Param('userId') userId: string, @Data() data: any) {
|
|
74
|
+
* // Handle event
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
function Subscribe(event) {
|
|
79
|
+
return (target, propertyKey, descriptor) => {
|
|
80
|
+
Reflect.defineMetadata(SUBSCRIBE_METADATA_KEY, event, target, propertyKey);
|
|
81
|
+
core_1.default.debug(`Subscribe decorator applied to ${target.constructor.name}.${String(propertyKey)} for event: ${event}`);
|
|
82
|
+
return descriptor;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get subscribe metadata from a method
|
|
87
|
+
*/
|
|
88
|
+
function getSubscribeMetadata(target, propertyKey) {
|
|
89
|
+
return Reflect.getMetadata(SUBSCRIBE_METADATA_KEY, target, propertyKey);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* OnConnect decorator for connection handlers
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* @OnConnect()
|
|
97
|
+
* handleConnection(@Client() client: WebSocketClient) {
|
|
98
|
+
* console.log('Client connected:', client.id);
|
|
99
|
+
* }
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
function OnConnect() {
|
|
103
|
+
return (target, propertyKey, descriptor) => {
|
|
104
|
+
Reflect.defineMetadata(ON_CONNECT_METADATA_KEY, true, target, propertyKey);
|
|
105
|
+
core_1.default.debug(`OnConnect decorator applied to ${target.constructor.name}.${String(propertyKey)}`);
|
|
106
|
+
return descriptor;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get OnConnect metadata
|
|
111
|
+
*/
|
|
112
|
+
function getOnConnectMetadata(target, propertyKey) {
|
|
113
|
+
return Reflect.getMetadata(ON_CONNECT_METADATA_KEY, target, propertyKey) || false;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* OnDisconnect decorator for disconnection handlers
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* @OnDisconnect()
|
|
121
|
+
* handleDisconnect(@Client() client: WebSocketClient) {
|
|
122
|
+
* console.log('Client disconnected:', client.id);
|
|
123
|
+
* }
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
function OnDisconnect() {
|
|
127
|
+
return (target, propertyKey, descriptor) => {
|
|
128
|
+
Reflect.defineMetadata(ON_DISCONNECT_METADATA_KEY, true, target, propertyKey);
|
|
129
|
+
core_1.default.debug(`OnDisconnect decorator applied to ${target.constructor.name}.${String(propertyKey)}`);
|
|
130
|
+
return descriptor;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get OnDisconnect metadata
|
|
135
|
+
*/
|
|
136
|
+
function getOnDisconnectMetadata(target, propertyKey) {
|
|
137
|
+
return Reflect.getMetadata(ON_DISCONNECT_METADATA_KEY, target, propertyKey) || false;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* OnMessage decorator for message handlers
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* @OnMessage('chat')
|
|
145
|
+
* handleMessage(@Client() client: WebSocketClient, @Data() data: any) {
|
|
146
|
+
* // Handle message
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
function OnMessage(event) {
|
|
151
|
+
return (target, propertyKey, descriptor) => {
|
|
152
|
+
Reflect.defineMetadata(ON_MESSAGE_METADATA_KEY, event, target, propertyKey);
|
|
153
|
+
core_1.default.debug(`OnMessage decorator applied to ${target.constructor.name}.${String(propertyKey)} for event: ${event}`);
|
|
154
|
+
return descriptor;
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get OnMessage metadata
|
|
159
|
+
*/
|
|
160
|
+
function getOnMessageMetadata(target, propertyKey) {
|
|
161
|
+
return Reflect.getMetadata(ON_MESSAGE_METADATA_KEY, target, propertyKey);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Client parameter decorator
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* handleConnection(@Client() client: WebSocketClient) {
|
|
169
|
+
* // client is injected
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
function Client() {
|
|
174
|
+
return (target, propertyKey, parameterIndex) => {
|
|
175
|
+
const existingParams = Reflect.getMetadata('hazel:ws:params', target, propertyKey) || [];
|
|
176
|
+
existingParams[parameterIndex] = 'client';
|
|
177
|
+
Reflect.defineMetadata('hazel:ws:params', existingParams, target, propertyKey);
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Data parameter decorator
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* handleMessage(@Data() data: any) {
|
|
186
|
+
* // data is injected
|
|
187
|
+
* }
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
function Data() {
|
|
191
|
+
return (target, propertyKey, parameterIndex) => {
|
|
192
|
+
const existingParams = Reflect.getMetadata('hazel:ws:params', target, propertyKey) || [];
|
|
193
|
+
existingParams[parameterIndex] = 'data';
|
|
194
|
+
Reflect.defineMetadata('hazel:ws:params', existingParams, target, propertyKey);
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Get parameter metadata
|
|
199
|
+
*/
|
|
200
|
+
function getParameterMetadata(target, propertyKey) {
|
|
201
|
+
return Reflect.getMetadata('hazel:ws:params', target, propertyKey) || [];
|
|
202
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hazeljs/websocket - WebSocket and SSE module for HazelJS
|
|
3
|
+
*/
|
|
4
|
+
export { WebSocketModule, type WebSocketModuleOptions } from './websocket.module';
|
|
5
|
+
export { WebSocketGateway, createWebSocketClient } from './websocket.gateway';
|
|
6
|
+
export { Realtime, Subscribe, OnConnect, OnDisconnect, OnMessage, Client, Data, getRealtimeMetadata, isRealtimeGateway, getSubscribeMetadata, getOnConnectMetadata, getOnDisconnectMetadata, getOnMessageMetadata, getParameterMetadata, } from './decorators/realtime.decorator';
|
|
7
|
+
export { SSEHandler, createSSEResponse, sendSSEMessage } from './sse/sse.handler';
|
|
8
|
+
export { RoomManager } from './room/room.manager';
|
|
9
|
+
export { type WebSocketClient, type WebSocketMessage, type WebSocketGatewayOptions, type Room, type WebSocketEventHandler, type ConnectionHandler, type DisconnectionHandler, type WebSocketServerOptions, type SSEOptions, type SSEMessage, type SubscriptionOptions, type WebSocketStats, } from './websocket.types';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,QAAQ,EACR,SAAS,EACT,SAAS,EACT,YAAY,EACZ,SAAS,EACT,MAAM,EACN,IAAI,EACJ,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,IAAI,EACT,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @hazeljs/websocket - WebSocket and SSE module for HazelJS
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RoomManager = exports.sendSSEMessage = exports.createSSEResponse = exports.SSEHandler = exports.getParameterMetadata = exports.getOnMessageMetadata = exports.getOnDisconnectMetadata = exports.getOnConnectMetadata = exports.getSubscribeMetadata = exports.isRealtimeGateway = exports.getRealtimeMetadata = exports.Data = exports.Client = exports.OnMessage = exports.OnDisconnect = exports.OnConnect = exports.Subscribe = exports.Realtime = exports.createWebSocketClient = exports.WebSocketGateway = exports.WebSocketModule = void 0;
|
|
7
|
+
var websocket_module_1 = require("./websocket.module");
|
|
8
|
+
Object.defineProperty(exports, "WebSocketModule", { enumerable: true, get: function () { return websocket_module_1.WebSocketModule; } });
|
|
9
|
+
var websocket_gateway_1 = require("./websocket.gateway");
|
|
10
|
+
Object.defineProperty(exports, "WebSocketGateway", { enumerable: true, get: function () { return websocket_gateway_1.WebSocketGateway; } });
|
|
11
|
+
Object.defineProperty(exports, "createWebSocketClient", { enumerable: true, get: function () { return websocket_gateway_1.createWebSocketClient; } });
|
|
12
|
+
var realtime_decorator_1 = require("./decorators/realtime.decorator");
|
|
13
|
+
Object.defineProperty(exports, "Realtime", { enumerable: true, get: function () { return realtime_decorator_1.Realtime; } });
|
|
14
|
+
Object.defineProperty(exports, "Subscribe", { enumerable: true, get: function () { return realtime_decorator_1.Subscribe; } });
|
|
15
|
+
Object.defineProperty(exports, "OnConnect", { enumerable: true, get: function () { return realtime_decorator_1.OnConnect; } });
|
|
16
|
+
Object.defineProperty(exports, "OnDisconnect", { enumerable: true, get: function () { return realtime_decorator_1.OnDisconnect; } });
|
|
17
|
+
Object.defineProperty(exports, "OnMessage", { enumerable: true, get: function () { return realtime_decorator_1.OnMessage; } });
|
|
18
|
+
Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return realtime_decorator_1.Client; } });
|
|
19
|
+
Object.defineProperty(exports, "Data", { enumerable: true, get: function () { return realtime_decorator_1.Data; } });
|
|
20
|
+
Object.defineProperty(exports, "getRealtimeMetadata", { enumerable: true, get: function () { return realtime_decorator_1.getRealtimeMetadata; } });
|
|
21
|
+
Object.defineProperty(exports, "isRealtimeGateway", { enumerable: true, get: function () { return realtime_decorator_1.isRealtimeGateway; } });
|
|
22
|
+
Object.defineProperty(exports, "getSubscribeMetadata", { enumerable: true, get: function () { return realtime_decorator_1.getSubscribeMetadata; } });
|
|
23
|
+
Object.defineProperty(exports, "getOnConnectMetadata", { enumerable: true, get: function () { return realtime_decorator_1.getOnConnectMetadata; } });
|
|
24
|
+
Object.defineProperty(exports, "getOnDisconnectMetadata", { enumerable: true, get: function () { return realtime_decorator_1.getOnDisconnectMetadata; } });
|
|
25
|
+
Object.defineProperty(exports, "getOnMessageMetadata", { enumerable: true, get: function () { return realtime_decorator_1.getOnMessageMetadata; } });
|
|
26
|
+
Object.defineProperty(exports, "getParameterMetadata", { enumerable: true, get: function () { return realtime_decorator_1.getParameterMetadata; } });
|
|
27
|
+
var sse_handler_1 = require("./sse/sse.handler");
|
|
28
|
+
Object.defineProperty(exports, "SSEHandler", { enumerable: true, get: function () { return sse_handler_1.SSEHandler; } });
|
|
29
|
+
Object.defineProperty(exports, "createSSEResponse", { enumerable: true, get: function () { return sse_handler_1.createSSEResponse; } });
|
|
30
|
+
Object.defineProperty(exports, "sendSSEMessage", { enumerable: true, get: function () { return sse_handler_1.sendSSEMessage; } });
|
|
31
|
+
var room_manager_1 = require("./room/room.manager");
|
|
32
|
+
Object.defineProperty(exports, "RoomManager", { enumerable: true, get: function () { return room_manager_1.RoomManager; } });
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Room, WebSocketClient } from '../websocket.types';
|
|
2
|
+
/**
|
|
3
|
+
* Room manager for WebSocket connections
|
|
4
|
+
*/
|
|
5
|
+
export declare class RoomManager {
|
|
6
|
+
private rooms;
|
|
7
|
+
private clientRooms;
|
|
8
|
+
/**
|
|
9
|
+
* Create a room
|
|
10
|
+
*/
|
|
11
|
+
createRoom(name: string): Room;
|
|
12
|
+
/**
|
|
13
|
+
* Get a room
|
|
14
|
+
*/
|
|
15
|
+
getRoom(name: string): Room | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Delete a room
|
|
18
|
+
*/
|
|
19
|
+
deleteRoom(name: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Add client to room
|
|
22
|
+
*/
|
|
23
|
+
addClientToRoom(clientId: string, roomName: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* Remove client from room
|
|
26
|
+
*/
|
|
27
|
+
removeClientFromRoom(clientId: string, roomName: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Remove client from all rooms
|
|
30
|
+
*/
|
|
31
|
+
removeClientFromAllRooms(clientId: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get all rooms a client is in
|
|
34
|
+
*/
|
|
35
|
+
getClientRooms(clientId: string): string[];
|
|
36
|
+
/**
|
|
37
|
+
* Get all clients in a room
|
|
38
|
+
*/
|
|
39
|
+
getRoomClients(roomName: string): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Check if client is in room
|
|
42
|
+
*/
|
|
43
|
+
isClientInRoom(clientId: string, roomName: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Get all rooms
|
|
46
|
+
*/
|
|
47
|
+
getAllRooms(): Room[];
|
|
48
|
+
/**
|
|
49
|
+
* Get room count
|
|
50
|
+
*/
|
|
51
|
+
getRoomCount(): number;
|
|
52
|
+
/**
|
|
53
|
+
* Get total client count across all rooms
|
|
54
|
+
*/
|
|
55
|
+
getTotalClientCount(): number;
|
|
56
|
+
/**
|
|
57
|
+
* Broadcast to room
|
|
58
|
+
*/
|
|
59
|
+
broadcastToRoom(roomName: string, event: string, data: unknown, clients: Map<string, WebSocketClient>, excludeClientId?: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Set room metadata
|
|
62
|
+
*/
|
|
63
|
+
setRoomMetadata(roomName: string, key: string, value: unknown): void;
|
|
64
|
+
/**
|
|
65
|
+
* Get room metadata
|
|
66
|
+
*/
|
|
67
|
+
getRoomMetadata(roomName: string, key: string): unknown;
|
|
68
|
+
/**
|
|
69
|
+
* Clear all rooms
|
|
70
|
+
*/
|
|
71
|
+
clear(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Get statistics
|
|
74
|
+
*/
|
|
75
|
+
getStats(): {
|
|
76
|
+
totalRooms: number;
|
|
77
|
+
totalClients: number;
|
|
78
|
+
averageClientsPerRoom: number;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=room.manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room.manager.d.ts","sourceRoot":"","sources":["../../../src/room/room.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG3D;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,WAAW,CAAuC;IAE1D;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAkB9B;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIvC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAoBjC;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAkBzD;;OAEG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAsB9D;;OAEG;IACH,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAchD;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAK1C;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAK1C;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAK3D;;OAEG;IACH,WAAW,IAAI,IAAI,EAAE;IAIrB;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,mBAAmB,IAAI,MAAM;IAQ7B;;OAEG;IACH,eAAe,CACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACrC,eAAe,CAAC,EAAE,MAAM,GACvB,IAAI;IAoBP;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAOpE;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAKvD;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,QAAQ,IAAI;QACV,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,qBAAqB,EAAE,MAAM,CAAC;KAC/B;CAWF"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RoomManager = void 0;
|
|
7
|
+
const core_1 = __importDefault(require("@hazeljs/core"));
|
|
8
|
+
/**
|
|
9
|
+
* Room manager for WebSocket connections
|
|
10
|
+
*/
|
|
11
|
+
class RoomManager {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.rooms = new Map();
|
|
14
|
+
this.clientRooms = new Map();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create a room
|
|
18
|
+
*/
|
|
19
|
+
createRoom(name) {
|
|
20
|
+
if (this.rooms.has(name)) {
|
|
21
|
+
return this.rooms.get(name);
|
|
22
|
+
}
|
|
23
|
+
const room = {
|
|
24
|
+
name,
|
|
25
|
+
clients: new Set(),
|
|
26
|
+
metadata: new Map(),
|
|
27
|
+
createdAt: Date.now(),
|
|
28
|
+
};
|
|
29
|
+
this.rooms.set(name, room);
|
|
30
|
+
core_1.default.debug(`Room created: ${name}`);
|
|
31
|
+
return room;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get a room
|
|
35
|
+
*/
|
|
36
|
+
getRoom(name) {
|
|
37
|
+
return this.rooms.get(name);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Delete a room
|
|
41
|
+
*/
|
|
42
|
+
deleteRoom(name) {
|
|
43
|
+
const room = this.rooms.get(name);
|
|
44
|
+
if (!room) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
// Remove room from all clients
|
|
48
|
+
for (const clientId of room.clients) {
|
|
49
|
+
const clientRooms = this.clientRooms.get(clientId);
|
|
50
|
+
if (clientRooms) {
|
|
51
|
+
clientRooms.delete(name);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
this.rooms.delete(name);
|
|
55
|
+
core_1.default.debug(`Room deleted: ${name}`);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Add client to room
|
|
60
|
+
*/
|
|
61
|
+
addClientToRoom(clientId, roomName) {
|
|
62
|
+
// Create room if it doesn't exist
|
|
63
|
+
if (!this.rooms.has(roomName)) {
|
|
64
|
+
this.createRoom(roomName);
|
|
65
|
+
}
|
|
66
|
+
const room = this.rooms.get(roomName);
|
|
67
|
+
room.clients.add(clientId);
|
|
68
|
+
// Track client's rooms
|
|
69
|
+
if (!this.clientRooms.has(clientId)) {
|
|
70
|
+
this.clientRooms.set(clientId, new Set());
|
|
71
|
+
}
|
|
72
|
+
this.clientRooms.get(clientId).add(roomName);
|
|
73
|
+
core_1.default.debug(`Client ${clientId} joined room ${roomName}`);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Remove client from room
|
|
77
|
+
*/
|
|
78
|
+
removeClientFromRoom(clientId, roomName) {
|
|
79
|
+
const room = this.rooms.get(roomName);
|
|
80
|
+
if (!room) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
room.clients.delete(clientId);
|
|
84
|
+
// Remove from client's rooms
|
|
85
|
+
const clientRooms = this.clientRooms.get(clientId);
|
|
86
|
+
if (clientRooms) {
|
|
87
|
+
clientRooms.delete(roomName);
|
|
88
|
+
}
|
|
89
|
+
// Delete room if empty
|
|
90
|
+
if (room.clients.size === 0) {
|
|
91
|
+
this.deleteRoom(roomName);
|
|
92
|
+
}
|
|
93
|
+
core_1.default.debug(`Client ${clientId} left room ${roomName}`);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Remove client from all rooms
|
|
97
|
+
*/
|
|
98
|
+
removeClientFromAllRooms(clientId) {
|
|
99
|
+
const clientRooms = this.clientRooms.get(clientId);
|
|
100
|
+
if (!clientRooms) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
for (const roomName of clientRooms) {
|
|
104
|
+
this.removeClientFromRoom(clientId, roomName);
|
|
105
|
+
}
|
|
106
|
+
this.clientRooms.delete(clientId);
|
|
107
|
+
core_1.default.debug(`Client ${clientId} removed from all rooms`);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get all rooms a client is in
|
|
111
|
+
*/
|
|
112
|
+
getClientRooms(clientId) {
|
|
113
|
+
const rooms = this.clientRooms.get(clientId);
|
|
114
|
+
return rooms ? Array.from(rooms) : [];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get all clients in a room
|
|
118
|
+
*/
|
|
119
|
+
getRoomClients(roomName) {
|
|
120
|
+
const room = this.rooms.get(roomName);
|
|
121
|
+
return room ? Array.from(room.clients) : [];
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Check if client is in room
|
|
125
|
+
*/
|
|
126
|
+
isClientInRoom(clientId, roomName) {
|
|
127
|
+
const room = this.rooms.get(roomName);
|
|
128
|
+
return room ? room.clients.has(clientId) : false;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get all rooms
|
|
132
|
+
*/
|
|
133
|
+
getAllRooms() {
|
|
134
|
+
return Array.from(this.rooms.values());
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get room count
|
|
138
|
+
*/
|
|
139
|
+
getRoomCount() {
|
|
140
|
+
return this.rooms.size;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get total client count across all rooms
|
|
144
|
+
*/
|
|
145
|
+
getTotalClientCount() {
|
|
146
|
+
let count = 0;
|
|
147
|
+
for (const room of this.rooms.values()) {
|
|
148
|
+
count += room.clients.size;
|
|
149
|
+
}
|
|
150
|
+
return count;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Broadcast to room
|
|
154
|
+
*/
|
|
155
|
+
broadcastToRoom(roomName, event, data, clients, excludeClientId) {
|
|
156
|
+
const room = this.rooms.get(roomName);
|
|
157
|
+
if (!room) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
for (const clientId of room.clients) {
|
|
161
|
+
if (excludeClientId && clientId === excludeClientId) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const client = clients.get(clientId);
|
|
165
|
+
if (client) {
|
|
166
|
+
client.send(event, data);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
core_1.default.debug(`Broadcast to room ${roomName}: ${event}`);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Set room metadata
|
|
173
|
+
*/
|
|
174
|
+
setRoomMetadata(roomName, key, value) {
|
|
175
|
+
const room = this.rooms.get(roomName);
|
|
176
|
+
if (room) {
|
|
177
|
+
room.metadata.set(key, value);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Get room metadata
|
|
182
|
+
*/
|
|
183
|
+
getRoomMetadata(roomName, key) {
|
|
184
|
+
const room = this.rooms.get(roomName);
|
|
185
|
+
return room ? room.metadata.get(key) : undefined;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Clear all rooms
|
|
189
|
+
*/
|
|
190
|
+
clear() {
|
|
191
|
+
this.rooms.clear();
|
|
192
|
+
this.clientRooms.clear();
|
|
193
|
+
core_1.default.info('All rooms cleared');
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get statistics
|
|
197
|
+
*/
|
|
198
|
+
getStats() {
|
|
199
|
+
const totalRooms = this.rooms.size;
|
|
200
|
+
const totalClients = this.getTotalClientCount();
|
|
201
|
+
const averageClientsPerRoom = totalRooms > 0 ? totalClients / totalRooms : 0;
|
|
202
|
+
return {
|
|
203
|
+
totalRooms,
|
|
204
|
+
totalClients,
|
|
205
|
+
averageClientsPerRoom: Math.round(averageClientsPerRoom * 100) / 100,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.RoomManager = RoomManager;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
+
import { SSEMessage, SSEOptions } from '../websocket.types';
|
|
3
|
+
/**
|
|
4
|
+
* Server-Sent Events (SSE) handler
|
|
5
|
+
*/
|
|
6
|
+
export declare class SSEHandler {
|
|
7
|
+
private connections;
|
|
8
|
+
private keepAliveIntervals;
|
|
9
|
+
/**
|
|
10
|
+
* Initialize SSE connection
|
|
11
|
+
*/
|
|
12
|
+
initConnection(req: IncomingMessage, res: ServerResponse, options?: SSEOptions): string;
|
|
13
|
+
/**
|
|
14
|
+
* Send message to a specific connection
|
|
15
|
+
*/
|
|
16
|
+
send(connectionId: string, message: SSEMessage): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Broadcast message to all connections
|
|
19
|
+
*/
|
|
20
|
+
broadcast(message: SSEMessage): void;
|
|
21
|
+
/**
|
|
22
|
+
* Close a specific connection
|
|
23
|
+
*/
|
|
24
|
+
closeConnection(connectionId: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Close all connections
|
|
27
|
+
*/
|
|
28
|
+
closeAll(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Get active connection count
|
|
31
|
+
*/
|
|
32
|
+
getConnectionCount(): number;
|
|
33
|
+
/**
|
|
34
|
+
* Check if connection exists
|
|
35
|
+
*/
|
|
36
|
+
hasConnection(connectionId: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Get all connection IDs
|
|
39
|
+
*/
|
|
40
|
+
getConnectionIds(): string[];
|
|
41
|
+
/**
|
|
42
|
+
* Generate unique connection ID
|
|
43
|
+
*/
|
|
44
|
+
private generateConnectionId;
|
|
45
|
+
/**
|
|
46
|
+
* Create a stream for continuous data
|
|
47
|
+
*/
|
|
48
|
+
createStream<T>(connectionId: string, dataSource: AsyncIterable<T> | Iterable<T>, options?: {
|
|
49
|
+
event?: string;
|
|
50
|
+
transform?: (data: T) => unknown;
|
|
51
|
+
}): AsyncGenerator<boolean>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Helper function to create SSE response
|
|
55
|
+
*/
|
|
56
|
+
export declare function createSSEResponse(res: ServerResponse, options?: SSEOptions): void;
|
|
57
|
+
/**
|
|
58
|
+
* Helper function to send SSE message
|
|
59
|
+
*/
|
|
60
|
+
export declare function sendSSEMessage(res: ServerResponse, message: SSEMessage): void;
|
|
61
|
+
//# sourceMappingURL=sse.handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.handler.d.ts","sourceRoot":"","sources":["../../../src/sse/sse.handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAG5D;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,WAAW,CAA0C;IAC7D,OAAO,CAAC,kBAAkB,CAA0C;IAEpE;;OAEG;IACH,cAAc,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM;IA0C3F;;OAEG;IACH,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO;IA0CxD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAQpC;;OAEG;IACH,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAgB3C;;OAEG;IACH,QAAQ,IAAI,IAAI;IAQhB;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAI5B;;OAEG;IACH,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI5C;;OAEG;IACH,gBAAgB,IAAI,MAAM,EAAE;IAI5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;IACI,YAAY,CAAC,CAAC,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,EAC1C,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAA;KAAO,GACjE,cAAc,CAAC,OAAO,CAAC;CAmB3B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,GAAE,UAAe,GAAG,IAAI,CAYrF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI,CAyB7E"}
|