@eleven-am/pondsocket 0.1.141 → 0.1.142

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
@@ -175,7 +175,7 @@ const endpoint = pond.createEndpoint('/api/socket', (req, res) => {
175
175
  const role = getRoleFromToken(token);
176
176
 
177
177
  // Handle socket connection and authentication for valid users
178
- res.accept({ role }); // Assign the user's role to the socket
178
+ res.accept({role}); // Assign the user's role to the socket
179
179
  } else {
180
180
  // Reject the connection for invalid users or without a token
181
181
  res.reject('Invalid token', 401);
@@ -186,9 +186,9 @@ const endpoint = pond.createEndpoint('/api/socket', (req, res) => {
186
186
  const profanityChannel = endpoint.createChannel('/channel/:id', async (req, res) => {
187
187
  // When joining the channel, any joinParams passed from the client will be available in the request payload
188
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;
189
+ const {role} = req.user.assigns;
190
+ const {username} = req.joinParams;
191
+ const {id} = req.event.params;
192
192
 
193
193
  // maybe retrieve the previous messages from the database
194
194
  const messages = await getMessagesFromDatabase(id);
@@ -196,7 +196,7 @@ const profanityChannel = endpoint.createChannel('/channel/:id', async (req, res)
196
196
  // Check if the user has the required role to join the channel
197
197
  if (role === 'admin') {
198
198
  // Accept the join request
199
- res.accept({ username, profanityCount: 0 })
199
+ res.accept({username, profanityCount: 0})
200
200
  // optionally you can track the presence of the user in the channel
201
201
  .trackPresence({
202
202
  username,
@@ -205,7 +205,7 @@ const profanityChannel = endpoint.createChannel('/channel/:id', async (req, res)
205
205
  onlineSince: Date.now(),
206
206
  })
207
207
  // and send the user the channel history
208
- .sendToUsers('history', { messages }, [req.user.id]);
208
+ .sendToUsers('history', {messages}, [req.user.id]);
209
209
 
210
210
  // Alternatively, you can also send messages to the user, NOTE that the user would be automatically subscribed to the channel.
211
211
  // res.send('history', { messages }, { username, profanityCount: 0 })
@@ -217,19 +217,19 @@ const profanityChannel = endpoint.createChannel('/channel/:id', async (req, res)
217
217
  // });
218
218
  } else {
219
219
  // Reject the join request
220
- res.reject('You do not have the required role to join this channel', 403);
220
+ res.decline('You do not have the required role to join this channel', 403);
221
221
  }
222
222
  });
223
223
 
224
224
  // Attach message event listener to the profanityChannel
225
225
  profanityChannel.onEvent('message', (req, res) => {
226
- const { text } = req.event.payload;
226
+ const {text} = req.event.payload;
227
227
 
228
228
  // Check for profanity
229
229
  if (isTextProfane(text)) {
230
230
  // Reject the message if it contains profanity
231
- res.reject('Profanity is not allowed', 400, {
232
- profanityCount: req.user.assigns.profanityCount + 1
231
+ res.decline('Profanity is not allowed', 400, {
232
+ profanityCount: req.user.assigns.profanityCount + 1
233
233
  });
234
234
 
235
235
  // note that profanityCount is updated so req.user.assigns.profanityCount will be updated
@@ -238,9 +238,9 @@ profanityChannel.onEvent('message', (req, res) => {
238
238
  res.evictUser('You have been kicked from the channel for using profanity');
239
239
  } else {
240
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' })
241
+ res.broadcast('profanity-warning', {message: 'Profanity is not allowed'})
242
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]);
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
244
  }
245
245
  } else {
246
246
  // Accept the message to allow broadcasting to other clients in the channel
@@ -252,8 +252,8 @@ profanityChannel.onEvent('message', (req, res) => {
252
252
  });
253
253
 
254
254
  profanityChannel.onEvent('presence/:presence', (req, res) => {
255
- const { presence } = req.event.params;
256
- const { username } = req.user.assigns;
255
+ const {presence} = req.event.params;
256
+ const {username} = req.user.assigns;
257
257
 
258
258
  // Handle presence events
259
259
  res.updatePresence({
@@ -265,7 +265,7 @@ profanityChannel.onEvent('presence/:presence', (req, res) => {
265
265
  });
266
266
 
267
267
  profanityChannel.onLeave((event) => {
268
- const { username } = event.assigns;
268
+ const {username} = event.assigns;
269
269
 
270
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
271
 
@@ -21,7 +21,7 @@ var __rest = (this && this.__rest) || function (s, e) {
21
21
  }
22
22
  return t;
23
23
  };
24
- var _Channel_engine, _ChannelEngine_instances, _ChannelEngine_receiver, _ChannelEngine_presenceEngine, _ChannelEngine_users, _ChannelEngine_parentEngine, _ChannelEngine_subscribe, _ChannelEngine_getUsersFromRecipients;
24
+ var _Channel_engine, _ChannelEngine_instances, _ChannelEngine_receiver, _ChannelEngine_presenceEngine, _ChannelEngine_users, _ChannelEngine_parentEngine, _ChannelEngine_subscribe, _ChannelEngine_getUsersFromRecipients, _ChannelEngine_buildSubscription, _ChannelEngine_removeUser;
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.ChannelEngine = exports.Channel = void 0;
27
27
  const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
@@ -46,17 +46,15 @@ class Channel {
46
46
  getUserData(userId) {
47
47
  return __classPrivateFieldGet(this, _Channel_engine, "f").getUserData(userId);
48
48
  }
49
- broadcastMessage(event, payload) {
50
- __classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
49
+ broadcast(event, payload) {
50
+ __classPrivateFieldGet(this, _Channel_engine, "f").sendMessage(pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
51
51
  }
52
- broadcastMessageFromUser(userId, event, payload) {
53
- __classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0, pondsocket_common_1.uuid)(), userId, pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
52
+ broadcastFrom(userId, event, payload) {
53
+ __classPrivateFieldGet(this, _Channel_engine, "f").sendMessage(userId, pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
54
54
  }
55
- sendToUser(userId, event, payload) {
56
- __classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.BROADCAST, event, payload);
57
- }
58
- sendToUsers(userIds, event, payload) {
59
- __classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, userIds, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
55
+ broadcastTo(userIds, event, payload) {
56
+ const users = Array.isArray(userIds) ? userIds : [userIds];
57
+ __classPrivateFieldGet(this, _Channel_engine, "f").sendMessage(pondsocket_common_1.SystemSender.CHANNEL, users, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
60
58
  }
61
59
  evictUser(userId, reason) {
62
60
  __classPrivateFieldGet(this, _Channel_engine, "f").kickUser(userId, reason !== null && reason !== void 0 ? reason : 'You have been banned from the channel');
@@ -70,6 +68,12 @@ class Channel {
70
68
  updatePresence(userId, presence) {
71
69
  __classPrivateFieldGet(this, _Channel_engine, "f").presenceEngine.updatePresence(userId, presence);
72
70
  }
71
+ subscribeTo(userId, channel) {
72
+ __classPrivateFieldGet(this, _Channel_engine, "f").subscribeTo(userId, channel);
73
+ }
74
+ unsubscribeFrom(userId, channel) {
75
+ __classPrivateFieldGet(this, _Channel_engine, "f").unsubscribeFrom(userId, channel);
76
+ }
73
77
  }
74
78
  exports.Channel = Channel;
75
79
  _Channel_engine = new WeakMap();
@@ -85,6 +89,21 @@ class ChannelEngine {
85
89
  __classPrivateFieldSet(this, _ChannelEngine_users, new Map(), "f");
86
90
  __classPrivateFieldSet(this, _ChannelEngine_parentEngine, parent, "f");
87
91
  }
92
+ /**
93
+ * @desc Gets the presence engine for the channel
94
+ */
95
+ get presenceEngine() {
96
+ var _a;
97
+ const presenceEngine = (_a = __classPrivateFieldGet(this, _ChannelEngine_presenceEngine, "f")) !== null && _a !== void 0 ? _a : new presence_1.PresenceEngine(this);
98
+ __classPrivateFieldSet(this, _ChannelEngine_presenceEngine, presenceEngine, "f");
99
+ return presenceEngine;
100
+ }
101
+ /**
102
+ * @desc Gets the number of users in the channel
103
+ */
104
+ get size() {
105
+ return __classPrivateFieldGet(this, _ChannelEngine_users, "f").size;
106
+ }
88
107
  /**
89
108
  * @desc Adds a user to the channel
90
109
  * @param userId - The id of the user to add
@@ -101,48 +120,18 @@ class ChannelEngine {
101
120
  __classPrivateFieldGet(this, _ChannelEngine_users, "f").set(userId, assigns);
102
121
  return __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_subscribe).call(this, userId, onMessage);
103
122
  }
104
- /**
105
- * @desc Removes a user from the channel
106
- * @param userId - The id of the user to remove
107
- * @param isGraceful - Whether the user is being removed gracefully
108
- */
109
- removeUser(userId, isGraceful) {
110
- var _a;
111
- const user = __classPrivateFieldGet(this, _ChannelEngine_users, "f").get(userId);
112
- if (user) {
113
- __classPrivateFieldGet(this, _ChannelEngine_users, "f").delete(userId);
114
- __classPrivateFieldGet(this, _ChannelEngine_receiver, "f").unsubscribe(userId);
115
- const userPresence = (_a = __classPrivateFieldGet(this, _ChannelEngine_presenceEngine, "f")) === null || _a === void 0 ? void 0 : _a.removePresence(userId);
116
- if (__classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").leaveCallback) {
117
- __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").leaveCallback({
118
- channel: new Channel(this),
119
- user: {
120
- id: userId,
121
- presence: userPresence !== null && userPresence !== void 0 ? userPresence : {},
122
- assigns: user,
123
- },
124
- });
125
- }
126
- if (__classPrivateFieldGet(this, _ChannelEngine_users, "f").size === 0) {
127
- __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").destroyChannel();
128
- }
129
- }
130
- else if (!isGraceful) {
131
- throw new pondError_1.ChannelError(`ChannelEngine: User with id ${userId} does not exist in channel ${this.name}`, 404, this.name);
132
- }
133
- }
134
123
  /**
135
124
  * @desc Kicks a user from the channel
136
125
  * @param userId - The id of the user to kick
137
126
  * @param reason - The reason for kicking the user
138
127
  */
139
128
  kickUser(userId, reason) {
140
- this.sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.SYSTEM, 'kicked_out', {
129
+ this.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.SYSTEM, 'kicked_out', {
141
130
  message: reason,
142
131
  code: 403,
143
132
  });
144
- this.removeUser(userId, false);
145
- this.sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.SYSTEM, 'kicked', {
133
+ __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_removeUser).call(this, userId);
134
+ this.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.SYSTEM, 'kicked', {
146
135
  userId,
147
136
  reason,
148
137
  });
@@ -152,11 +141,11 @@ class ChannelEngine {
152
141
  * @param reason - The reason for self-destructing the channel
153
142
  */
154
143
  destroy(reason) {
155
- this.sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.ERROR, 'destroyed', {
144
+ this.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.ERROR, 'destroyed', {
156
145
  message: reason !== null && reason !== void 0 ? reason : 'Channel has been destroyed',
157
146
  });
158
- __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").destroyChannel();
159
- __classPrivateFieldGet(this, _ChannelEngine_users, "f").forEach((_, userId) => this.removeUser(userId, true));
147
+ __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").destroyChannel(this.name);
148
+ __classPrivateFieldGet(this, _ChannelEngine_users, "f").forEach((_, userId) => __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_removeUser).call(this, userId));
160
149
  }
161
150
  /**
162
151
  * @desc Updates a user's assigns
@@ -207,7 +196,7 @@ class ChannelEngine {
207
196
  * @param event - The event name
208
197
  * @param payload - The payload of the message
209
198
  */
210
- sendMessage(requestId, sender, recipient, action, event, payload) {
199
+ sendMessage(sender, recipient, action, event, payload, requestId = (0, pondsocket_common_1.uuid)()) {
211
200
  if (!__classPrivateFieldGet(this, _ChannelEngine_users, "f").has(sender) && sender !== pondsocket_common_1.SystemSender.CHANNEL) {
212
201
  throw new pondError_1.ChannelError(`ChannelEngine: User with id ${sender} does not exist in channel ${this.name}`, 404, this.name);
213
202
  }
@@ -237,41 +226,42 @@ class ChannelEngine {
237
226
  action: pondsocket_common_1.ServerActions.BROADCAST,
238
227
  channelName: this.name,
239
228
  requestId: message.requestId,
240
- recipients: __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_getUsersFromRecipients).call(this, message.addresses || pondsocket_common_1.ChannelReceiver.ALL_USERS, userId),
241
229
  };
242
230
  const request = new eventRequest_1.EventRequest(responseEvent, this);
243
231
  const response = new eventResponse_1.EventResponse(responseEvent, this);
244
- __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").execute(request, response, () => {
245
- this.sendMessage(responseEvent.requestId, pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.ERROR, pondsocket_common_1.ErrorTypes.HANDLER_NOT_FOUND, {
232
+ __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").middleware.run(request, response, () => {
233
+ this.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.ERROR, pondsocket_common_1.ErrorTypes.HANDLER_NOT_FOUND, {
246
234
  message: 'A handler did not respond to the event',
247
235
  code: 404,
248
- });
236
+ }, message.requestId);
249
237
  });
250
238
  }
251
239
  /**
252
- * @desc Gets the presence engine for the channel
240
+ * @desc Subscribes a user to a channel, Will join the channel if it exists or add to pending subscriptions
241
+ * @param userId - The id of the user to subscribe
242
+ * @param channel - The name of the channel to subscribe to
253
243
  */
254
- get presenceEngine() {
255
- var _a;
256
- const presenceEngine = (_a = __classPrivateFieldGet(this, _ChannelEngine_presenceEngine, "f")) !== null && _a !== void 0 ? _a : new presence_1.PresenceEngine(this);
257
- __classPrivateFieldSet(this, _ChannelEngine_presenceEngine, presenceEngine, "f");
258
- return presenceEngine;
244
+ subscribeTo(userId, channel) {
245
+ __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").parent.subscribeTo(userId, channel);
259
246
  }
260
247
  /**
261
- * @desc Gets the number of users in the channel
248
+ * @desc Unsubscribes a user from a channel
249
+ * @param userId - The id of the user to unsubscribe
250
+ * @param channel - The name of the channel to unsubscribe from
262
251
  */
263
- get size() {
264
- return __classPrivateFieldGet(this, _ChannelEngine_users, "f").size;
252
+ unsubscribeFrom(userId, channel) {
253
+ __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").parent.unsubscribeFrom(userId, channel);
265
254
  }
266
255
  }
267
256
  exports.ChannelEngine = ChannelEngine;
268
257
  _ChannelEngine_receiver = new WeakMap(), _ChannelEngine_presenceEngine = new WeakMap(), _ChannelEngine_users = new WeakMap(), _ChannelEngine_parentEngine = new WeakMap(), _ChannelEngine_instances = new WeakSet(), _ChannelEngine_subscribe = function _ChannelEngine_subscribe(userId, onMessage) {
269
- return __classPrivateFieldGet(this, _ChannelEngine_receiver, "f").subscribeWith(userId, (_a) => {
258
+ const unsubscribe = __classPrivateFieldGet(this, _ChannelEngine_receiver, "f").subscribe((_a) => {
270
259
  var { recipients } = _a, event = __rest(_a, ["recipients"]);
271
260
  if (recipients.includes(userId)) {
272
261
  onMessage(event);
273
262
  }
274
263
  });
264
+ return __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_buildSubscription).bind(this, userId, unsubscribe);
275
265
  }, _ChannelEngine_getUsersFromRecipients = function _ChannelEngine_getUsersFromRecipients(recipients, sender) {
276
266
  const allUsers = Array.from(__classPrivateFieldGet(this, _ChannelEngine_users, "f").keys());
277
267
  let users;
@@ -296,4 +286,34 @@ _ChannelEngine_receiver = new WeakMap(), _ChannelEngine_presenceEngine = new Wea
296
286
  break;
297
287
  }
298
288
  return users;
289
+ }, _ChannelEngine_buildSubscription = function _ChannelEngine_buildSubscription(userId, unsubscribe) {
290
+ var _a;
291
+ const user = __classPrivateFieldGet(this, _ChannelEngine_users, "f").get(userId);
292
+ if (!user) {
293
+ throw new pondError_1.ChannelError(`ChannelEngine: User with id ${userId} does not exist in channel ${this.name}`, 404, this.name);
294
+ }
295
+ unsubscribe();
296
+ __classPrivateFieldGet(this, _ChannelEngine_users, "f").delete(userId);
297
+ const userPresence = (_a = __classPrivateFieldGet(this, _ChannelEngine_presenceEngine, "f")) === null || _a === void 0 ? void 0 : _a.removePresence(userId);
298
+ if (__classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").leaveCallback) {
299
+ __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").leaveCallback({
300
+ channel: new Channel(this),
301
+ user: {
302
+ id: userId,
303
+ presence: userPresence !== null && userPresence !== void 0 ? userPresence : {},
304
+ assigns: user,
305
+ },
306
+ });
307
+ }
308
+ if (__classPrivateFieldGet(this, _ChannelEngine_users, "f").size === 0) {
309
+ __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").destroyChannel(this.name);
310
+ }
311
+ }, _ChannelEngine_removeUser = function _ChannelEngine_removeUser(userId) {
312
+ const cachedUser = __classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").parent.getUser(userId);
313
+ const unsubscribe = cachedUser.subscriptions.get(this.name);
314
+ if (!unsubscribe) {
315
+ throw new pondError_1.ChannelError(`ChannelEngine: User with id ${userId} does not exist in channel ${this.name}`, 404, this.name);
316
+ }
317
+ unsubscribe();
318
+ cachedUser.subscriptions.delete(this.name);
299
319
  };