@eleven-am/pondsocket 0.1.93 → 0.1.95
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 +489 -107
- package/nest.js +64 -50
- package/package.json +4 -4
- package/types.d.ts +1 -1
package/README.md
CHANGED
|
@@ -1,139 +1,521 @@
|
|
|
1
|
-
|
|
2
1
|
# PondSocket
|
|
3
2
|
|
|
4
|
-
PondSocket is a
|
|
5
|
-
|
|
3
|
+
PondSocket is a high-performance, minimalist, and bidirectional socket framework designed for Node.js. It provides a seamless way to handle real-time communication between server and client applications, making it an ideal choice for building WebSocket-based projects.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
To integrate PondSocket into your Node.js project, simply install it via npm:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
10
|
+
npm install @eleven-am/pondsocket
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
PondSocket simplifies the complexity of handling WebSocket connections by abstracting the communication process into individual requests rather than dealing with intricate callbacks within the connection event. It offers a lightweight yet powerful solution for managing bidirectional communication channels, enabling real-time updates and collaboration between server and client components.
|
|
16
|
+
|
|
17
|
+
## Server-side Usage
|
|
18
|
+
|
|
19
|
+
When setting up the server, PondSocket allows you to create multiple endpoints, each serving as a gateway for sockets to connect and communicate. Each endpoint operates independently, ensuring that sockets from one endpoint cannot interact with sockets from another. This isolation enhances security and simplifies resource management.
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
import PondSocket from "@eleven-am/pondsocket";
|
|
23
|
+
|
|
24
|
+
const pond = new PondSocket();
|
|
25
|
+
|
|
26
|
+
// Create an endpoint for handling socket connections
|
|
27
|
+
const endpoint = pond.createEndpoint('/api/socket', (req, res) => {
|
|
28
|
+
// Handle socket connection and authentication
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Start the server
|
|
32
|
+
pond.listen(3000);
|
|
33
|
+
|
|
34
|
+
// Or alternatively, working with express
|
|
35
|
+
import pondSocket from "@eleven-am/pondsocket/express";
|
|
36
|
+
import express from "express";
|
|
37
|
+
|
|
38
|
+
const app = pondSocket(express());
|
|
39
|
+
|
|
40
|
+
const endpoint = app.upgrade('/api/socket', (req, res) => {
|
|
41
|
+
// Handle socket connection and authentication
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
app.listen(3000);
|
|
35
45
|
```
|
|
36
46
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (!isAdmin)
|
|
44
|
-
return res.reject('You are not an admin');
|
|
45
|
-
|
|
46
|
-
res.accept({
|
|
47
|
-
assign: {
|
|
48
|
-
admin: true,
|
|
49
|
-
joinedDate: new Date()
|
|
50
|
-
},
|
|
51
|
-
presence: {
|
|
52
|
-
state: 'online'
|
|
53
|
-
},
|
|
54
|
-
channelData: {
|
|
55
|
-
locked: true,
|
|
56
|
-
numberOfUsers: channel.presence.length
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
});
|
|
47
|
+
Within each endpoint, sockets interact through channels. Channels provide an organized way to group users and manage efficient communication among them. When users join a channel, they can participate in real-time events and exchange information with other users in the same channel.
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
const channel = endpoint.createChannel('/channel/:id', (req, res) => {
|
|
51
|
+
// Handle the join request, which is sent when a user attempts to join the channel
|
|
52
|
+
});
|
|
60
53
|
```
|
|
61
54
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
res.assign({
|
|
72
|
-
assign: {
|
|
73
|
-
pingDate: new Date(),
|
|
74
|
-
users: users.length
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// res.reject('curse words are not allowed on a child friendly channel')
|
|
79
|
-
// channel.closeFromChannel(req.client.clientId);
|
|
80
|
-
})
|
|
55
|
+
## Client-side Usage
|
|
56
|
+
|
|
57
|
+
On the client-side, PondSocket provides the PondClient class to establish connections with the server. Clients can easily initiate connections, join channels, and participate in real-time interactions.
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
import PondClient from "@eleven-am/pondsocket/client";
|
|
61
|
+
|
|
62
|
+
const socket = new PondClient('/api/socket', {});
|
|
63
|
+
socket.connect();
|
|
81
64
|
```
|
|
82
65
|
|
|
83
|
-
|
|
84
|
-
You can choose to decline the message being sent, or you can allow the message to be sent as usual. You can also do all the normal assigns to the channel, or user.
|
|
85
|
-
In case there is no *on* function, the message will be sent without any action being taken.
|
|
66
|
+
Once connected, clients can create and join channels to engage in real-time communication with other users and the server.
|
|
86
67
|
|
|
87
|
-
|
|
68
|
+
```javascript
|
|
69
|
+
const channel = socket.createChannel('/channel/123');
|
|
70
|
+
channel.join();
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Node Client
|
|
88
74
|
|
|
89
|
-
|
|
90
|
-
import { PondClient } from "@eleven-am/pondsocket/client";
|
|
75
|
+
PondSocket also offers a Node.js client, which can be imported using:
|
|
91
76
|
|
|
92
|
-
|
|
93
|
-
|
|
77
|
+
```javascript
|
|
78
|
+
import PondClient from "@eleven-am/pondsocket/node";
|
|
94
79
|
```
|
|
95
80
|
|
|
96
|
-
|
|
97
|
-
|
|
81
|
+
This node client allows you to turn another server into a client, enabling easy communication between different server instances.
|
|
82
|
+
|
|
83
|
+
## Key Features
|
|
84
|
+
|
|
85
|
+
- **Simple and Efficient API**: PondSocket offers an easy-to-use API, making WebSocket communication straightforward and hassle-free.
|
|
86
|
+
- **Organized Channels**: Channels provide a structured approach for grouping users and facilitating efficient communication.
|
|
87
|
+
- **Assigns**: PondSocket allows the storage of private information for users and channels, enhancing data security.
|
|
88
|
+
- **Presence**: The presence feature keeps track of users' current states and notifies other users about any changes.
|
|
89
|
+
- **Broadcasting**: PondSocket enables broadcasting messages to all users or specific groups within a channel, facilitating real-time updates.
|
|
90
|
+
- **Typed and Well-documented**: The codebase is thoroughly documented and typed, providing a seamless development experience with improved IDE suggestions.
|
|
91
|
+
|
|
92
|
+
## Examples
|
|
98
93
|
|
|
99
|
-
|
|
100
|
-
You can just create multiple channels and maintain the single socket connection.
|
|
94
|
+
### Client-side Example with Authentication
|
|
101
95
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
96
|
+
To connect to the PondSocket server and send messages while associating a username with the client connection, follow the steps below:
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
import PondClient from "@eleven-am/pondsocket/client";
|
|
100
|
+
|
|
101
|
+
// Your server URL
|
|
102
|
+
const serverUrl = 'ws://your-server-url/api/socket';
|
|
103
|
+
|
|
104
|
+
// Your authenticated user's token (replace with actual token)
|
|
105
|
+
const authToken = 'your-auth-token';
|
|
106
|
+
|
|
107
|
+
// Your username (replace with actual username)
|
|
108
|
+
const username = 'user123';
|
|
109
|
+
|
|
110
|
+
// Create a new PondClient instance
|
|
111
|
+
const socket = new PondClient(serverUrl, { token: authToken });
|
|
112
|
+
|
|
113
|
+
// Connect to the server
|
|
114
|
+
socket.connect();
|
|
115
|
+
|
|
116
|
+
// Add event listeners to handle various scenarios
|
|
117
|
+
socket.onConnectionChange((connected) => {
|
|
118
|
+
if (connected) {
|
|
119
|
+
console.log('Connected to the server.');
|
|
120
|
+
} else {
|
|
121
|
+
console.log('Disconnected from the server.');
|
|
106
122
|
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Create a channel and join it
|
|
126
|
+
const channel = socket.createChannel('/channel/123', { username });
|
|
127
|
+
channel.join();
|
|
128
|
+
|
|
129
|
+
// Send a message to the server
|
|
130
|
+
const message = "Hello, PondSocket!";
|
|
131
|
+
channel.broadcast('message', { text: message });
|
|
107
132
|
|
|
108
|
-
|
|
109
|
-
|
|
133
|
+
// Handle received messages
|
|
134
|
+
// Certain methods in the channel instance returns a subscription function, which can be used to unsubscribe from the event
|
|
135
|
+
const subscription = channel.onMessage((event, message) => {
|
|
136
|
+
console.log(`Received message from server: ${message.text}`);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Unsubscribe from the event
|
|
140
|
+
subscription();
|
|
110
141
|
```
|
|
111
142
|
|
|
112
|
-
|
|
143
|
+
The client will now connect to the server, and the server will receive the necessary headers automatically, including any authentication tokens or cookies, as required by the browser.
|
|
113
144
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
145
|
+
### Server-side Example with Authentication and check for profanity before broadcasting
|
|
146
|
+
|
|
147
|
+
To create a PondSocket server that accepts authenticated connections and checks for profanity before broadcasting messages, follow the steps below:
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
import PondSocket from "@eleven-am/pondsocket";
|
|
151
|
+
|
|
152
|
+
// Helper functions for token validation
|
|
153
|
+
function isValidToken(token) {
|
|
154
|
+
// Implement your token validation logic here
|
|
155
|
+
// Return true if the token is valid, false otherwise
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function getRoleFromToken(token) {
|
|
160
|
+
// Implement the logic to extract the user's role from the token
|
|
161
|
+
// Return the user's role
|
|
162
|
+
return 'user';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function isTextProfane(text) {
|
|
166
|
+
// Implement your profanity check logic here
|
|
167
|
+
// Return true if the text is profane, false otherwise
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getMessagesFromDatabase(channelId) {
|
|
172
|
+
// Implement your logic to retrieve messages from the database
|
|
173
|
+
// Return an array of messages
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const pond = new PondSocket();
|
|
178
|
+
|
|
179
|
+
// Create an endpoint for handling socket connections
|
|
180
|
+
const endpoint = pond.createEndpoint('/api/socket', (req, res) => {
|
|
181
|
+
// Depending if the user already has cookies set, they can be accessed from the request headers or the request address
|
|
182
|
+
const token = req.query.token; // If the token is passed as a query parameter
|
|
183
|
+
|
|
184
|
+
// Perform token validation here
|
|
185
|
+
if (isValidToken(token)) {
|
|
186
|
+
// Extract the authenticated user's username
|
|
187
|
+
const role = getRoleFromToken(token);
|
|
188
|
+
|
|
189
|
+
// Handle socket connection and authentication for valid users
|
|
190
|
+
res.accept({ role }); // Assign the user's role to the socket
|
|
191
|
+
} else {
|
|
192
|
+
// Reject the connection for invalid users or without a token
|
|
193
|
+
res.reject('Invalid token', 401);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Create a channel, providing a callback that is called when a user attempts to join the channel
|
|
198
|
+
const profanityChannel = endpoint.createChannel('/channel/:id', async (req, res) => {
|
|
199
|
+
// When joining the channel, any joinParams passed from the client will be available in the request payload
|
|
200
|
+
// Also any previous assigns on the socket will be available in the request payload as well
|
|
201
|
+
const { role } = req.user.assigns;
|
|
202
|
+
const { username } = req.joinParams;
|
|
203
|
+
const { id } = req.event.params;
|
|
204
|
+
|
|
205
|
+
// maybe retrieve the previous messages from the database
|
|
206
|
+
const messages = await getMessagesFromDatabase(id);
|
|
207
|
+
|
|
208
|
+
// Check if the user has the required role to join the channel
|
|
209
|
+
if (role === 'admin') {
|
|
210
|
+
// Accept the join request
|
|
211
|
+
res.accept({ username, profanityCount: 0 })
|
|
212
|
+
// optionally you can track the presence of the user in the channel
|
|
213
|
+
.trackPresence({
|
|
214
|
+
username,
|
|
215
|
+
role,
|
|
216
|
+
status: 'online',
|
|
217
|
+
onlineSince: Date.now(),
|
|
218
|
+
})
|
|
219
|
+
// and send the user the channel history
|
|
220
|
+
.sendToUsers('history', { messages }, [req.user.id]);
|
|
221
|
+
|
|
222
|
+
// Alternatively, you can also send messages to the user, NOTE that the user would be automatically subscribed to the channel.
|
|
223
|
+
// res.send('history', { messages }, { username, profanityCount: 0 })
|
|
224
|
+
// .trackPresence({
|
|
225
|
+
// username,
|
|
226
|
+
// role,
|
|
227
|
+
// status: 'online',
|
|
228
|
+
// onlineSince: Date.now(),
|
|
229
|
+
// });
|
|
230
|
+
} else {
|
|
231
|
+
// Reject the join request
|
|
232
|
+
res.reject('You do not have the required role to join this channel', 403);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Attach message event listener to the profanityChannel
|
|
237
|
+
profanityChannel.onEvent('message', (req, res) => {
|
|
238
|
+
const { text } = req.event.payload;
|
|
239
|
+
|
|
240
|
+
// Check for profanity
|
|
241
|
+
if (isTextProfane(text)) {
|
|
242
|
+
// Reject the message if it contains profanity
|
|
243
|
+
res.reject('Profanity is not allowed', 400, {
|
|
244
|
+
profanityCount: req.user.assigns.profanityCount + 1
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// note that profanityCount is updated so req.user.assigns.profanityCount will be updated
|
|
248
|
+
if (req.user.assigns.profanityCount >= 3) {
|
|
249
|
+
// Kick the user from the channel if they have used profanity more than 3 times
|
|
250
|
+
res.evictUser('You have been kicked from the channel for using profanity');
|
|
251
|
+
} else {
|
|
252
|
+
// you can broadcast a message to all users or In the channel that profanity is not allowed
|
|
253
|
+
res.broadcast('profanity-warning', { message: 'Profanity is not allowed' })
|
|
254
|
+
// or you can send a message to the user that profanity is not allowed
|
|
255
|
+
.sendToUsers('profanity-warning', { message: `You have used profanity ${profanityCount} times. You will be kicked from the channel if you use profanity more than 3 times.` }, [req.user.id]);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
// Accept the message to allow broadcasting to other clients in the channel
|
|
259
|
+
res.accept();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// for more complete access to the channel, you can use the channel instance
|
|
263
|
+
// const channel = req.channel;
|
|
264
|
+
});
|
|
118
265
|
|
|
119
|
-
|
|
120
|
-
|
|
266
|
+
profanityChannel.onEvent('presence/:presence', (req, res) => {
|
|
267
|
+
const { presence } = req.event.params;
|
|
268
|
+
const { username } = req.user.assigns;
|
|
269
|
+
|
|
270
|
+
// Handle presence events
|
|
271
|
+
res.updatePresence({
|
|
272
|
+
username,
|
|
273
|
+
role,
|
|
274
|
+
onlineSince: Date.now(),
|
|
275
|
+
status: presence,
|
|
121
276
|
});
|
|
277
|
+
});
|
|
122
278
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
subscriptionMessage.unsubscribe();
|
|
126
|
-
```
|
|
279
|
+
profanityChannel.onLeave((event) => {
|
|
280
|
+
const { username } = event.assigns;
|
|
127
281
|
|
|
128
|
-
|
|
129
|
-
suggestions should be provided by your IDE.
|
|
282
|
+
// When a user leaves the channel, PondSocket will automatically remove the user from the presence list and inform other users in the channel
|
|
130
283
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
name: 'eleven-am',
|
|
134
|
-
message: 'I am the man, man'
|
|
135
|
-
})
|
|
284
|
+
// perform a cleanup operation here
|
|
285
|
+
});
|
|
136
286
|
|
|
137
|
-
|
|
138
|
-
|
|
287
|
+
// Start the server
|
|
288
|
+
pond.listen(3000, () => {
|
|
289
|
+
console.log('PondSocket server listening on port 3000');
|
|
290
|
+
});
|
|
139
291
|
```
|
|
292
|
+
|
|
293
|
+
## API Documentation
|
|
294
|
+
|
|
295
|
+
### PondSocket
|
|
296
|
+
|
|
297
|
+
The `PondSocket` class is the core class that represents the socket server.
|
|
298
|
+
|
|
299
|
+
**Constructor:**
|
|
300
|
+
|
|
301
|
+
- `constructor(server?: HTTPServer, socketServer?: WebSocketServer)`: Creates a new instance of the PondSocket with an optional HTTP server and WebSocket server.
|
|
302
|
+
|
|
303
|
+
**Methods:**
|
|
304
|
+
|
|
305
|
+
- `listen(...args: any[]): HTTPServer`: Specifies the port to listen on with the provided arguments.
|
|
306
|
+
|
|
307
|
+
- `close(callback?: () => void): HTTPServer`: Closes the server, and an optional callback can be provided.
|
|
308
|
+
|
|
309
|
+
- `createEndpoint<Path extends string>(path: PondPath<Path>, handler: (request: IncomingConnection<Path>, response: ConnectionResponse) => void | Promise<void>): Endpoint`: Accepts a new socket upgrade request on the provided endpoint using the handler function to authenticate the socket.
|
|
310
|
+
|
|
311
|
+
### ConnectionResponse
|
|
312
|
+
|
|
313
|
+
The `ConnectionResponse` class represents the response object for the incoming connection.
|
|
314
|
+
|
|
315
|
+
**Methods:**
|
|
316
|
+
|
|
317
|
+
- `accept(assigns?: PondAssigns): void`: Accepts the request and optionally assigns data to the client.
|
|
318
|
+
|
|
319
|
+
- `reject(message?: string, errorCode?: number): void`: Rejects the request with the given error message and optional error code.
|
|
320
|
+
|
|
321
|
+
- `send(event: string, payload: PondMessage, assigns?: PondAssigns): void`: Emits a direct message to the client with the specified event and payload.
|
|
322
|
+
|
|
323
|
+
### Endpoint
|
|
324
|
+
|
|
325
|
+
The `Endpoint` class represents an endpoint in the PondSocket server where channels can be created.
|
|
326
|
+
|
|
327
|
+
**Methods:**
|
|
328
|
+
|
|
329
|
+
- `createChannel<Path extends string>(path: PondPath<Path>, handler: (request: JoinRequest<Path>, response: JoinResponse) => void | Promise<void>): PondChannel`: Adds a new PondChannel to this path on this endpoint with the provided handler function to authenticate the client.
|
|
330
|
+
|
|
331
|
+
- `broadcast(event: string, payload: PondMessage): void`: Broadcasts a message to all clients connected to this endpoint with the specified event and payload.
|
|
332
|
+
|
|
333
|
+
- `closeConnection(clientIds: string | string[]): void`: Closes specific clients connected to this endpoint identified by the provided clientIds.
|
|
334
|
+
|
|
335
|
+
### JoinRequest
|
|
336
|
+
|
|
337
|
+
The `JoinRequest` class represents the request object when a client joins a channel.
|
|
338
|
+
|
|
339
|
+
**Properties:**
|
|
340
|
+
|
|
341
|
+
- `event: PondEvent<Path>`: The event associated with the request.
|
|
342
|
+
|
|
343
|
+
- `channelName: string`: The name of the channel.
|
|
344
|
+
|
|
345
|
+
- `assigns: UserAssigns`: The assigns data for the client.
|
|
346
|
+
|
|
347
|
+
- `presence: UserPresences`: The presence data for the client.
|
|
348
|
+
|
|
349
|
+
- `joinParams: JoinParams`: The join parameters for the client.
|
|
350
|
+
|
|
351
|
+
- `user: UserData`: The user data associated with the client.
|
|
352
|
+
|
|
353
|
+
- `channel: Channel`: The Channel instance associated with the request.
|
|
354
|
+
|
|
355
|
+
### JoinResponse
|
|
356
|
+
|
|
357
|
+
The `JoinResponse` class represents the response object for the join request.
|
|
358
|
+
|
|
359
|
+
**Methods:**
|
|
360
|
+
|
|
361
|
+
- `accept(assigns?: PondAssigns): JoinResponse`: Accepts the join request and optionally assigns data to the client.
|
|
362
|
+
|
|
363
|
+
- `reject(message?: string, errorCode?: number): JoinResponse`: Rejects the join request with the given error message and optional error code.
|
|
364
|
+
|
|
365
|
+
- `send(event: string, payload: PondMessage, assigns?: PondAssigns): JoinResponse`: Emits a direct message to the client with the specified event, payload, and optional assigns data.
|
|
366
|
+
|
|
367
|
+
- `broadcast(event: string, payload: PondMessage): JoinResponse`: Emits a message to all clients in the channel with the specified event and payload.
|
|
368
|
+
|
|
369
|
+
- `broadcastFromUser(event: string, payload: PondMessage): JoinResponse`: Emits a message to all clients in the channel except the sender with the specified event and payload.
|
|
370
|
+
|
|
371
|
+
- `sendToUsers(event: string, payload: PondMessage, userIds: string[]): JoinResponse`: Emits a message to a specific set of clients identified by the provided userIds with the specified event and payload.
|
|
372
|
+
|
|
373
|
+
- `trackPresence(presence: PondPresence): JoinResponse`: Tracks the presence of the client in the channel.
|
|
374
|
+
|
|
375
|
+
### PondChannel
|
|
376
|
+
|
|
377
|
+
The `PondChannel` class represents a Generic channel in the PondSocket server. It is used to create a channel whose path matches the provided PondPath.
|
|
378
|
+
|
|
379
|
+
**Methods:**
|
|
380
|
+
|
|
381
|
+
- `onEvent<Event extends string>(event: PondPath<Event>, handler: (request: EventRequest<Event>, response: EventResponse) => void | Promise<void>): void`: Handles an event request made by a user for the specified event with the provided handler function.
|
|
382
|
+
|
|
383
|
+
- `broadcast(event: string, payload: PondMessage, channelName?: string): void`: Broadcasts a message to all users in the channel with the specified event and payload. Optionally, a specific channel name can be provided to broadcast the message only to users in that channel.
|
|
384
|
+
|
|
385
|
+
- `onLeave(handler: (event: LeaveEvent) => void | Promise<void>): void`: Handles a leave event for the channel with the provided handler function when a user leaves the channel.
|
|
386
|
+
|
|
387
|
+
### EventRequest
|
|
388
|
+
|
|
389
|
+
The `EventRequest` class represents the request object when an event is received from a client.
|
|
390
|
+
|
|
391
|
+
**Properties:**
|
|
392
|
+
|
|
393
|
+
- `event: PondEvent<Path>`: The event associated with the request.
|
|
394
|
+
|
|
395
|
+
- `channelName: string`: The name of the channel.
|
|
396
|
+
|
|
397
|
+
- `assigns: UserAssigns`: The assigns data for the client.
|
|
398
|
+
|
|
399
|
+
- `presence: UserPresences`: The presence data for the client.
|
|
400
|
+
|
|
401
|
+
- `user: UserData`: The user data associated with the client.
|
|
402
|
+
|
|
403
|
+
- `channel: Channel`: The Channel instance associated with the request.
|
|
404
|
+
|
|
405
|
+
### EventResponse
|
|
406
|
+
|
|
407
|
+
The `EventResponse` class represents the response object for handling events from clients.
|
|
408
|
+
|
|
409
|
+
**Methods:**
|
|
410
|
+
|
|
411
|
+
- `accept(assigns?: PondAssigns): EventResponse`: Accepts the request and optionally assigns data to the client.
|
|
412
|
+
|
|
413
|
+
- `reject(message?: string, errorCode?: number, assigns?: PondAssigns): EventResponse`: Rejects the request with the given error message, optional error code, and optional assigns data.
|
|
414
|
+
|
|
415
|
+
- `send(event: string, payload: PondMessage, assigns?: PondAssigns): void`: Emits a direct message to the client with the specified event, payload, and optional assigns data.
|
|
416
|
+
|
|
417
|
+
- `broadcast(event: string, payload: PondMessage): EventResponse`: Sends a message to all clients in the channel with the specified event and payload.
|
|
418
|
+
|
|
419
|
+
- `broadcastFromUser(event: string, payload: PondMessage): EventResponse`: Sends a message to all clients in the channel except the sender with the specified event and payload.
|
|
420
|
+
|
|
421
|
+
- `sendToUsers(event: string, payload: PondMessage, userIds: string[]): EventResponse`: Sends a message to a specific set of clients identified by the provided userIds with the specified event and payload.
|
|
422
|
+
|
|
423
|
+
- `trackPresence(presence: PondPresence, userId?: string): EventResponse`: Tracks a user's presence in the channel.
|
|
424
|
+
|
|
425
|
+
- `updatePresence(presence: PondPresence, userId?: string): EventResponse`: Updates a user's presence in the channel.
|
|
426
|
+
|
|
427
|
+
- `unTrackPresence(userId?: string): EventResponse`: Removes a user's presence from the channel.
|
|
428
|
+
|
|
429
|
+
- `evictUser(reason: string, userId?: string): void`: Evicts a user from the channel.
|
|
430
|
+
|
|
431
|
+
- `closeChannel(reason: string): void`: Closes the channel from the server-side for all clients.
|
|
432
|
+
|
|
433
|
+
### Channel
|
|
434
|
+
|
|
435
|
+
The `Channel` class represents a single Channel created by the PondSocket server. Note that a PondChannel can have multiple channels associated with it.
|
|
436
|
+
|
|
437
|
+
**Methods:**
|
|
438
|
+
|
|
439
|
+
- `name: string`: The name of the channel.
|
|
440
|
+
|
|
441
|
+
- `getAssigns: UserAssigns`: Gets the current assign data for the client.
|
|
442
|
+
|
|
443
|
+
- `getUserData(userId: string): UserData`: Gets the assign data for a specific user identified by the provided `userId`.
|
|
444
|
+
|
|
445
|
+
- `broadcastMessage(event: string, payload: PondMessage): void`: Broadcasts a message to every client in the channel with the specified event and payload.
|
|
446
|
+
|
|
447
|
+
- `sendToUser(userId: string, event: string, payload: PondMessage): void`: Sends a message to a specific client in the channel identified by the provided `userId`, with the specified event and payload.
|
|
448
|
+
|
|
449
|
+
- `sendToUsers(userIdS: string[], event: string, payload: PondMessage): void`: Sends a message to a specific set of clients identified by the provided `userIdS`, with the specified event and payload.
|
|
450
|
+
|
|
451
|
+
- `evictUser(userId: string, reason?: string): void`: Bans a user from the channel identified by the provided `userId`. Optionally, you can provide a `reason` for the ban.
|
|
452
|
+
|
|
453
|
+
- `trackPresence(userId: string, presence: PondPresence): void`: Tracks a user's presence in the channel identified by the provided `userId`.
|
|
454
|
+
|
|
455
|
+
- `removePresence(userId: string): void`: Removes a user's presence from the channel identified by the provided `userId`.
|
|
456
|
+
|
|
457
|
+
- `updatePresence(userId: string, presence: PondPresence): void`: Updates a user's presence in the channel identified by the provided `userId`.
|
|
458
|
+
|
|
459
|
+
### PondClient
|
|
460
|
+
|
|
461
|
+
The `PondClient` class represents a client that connects to the PondSocket server.
|
|
462
|
+
|
|
463
|
+
**Constructor:**
|
|
464
|
+
|
|
465
|
+
- `constructor(endpoint: string, params?: Record<string, any>)`: Creates a new instance of the PondClient with the provided endpoint URL and optional parameters.
|
|
466
|
+
|
|
467
|
+
**Methods:**
|
|
468
|
+
|
|
469
|
+
- `connect(backoff?: number): void`: Connects to the server with an optional backoff time.
|
|
470
|
+
|
|
471
|
+
- `getState(): boolean`: Returns the current state of the socket.
|
|
472
|
+
|
|
473
|
+
- `disconnect(): void`: Disconnects the socket.
|
|
474
|
+
|
|
475
|
+
- `createChannel(name: string, params?: JoinParams): ClientChannel`: Creates a channel with the given name and optional join parameters.
|
|
476
|
+
|
|
477
|
+
- `onConnectionChange(callback: (state: boolean) => void): Unsubscribe`: Subscribes to the connection state changes and calls the provided callback when the state changes.
|
|
478
|
+
|
|
479
|
+
### ClientChannel
|
|
480
|
+
|
|
481
|
+
The `ClientChannel` class represents a channel in the PondClient.
|
|
482
|
+
|
|
483
|
+
**Methods:**
|
|
484
|
+
|
|
485
|
+
- `join(): void`: Connects to the channel.
|
|
486
|
+
|
|
487
|
+
- `leave(): void`: Disconnects from the channel.
|
|
488
|
+
|
|
489
|
+
- `onMessage(callback: (event: string, message: PondMessage) => void): Unsubscribe`: Monitors the channel for messages and calls the provided callback when a message is received.
|
|
490
|
+
|
|
491
|
+
- `onMessageEvent(event: string, callback: (message: PondMessage) => void): Unsubscribe`: Monitors the channel for messages with the specified event and calls the provided callback when a message is received.
|
|
492
|
+
|
|
493
|
+
- `onChannelStateChange(callback: (connected: ChannelState) => void): Unsubscribe`: Monitors the channel state of the channel and calls the provided callback when the connection state changes.
|
|
494
|
+
|
|
495
|
+
- `onJoin(callback: (presence: PondPresence) => void): Unsubscribe`: Detects when clients join the channel and calls the provided callback when a client joins the channel.
|
|
496
|
+
|
|
497
|
+
- `onLeave(callback: (presence: PondPresence) => void): Unsubscribe`: Detects when clients leave the channel and calls the provided callback when a client leaves the channel.
|
|
498
|
+
|
|
499
|
+
- `onPresenceChange(callback: (presence: PresencePayload) => void): Unsubscribe`: Detects when clients change their presence in the channel and calls the provided callback when a client changes their presence in the channel.
|
|
500
|
+
|
|
501
|
+
- `sendMessage(event: string, payload: PondMessage, recipient: string[]): void`: Sends a message to specific clients in the channel with the specified event, payload, and recipient.
|
|
502
|
+
|
|
503
|
+
- `broadcastFrom(event: string, payload: PondMessage): void`: Broadcasts a message to every other client in the channel except yourself with the specified event and payload.
|
|
504
|
+
|
|
505
|
+
- `broadcast(event: string, payload: PondMessage): void`: Broadcasts a message to the channel, including yourself, with the specified event and payload.
|
|
506
|
+
|
|
507
|
+
- `getPresence(): PondPresence[]`: Gets the current presence of the channel.
|
|
508
|
+
|
|
509
|
+
- `onUsersChange(callback: (users: PondPresence[]) => void): Unsubscribe`: Monitors the presence of the channel and calls the provided callback when the presence changes.
|
|
510
|
+
|
|
511
|
+
- `isConnected(): boolean`: Gets the current connection state of the channel.
|
|
512
|
+
|
|
513
|
+
- `onConnectionChange(callback: (connected: boolean) => void): Unsubscribe`: Monitors the connection state of the channel and calls the provided callback when the connection state changes.
|
|
514
|
+
|
|
515
|
+
## License
|
|
516
|
+
|
|
517
|
+
PondSocket is released under the GPL-3.0 License. Please refer to the `LICENSE` file for detailed licensing information.
|
|
518
|
+
|
|
519
|
+
## Conclusion
|
|
520
|
+
|
|
521
|
+
PondSocket is a powerful and versatile solution for building real-time applications that require efficient bidirectional communication between server and client components. Its minimalist design and comprehensive feature set make it an excellent choice for WebSocket-based projects, providing developers with a straightforward and reliable tool for building real-time communication systems. With the Node.js client, it also allows for easy communication between multiple server instances, expanding its capabilities even further.
|
package/nest.js
CHANGED
|
@@ -20,7 +20,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
20
20
|
return t;
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
-
exports.PondSocketModule = exports.Endpoint = exports.Channel = exports.EndpointInstance = exports.ChannelInstance = exports.
|
|
23
|
+
exports.PondSocketModule = exports.Endpoint = exports.Channel = exports.EndpointInstance = exports.ChannelInstance = exports.OnLeaveEvent = exports.OnEvent = exports.OnJoinRequest = exports.OnConnectionRequest = exports.GetLeaveEvent = exports.GetEventRequest = exports.GetEventResponse = exports.GetEventQuery = exports.GetEventParams = exports.GetEventPayload = exports.GetJoinParams = exports.GetJoinResponse = exports.GetJoinRequest = exports.GetConnectionQuery = exports.GetConnectionHeaders = exports.GetConnectionParams = exports.GetConnectionRequestId = exports.GetConnectionResponse = exports.GetConnectionRequest = exports.GetUserPresences = exports.GetInternalChannel = exports.GetUserData = exports.createParamDecorator = exports.PondGuards = void 0;
|
|
24
24
|
const http_1 = require("http");
|
|
25
25
|
const common_1 = require("@nestjs/common");
|
|
26
26
|
// eslint-disable-next-line import/no-unresolved
|
|
@@ -47,14 +47,11 @@ function createClassDecorator(key, value) {
|
|
|
47
47
|
// eslint-disable-next-line new-cap
|
|
48
48
|
return (0, common_1.applyDecorators)((0, common_1.Injectable)(), (0, common_1.SetMetadata)(key, value));
|
|
49
49
|
}
|
|
50
|
-
function getClassMetadata(key, target) {
|
|
51
|
-
var _a;
|
|
52
|
-
return (_a = Reflect.getMetadata(key, target)) !== null && _a !== void 0 ? _a : null;
|
|
53
|
-
}
|
|
54
50
|
function manageClassData(key, target) {
|
|
55
51
|
return {
|
|
56
52
|
get() {
|
|
57
|
-
|
|
53
|
+
var _a;
|
|
54
|
+
return ((_a = Reflect.getMetadata(key, target)) !== null && _a !== void 0 ? _a : null);
|
|
58
55
|
},
|
|
59
56
|
set(value) {
|
|
60
57
|
Reflect.defineMetadata(key, value, target);
|
|
@@ -62,10 +59,12 @@ function manageClassData(key, target) {
|
|
|
62
59
|
};
|
|
63
60
|
}
|
|
64
61
|
function manageMethodData(key, target, propertyKey) {
|
|
62
|
+
function getter() {
|
|
63
|
+
var _a;
|
|
64
|
+
return ((_a = Reflect.getMetadata(key, target, propertyKey)) !== null && _a !== void 0 ? _a : null);
|
|
65
|
+
}
|
|
65
66
|
return {
|
|
66
|
-
get
|
|
67
|
-
return Reflect.getMetadata(key, target, propertyKey);
|
|
68
|
-
},
|
|
67
|
+
get: getter,
|
|
69
68
|
set(value) {
|
|
70
69
|
Reflect.defineMetadata(key, value, target, propertyKey);
|
|
71
70
|
},
|
|
@@ -90,21 +89,20 @@ function manageHandlers(key, target) {
|
|
|
90
89
|
};
|
|
91
90
|
}
|
|
92
91
|
function manageParameters(target, propertyKey) {
|
|
93
|
-
|
|
94
|
-
var _a;
|
|
95
|
-
return (_a = Reflect.getMetadata(parametersKey, target, propertyKey)) !== null && _a !== void 0 ? _a : [];
|
|
96
|
-
}
|
|
92
|
+
const { get, set } = manageMethodData(parametersKey, target, propertyKey);
|
|
97
93
|
return {
|
|
98
|
-
get
|
|
94
|
+
get() {
|
|
95
|
+
return get() || [];
|
|
96
|
+
},
|
|
99
97
|
set(index, callback) {
|
|
100
|
-
const handlers =
|
|
101
|
-
|
|
98
|
+
const handlers = get() || [];
|
|
99
|
+
set([
|
|
102
100
|
...handlers,
|
|
103
101
|
{
|
|
104
102
|
index,
|
|
105
103
|
callback,
|
|
106
104
|
},
|
|
107
|
-
]
|
|
105
|
+
]);
|
|
108
106
|
},
|
|
109
107
|
};
|
|
110
108
|
}
|
|
@@ -135,13 +133,14 @@ function managePropertyData(key, target) {
|
|
|
135
133
|
}
|
|
136
134
|
function PondGuards(...guards) {
|
|
137
135
|
return (target, propertyKey) => {
|
|
136
|
+
var _a, _b;
|
|
138
137
|
if (propertyKey) {
|
|
139
138
|
const { get, set } = manageMethodData(pondGuardsKey, target, propertyKey);
|
|
140
|
-
set([...get(), ...guards]);
|
|
139
|
+
set([...((_a = get()) !== null && _a !== void 0 ? _a : []), ...guards]);
|
|
141
140
|
}
|
|
142
141
|
else {
|
|
143
142
|
const { get, set } = manageClassData(pondGuardsKey, target);
|
|
144
|
-
set([...get(), ...guards]);
|
|
143
|
+
set([...((_b = get()) !== null && _b !== void 0 ? _b : []), ...guards]);
|
|
145
144
|
}
|
|
146
145
|
};
|
|
147
146
|
}
|
|
@@ -149,11 +148,20 @@ exports.PondGuards = PondGuards;
|
|
|
149
148
|
function resolveGuards(moduleRef, request, target, propertyKey) {
|
|
150
149
|
var _a, _b;
|
|
151
150
|
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
-
const
|
|
153
|
-
|
|
151
|
+
const retrieveGuard = (Guard) => {
|
|
152
|
+
try {
|
|
153
|
+
return moduleRef.get(Guard, { strict: false });
|
|
154
|
+
}
|
|
155
|
+
catch (e) {
|
|
156
|
+
console.warn(`Unable to resolve guard: ${Guard.name}, creating new instance, WARNING: this will not inject dependencies. To fix this, add the guard to the providers array of the PondSocketModule.`);
|
|
157
|
+
return new Guard();
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
const { get: getClassGuards } = manageClassData(pondGuardsKey, target.constructor);
|
|
161
|
+
const { get: getMethodGuards } = manageMethodData(pondGuardsKey, target, propertyKey);
|
|
154
162
|
const classGuards = (_a = getClassGuards()) !== null && _a !== void 0 ? _a : [];
|
|
155
163
|
const methodGuards = (_b = getMethodGuards()) !== null && _b !== void 0 ? _b : [];
|
|
156
|
-
const instances = [...classGuards, ...methodGuards].map((guard) =>
|
|
164
|
+
const instances = [...classGuards, ...methodGuards].map((guard) => retrieveGuard(guard));
|
|
157
165
|
const promises = instances.map((instance) => instance.canActivate(request));
|
|
158
166
|
const results = yield Promise.all(promises);
|
|
159
167
|
return results.every((result) => result);
|
|
@@ -336,20 +344,26 @@ function GetEventPayload() {
|
|
|
336
344
|
exports.GetEventPayload = GetEventPayload;
|
|
337
345
|
function GetEventParams() {
|
|
338
346
|
return createParamDecorator((_, request) => {
|
|
339
|
-
const { eventRequest } = request;
|
|
347
|
+
const { eventRequest, joinRequest } = request;
|
|
340
348
|
if (eventRequest) {
|
|
341
349
|
return eventRequest.event.params;
|
|
342
350
|
}
|
|
351
|
+
else if (joinRequest) {
|
|
352
|
+
return joinRequest.event.params;
|
|
353
|
+
}
|
|
343
354
|
throw new Error('Invalid decorator usage: GetEventParams');
|
|
344
355
|
})(null);
|
|
345
356
|
}
|
|
346
357
|
exports.GetEventParams = GetEventParams;
|
|
347
358
|
function GetEventQuery() {
|
|
348
359
|
return createParamDecorator((_, request) => {
|
|
349
|
-
const { eventRequest } = request;
|
|
360
|
+
const { eventRequest, joinRequest } = request;
|
|
350
361
|
if (eventRequest) {
|
|
351
362
|
return eventRequest.event.query;
|
|
352
363
|
}
|
|
364
|
+
else if (joinRequest) {
|
|
365
|
+
return joinRequest.event.query;
|
|
366
|
+
}
|
|
353
367
|
throw new Error('Invalid decorator usage: GetEventQuery');
|
|
354
368
|
})(null);
|
|
355
369
|
}
|
|
@@ -396,7 +410,7 @@ function OnConnectionRequest() {
|
|
|
396
410
|
const res = {
|
|
397
411
|
connection: response,
|
|
398
412
|
};
|
|
399
|
-
const canProceed = yield resolveGuards(moduleRef, req,
|
|
413
|
+
const canProceed = yield resolveGuards(moduleRef, req, instance, propertyKey);
|
|
400
414
|
if (canProceed) {
|
|
401
415
|
const data = yield originalMethod.apply(instance, resolveParameters(req, res, target, propertyKey));
|
|
402
416
|
if (!response.hasResponded) {
|
|
@@ -441,7 +455,7 @@ function OnJoinRequest() {
|
|
|
441
455
|
const res = {
|
|
442
456
|
joinResponse: response,
|
|
443
457
|
};
|
|
444
|
-
const canProceed = yield resolveGuards(moduleRef, req,
|
|
458
|
+
const canProceed = yield resolveGuards(moduleRef, req, instance, propertyKey);
|
|
445
459
|
if (canProceed) {
|
|
446
460
|
const data = yield originalMethod.apply(instance, resolveParameters(req, res, target, propertyKey));
|
|
447
461
|
if (!response.hasResponded) {
|
|
@@ -475,25 +489,6 @@ function OnJoinRequest() {
|
|
|
475
489
|
};
|
|
476
490
|
}
|
|
477
491
|
exports.OnJoinRequest = OnJoinRequest;
|
|
478
|
-
function OnLeaveEvent() {
|
|
479
|
-
return (target, propertyKey, descriptor) => {
|
|
480
|
-
const originalMethod = descriptor.value;
|
|
481
|
-
const { set } = manageOnLeaveHandlers(target);
|
|
482
|
-
set('', (instance, _, event) => __awaiter(this, void 0, void 0, function* () {
|
|
483
|
-
try {
|
|
484
|
-
yield originalMethod.apply(instance, resolveParameters({
|
|
485
|
-
leveeEvent: event,
|
|
486
|
-
}, {}, target, propertyKey));
|
|
487
|
-
}
|
|
488
|
-
catch (error) {
|
|
489
|
-
if (error instanceof Error) {
|
|
490
|
-
console.error(error.message);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
}));
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
exports.OnLeaveEvent = OnLeaveEvent;
|
|
497
492
|
function OnEvent(event = '*') {
|
|
498
493
|
return (target, propertyKey, descriptor) => {
|
|
499
494
|
const originalMethod = descriptor.value;
|
|
@@ -508,7 +503,7 @@ function OnEvent(event = '*') {
|
|
|
508
503
|
const res = {
|
|
509
504
|
eventResponse: response,
|
|
510
505
|
};
|
|
511
|
-
const canProceed = yield resolveGuards(moduleRef, req,
|
|
506
|
+
const canProceed = yield resolveGuards(moduleRef, req, instance, propertyKey);
|
|
512
507
|
if (canProceed) {
|
|
513
508
|
const data = yield originalMethod.apply(instance, resolveParameters(req, res, target, propertyKey));
|
|
514
509
|
if (!response.hasResponded) {
|
|
@@ -545,6 +540,25 @@ function OnEvent(event = '*') {
|
|
|
545
540
|
};
|
|
546
541
|
}
|
|
547
542
|
exports.OnEvent = OnEvent;
|
|
543
|
+
function OnLeaveEvent() {
|
|
544
|
+
return (target, propertyKey, descriptor) => {
|
|
545
|
+
const originalMethod = descriptor.value;
|
|
546
|
+
const { set } = manageOnLeaveHandlers(target);
|
|
547
|
+
set('', (instance, _, event) => __awaiter(this, void 0, void 0, function* () {
|
|
548
|
+
try {
|
|
549
|
+
yield originalMethod.apply(instance, resolveParameters({
|
|
550
|
+
leveeEvent: event,
|
|
551
|
+
}, {}, target, propertyKey));
|
|
552
|
+
}
|
|
553
|
+
catch (error) {
|
|
554
|
+
if (error instanceof Error) {
|
|
555
|
+
console.error(error.message);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}));
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
exports.OnLeaveEvent = OnLeaveEvent;
|
|
548
562
|
function ChannelInstance(name) {
|
|
549
563
|
return (target, propertyKey) => {
|
|
550
564
|
const { build } = manageChannelInstance(target);
|
|
@@ -570,7 +584,7 @@ const setEndpoint = (path = '*') => createClassDecorator(endpointClassKey, path)
|
|
|
570
584
|
const setChannels = (channels) => createClassDecorator(channelsClassKey, channels);
|
|
571
585
|
const getChannels = (target) => {
|
|
572
586
|
var _a;
|
|
573
|
-
return (_a =
|
|
587
|
+
return (_a = manageClassData(channelsClassKey, target).get()) !== null && _a !== void 0 ? _a : [];
|
|
574
588
|
};
|
|
575
589
|
const Endpoint = (metadata) => (0, common_1.applyDecorators)(setChannels(metadata.channels), setEndpoint(metadata.path));
|
|
576
590
|
exports.Endpoint = Endpoint;
|
|
@@ -589,7 +603,7 @@ class PondSocketService {
|
|
|
589
603
|
};
|
|
590
604
|
}
|
|
591
605
|
manageEndpoint(socket, endpoint) {
|
|
592
|
-
const endpointMetadata =
|
|
606
|
+
const endpointMetadata = manageClassData(endpointClassKey, endpoint).get();
|
|
593
607
|
if (!endpointMetadata) {
|
|
594
608
|
return;
|
|
595
609
|
}
|
|
@@ -611,7 +625,7 @@ class PondSocketService {
|
|
|
611
625
|
});
|
|
612
626
|
}
|
|
613
627
|
manageChannel(channel, endpoint) {
|
|
614
|
-
const channelMetadata =
|
|
628
|
+
const channelMetadata = manageClassData(channelClassKey, channel).get();
|
|
615
629
|
if (!channelMetadata) {
|
|
616
630
|
return;
|
|
617
631
|
}
|
|
@@ -652,8 +666,8 @@ class PondSocketModule {
|
|
|
652
666
|
inject: [core_1.ModuleRef, core_1.HttpAdapterHost],
|
|
653
667
|
};
|
|
654
668
|
return {
|
|
669
|
+
imports,
|
|
655
670
|
module: PondSocketModule,
|
|
656
|
-
imports: [...imports, ...endpoints, ...channels],
|
|
657
671
|
providers: [...providers, ...endpoints, ...channels, pondSocketProvider],
|
|
658
672
|
exports: [...exports, ...channels],
|
|
659
673
|
global: isGlobal,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eleven-am/pondsocket",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.95",
|
|
4
4
|
"description": "PondSocket is a fast simple socket server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"socket",
|
|
@@ -29,12 +29,13 @@
|
|
|
29
29
|
"url": "git+https://github.com/Eleven-am/pondSocket.git"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
+
"@nestjs/common": "^10.3.0",
|
|
33
|
+
"@nestjs/core": "^10.3.0",
|
|
34
|
+
"reflect-metadata": "^0.1.14",
|
|
32
35
|
"websocket": "^1.0.34",
|
|
33
36
|
"ws": "^8.15.1"
|
|
34
37
|
},
|
|
35
38
|
"devDependencies": {
|
|
36
|
-
"@nestjs/common": "^10.3.0",
|
|
37
|
-
"@nestjs/core": "^10.3.0",
|
|
38
39
|
"@types/express": "^4.17.21",
|
|
39
40
|
"@types/jest": "^29.5.11",
|
|
40
41
|
"@types/node": "^20.10.5",
|
|
@@ -45,7 +46,6 @@
|
|
|
45
46
|
"eslint-plugin-file-progress": "^1.3.0",
|
|
46
47
|
"eslint-plugin-import": "^2.29.1",
|
|
47
48
|
"jest": "^29.7.0",
|
|
48
|
-
"reflect-metadata": "^0.1.14",
|
|
49
49
|
"superwstest": "^2.0.3",
|
|
50
50
|
"ts-jest": "^29.1.1",
|
|
51
51
|
"ts-node": "^10.9.2",
|
package/types.d.ts
CHANGED
|
@@ -836,7 +836,7 @@ declare function DEndpoint(metadata: EndpointMetadata): ClassDecorator;
|
|
|
836
836
|
* Decorator to add a guard to a class or method.
|
|
837
837
|
* @param guards - The guards to add.
|
|
838
838
|
*/
|
|
839
|
-
declare function PondGuards (...guards: Constructor<CanActivate>[]):
|
|
839
|
+
declare function PondGuards (...guards: Constructor<CanActivate>[]): MethodDecorator & ClassDecorator;
|
|
840
840
|
|
|
841
841
|
declare class PondSocketModule {
|
|
842
842
|
/**
|