@soundworks/core 4.0.0-alpha.0 → 4.0.0-alpha.2

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.
@@ -6,66 +6,80 @@ import {
6
6
  unpackStringMessage,
7
7
  } from '../common/sockets-utils.js';
8
8
 
9
- // const CONNECTING = 0;
10
- // const OPEN = 1;
11
- // const CLOSING = 2;
12
- // const CLOSED = 3;
13
- // const READY_STATES = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
9
+ // Status codes:
10
+ //
11
+ // CONNECTING = 0;
12
+ // OPEN = 1;
13
+ // CLOSING = 2;
14
+ // CLOSED = 3;
15
+ // READY_STATES = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
14
16
 
15
17
  /**
16
- * Simple wrapper with simple pubsub system built on top of `ws` sockets.
17
- * The abstraction contains two different socket:
18
- * - one configured for string (JSON compatible) messages
19
- * - one configured with `binaryType=arraybuffer` for streaming data more
20
- * efficiently.
18
+ * The Socket class is a simple publish / subscribe wrapper built on top of the
19
+ * [ws](https://github.com/websockets/ws) library. An instance of {@link server.Socket}
20
+ * is automatically created per client when it connects (see {@link server.Client#socket}).
21
21
  *
22
- * @see https://github.com/websockets/ws
22
+ * _Important: In most cases, you should consider using a {@link client.SharedState}
23
+ * rather than directly using the sockets._
24
+ *
25
+ * The Socket class contains two different WebSockets:
26
+ * - a socket configured with `binaryType = 'blob'` for JSON compatible data
27
+ * types (i.e. string, number, boolean, object, array and null).
28
+ * - a socket configured with `binaryType= 'arraybuffer'` for efficient streaming
29
+ * of binary data.
23
30
  *
24
31
  * @memberof server
32
+ * @hideconstructor
25
33
  */
