@soundworks/core 4.0.0-alpha.22 → 4.0.0-alpha.23

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.
Files changed (85) hide show
  1. package/CHANGELOG.md +9 -3
  2. package/package.json +13 -14
  3. package/src/client/Client.js +224 -188
  4. package/src/client/Socket.js +74 -241
  5. package/src/common/constants.js +0 -1
  6. package/src/common/logger.js +15 -0
  7. package/src/common/sockets-utils.js +0 -63
  8. package/src/common/version.js +1 -1
  9. package/src/server/Plugin.js +22 -10
  10. package/src/server/Server.js +22 -46
  11. package/src/server/Socket.js +126 -250
  12. package/src/server/Sockets.js +103 -127
  13. package/src/server/audit-network-latency.worker.js +4 -3
  14. package/types/client/Client.d.ts +41 -8
  15. package/types/client/Client.d.ts.map +1 -1
  16. package/types/client/Context.d.ts +40 -14
  17. package/types/client/Context.d.ts.map +1 -1
  18. package/types/client/Plugin.d.ts +42 -41
  19. package/types/client/Plugin.d.ts.map +1 -1
  20. package/types/client/PluginManager.d.ts +26 -11
  21. package/types/client/PluginManager.d.ts.map +1 -1
  22. package/types/client/SharedState.d.ts +1 -1
  23. package/types/client/SharedState.d.ts.map +1 -1
  24. package/types/client/SharedStateCollection.d.ts +41 -0
  25. package/types/client/SharedStateCollection.d.ts.map +1 -0
  26. package/types/client/Socket.d.ts +41 -30
  27. package/types/client/Socket.d.ts.map +1 -1
  28. package/types/client/StateManager.d.ts +1 -1
  29. package/types/client/StateManager.d.ts.map +1 -1
  30. package/types/client/index.d.ts +0 -8
  31. package/types/common/BasePlugin.d.ts +24 -19
  32. package/types/common/BasePlugin.d.ts.map +1 -1
  33. package/types/common/BasePluginManager.d.ts +17 -5
  34. package/types/common/BasePluginManager.d.ts.map +1 -1
  35. package/types/common/BaseSharedState.d.ts +100 -29
  36. package/types/common/BaseSharedState.d.ts.map +1 -1
  37. package/types/common/BaseSharedStateCollection.d.ts +183 -0
  38. package/types/common/BaseSharedStateCollection.d.ts.map +1 -0
  39. package/types/common/BaseStateManager.d.ts +83 -18
  40. package/types/common/BaseStateManager.d.ts.map +1 -1
  41. package/types/common/BatchedTransport.d.ts +21 -0
  42. package/types/common/BatchedTransport.d.ts.map +1 -0
  43. package/types/common/ParameterBag.d.ts +61 -40
  44. package/types/common/ParameterBag.d.ts.map +1 -1
  45. package/types/common/PromiseStore.d.ts +11 -0
  46. package/types/common/PromiseStore.d.ts.map +1 -0
  47. package/types/common/SharedStatePrivate.d.ts +4 -3
  48. package/types/common/SharedStatePrivate.d.ts.map +1 -1
  49. package/types/common/constants.d.ts +10 -1
  50. package/types/common/constants.d.ts.map +1 -1
  51. package/types/common/logger.d.ts +1 -1
  52. package/types/common/sockets-utils.d.ts.map +1 -1
  53. package/types/common/version.d.ts +3 -0
  54. package/types/common/version.d.ts.map +1 -0
  55. package/types/server/Client.d.ts +5 -0
  56. package/types/server/Client.d.ts.map +1 -1
  57. package/types/server/Context.d.ts +162 -22
  58. package/types/server/Context.d.ts.map +1 -1
  59. package/types/server/ContextManager.d.ts +4 -4
  60. package/types/server/ContextManager.d.ts.map +1 -1
  61. package/types/server/Plugin.d.ts +56 -55
  62. package/types/server/Plugin.d.ts.map +1 -1
  63. package/types/server/PluginManager.d.ts +26 -6
  64. package/types/server/PluginManager.d.ts.map +1 -1
  65. package/types/server/Server.d.ts +207 -70
  66. package/types/server/Server.d.ts.map +1 -1
  67. package/types/server/SharedState.d.ts +1 -1
  68. package/types/server/SharedState.d.ts.map +1 -1
  69. package/types/server/SharedStateCollection.d.ts +41 -0
  70. package/types/server/SharedStateCollection.d.ts.map +1 -0
  71. package/types/server/Socket.d.ts +93 -57
  72. package/types/server/Socket.d.ts.map +1 -1
  73. package/types/server/Sockets.d.ts +32 -25
  74. package/types/server/Sockets.d.ts.map +1 -1
  75. package/types/server/StateManager.d.ts +242 -27
  76. package/types/server/StateManager.d.ts.map +1 -1
  77. package/types/server/audit-network-latency.worker.d.ts +2 -1
  78. package/types/server/audit-schema.d.ts +8 -8
  79. package/types/server/crypto.d.ts +3 -0
  80. package/types/server/crypto.d.ts.map +1 -0
  81. package/types/server/index.d.ts +0 -4
  82. package/types/common/promise-store.d.ts +0 -4
  83. package/types/common/promise-store.d.ts.map +0 -1
  84. package/types/common/utils.d.ts +0 -5
  85. package/types/common/utils.d.ts.map +0 -1
