@eleven-am/pondsocket 0.1.210 → 0.1.212

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 CHANGED
@@ -14,60 +14,6 @@ npm install @eleven-am/pondsocket
14
14
 
15
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
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
-
35
- 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.
36
-
37
- ```javascript
38
- const channel = endpoint.createChannel('/channel/:id', (req, res) => {
39
- // Handle the join request, which is sent when a user attempts to join the channel
40
- });
41
- ```
42
-
43
- ## Client-side Usage
44
-
45
- 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.
46
-
47
- ```javascript
48
- import PondClient from "@eleven-am/pondsocket-client";
49
-
50
- const socket = new PondClient('/api/socket', {});
51
- socket.connect();
52
- ```
53
-
54
- Once connected, clients can create and join channels to engage in real-time communication with other users and the server.
55
-
56
- ```javascript
57
- const channel = socket.createChannel('/channel/123');
58
- channel.join();
59
- ```
60
-
61
- ### Node Client
62
-
63
- PondSocket also offers a Node.js client, which can be imported using:
64
-
65
- ```javascript
66
- import PondClient from "@eleven-am/pondsocket-client";
67
- ```
68
-
69
- This node client allows you to turn another server into a client, enabling easy communication between different server instances.
70
-
71
17
  ## Key Features
72
18
 
73
19
  - **Simple and Efficient API**: PondSocket offers an easy-to-use API, making WebSocket communication straightforward and hassle-free.
@@ -75,437 +21,192 @@ This node client allows you to turn another server into a client, enabling easy
75
21
  - **Assigns**: PondSocket allows the storage of private information for users and channels, enhancing data security.
76
22
  - **Presence**: The presence feature keeps track of users' current states and notifies other users about any changes.
77
23
  - **Broadcasting**: PondSocket enables broadcasting messages to all users or specific groups within a channel, facilitating real-time updates.
78
- - **Typed and Well-documented**: The codebase is thoroughly documented and typed, providing a seamless development experience with improved IDE suggestions.
24
+ - **Type Safety**: The codebase is thoroughly typed with TypeScript, providing a seamless development experience with improved IDE suggestions.
25
+ - **Middleware Support**: Extensible middleware system for request processing and validation.
26
+ - **Distributed Support**: Built-in support for distributed deployment with state synchronization.
79
27
 
80
- ## Examples
81
-
82
- ### Client-side Example with Authentication
83
-
84
- To connect to the PondSocket server and send messages while associating a username with the client connection, follow the steps below:
85
-
86
- ```javascript
87
- import PondClient from "@eleven-am/pondsocket-client";
88
-
89
- // Your server URL
90
- const serverUrl = 'ws://your-server-url/api/socket';
91
-
92
- // Your authenticated user's token (replace with actual token)
93
- const authToken = 'your-auth-token';
94
-
95
- // Your username (replace with actual username)
96
- const username = 'user123';
97
-
98
- // Create a new PondClient instance
99
- const socket = new PondClient(serverUrl, { token: authToken });
100
-
101
- // Connect to the server
102
- socket.connect();
103
-
104
- // Add event listeners to handle various scenarios
105
- socket.onConnectionChange((connected) => {
106
- if (connected) {
107
- console.log('Connected to the server.');
108
- } else {
109
- console.log('Disconnected from the server.');
110
- }
111
- });
112
-
113
- // Create a channel and join it
114
- const channel = socket.createChannel('/channel/123', { username });
115
- channel.join();
116
-
117
- // Send a message to the server
118
- const message = "Hello, PondSocket!";
119
- channel.broadcast('message', { text: message });
120
-
121
- // Handle received messages
122
- // Certain methods in the channel instance returns a subscription function, which can be used to unsubscribe from the event
123
- const subscription = channel.onMessage((event, message) => {
124
- console.log(`Received message from server: ${message.text}`);
125
- });
126
-
127
- // Unsubscribe from the event
128
- subscription();
129
- ```
130
-
131
- 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.
132
-
133
- ### Server-side Example with Authentication and check for profanity before broadcasting
28
+ ## Server-side Usage
134
29
 
135
- To create a PondSocket server that accepts authenticated connections and checks for profanity before broadcasting messages, follow the steps below:
30
+ 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.
136
31
 
