@hazeljs/websocket 0.7.9 → 0.8.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 +15 -15
- package/dist/websocket.test.js +108 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ export class ChatGateway {
|
|
|
57
57
|
@OnMessage('message')
|
|
58
58
|
handleMessage(client: WebSocketClient, @Data() data: { text: string }) {
|
|
59
59
|
console.log('Received message:', data.text);
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
// Broadcast to all clients
|
|
62
62
|
client.broadcast('message', {
|
|
63
63
|
from: client.id,
|
|
@@ -125,10 +125,10 @@ Handle client connections:
|
|
|
125
125
|
@OnConnect()
|
|
126
126
|
handleConnection(client: WebSocketClient) {
|
|
127
127
|
console.log('New client:', client.id);
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
// Send welcome message
|
|
130
130
|
client.emit('welcome', { message: 'Hello!' });
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
// Store client data
|
|
133
133
|
client.data.username = 'Guest';
|
|
134
134
|
}
|
|
@@ -142,7 +142,7 @@ Handle client disconnections:
|
|
|
142
142
|
@OnDisconnect()
|
|
143
143
|
handleDisconnect(client: WebSocketClient) {
|
|
144
144
|
console.log('Client left:', client.id);
|
|
145
|
-
|
|
145
|
+
|
|
146
146
|
// Notify others
|
|
147
147
|
client.broadcast('user-left', {
|
|
148
148
|
userId: client.id,
|
|
@@ -159,7 +159,7 @@ Handle specific messages:
|
|
|
159
159
|
@OnMessage('chat-message')
|
|
160
160
|
handleChatMessage(client: WebSocketClient, @Data() data: ChatMessage) {
|
|
161
161
|
console.log('Chat message from', client.id, ':', data.text);
|
|
162
|
-
|
|
162
|
+
|
|
163
163
|
// Broadcast to all
|
|
164
164
|
client.broadcast('chat-message', {
|
|
165
165
|
from: client.data.username,
|
|
@@ -177,7 +177,7 @@ Subscribe to events:
|
|
|
177
177
|
@Subscribe('join-room')
|
|
178
178
|
handleJoinRoom(client: WebSocketClient, @Data() data: { room: string }) {
|
|
179
179
|
client.join(data.room);
|
|
180
|
-
|
|
180
|
+
|
|
181
181
|
// Notify room members
|
|
182
182
|
client.to(data.room).emit('user-joined', {
|
|
183
183
|
userId: client.id,
|
|
@@ -270,7 +270,7 @@ handlePrivateMessage(
|
|
|
270
270
|
@Data() data: { to: string; text: string }
|
|
271
271
|
) {
|
|
272
272
|
const targetClient = this.server.getClient(data.to);
|
|
273
|
-
|
|
273
|
+
|
|
274
274
|
if (targetClient) {
|
|
275
275
|
targetClient.emit('private-message', {
|
|
276
276
|
from: client.id,
|
|
@@ -307,7 +307,7 @@ export class ChatGateway {
|
|
|
307
307
|
@OnConnect()
|
|
308
308
|
async handleConnection(client: WebSocketClient) {
|
|
309
309
|
const token = client.handshake.query.token;
|
|
310
|
-
|
|
310
|
+
|
|
311
311
|
try {
|
|
312
312
|
const user = await this.authService.verifyToken(token);
|
|
313
313
|
client.data.user = user;
|
|
@@ -352,7 +352,7 @@ export class ChatGateway {
|
|
|
352
352
|
@OnConnect()
|
|
353
353
|
handleConnection(client: WebSocketClient) {
|
|
354
354
|
console.log(`Client connected: ${client.id}`);
|
|
355
|
-
|
|
355
|
+
|
|
356
356
|
client.emit('connected', {
|
|
357
357
|
clientId: client.id,
|
|
358
358
|
message: 'Welcome to the chat!',
|
|
@@ -362,10 +362,10 @@ export class ChatGateway {
|
|
|
362
362
|
@OnDisconnect()
|
|
363
363
|
handleDisconnect(client: WebSocketClient) {
|
|
364
364
|
console.log(`Client disconnected: ${client.id}`);
|
|
365
|
-
|
|
365
|
+
|
|
366
366
|
// Notify rooms
|
|
367
367
|
const rooms = client.rooms;
|
|
368
|
-
rooms.forEach(room => {
|
|
368
|
+
rooms.forEach((room) => {
|
|
369
369
|
client.to(room).emit('user-left', {
|
|
370
370
|
userId: client.id,
|
|
371
371
|
username: client.data.username,
|
|
@@ -377,14 +377,14 @@ export class ChatGateway {
|
|
|
377
377
|
handleJoinRoom(client: WebSocketClient, @Data() data: JoinRoomData) {
|
|
378
378
|
client.join(data.room);
|
|
379
379
|
client.data.username = data.username;
|
|
380
|
-
|
|
380
|
+
|
|
381
381
|
// Notify room members
|
|
382
382
|
client.to(data.room).emit('user-joined', {
|
|
383
383
|
userId: client.id,
|
|
384
384
|
username: data.username,
|
|
385
385
|
room: data.room,
|
|
386
386
|
});
|
|
387
|
-
|
|
387
|
+
|
|
388
388
|
// Confirm to sender
|
|
389
389
|
client.emit('joined-room', {
|
|
390
390
|
room: data.room,
|
|
@@ -395,7 +395,7 @@ export class ChatGateway {
|
|
|
395
395
|
@Subscribe('leave-room')
|
|
396
396
|
handleLeaveRoom(client: WebSocketClient, @Data() data: { room: string }) {
|
|
397
397
|
client.leave(data.room);
|
|
398
|
-
|
|
398
|
+
|
|
399
399
|
// Notify room
|
|
400
400
|
client.to(data.room).emit('user-left', {
|
|
401
401
|
userId: client.id,
|
|
@@ -437,7 +437,7 @@ export class ChatGateway {
|
|
|
437
437
|
|
|
438
438
|
private getRoomMembers(room: string): any[] {
|
|
439
439
|
const clients = this.server.getClientsInRoom(room);
|
|
440
|
-
return clients.map(c => ({
|
|
440
|
+
return clients.map((c) => ({
|
|
441
441
|
id: c.id,
|
|
442
442
|
username: c.data.username,
|
|
443
443
|
}));
|
package/dist/websocket.test.js
CHANGED
|
@@ -1,17 +1,55 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
2
18
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
19
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
20
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
21
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
22
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
23
|
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
8
41
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
42
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
43
|
};
|
|
11
44
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
45
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
46
|
};
|
|
47
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
48
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
49
|
+
};
|
|
14
50
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
const http = __importStar(require("http"));
|
|
52
|
+
const ws_1 = __importDefault(require("ws"));
|
|
15
53
|
const room_manager_1 = require("./room/room.manager");
|
|
16
54
|
const sse_handler_1 = require("./sse/sse.handler");
|
|
17
55
|
const websocket_gateway_1 = require("./websocket.gateway");
|
|
@@ -724,6 +762,76 @@ describe('WebSocketGateway', () => {
|
|
|
724
762
|
expect(stats.messagesSent).toBe(1);
|
|
725
763
|
});
|
|
726
764
|
});
|
|
765
|
+
describe('close() without server', () => {
|
|
766
|
+
it('resolves when no WebSocketServer was started', async () => {
|
|
767
|
+
const g = new websocket_gateway_1.WebSocketGateway();
|
|
768
|
+
await expect(g.close()).resolves.toBeUndefined();
|
|
769
|
+
});
|
|
770
|
+
});
|
|
771
|
+
describe('attachToServer (integration)', () => {
|
|
772
|
+
it('registers clients, handles JSON messages, invalid payload, and close', async () => {
|
|
773
|
+
const httpServer = http.createServer();
|
|
774
|
+
const gw = new websocket_gateway_1.WebSocketGateway();
|
|
775
|
+
gw.attachToServer(httpServer, {
|
|
776
|
+
path: '/custom-ws',
|
|
777
|
+
perMessageDeflate: true,
|
|
778
|
+
maxPayload: 512 * 1024,
|
|
779
|
+
});
|
|
780
|
+
await new Promise((resolve) => httpServer.listen(0, resolve));
|
|
781
|
+
const { port } = httpServer.address();
|
|
782
|
+
const ws = new ws_1.default(`ws://127.0.0.1:${port}/custom-ws`);
|
|
783
|
+
await new Promise((resolve, reject) => {
|
|
784
|
+
ws.once('open', () => resolve());
|
|
785
|
+
ws.once('error', reject);
|
|
786
|
+
});
|
|
787
|
+
expect(gw.getClientCount()).toBe(1);
|
|
788
|
+
ws.send(JSON.stringify({ event: 'ping', data: { n: 1 }, timestamp: Date.now() }));
|
|
789
|
+
await new Promise((r) => setTimeout(r, 30));
|
|
790
|
+
ws.send('not-valid-json');
|
|
791
|
+
await new Promise((r) => setTimeout(r, 30));
|
|
792
|
+
await new Promise((resolve) => {
|
|
793
|
+
ws.once('close', () => resolve());
|
|
794
|
+
ws.close();
|
|
795
|
+
});
|
|
796
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
797
|
+
await gw.close();
|
|
798
|
+
await new Promise((resolve, reject) => {
|
|
799
|
+
httpServer.close((err) => (err ? reject(err) : resolve()));
|
|
800
|
+
});
|
|
801
|
+
});
|
|
802
|
+
it('invokes wss error handler without throwing', async () => {
|
|
803
|
+
const httpServer = http.createServer();
|
|
804
|
+
const gw = new websocket_gateway_1.WebSocketGateway();
|
|
805
|
+
const wss = gw.attachToServer(httpServer, { path: '/ws' });
|
|
806
|
+
await new Promise((resolve) => httpServer.listen(0, resolve));
|
|
807
|
+
await new Promise((resolve) => {
|
|
808
|
+
wss.emit('error', new Error('synthetic'));
|
|
809
|
+
setImmediate(() => resolve());
|
|
810
|
+
});
|
|
811
|
+
await gw.close();
|
|
812
|
+
await new Promise((resolve, reject) => {
|
|
813
|
+
httpServer.close((err) => (err ? reject(err) : resolve()));
|
|
814
|
+
});
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
describe('listen (standalone integration)', () => {
|
|
818
|
+
it('accepts connections on ephemeral port', async () => {
|
|
819
|
+
const gw = new websocket_gateway_1.WebSocketGateway();
|
|
820
|
+
const wss = gw.listen(0, { path: '/ws' });
|
|
821
|
+
const addr = wss.address();
|
|
822
|
+
const port = typeof addr === 'object' && addr !== null ? addr.port : 0;
|
|
823
|
+
expect(port).toBeGreaterThan(0);
|
|
824
|
+
const ws = new ws_1.default(`ws://127.0.0.1:${port}/ws`);
|
|
825
|
+
await new Promise((resolve, reject) => {
|
|
826
|
+
ws.once('open', () => resolve());
|
|
827
|
+
ws.once('error', reject);
|
|
828
|
+
});
|
|
829
|
+
expect(gw.getClientCount()).toBe(1);
|
|
830
|
+
ws.close();
|
|
831
|
+
await new Promise((r) => ws.once('close', () => r()));
|
|
832
|
+
await gw.close();
|
|
833
|
+
});
|
|
834
|
+
});
|
|
727
835
|
});
|
|
728
836
|
describe('WebSocket Decorators', () => {
|
|
729
837
|
describe('@Realtime', () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hazeljs/websocket",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "WebSocket and Server-Sent Events module for HazelJS framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@hazeljs/core": ">=0.2.0-beta.0"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "8b7685d1250c4622f25d83992f58e13a59bb3dba"
|
|
55
55
|
}
|