@@ -2,34 +2,16 @@ import { isBrowser } from '@ircam/sc-utils';
2
2
  import WebSocket from 'isomorphic-ws';
3
3
 
4
4
  import {
5
- PING_INTERVAL,
6
- PING_LATENCY_TOLERANCE,
7
5
  PING_MESSAGE,
8
6
  PONG_MESSAGE,
9
7
  } from '../common/constants.js';
10
8
  import logger from '../common/logger.js';
11
9
  import {
12
- packBinaryMessage,
13
- unpackBinaryMessage,
14
10
  packStringMessage,
15
11
  unpackStringMessage,
16
12
  } from '../common/sockets-utils.js';
17
13
 
18
- // WebSocket events:
19
- //
20
- // `close`:
21
- // Fired when a connection with a websocket is closed.
22
- // Also available via the onclose property
23
- // `error`:
24
- // Fired when a connection with a websocket has been closed because of an error,
25
- // such as whensome data couldn't be sent.
26
- // Also available via the onerror property.
27
- // `message`:
28
- // Fired when data is received through a websocket.
29
- // Also available via the onmessage property.
30
- // `open`:
31
- // Fired when a connection with a websocket is opened.
32
- // Also available via the onopen property.
14
+ export const kSocketTerminate = Symbol('soundworks:socket-terminate');
33
15
 
34
16
  /**
35
17
  * The Socket class is a simple publish / subscribe wrapper built on top of the
@@ -53,26 +35,10 @@ import {
53
35
  * @hideconstructor
54
36
  */