137
- ```javascript
32
+ ```typescript
138
33
  import PondSocket from "@eleven-am/pondsocket";
139
34
 
140
- // Helper functions for token validation
141
- function isValidToken(token) {
142
- // Implement your token validation logic here
143
- // Return true if the token is valid, false otherwise
144
- return true;
145
- }
146
-
147
- function getRoleFromToken(token) {
148
- // Implement the logic to extract the user's role from the token
149
- // Return the user's role
150
- return 'user';
151
- }
152
-
153
- function isTextProfane(text) {
154
- // Implement your profanity check logic here
155
- // Return true if the text is profane, false otherwise
156
- return false;
157
- }
158
-
159
- function getMessagesFromDatabase(channelId) {
160
- // Implement your logic to retrieve messages from the database
161
- // Return an array of messages
162
- return [];
163
- }
164
-
165
35
  const pond = new PondSocket();
166
36
 
167
37
  // Create an endpoint for handling socket connections
168
- const endpoint = pond.createEndpoint('/api/socket', (req, res) => {
169
- // Depending if the user already has cookies set, they can be accessed from the request headers or the request address
170
- const token = req.query.token; // If the token is passed as a query parameter
171
-
172
- // Perform token validation here
38
+ const endpoint = pond.createEndpoint('/api/socket', (ctx, next) => {
39
+ // Handle socket connection and authentication
40
+ const token = ctx.request.query.token;
41
+
173
42
  if (isValidToken(token)) {
174
- // Extract the authenticated user's username
175
43
  const role = getRoleFromToken(token);
176
-
177
- // Handle socket connection and authentication for valid users
178
- res.accept({role}); // Assign the user's role to the socket
44
+ ctx.accept({ role }); // Assign the user's role to the socket
179
45
  } else {
180
- // Reject the connection for invalid users or without a token
181
- res.reject('Invalid token', 401);
46
+ ctx.reject('Invalid token', 401);
182
47
  }
183
48
  });
184
49
 
185
- // Create a channel, providing a callback that is called when a user attempts to join the channel
186
- const profanityChannel = endpoint.createChannel('/channel/:id', async (req, res) => {
187
- // When joining the channel, any joinParams passed from the client will be available in the request payload
188
- // Also any previous assigns on the socket will be available in the request payload as well
189
- const {role} = req.user.assigns;
190
- const {username} = req.joinParams;
191
- const {id} = req.event.params;
192
-
193
- // maybe retrieve the previous messages from the database
194
- const messages = await getMessagesFromDatabase(id);
50
+ // Create a channel with path parameters
51
+ const channel = endpoint.createChannel('/channel/:id', (ctx, next) => {
52
+ const { role } = ctx.user.assigns;
53
+ const { username } = ctx.joinParams;
54
+ const { id } = ctx.event.params;
195
55
 
196
- // Check if the user has the required role to join the channel
197
56
  if (role === 'admin') {
198
- // Accept the join request
199
- res.accept({username, profanityCount: 0})
200
- // optionally you can track the presence of the user in the channel
57
+ ctx.accept({ username })
201
58
  .trackPresence({
202
59
  username,
203
60
  role,
204
61
  status: 'online',
205
62
  onlineSince: Date.now(),
206
- })
207
- // and send the user the channel history
208
- .sendToUsers('history', {messages}, [req.user.id]);
209
-
210
- // Alternatively, you can also send messages to the user, NOTE that the user would be automatically subscribed to the channel.
211
- // res.send('history', { messages }, { username, profanityCount: 0 })
212
- // .trackPresence({
213
- // username,
214
- // role,
215
- // status: 'online',
216
- // onlineSince: Date.now(),
217
- // });
63
+ });
218
64
  } else {
219
- // Reject the join request
220
- res.decline('You do not have the required role to join this channel', 403);
65
+ ctx.decline('Insufficient permissions', 403);
221
66
  }
222
67
  });
223
68
 
224
- // Attach message event listener to the profanityChannel
225
- profanityChannel.onEvent('message', (req, res) => {
226
- const {text} = req.event.payload;
227
-
228
- // Check for profanity
229
- if (isTextProfane(text)) {
230
- // Reject the message if it contains profanity
231
- res.decline('Profanity is not allowed', 400, {
232
- profanityCount: req.user.assigns.profanityCount + 1
233
- });
234
-
235
- // note that profanityCount is updated so req.user.assigns.profanityCount will be updated
236
- if (req.user.assigns.profanityCount >= 3) {
237
- // Kick the user from the channel if they have used profanity more than 3 times
238
- res.evictUser('You have been kicked from the channel for using profanity');
239
- } else {
240
- // you can broadcast a message to all users or In the channel that profanity is not allowed
241
- res.broadcast('profanity-warning', {message: 'Profanity is not allowed'})
242
- // or you can send a message to the user that profanity is not allowed
243
- .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]);
244
- }
245
- } else {
246
- // Accept the message to allow broadcasting to other clients in the channel
247
- res.accept();
248
- }
249
-
250
- // for more complete access to the channel, you can use the channel instance
251
- // const channel = req.channel;
252
- });
253
-
254
- profanityChannel.onEvent('presence/:presence', (req, res) => {
255
- const {presence} = req.event.params;
256
- const {username} = req.user.assigns;
257
-
258
- // Handle presence events
259
- res.updatePresence({
260
- username,
261
- role,
262
- onlineSince: Date.now(),
263
- status: presence,
264
- });
265
- });
266
-
267
- profanityChannel.onLeave((event) => {
268
- const {username} = event.assigns;
269
-
270
- // When a user leaves the channel, PondSocket will automatically remove the user from the presence list and inform other users in the channel
271
-
272
- // perform a cleanup operation here
69
+ // Handle channel events
70
+ channel.onEvent('message', (ctx, next) => {
71
+ const { text } = ctx.event.payload;
72
+
73
+ // Broadcast to all users in the channel
74
+ ctx.broadcast('message', { text });
75
+
76
+ // Or broadcast to specific users
77
+ ctx.broadcastTo(['user1', 'user2'], 'message', { text });
78
+
79
+ // Or broadcast to all except sender
80
+ ctx.broadcastFrom('message', { text });
273
81
  });
274
82
 
275
83
  // Start the server
276
- pond.listen(3000, () => {
277
- console.log('PondSocket server listening on port 3000');
278
- });
84
+ pond.listen(3000);
279
85
  ```
280
86
 
281
- ## API Documentation
282
-
283
- ### PondSocket
284
-
285
- The `PondSocket` class is the core class that represents the socket server.
286
-
287
- **Constructor:**
288
-
289
- - `constructor(server?: HTTPServer, socketServer?: WebSocketServer)`: Creates a new instance of the PondSocket with an optional HTTP server and WebSocket server.
290
-
291
- **Methods:**
292
-
293
- - `listen(...args: any[]): HTTPServer`: Specifies the port to listen on with the provided arguments.
294
-
295
- - `close(callback?: () => void): HTTPServer`: Closes the server, and an optional callback can be provided.
296
-
297
- - `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.
298
-
299
- ### ConnectionResponse
300
-
301
- The `ConnectionResponse` class represents the response object for the incoming connection.
302
-
303
- **Methods:**
304
-
305
- - `accept(assigns?: PondAssigns): void`: Accepts the request and optionally assigns data to the client.
306
-
307
- - `reject(message?: string, errorCode?: number): void`: Rejects the request with the given error message and optional error code.
308
-
309
- - `send(event: string, payload: PondMessage, assigns?: PondAssigns): void`: Emits a direct message to the client with the specified event and payload.
310
-
311
- ### Endpoint
312
-
313
- The `Endpoint` class represents an endpoint in the PondSocket server where channels can be created.
314
-
315
- **Methods:**
316
-
317
- - `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.
318
-
319
- - `broadcast(event: string, payload: PondMessage): void`: Broadcasts a message to all clients connected to this endpoint with the specified event and payload.
320
-
321
- - `closeConnection(clientIds: string | string[]): void`: Closes specific clients connected to this endpoint identified by the provided clientIds.
322
-
323
- ### JoinRequest
324
-
325
- The `JoinRequest` class represents the request object when a client joins a channel.
326
-
327
- **Properties:**
328
-
329
- - `event: PondEvent<Path>`: The event associated with the request.
330
-
331
- - `channelName: string`: The name of the channel.
332
-
333
- - `assigns: UserAssigns`: The assigns data for the client.
334
-
335
- - `presence: UserPresences`: The presence data for the client.
336
-
337
- - `joinParams: JoinParams`: The join parameters for the client.
338
-
339
- - `user: UserData`: The user data associated with the client.
340
-
341
- - `channel: Channel`: The Channel instance associated with the request.
342
-
343
- ### JoinResponse
344
-
345
- The `JoinResponse` class represents the response object for the join request.
346
-
347
- **Methods:**
348
-
349
- - `accept(assigns?: PondAssigns): JoinResponse`: Accepts the join request and optionally assigns data to the client.
350
-
351
- - `reject(message?: string, errorCode?: number): JoinResponse`: Rejects the join request with the given error message and optional error code.
352
-
353
- - `send(event: string, payload: PondMessage, assigns?: PondAssigns): JoinResponse`: Emits a direct message to the client with the specified event, payload, and optional assigns data.
354
-
355
- - `broadcast(event: string, payload: PondMessage): JoinResponse`: Emits a message to all clients in the channel with the specified event and payload.
356
-
357
- - `broadcastFromUser(event: string, payload: PondMessage): JoinResponse`: Emits a message to all clients in the channel except the sender with the specified event and payload.
358
-
359
- - `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.
360
-
361
- - `trackPresence(presence: PondPresence): JoinResponse`: Tracks the presence of the client in the channel.
362
-
363
- ### PondChannel
364
-
365
- The `PondChannel` class represents a Generic channel in the PondSocket server. It is used to create a channel whose path matches the provided PondPath.
366
-
367
- **Methods:**
368
-
369
- - `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.
370
-
371
- - `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.
372
-
373
- - `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.
374
-
375
- ### EventRequest
376
-
377
- The `EventRequest` class represents the request object when an event is received from a client.
378
-
379
- **Properties:**
380
-
381
- - `event: PondEvent<Path>`: The event associated with the request.
382
-
383
- - `channelName: string`: The name of the channel.
384
-
385
- - `assigns: UserAssigns`: The assigns data for the client.
386
-
387
- - `presence: UserPresences`: The presence data for the client.
388
-
389
- - `user: UserData`: The user data associated with the client.
390
-
391
- - `channel: Channel`: The Channel instance associated with the request.
392
-
393
- ### EventResponse
394
-
395
- The `EventResponse` class represents the response object for handling events from clients.
396
-
397
- **Methods:**
398
-
399
- - `accept(assigns?: PondAssigns): EventResponse`: Accepts the request and optionally assigns data to the client.
400
-
401
- - `reject(message?: string, errorCode?: number, assigns?: PondAssigns): EventResponse`: Rejects the request with the given error message, optional error code, and optional assigns data.
402
-
403
- - `send(event: string, payload: PondMessage, assigns?: PondAssigns): void`: Emits a direct message to the client with the specified event, payload, and optional assigns data.
404
-
405
- - `broadcast(event: string, payload: PondMessage): EventResponse`: Sends a message to all clients in the channel with the specified event and payload.
406
-
407
- - `broadcastFromUser(event: string, payload: PondMessage): EventResponse`: Sends a message to all clients in the channel except the sender with the specified event and payload.
408
-
409
- - `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.
410
-
411
- - `trackPresence(presence: PondPresence, userId?: string): EventResponse`: Tracks a user's presence in the channel.
412
-
413
- - `updatePresence(presence: PondPresence, userId?: string): EventResponse`: Updates a user's presence in the channel.
414
-
415
- - `unTrackPresence(userId?: string): EventResponse`: Removes a user's presence from the channel.
416
-
417
- - `evictUser(reason: string, userId?: string): void`: Evicts a user from the channel.
418
-
419
- - `closeChannel(reason: string): void`: Closes the channel from the server-side for all clients.
420
-
421
- ### Channel
422
-
423
- The `Channel` class represents a single Channel created by the PondSocket server. Note that a PondChannel can have multiple channels associated with it.
424
-
425
- **Methods:**
426
-
427
- - `name: string`: The name of the channel.
428
-
429
- - `getAssigns: UserAssigns`: Gets the current assign data for the client.
430
-
431
- - `getUserData(userId: string): UserData`: Gets the assign data for a specific user identified by the provided `userId`.
432
-
433
- - `broadcastMessage(event: string, payload: PondMessage): void`: Broadcasts a message to every client in the channel with the specified event and payload.
434
-
435
- - `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.
436
-
437
- - `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.
438
-
439
- - `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.
440
-
441
- - `trackPresence(userId: string, presence: PondPresence): void`: Tracks a user's presence in the channel identified by the provided `userId`.
442
-
443
- - `removePresence(userId: string): void`: Removes a user's presence from the channel identified by the provided `userId`.
444
-
445
- - `updatePresence(userId: string, presence: PondPresence): void`: Updates a user's presence in the channel identified by the provided `userId`.
446
-
447
- ### PondClient
448
-
449
- The `PondClient` class represents a client that connects to the PondSocket server.
87
+ ## Client-side Usage
450
88
 
451
- **Constructor:**
89
+ 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.
452
90
 
453
- - `constructor(endpoint: string, params?: Record<string, any>)`: Creates a new instance of the PondClient with the provided endpoint URL and optional parameters.
91
+ ```typescript
92
+ import PondClient from "@eleven-am/pondsocket-client";
454
93
 
455
- **Methods:**
94
+ // Create a new client instance
95
+ const socket = new PondClient('ws://your-server/api/socket', {
96
+ token: 'your-auth-token'
97
+ });
456
98
 
457
- - `connect(backoff?: number): void`: Connects to the server with an optional backoff time.
99
+ // Connect to the server
100
+ socket.connect();
458
101
 
459
- - `getState(): boolean`: Returns the current state of the socket.
102
+ // Handle connection state changes
103
+ socket.onConnectionChange((connected) => {
104
+ if (connected) {
105
+ console.log('Connected to the server');
106
+ } else {
107
+ console.log('Disconnected from the server');
108
+ }
109
+ });
460
110
 
461
- - `disconnect(): void`: Disconnects the socket.
111
+ // Create and join a channel
112
+ const channel = socket.createChannel('/channel/123', {
113
+ username: 'user123'
114
+ });
462
115
 
463
- - `createChannel(name: string, params?: JoinParams): ClientChannel`: Creates a channel with the given name and optional join parameters.
116
+ // Join the channel
117
+ channel.join();
464
118
 
465
- - `onConnectionChange(callback: (state: boolean) => void): Unsubscribe`: Subscribes to the connection state changes and calls the provided callback when the state changes.
119
+ // Handle channel events
120
+ const subscription = channel.onMessage((event, message) => {
121
+ console.log(`Received message: ${message.text}`);
122
+ });
466
123
 
467
- ### ClientChannel
124
+ // Send a message
125
+ channel.broadcast('message', { text: 'Hello, PondSocket!' });
468
126
 
469
- The `ClientChannel` class represents a channel in the PondClient.
127
+ // Leave the channel
128
+ channel.leave();
470
129
 
471
- **Methods:**
130
+ // Unsubscribe from events
131
+ subscription();
132
+ ```
472
133
 
473
- - `join(): void`: Connects to the channel.
134
+ ## Advanced Features
474
135
 
475
- - `leave(): void`: Disconnects from the channel.
136
+ ### Presence Management
476
137
 
477
- - `onMessage(callback: (event: string, message: PondMessage) => void): Unsubscribe`: Monitors the channel for messages and calls the provided callback when a message is received.
138
+ ```typescript
139
+ // Server-side
140
+ channel.onEvent('presence', (ctx, next) => {
141
+ ctx.trackPresence({
142
+ username: ctx.user.assigns.username,
143
+ status: 'online',
144
+ lastSeen: Date.now()
145
+ });
146
+ });
478
147
 
479
- - `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.
148
+ // Client-side
149
+ channel.onPresence((presences) => {
150
+ console.log('Current users:', presences);
151
+ });
152
+ ```
480
153
 
481
- - `onChannelStateChange(callback: (connected: ChannelState) => void): Unsubscribe`: Monitors the channel state of the channel and calls the provided callback when the connection state changes.
154
+ ### User Assigns
482
155
 
483
- - `onJoin(callback: (presence: PondPresence) => void): Unsubscribe`: Detects when clients join the channel and calls the provided callback when a client joins the channel.
156
+ ```typescript
157
+ // Server-side
158
+ channel.onEvent('update-profile', (ctx, next) => {
159
+ ctx.assign({
160
+ ...ctx.user.assigns,
161
+ profile: ctx.event.payload
162
+ });
163
+ });
484
164
 
485
- - `onLeave(callback: (presence: PondPresence) => void): Unsubscribe`: Detects when clients leave the channel and calls the provided callback when a client leaves the channel.
165
+ // Client-side
166
+ channel.onAssigns((assigns) => {
167
+ console.log('User data updated:', assigns);
168
+ });
169
+ ```
486
170
 
487
- - `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.
171
+ ### Error Handling
488
172
 
489
- - `sendMessage(event: string, payload: PondMessage, recipient: string[]): void`: Sends a message to specific clients in the channel with the specified event, payload, and recipient.
173
+ ```typescript
174
+ // Server-side
175
+ channel.onEvent('message', (ctx, next) => {
176
+ try {
177
+ // Your logic here
178
+ ctx.accept();
179
+ } catch (error) {
180
+ ctx.decline(error.message, 400);
181
+ }
182
+ });
490
183
 
491
- - `sendForResponse(event: string, payload: PondMessage): Promise<PondMessage>`: Sends a message to the server with the specified event, payload, and returns a promise that resolves with the response.
184
+ // Client-side
185
+ channel.onError((error) => {
186
+ console.error('Channel error:', error);
187
+ });
188
+ ```
492
189
 
493
- - `broadcastFrom(event: string, payload: PondMessage): void`: Broadcasts a message to every other client in the channel except yourself with the specified event and payload.
190
+ ## Distributed Deployment
494
191
 
495
- - `broadcast(event: string, payload: PondMessage): void`: Broadcasts a message to the channel, including yourself, with the specified event and payload.
192
+ PondSocket supports distributed deployment through its distributed backend system. This allows you to scale your application across multiple nodes while maintaining state synchronization.
496
193
 
497
- - `getPresence(): PondPresence[]`: Gets the current presence of the channel.
194
+ ```typescript
195
+ import PondSocket from "@eleven-am/pondsocket";
196
+ import { RedisBackend } from "@eleven-am/pondsocket";
498
197
 
499
- - `onUsersChange(callback: (users: PondPresence[]) => void): Unsubscribe`: Monitors the presence of the channel and calls the provided callback when the presence changes.
198
+ const pond = new PondSocket({
199
+ backend: new RedisBackend({
200
+ host: 'localhost',
201
+ port: 6379
202
+ })
203
+ });
204
+ ```
500
205
 
501
- - `isConnected(): boolean`: Gets the current connection state of the channel.
206
+ ## Contributing
502
207
 
503
- - `onConnectionChange(callback: (connected: boolean) => void): Unsubscribe`: Monitors the connection state of the channel and calls the provided callback when the connection state changes.
208
+ Contributions are welcome! Please feel free to submit a Pull Request.
504
209
 
505
210
  ## License
506
211
 
507
- PondSocket is released under the GPL-3.0 License. Please refer to the `LICENSE` file for detailed licensing information.
508
-
509
- ## Conclusion
510
-
511
- 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.
212
+ This project is licensed under the GPL-3.0 License - see the LICENSE file for details.
@@ -430,7 +430,6 @@ _ChannelEngine_endpointId = new WeakMap(), _ChannelEngine_backend = new WeakMap(
430
430
  __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_handleDistributedMessage).call(this, message);
431
431
  }), "f");
432
432
  }, _ChannelEngine_handleDistributedMessage = function _ChannelEngine_handleDistributedMessage(message) {
433
- console.log(message);
434
433
  switch (message.type) {
435
434
  case types_1.DistributedMessageType.STATE_REQUEST:
436
435
  __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_handleStateRequest).call(this, message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eleven-am/pondsocket",
3
- "version": "0.1.210",
3
+ "version": "0.1.212",
4
4
  "description": "PondSocket is a fast simple socket server",
5
5
  "keywords": [
6
6
  "socket",