26
34
  class Socket {
27
35
  constructor(ws, binaryWs, rooms, sockets, options = {}) {
28
-
29
36
  /**
30
- * Reference to the sockets object, is mainly dedicated to allow
31
- * broadcasting from a given socket instance.
32
- * @type {server.Sockets}
33
- * @example
34
- * socket.sockets.broadcast('my-room', this, 'update-value', 1);
37
+ * Configuration object
38
+ *
39
+ * @type {object}
35
40
  */
36
- this.sockets = sockets;
41
+ this.config = {
42
+ pingInterval: 5 * 1000,
43
+ ...options,
44
+ };
37
45
 
38
46
  /**
39
47
  * `ws` socket instance configured with `binaryType=blob` (string)
48
+ *
49
+ * @type {object}
40
50
  * @private
41
- * @type {Object}
42
51
  */
43
52
  this.ws = ws;
44
53
 
45
54
  /**
46
55
  * `ws` socket instance configured with `binaryType=arraybuffer` (TypedArray)
56
+ *
57
+ * @type {object}
47
58
  * @private
48
- * @type {Object}
49
59
  */
50
60
  this.binaryWs = binaryWs;
51
61
 
52
62
  /**
53
- * `ws` socket instance configured with `binaryType=arraybuffer` (TypedArray)
54
- * @private
55
- * @type {Map}
63
+ * Reference to the sockets object, is mainly dedicated to allow
64
+ * broadcasting from a given socket instance.
65
+ *
66
+ * @type {server.Sockets}
67
+ * @example
68
+ * socket.sockets.broadcast('my-room', this, 'update-value', 1);
56
69
  */
57
- this.rooms = rooms;
70
+ this.sockets = sockets;
58
71
 
59
72
  /**
60
- * Configuration object
61
- * @type {Object}
73
+ * Reference to the rooms object
74
+ *
75
+ * @type {Map}
76
+ * @private
62
77
  */
63
- this.config = {
64
- pingInterval: 5 * 1000,
65
- ...options,
66
- };
78
+ this.rooms = rooms;
67
79
 
80
+ /** @private */
68
81
  this._stringListeners = new Map();
82
+ /** @private */
69
83
  this._binaryListeners = new Map();
70
84
 
71
85
  // ----------------------------------------------------------
@@ -150,9 +164,11 @@ class Socket {
150
164
  }
151
165
 
152
166
  /**
153
- * Called when the string socket closes (aka client reload).
167
+ * Removes all listeners and immediately close the two sockets. Is automatically
168
+ * called on `server.stop()`
169
+ *
170
+ * @private
154
171
  */
155
- /** @private */
156
172
  terminate() {
157
173
  // clear ping/pong check
158
174
  clearInterval(this._intervalId);
@@ -190,7 +206,12 @@ class Socket {
190
206
  this.ws.terminate();
191
207
  }
192
208
 
193
- /** @private */
209
+ /**
210
+ * @param {boolean} binary - Emit to either the string or binary socket.
211
+ * @param {string} channel - Channel name.
212
+ * @param {...*} args - Content of the message.
213
+ * @private
214
+ */
194
215
  _emit(binary, channel, ...args) {
195
216
  const listeners = binary ? this._binaryListeners : this._stringListeners;
196
217
 
@@ -200,7 +221,12 @@ class Socket {
200
221
  }
201
222
  }
202
223
 
203
- /** @private */
224
+ /**
225
+ * @param {Function[]} listeners - List of listeners, either for the string or binary socket.
226
+ * @param {string} channel - Channel name.
227
+ * @param {Function} callback - The function to be added to the listeners.
228
+ * @private
229
+ */
204
230
  _addListener(listeners, channel, callback) {
205
231
  if (!listeners.has(channel)) {
206
232
  listeners.set(channel, new Set());
@@ -210,7 +236,12 @@ class Socket {
210
236
  callbacks.add(callback);
211
237
  }
212
238
 
213
- /** @private */
239
+ /**
240
+ * @param {Function[]} listeners - List of listeners, either for the string or binary socket.
241
+ * @param {string} channel - Channel name.
242
+ * @param {Function} callback - The function to be removed from the listeners.
243
+ * @private
244
+ */
214
245
  _removeListener(listeners, channel, callback) {
215
246
  if (listeners.has(channel)) {
216
247
  const callbacks = listeners.get(channel);
@@ -222,16 +253,24 @@ class Socket {
222
253
  }
223
254
  }
224
255
 
225
- /** @private */
256
+ /**
257
+ * @param {Function[]} listeners - List of listeners, either for the string or binary socket.
258
+ * @param {string} [channel=null] - Channel name of the listeners to remove. If null
259
+ * all the listeners are cleared.
260
+ * @private
261
+ */
226
262
  _removeAllListeners(listeners, channel) {
227
- if (listeners.has(channel)) {
263
+ if (channel === null) {
264
+ listeners.clear();
265
+ } else if (listeners.has(channel)) {
228
266
  listeners.delete(channel);
229
267
  }
230
268
  }
231
269
 
232
270
  /**
233
271
  * Add the socket to a room
234
- * @param {String} roomId - Id of the room
272
+ *
273
+ * @param {string} roomId - Id of the room.
235
274
  */
236
275
  addToRoom(roomId) {
237
276
  if (!this.rooms.has(roomId)) {
@@ -244,7 +283,8 @@ class Socket {
244
283
 
245
284
  /**
246
285
  * Remove the socket from a room
247
- * @param {String} roomId - Id of the room
286
+ *
287
+ * @param {string} roomId - Id of the room.
248
288
  */
249
289
  removeFromRoom(roomId) {
250
290
  if (this.rooms.has(roomId)) {
@@ -254,10 +294,11 @@ class Socket {
254
294
  }
255
295
 
256
296
  /**
257
- * Sends JSON compatible messages on a given channel
297
+ * Send messages with JSON compatible data types on a given channel.
258
298
  *
259
- * @param {String} channel - Channel of the message
260
- * @param {...*} args - Arguments of the message (as many as needed, of any type)
299
+ * @param {string} channel - Channel name.
300
+ * @param {...*} args - Payload of the message. As many arguments as needed, of
301
+ * JSON compatible data types (i.e. string, number, boolean, object, array and null).
261
302
  */
262
303
  send(channel, ...args) {
263
304
  const msg = packStringMessage(channel, ...args);
@@ -276,39 +317,41 @@ class Socket {
276
317
  }
277
318
 
278
319
  /**
279
- * Listen JSON compatible messages on a given channel
320
+ * Listen messages with JSON compatible data types on a given channel.
280
321
  *
281
- * @param {String} channel - Channel of the message
282
- * @param {Function} callback - Callback to execute when a message is received
322
+ * @param {string} channel - Channel name.
323
+ * @param {Function} callback - Callback to execute when a message is received,
324
+ * arguments of the callback function will match the arguments sent using the
325
+ * {@link server.Socket#send} method.
283
326
  */
284
327
  addListener(channel, callback) {
285
328
  this._addListener(this._stringListeners, channel, callback);
286
329
  }
287
330
 
288
331
  /**
289
- * Remove a listener from JSON compatible messages on a given channel
332
+ * Remove a listener of messages with JSON compatible data types from a given channel.
290
333
  *
291
- * @param {String} channel - Channel of the message
292
- * @param {Function} callback - Callback to cancel
334
+ * @param {string} channel - Channel name.
335
+ * @param {Function} callback - Callback to remove.
293
336
  */
294
337
  removeListener(channel, callback) {
295
338
  this._removeListener(this._stringListeners, channel, callback);
296
339
  }
297
340
 
298
341
  /**
299
- * Remove all listeners from JSON compatible messages on a given channel
342
+ * Remove all listeners of messages with JSON compatible data types.
300
343
  *
301
- * @param {String} channel - Channel of the message
344
+ * @param {string} channel - Channel name.
302
345
  */
303
- removeAllListeners(channel) {
346
+ removeAllListeners(channel = null) {
304
347
  this._removeAllListeners(this._stringListeners, channel);
305
348
  }
306
349
 
307
350
  /**
308
- * Sends binary messages on a given channel
351
+ * Send binary messages on a given channel.
309
352
  *
310
- * @param {String} channel - Channel of the message
311
- * @param {TypedArray} typedArray - Data to send
353
+ * @param {string} channel - Channel name.
354
+ * @param {TypedArray} typedArray - Binary data to be sent.
312
355
  */
313
356
  sendBinary(channel, typedArray) {
314
357
  const msg = packBinaryMessage(channel, typedArray);
@@ -323,29 +366,29 @@ class Socket {
323
366
  /**
324
367
  * Listen binary messages on a given channel
325
368
  *
326
- * @param {String} channel - Channel of the message
327
- * @param {Function} callback - Callback to execute when a message is received
369
+ * @param {string} channel - Channel name.
370
+ * @param {Function} callback - Callback to execute when a message is received.
328
371
  */
329
372
  addBinaryListener(channel, callback) {
330
373
  this._addListener(this._binaryListeners, channel, callback);
331
374
  }
332
375
 
333
376
  /**
334
- * Remove a listener from binary compatible messages on a given channel
377
+ * Remove a listener of binary compatible messages from a given channel
335
378
  *
336
- * @param {String} channel - Channel of the message
337
- * @param {Function} callback - Callback to cancel
379
+ * @param {string} channel - Channel name.
380
+ * @param {Function} callback - Callback to remove.
338
381
  */
339
382
  removeBinaryListener(channel, callback) {
340
383
  this._removeListener(this._binaryListeners, channel, callback);
341
384
  }
342
385
 
343
386
  /**
344
- * Remove all listeners from binary compatible messages on a given channel
387
+ * Remove all listeners of binary compatible messages on a given channel
345
388
  *
346
- * @param {String} channel - Channel of the message
389
+ * @param {string} channel - Channel of the message.
347
390
  */
348
- removeAllBinaryListeners(channel) {
391
+ removeAllBinaryListeners(channel = null) {
349
392
  this._removeAllListeners(this._binaryListeners, channel);
350
393
  }
351
394
  }
@@ -11,7 +11,8 @@ import Socket from './Socket.js';
11
11
  const __dirname = fileURLToPath(new URL('.', import.meta.url));
12
12
 
13
13
  /**
14
- * Websocket server that creates and host all {@link server.Socket} instance.
14
+ * Manager all {@link server.Socket} instances.
15
+ *
15
16
  * Most of the time, you shouldn't have to use this class instance directely, but
16
17
  * it could be usefull in some situations, for broadcasting messages, creating rooms, etc.
17
18
  *
@@ -36,9 +37,9 @@ class Sockets {
36
37
  }
37
38
 
38
39
  /**
39
- * Initialize sockets, all sockets are added by default added to two rooms:
40
+ * Initialize sockets, all sockets are added to two rooms by default:
40
41
  * - to the room corresponding to the client `role`
41
- * - to the '*' that holds all connected sockets
42
+ * - to the '*' room that holds all connected sockets
42
43
  *
43
44
  * @private
44
45
  */
@@ -100,7 +101,11 @@ class Sockets {
100
101
  });
101
102
  }
102
103
 
103
- /** @protected */
104
+ /**
105
+ * Terminate all existing sockets
106
+ *
107
+ * @private
108
+ */
104
109
  terminate() {
105
110
  // terminate stat worker thread
106
111
  this._latencyStatsWorker.terminate();
@@ -146,7 +151,7 @@ class Sockets {
146
151
  * Add a socket to a room
147
152
  *
148
153
  * @param {server.Socket} socket - Socket to add to the room.
149
- * @param {String} roomId - Id of the room
154
+ * @param {String} roomId - Id of the room.
150
155
  */
151
156
  addToRoom(socket, roomId) {
152
157
  socket.addToRoom(roomId);
@@ -156,39 +161,39 @@ class Sockets {
156
161
  * Remove a socket from a room
157
162
  *
158
163
  * @param {server.Socket} socket - Socket to remove from the room.
159
- * @param {String} [roomId=null] - Id of the room
164
+ * @param {String} roomId - Id of the room.
160
165
  */
161
166
  removeFromRoom(socket, roomId) {
162
167
  socket.removeFromRoom(roomId);
163
168
  }
164
169
 
165
170
  /**
166
- * Send a string message to all client of given room(s). If no room
167
- * not specified, the message is sent to all clients
171
+ * Send a message of JSON compatible data types to all client of given room(s).
172
+ * If no room is specified, the message is sent to all clients.
173
+ *
168
174
  *
169
175
  * @param {String|Array} roomsIds - Ids of the rooms that must receive
170
- * the message. If null the message is sent to all clients
171
- * @param {server.Socket} excludeSocket - Optionnal
172
- * socket to ignore when broadcasting the message, typically the client
173
- * at the origin of the message
174
- * @param {String} channel - Channel of the message
175
- * @param {...*} args - Arguments of the message (as many as needed, of any type)
176
+ * the message. If `null` the message is sent to all clients.
177
+ * @param {server.Socket} excludeSocket - Optionnal socket to ignore when
178
+ * broadcasting the message, typically the client at the origin of the message.
179
+ * @param {String} channel - Channel name.
180
+ * @param {...*} args - Payload of the message. As many arguments as needed, of
181
+ * JSON compatible data types (i.e. string, number, boolean, object, array and null).
176
182
  */
177
183
  broadcast(roomIds, excludeSocket, channel, ...args) {
178
184
  this._broadcast(false, roomIds, excludeSocket, channel, ...args);
179
185
  }
180
186
 
181
187
  /**
182
- * Send a binary message (TypedArray) to all client of given room(s). If no room
183
- * not specified, the message is sent to all clients
188
+ * Send a binary message to all client of given room(s). If no room is specified
189
+ * specified, the message is sent to all clients.
184
190
  *
185
191
  * @param {String|Array} roomsIds - Ids of the rooms that must receive
186
- * the message. If null the message is sent to all clients
187
- * @param {server.Socket} excludeSocket - Optionnal
188
- * socket to ignore when broadcasting the message, typically the client
189
- * at the origin of the message
190
- * @param {String} channel - Channel of the message
191
- * @param {...*} args - Arguments of the message (as many as needed, of any type)
192
+ * the message. If `null` the message is sent to all clients.
193
+ * @param {server.Socket} excludeSocket - Optionnal socket to ignore when
194
+ * broadcasting the message, typically the client at the origin of the message.
195
+ * @param {string} channel - Channel name.
196
+ * @param {TypedArray} typedArray - Binary data to be sent.
192
197
  */
193
198
  broadcastBinary(roomIds, excludeSocket, channel, typedArray) {
194
199
  this._broadcast(true, roomIds, excludeSocket, channel, typedArray);