55
37
  class Socket {
56
- constructor() {
57
- /**
58
- * WebSocket instance configured with `binaryType = 'blob'`.
59
- *
60
- * @private
61
- */
62
- this.ws = null;
63
- /**
64
- * WebSocket instance configured with `binaryType = 'arraybuffer'`.
65
- *
66
- * @private
67
- */
68
- this.binaryWs = null;
69
- /** @private */
70
- this._stringListeners = new Map();
71
- /** @private */
72
- this._binaryListeners = new Map();
73
- /** @private */
74
- this._heartbeatId = null;
75
- }
38
+ #socket = null;
39
+ #listeners = new Map();
40
+
41
+ constructor() {}
76
42
 
77
43
  /**
78
44
  * Initialize a websocket connection with the server. Automatically called
@@ -80,20 +46,10 @@ class Socket {
80
46
  *
81
47
  * @param {string} role - Role of the client (see {@link client.Client#role})
82
48
  * @param {object} config - Configuration of the sockets
83
- * @protected
84
- * @ignore
49
+ * @private
85
50
  */
86
51
  async init(role, config) {
87
- // unique key that allows to associate the two sockets to the same client.
88
- // note: the key is only used to pair to two sockets, so its usage is very
89
- // limited in time therefore a random number should hopefully be sufficient.
90
- const key = (Math.random() + '').replace(/^0\./, '');
91
-
92
- // open web sockets
93
52
  let { path } = config.env.websockets;
94
-
95
- // @note: keep this check
96
- // backward compatibility w/ assetsDomain and websocket old config way
97
53
  // cf. https://github.com/collective-soundworks/soundworks/issues/35
98
54
  if (config.env.subpath) {
99
55
  path = `${config.env.subpath}/${path}`;
@@ -121,77 +77,66 @@ class Socket {
121
77
  };
122
78
  }
123
79
 
124
- const url = `${protocol}//${serverAddress}:${port}/${path}`;
125
- let queryParams = `role=${role}&key=${key}`;
80
+ let queryParams = `role=${role}`;
126
81
 
127
82
  if (config.token) {
128
83
  queryParams += `&token=${config.token}`;
129
84
  }
130
85
 
86
+ const url = `${protocol}//${serverAddress}:${port}/${path}?${queryParams}`;
87
+
131
88
  // ----------------------------------------------------------
132
- // init string socket
89
+ // Init socket
133
90
  // ----------------------------------------------------------
134
- const stringSocketUrl = `${url}?binary=0&${queryParams}`;
135
-
136
- await new Promise(resolve => {
91
+ return new Promise(resolve => {
137
92
  let connectionRefusedLogged = false;
138
93
 
139
94
  const trySocket = async () => {
140
- const ws = new WebSocket(stringSocketUrl, webSocketOptions);
95
+ const ws = new WebSocket(url, webSocketOptions);
141
96
 
142
- ws.addEventListener('open', connectEvent => {
97
+ ws.addEventListener('open', openEvent => {
143
98
  // parse incoming messages for pubsub
144
- this.ws = ws;
99
+ this.#socket = ws;
145
100
 
146
- // Heartbeat ping / pong check, to detect if connection has been
147
- // broken but not detected by the client
148
- // @note (2024-04): unstable and creates more issues than it solves, disable
149
- // for now and review later
150
- // const heartbeat = () => {
151
- // clearTimeout(this._heartbeatId);
152
-
153
- // this._heartbeatId = setTimeout(() => {
154
- // console.log('> HEARTBEAT missed, closing...');
155
- // this.terminate();
156
- // }, PING_INTERVAL + PING_LATENCY_TOLERANCE);
157
- // };
158
-
159
- // heartbeat();
160
-
161
- this.ws.addEventListener('message', e => {
101
+ this.#socket.addEventListener('message', e => {
162
102
  if (e.data === PING_MESSAGE) {
163
103
  // heartbeat();
164
- this.ws.send(PONG_MESSAGE);
104
+ this.#socket.send(PONG_MESSAGE);
165
105
  // do not propagate ping / pong messages
166
106
  return;
167
107
  }
168
108
 
169
109
  const [channel, args] = unpackStringMessage(e.data);
170
- this._emit(false, channel, ...args);
110
+ this.#dispatchEvent(channel, ...args);
171
111
  });
172
112
 
173
- // broadcast all `WebSocket` native events
174
- this.ws.addEventListener('close', (e) => {
175
- clearTimeout(this._heartbeatId);
176
- this._emit(false, 'close', e);
177
- });
178
-
179
- this.ws.addEventListener('error', (e) => {
180
- clearTimeout(this._heartbeatId);
181
- this._emit(false, 'error', e);
182
- });
183
-
184
- this.ws.addEventListener('upgrade', (e) => {
185
- this._emit(false, 'upgrade', e);
186
- });
187
-
188
- this.ws.addEventListener('message', (e) => {
189
- this._emit(false, 'message', e);
190
- });
113
+ // propagate "native" events
114
+ // `close`:
115
+ // Fired when a connection with a websocket is closed.
116
+ // Also available via the onclose property
117
+ // `error`:
118
+ // Fired when a connection with a websocket has been closed because of an error,
119
+ // such as whensome data couldn't be sent.
120
+ // Also available via the onerror property.
121
+ // `message`:
122
+ // Fired when data is received through a websocket.
123
+ // Also available via the onmessage property.
124
+ // `open`:
125
+ // Fired when a connection with a websocket is opened.
126
+ // Also available via the onopen property.
127
+ [
128
+ 'close',
129
+ 'error',
130
+ 'upgrade',
131
+ 'message',
132
+ ].forEach(eventName => {
133
+ this.#socket.addEventListener(eventName, e => {
134
+ this.#dispatchEvent(eventName, e);
135
+ });
136
+ })
191
137
 
192
138
  // forward open event
193
- this._emit(false, 'open', connectEvent);
194
-
139
+ this.#dispatchEvent('open', openEvent);
195
140
  // continue with raw socket
196
141
  resolve();
197
142
  });
@@ -207,11 +152,13 @@ class Socket {
207
152
 
208
153
  // for node clients, retry connection
209
154
  if (e.error && e.error.code === 'ECONNREFUSED') {
155
+ // we want to log the warning just once
210
156
  if (!connectionRefusedLogged) {
211
157
  logger.log('[soundworks.Socket] Connection refused, waiting for the server to start');
212
158
  connectionRefusedLogged = true;
213
159
  }
214
160
 
161
+ // retry in 1 second
215
162
  setTimeout(trySocket, 1000);
216
163
  }
217
164
  }
@@ -220,39 +167,6 @@ class Socket {
220
167
 
221
168
  trySocket();
222
169
  });
223
-
224
- // ----------------------------------------------------------
225
- // init binary socket
226
- // ----------------------------------------------------------
227
- const binarySocketUrl = `${url}?binary=1&${queryParams}`;
228
-
229
- await new Promise(resolve => {
230
- const ws = new WebSocket(binarySocketUrl, webSocketOptions);
231
- ws.binaryType = 'arraybuffer';
232
-
233
- ws.addEventListener('open', connectEvent => {
234
- // parse incoming messages for pubsub
235
- this.binaryWs = ws;
236
- this.binaryWs.addEventListener('message', e => {
237
- const [channel, data] = unpackBinaryMessage(e.data);
238
- this._emit(true, channel, data);
239
- });
240
-
241
- // broadcast all `WebSocket` native events
242
- ['close', 'error', 'upgrade', 'message'].forEach(eventName => {
243
- this.binaryWs.addEventListener(eventName, (e) => {
244
- this._emit(true, eventName, e);
245
- });
246
- });
247
-
248
- // forward open event
249
- this._emit(true, 'open', connectEvent);
250
- resolve();
251
- });
252
- });
253
-
254
- // wait for both sockets connected
255
- return Promise.resolve();
256
170
  }
257
171
 
258
172
  /**
@@ -261,28 +175,18 @@ class Socket {
261
175
  *
262
176
  * Is also called when a disconnection is detected by the heartbeat (note that
263
177
  * in this case, the launcher will call `client.stop()` but the listeners are
264
- * already cleared so the event will be trigerred only once)
265
- *
266
- * @private
178
+ * already cleared so the event will be trigerred only once.
267
179
  */
268
- async terminate() {
269
- const closeListeners = this._stringListeners.get('close');
270
- const closeBinaryListeners = this._binaryListeners.get('close');
271
-
180
+ async [kSocketTerminate]() {
181
+ const closeListeners = this.#listeners.get('close');
272
182
  this.removeAllListeners();
273
- this.removeAllBinaryListeners();
274
183
 
275
- this.ws.close();
276
- this.binaryWs.close();
184
+ this.#socket.close();
277
185
 
278
186
  if (closeListeners) {
279
187
  closeListeners.forEach(listener => listener());
280
188
  }
281
189
 
282
- if (closeBinaryListeners) {
283
- closeBinaryListeners.forEach(listener => listener());
284
- }
285
-
286
190
  return Promise.resolve();
287
191
  }
288
192
 
@@ -290,63 +194,14 @@ class Socket {
290
194
  * @param {boolean} binary - Emit to either the string or binary socket.
291
195
  * @param {string} channel - Channel name.
292
196
  * @param {...*} args - Content of the message.
293
- * @private
294
197
  */
295
- _emit(binary, channel, ...args) {
296
- const listeners = binary ? this._binaryListeners : this._stringListeners;
297
-
298
- if (listeners.has(channel)) {
299
- const callbacks = listeners.get(channel);
198
+ #dispatchEvent(channel, ...args) {
199
+ if (this.#listeners.has(channel)) {
200
+ const callbacks = this.#listeners.get(channel);
300
201
  callbacks.forEach(callback => callback(...args));
301
202
  }
302
203
  }
303
204
 
304
- /**
305
- * @param {Function[]} listeners - List of listeners, either for the string or binary socket.
306
- * @param {string} channel - Channel name.
307
- * @param {Function} callback - The function to be added to the listeners.
308
- * @private
309
- */
310
- _addListener(listeners, channel, callback) {
311
- if (!listeners.has(channel)) {
312
- listeners.set(channel, new Set());
313
- }
314
-
315
- const callbacks = listeners.get(channel);
316
- callbacks.add(callback);
317
- }
318
-
319
- /**
320
- * @param {Function[]} listeners - List of listeners, either for the string or binary socket.
321
- * @param {string} channel - Channel name.
322
- * @param {Function} callback - The function to be removed from the listeners.
323
- * @private
324
- */
325
- _removeListener(listeners, channel, callback) {
326
- if (listeners.has(channel)) {
327
- const callbacks = listeners.get(channel);
328
- callbacks.delete(callback);
329
-
330
- if (callbacks.size === 0) {
331
- listeners.delete(channel);
332
- }
333
- }
334
- }
335
-
336
- /**
337
- * @param {Function[]} listeners - List of listeners, either for the string or binary socket.
338
- * @param {string} [channel=null] - Channel name of the listeners to remove. If null
339
- * all the listeners are cleared.
340
- * @private
341
- */
342
- _removeAllListeners(listeners, channel = null) {
343
- if (channel === null) {
344
- listeners.clear();
345
- } else if (listeners.has(channel)) {
346
- listeners.delete(channel);
347
- }
348
- }
349
-
350
205
  /**
351
206
  * Send messages with JSON compatible data types on a given channel.
352
207
  *
@@ -355,8 +210,10 @@ class Socket {
355
210
  * JSON compatible data types (i.e. string, number, boolean, object, array and null).
356
211
  */
357
212
  send(channel, ...args) {
358
- const msg = packStringMessage(channel, ...args);
359
- this.ws.send(msg);
213
+ if (this.#socket.readyState === 1) {
214
+ const msg = packStringMessage(channel, ...args);
215
+ this.#socket.send(msg);
216
+ }
360
217
  }
361
218
 
362
219
  /**
@@ -368,7 +225,12 @@ class Socket {
368
225
  * {@link server.Socket#send} method.
369
226
  */
370
227
  addListener(channel, callback) {
371
- this._addListener(this._stringListeners, channel, callback);
228
+ if (!this.#listeners.has(channel)) {
229
+ this.#listeners.set(channel, new Set());
230
+ }
231
+
232
+ const callbacks = this.#listeners.get(channel);
233
+ callbacks.add(callback);
372
234
  }
373
235
 
374
236
  /**
@@ -378,7 +240,14 @@ class Socket {
378
240
  * @param {Function} callback - Callback to remove.
379
241
  */
380
242
  removeListener(channel, callback) {
381
- this._removeListener(this._stringListeners, channel, callback);
243
+ if (this.#listeners.has(channel)) {
244
+ const callbacks = this.#listeners.get(channel);
245
+ callbacks.delete(callback);
246
+
247
+ if (callbacks.size === 0) {
248
+ this.#listeners.delete(channel);
249
+ }
250
+ }
382
251
  }
383
252
 
384
253
  /**
@@ -387,47 +256,11 @@ class Socket {
387
256
  * @param {string} channel - Channel name.
388
257
  */
389
258
  removeAllListeners(channel = null) {
390
- this._removeAllListeners(this._stringListeners, channel);
391
- }
392
-
393
- /**
394
- * Send binary messages on a given channel.
395
- *
396
- * @param {string} channel - Channel name.
397
- * @param {TypedArray} typedArray - Binary data to be sent.
398
- */
399
- sendBinary(channel, typedArray) {
400
- const msg = packBinaryMessage(channel, typedArray);
401
- this.binaryWs.send(msg);
402
- }
403
-
404
- /**
405
- * Listen binary messages on a given channel
406
- *
407
- * @param {string} channel - Channel name.
408
- * @param {Function} callback - Callback to execute when a message is received.
409
- */
410
- addBinaryListener(channel, callback) {
411
- this._addListener(this._binaryListeners, channel, callback);
412
- }
413
-
414
- /**
415
- * Remove a listener of binary compatible messages from a given channel
416
- *
417
- * @param {string} channel - Channel name.
418
- * @param {Function} callback - Callback to remove.
419
- */
420
- removeBinaryListener(channel, callback) {
421
- this._removeListener(this._binaryListeners, channel, callback);
422
- }
423
-
424
- /**
425
- * Remove all listeners of binary compatible messages on a given channel
426
- *
427
- * @param {string} channel - Channel of the message.
428
- */
429
- removeAllBinaryListeners(channel = null) {
430
- this._removeAllListeners(this._binaryListeners, channel);
259
+ if (channel === null) {
260
+ this.#listeners.clear();
261
+ } else if (this.#listeners.has(channel)) {
262
+ this.#listeners.delete(channel);
263
+ }
431
264
  }
432
265
  }
433
266
 
@@ -2,7 +2,6 @@
2
2
  export const SERVER_ID = -1;
3
3
 
4
4
  export const PING_INTERVAL = 10 * 1000;
5
- export const PING_LATENCY_TOLERANCE = 1000;
6
5
  export const PING_MESSAGE = 'h:ping';
7
6
  export const PONG_MESSAGE = 'h:pong';
8
7
 
@@ -126,6 +126,21 @@ const logger = {
126
126
  console.log(` ${name} ${chalk.red('errors')}`);
127
127
  },
128
128
 
129
+ warnVersionDiscepancies(clientRole, clientVersion, serverVersion) {
130
+ console.warn(`
131
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
132
+
133
+ WARNING
134
+
135
+ Version discrepancies between server and "${clientRole}" client:
136
+ + server: ${serverVersion} | client: ${clientVersion}
137
+
138
+ This might lead to unexpected behavior, you should consider to re-install your
139
+ dependencies on both your server and clients.
140
+
141
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`);
142
+ },
143
+
129
144
  log(msg) {
130
145
  if (!this.verbose) {
131
146
  return;
@@ -1,66 +1,3 @@
1
- import 'fast-text-encoding';
2
-
3
- const encoder = new TextEncoder('utf-8');
4
- const decoder = new TextDecoder('utf-8');
5
-
6
- const types = [
7
- 'Int8Array',
8
- 'Uint8Array',
9
- 'Uint8ClampedArray',
10
- 'Int16Array',
11
- 'Uint16Array',
12
- 'Int32Array',
13
- 'Uint32Array',
14
- 'Float32Array',
15
- 'Float64Array',
16
- 'BigInt64Array',
17
- 'BigUint64Array',
18
- ];
19
-
20
- // @note - probably some room for optimizations
21
-
22
- /** @private */
23
- export function packBinaryMessage(channel, data) {
24
- const channelBuffer = encoder.encode(channel);
25
- const channelSize = channelBuffer.byteLength;
26
- const startOffset = Math.ceil((channelSize + 3) / data.BYTES_PER_ELEMENT) * data.BYTES_PER_ELEMENT;
27
- const bufferSize = startOffset + data.byteLength;
28
- const typeName = data.constructor.name;
29
- const typeIndex = types.indexOf(typeName);
30
-
31
- if (typeIndex === -1) {
32
- throw new Error(`Invalid TypedArray type: ${typeName}`);
33
- }
34
-
35
- const view = new Uint8Array(bufferSize);
36
- view[0] = channelSize;
37
- view[1] = typeIndex;
38
- view[2] = startOffset;
39
-
40
- view.set(channelBuffer, 3, channelSize);
41
- view.set(new Uint8Array(data.buffer), startOffset, data.byteLength);
42
-
43
- return view.buffer;
44
- }
45
-
46
- /** @private */
47
- export function unpackBinaryMessage(buffer /* arraybuffer */) {
48
- const infos = new Uint8Array(buffer, 0, 3);
49
- const channelSize = infos[0];
50
- const typeIndex = infos[1];
51
- const startOffset = infos[2];
52
-
53
- // need to slice as the library recreates a UInt8Array from the whole buffer
54
- // @todo - see if this copy could be avoided (probably needs a pull request)
55
- const channelBuffer = new Uint8Array(buffer.slice(3, 3 + channelSize));
56
- const channel = decoder.decode(channelBuffer);
57
- const type = types[typeIndex];
58
- // slice (copy) the underlying ArrayBuffer to create a clean TypedArray
59
- const data = new globalThis[type](buffer.slice(startOffset));
60
-
61
- return [channel, data];
62
- }
63
-
64
1
  /** @private */
65
2
  export function packStringMessage(channel, ...args) {
66
3
  return JSON.stringify([channel, args]);
@@ -1,2 +1,2 @@
1
1
  // [WARNING] This file is generated, do not edit
2
- export default '4.0.0-alpha.22';
2
+ export default '4.0.0-alpha.23';
@@ -33,6 +33,9 @@ import BasePlugin from '../common/BasePlugin.js';
33
33
  * @inheritdoc
34
34
  */
35
35
  class Plugin extends BasePlugin {
36
+ #server = null;
37
+ #clients = new Set();
38
+
36
39
  /**
37
40
  * @param {server.Server} server - The soundworks server instance.
38
41
  * @param {string} id - User defined id of the plugin as defined in
@@ -40,16 +43,25 @@ class Plugin extends BasePlugin {
40
43
  */
41
44
  constructor(server, id) {
42
45
  super(id);
46
+ this.#server = server;
47
+ }
43
48
 
44
- /**
45
- * Instance of soundworks server.
46
- * @type {server.Server}
47
- * @see {@link server.Server}
48
- */
49
- this.server = server;
49
+ /**
50
+ * Instance of soundworks server.
51
+ * @type {server.Server}
52
+ * @see {@link server.Server}
53
+ */
54
+ get server() {
55
+ return this.#server;
56
+ }
50
57
 
51
- /** @private */
52
- this.clients = new Set();
58
+ /**
59
+ * Set of the clients registered in the plugin.
60
+ * @type {Set<server.Client>}
61
+ * @see {@link server.Client}
62
+ */
63
+ get clients() {
64
+ return this.#clients;
53
65
  }
54
66
 
55
67
  /**
@@ -60,7 +72,7 @@ class Plugin extends BasePlugin {
60
72
  * @param {server.Client} client
61
73
  */
62
74
  async addClient(client) {
63
- this.clients.add(client);
75
+ this.#clients.add(client);
64
76
  }
65
77
 
66
78
  /**
@@ -71,7 +83,7 @@ class Plugin extends BasePlugin {
71
83
  * @param {server.Client} client
72
84
  */
73
85
  async removeClient(client) {
74
- this.clients.delete(client);
86
+ this.#clients.delete(client);
75
87
  }
76
88
  }
77
89