@soundworks/core 4.0.0-alpha.28 → 4.0.0-alpha.29

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 (127) hide show
  1. package/.jsdoc +3 -1
  2. package/CHANGELOG.md +11 -5
  3. package/package.json +5 -5
  4. package/src/client/Client.js +78 -83
  5. package/src/client/{Context.js → ClientContext.js} +48 -38
  6. package/src/client/ClientContextManager.js +115 -0
  7. package/src/client/{Plugin.js → ClientPlugin.js} +22 -18
  8. package/src/client/{PluginManager.js → ClientPluginManager.js} +39 -35
  9. package/src/client/{Socket.js → ClientSocket.js} +54 -65
  10. package/src/client/{StateManager.js → ClientStateManager.js} +7 -8
  11. package/src/client/index.js +17 -41
  12. package/src/common/BasePlugin.js +56 -51
  13. package/src/common/BasePluginManager.js +175 -139
  14. package/src/common/BaseStateManager.js +316 -120
  15. package/src/common/BatchedTransport.js +24 -24
  16. package/src/common/ParameterBag.js +18 -6
  17. package/src/common/PromiseStore.js +1 -0
  18. package/src/common/{BaseSharedState.js → SharedState.js} +271 -199
  19. package/src/common/{BaseSharedStateCollection.js → SharedStateCollection.js} +92 -61
  20. package/src/common/logger.js +5 -0
  21. package/src/common/shared-state-types.js +76 -0
  22. package/src/common/version.js +1 -1
  23. package/src/server/Server.js +391 -354
  24. package/src/server/ServerClient.js +73 -0
  25. package/src/server/{Context.js → ServerContext.js} +85 -66
  26. package/src/server/{ContextManager.js → ServerContextManager.js} +98 -85
  27. package/src/server/{Plugin.js → ServerPlugin.js} +10 -24
  28. package/src/server/{PluginManager.js → ServerPluginManager.js} +76 -69
  29. package/src/server/{Socket.js → ServerSocket.js} +19 -18
  30. package/src/server/{Sockets.js → ServerSockets.js} +36 -27
  31. package/src/server/ServerStateManager.js +515 -0
  32. package/src/{common → server}/SharedStatePrivate.js +61 -26
  33. package/src/server/audit-schema.js +1 -1
  34. package/src/server/crypto.js +2 -0
  35. package/src/server/index.js +18 -21
  36. package/types/client/Client.d.ts +74 -95
  37. package/types/client/{Context.d.ts → ClientContext.d.ts} +25 -26
  38. package/types/client/{ContextManager.d.ts → ClientContextManager.d.ts} +19 -22
  39. package/types/client/{Plugin.d.ts → ClientPlugin.d.ts} +17 -20
  40. package/types/client/{PluginManager.d.ts → ClientPluginManager.d.ts} +13 -36
  41. package/types/client/ClientSocket.d.ts +74 -0
  42. package/types/client/{StateManager.d.ts → ClientStateManager.d.ts} +11 -15
  43. package/types/client/index.d.ts +26 -2
  44. package/types/common/BasePlugin.d.ts +52 -46
  45. package/types/common/BasePluginManager.d.ts +68 -44
  46. package/types/common/BaseStateManager.d.ts +207 -97
  47. package/types/common/BatchedTransport.d.ts +1 -5
  48. package/types/common/ParameterBag.d.ts +16 -18
  49. package/types/common/PromiseStore.d.ts +1 -1
  50. package/types/common/SharedState.d.ts +297 -0
  51. package/types/common/{BaseSharedStateCollection.d.ts → SharedStateCollection.d.ts} +34 -18
  52. package/types/common/constants.d.ts +0 -2
  53. package/types/common/logger.d.ts +2 -1
  54. package/types/common/shared-state-types.d.ts +83 -0
  55. package/types/common/sockets-utils.d.ts +0 -5
  56. package/types/common/version.d.ts +1 -2
  57. package/types/server/Server.d.ts +78 -132
  58. package/types/server/ServerClient.d.ts +45 -0
  59. package/types/server/{Context.d.ts → ServerContext.d.ts} +53 -43
  60. package/types/server/ServerContextManager.d.ts +80 -0
  61. package/types/server/{Plugin.d.ts → ServerPlugin.d.ts} +19 -33
  62. package/types/server/{PluginManager.d.ts → ServerPluginManager.d.ts} +39 -37
  63. package/types/server/ServerSocket.d.ts +85 -0
  64. package/types/server/ServerSockets.d.ts +50 -0
  65. package/types/server/ServerStateManager.d.ts +189 -0
  66. package/types/server/SharedStatePrivate.d.ts +21 -0
  67. package/types/server/audit-network-latency.worker.d.ts +1 -2
  68. package/types/server/audit-schema.d.ts +0 -1
  69. package/types/server/crypto.d.ts +2 -1
  70. package/types/server/index.d.ts +24 -2
  71. package/src/client/ContextManager.js +0 -111
  72. package/src/client/SharedState.js +0 -84
  73. package/src/client/SharedStateCollection.js +0 -38
  74. package/src/server/Client.js +0 -55
  75. package/src/server/SharedState.js +0 -85
  76. package/src/server/SharedStateCollection.js +0 -39
  77. package/src/server/StateManager.js +0 -696
  78. package/types/client/Client.d.ts.map +0 -1
  79. package/types/client/Context.d.ts.map +0 -1
  80. package/types/client/ContextManager.d.ts.map +0 -1
  81. package/types/client/Plugin.d.ts.map +0 -1
  82. package/types/client/PluginManager.d.ts.map +0 -1
  83. package/types/client/SharedState.d.ts +0 -85
  84. package/types/client/SharedState.d.ts.map +0 -1
  85. package/types/client/SharedStateCollection.d.ts +0 -41
  86. package/types/client/SharedStateCollection.d.ts.map +0 -1
  87. package/types/client/Socket.d.ts +0 -149
  88. package/types/client/Socket.d.ts.map +0 -1
  89. package/types/client/StateManager.d.ts.map +0 -1
  90. package/types/client/index.d.ts.map +0 -1
  91. package/types/common/BasePlugin.d.ts.map +0 -1
  92. package/types/common/BasePluginManager.d.ts.map +0 -1
  93. package/types/common/BaseSharedState.d.ts +0 -244
  94. package/types/common/BaseSharedState.d.ts.map +0 -1
  95. package/types/common/BaseSharedStateCollection.d.ts.map +0 -1
  96. package/types/common/BaseStateManager.d.ts.map +0 -1
  97. package/types/common/BatchedTransport.d.ts.map +0 -1
  98. package/types/common/ParameterBag.d.ts.map +0 -1
  99. package/types/common/PromiseStore.d.ts.map +0 -1
  100. package/types/common/SharedStatePrivate.d.ts +0 -21
  101. package/types/common/SharedStatePrivate.d.ts.map +0 -1
  102. package/types/common/constants.d.ts.map +0 -1
  103. package/types/common/logger.d.ts.map +0 -1
  104. package/types/common/sockets-utils.d.ts.map +0 -1
  105. package/types/common/version.d.ts.map +0 -1
  106. package/types/server/Client.d.ts +0 -45
  107. package/types/server/Client.d.ts.map +0 -1
  108. package/types/server/Context.d.ts.map +0 -1
  109. package/types/server/ContextManager.d.ts +0 -69
  110. package/types/server/ContextManager.d.ts.map +0 -1
  111. package/types/server/Plugin.d.ts.map +0 -1
  112. package/types/server/PluginManager.d.ts.map +0 -1
  113. package/types/server/Server.d.ts.map +0 -1
  114. package/types/server/SharedState.d.ts +0 -86
  115. package/types/server/SharedState.d.ts.map +0 -1
  116. package/types/server/SharedStateCollection.d.ts +0 -41
  117. package/types/server/SharedStateCollection.d.ts.map +0 -1
  118. package/types/server/Socket.d.ts +0 -164
  119. package/types/server/Socket.d.ts.map +0 -1
  120. package/types/server/Sockets.d.ts +0 -80
  121. package/types/server/Sockets.d.ts.map +0 -1
  122. package/types/server/StateManager.d.ts +0 -405
  123. package/types/server/StateManager.d.ts.map +0 -1
  124. package/types/server/audit-network-latency.worker.d.ts.map +0 -1
  125. package/types/server/audit-schema.d.ts.map +0 -1
  126. package/types/server/crypto.d.ts.map +0 -1
  127. package/types/server/index.d.ts.map +0 -1
@@ -1,18 +1,5 @@
1
1
  import BasePlugin from '../common/BasePlugin.js';
2
2
 
3
- /**
4
- * Callback executed when the plugin state is updated.
5
- *
6
- * @callback server.Plugin~onStateChangeCallback
7
- * @param {server.Plugin#state} state - Current state of the plugin.
8
- */
9
-
10
- /**
11
- * Delete the registered {@link server.Plugin~onStateChangeCallback}.
12
- *
13
- * @callback server.Plugin~deleteOnStateChangeCallback
14
- */
15
-
16
3
  /**
17
4
  * Base class to extend in order to create the server-side counterpart of a
18
5
  * `soundworks` plugin.
@@ -28,18 +15,17 @@ import BasePlugin from '../common/BasePlugin.js';
28
15
  *
29
16
  * _Creating new plugins should be considered an advanced usage._
30
17
  *
31
- * @memberof server
32
18
  * @extends BasePlugin
33
19
  * @inheritdoc
34
20
  */
35
- class Plugin extends BasePlugin {
21
+ class ServerPlugin extends BasePlugin {
36
22
  #server = null;
37
23
  #clients = new Set();
38
24
 
39
25
  /**
40
- * @param {server.Server} server - The soundworks server instance.
26
+ * @param {Server} server - The soundworks server instance.
41
27
  * @param {string} id - User defined id of the plugin as defined in
42
- * {@link server.PluginManager#register}.
28
+ * {@link ServerPluginManager#register}.
43
29
  */
44
30
  constructor(server, id) {
45
31
  super(id);
@@ -48,8 +34,8 @@ class Plugin extends BasePlugin {
48
34
 
49
35
  /**
50
36
  * Instance of soundworks server.
51
- * @type {server.Server}
52
- * @see {@link server.Server}
37
+ * @type {Server}
38
+ * @see {@link Server}
53
39
  */
54
40
  get server() {
55
41
  return this.#server;
@@ -57,8 +43,8 @@ class Plugin extends BasePlugin {
57
43
 
58
44
  /**
59
45
  * Set of the clients registered in the plugin.
60
- * @type {Set<server.Client>}
61
- * @see {@link server.Client}
46
+ * @type {Set<ServerClient>}
47
+ * @see {@link ServerClient}
62
48
  */
63
49
  get clients() {
64
50
  return this.#clients;
@@ -69,7 +55,7 @@ class Plugin extends BasePlugin {
69
55
  * connects to the application. Override this method if you need to perform
70
56
  * some particular logic (e.g. creating a shared state) for each clients.
71
57
  *
72
- * @param {server.Client} client
58
+ * @param {ServerClient} client
73
59
  */
74
60
  async addClient(client) {
75
61
  this.#clients.add(client);
@@ -80,11 +66,11 @@ class Plugin extends BasePlugin {
80
66
  * disconnects from the application. Override this method if you need to perform
81
67
  * some particular logic (e.g. creating a shared state) for each clients.
82
68
  *
83
- * @param {server.Client} client
69
+ * @param {ServerClient} client
84
70
  */
85
71
  async removeClient(client) {
86
72
  this.#clients.delete(client);
87
73
  }
88
74
  }
89
75
 
90
- export default Plugin;
76
+ export default ServerPlugin;
@@ -1,28 +1,18 @@
1
- import BasePluginManager from '../common/BasePluginManager.js';
2
- import Plugin from './Plugin.js';
1
+ import BasePluginManager, {
2
+ kPluginManagerInstances,
3
+ } from '../common/BasePluginManager.js';
4
+ import ServerPlugin from './ServerPlugin.js';
3
5
  import Server from './Server.js';
4
6
 
5
- /**
6
- * Callback executed when a plugin internal state is updated.
7
- *
8
- * @callback server.PluginManager~onStateChangeCallback
9
- * @param {object<server.Plugin#id, server.Plugin>} fullState - List of all plugins.
10
- * @param {server.Plugin|null} initiator - Plugin that initiated the update or `null`
11
- * if the change was initiated by the state manager (i.e. when the initialization
12
- * of the plugins starts).
13
- */
14
-
15
- /**
16
- * Delete the registered {@link server.PluginManager~onStateChangeCallback}.
17
- *
18
- * @callback server.PluginManager~deleteOnStateChangeCallback
19
- */
7
+ export const kServerPluginManagerCheckRegisteredPlugins = Symbol('soundworks:server-plugin-manager-check-registered-plugins');
8
+ export const kServerPluginManagerAddClient = Symbol('soundworks:server-plugin-manager-add-client');
9
+ export const kServerPluginManagerRemoveClient = Symbol('soundworks:server-plugin-manager-remove-client');
20
10
 
21
11
  /**
22
12
  * The `PluginManager` allows to register and retrieve `soundworks` plugins.
23
13
  *
24
14
  * Plugins should always be registered both client-side and server-side,
25
- * and before {@link client.Client#start} or {@link server.Server#start}
15
+ * and before {@link Client#start} or {@link Server#start}
26
16
  * to be properly initialized.
27
17
  *
28
18
  * In some sitautions, you might want to register the same plugin factory several times
@@ -70,12 +60,11 @@ import Server from './Server.js';
70
60
  * }, 1000);
71
61
  * ```
72
62
  *
73
- * @memberof server
74
63
  * @extends BasePluginManager
75
64
  * @inheritdoc
76
65
  * @hideconstructor
77
66
  */
78
- class PluginManager extends BasePluginManager {
67
+ class ServerPluginManager extends BasePluginManager {
79
68
  constructor(server) {
80
69
  if (!(server instanceof Server)) {
81
70
  throw new Error(`[soundworks.PluginManager] Invalid argument, "new PluginManager(server)" should receive an instance of "soundworks.Server" as argument`);
@@ -84,64 +73,23 @@ class PluginManager extends BasePluginManager {
84
73
  super(server);
85
74
  }
86
75
 
87
- register(id, factory = null, options = {}, deps = []) {
88
- const ctor = factory(Plugin);
89
-
90
- if (!(ctor.prototype instanceof Plugin)) {
91
- throw new Error(`[soundworks.PluginManager] Invalid argument, "pluginManager.register" second argument should be a factory function returning a class extending the "Plugin" base class`);
92
- }
93
-
94
- super.register(id, ctor, options, deps);
95
- }
96
-
97
- /**
98
- * Retrieve an fully started instance of a registered plugin.
99
- *
100
- * Be aware that the `get` method resolves only when the plugin is fully 'started',
101
- * which is what we want 99.99% of the time. As such, and to prevent the application
102
- * to be stuck in some kind of Promise dead lock, this method will throw if
103
- * used before `server.init()` (or `server.start()`).
104
- *
105
- * To handle the remaining 0.01% cases and access plugin instances during their
106
- * initialization (e.g. to display initialization screen, etc.), you should rely
107
- * on the `onStateChange` method.
108
- *
109
- * _Note: the async API is designed to enable the dynamic creation of plugins
110
- * (hopefully without brealing changes) in a future release._
111
- *
112
- * @param {server.Plugin#id} id - Id of the plugin as defined when registered.
113
- * @returns {server.Plugin}
114
- * @see {@link server.PluginManager#onStateChange}
115
- *
116
- * @private
117
- */
118
- async get(id) {
119
- if (this.status !== 'started') {
120
- throw new Error(`[soundworks.PluginManager] Cannot get plugin before "server.init()"`);
121
- }
122
-
123
- return super.unsafeGet(id);
124
- }
125
-
126
- // server only methods
127
-
128
- /** private */
129
- checkRegisteredPlugins(registeredPlugins) {
76
+ /** @private */
77
+ [kServerPluginManagerCheckRegisteredPlugins](registeredPlugins) {
130
78
  let missingPlugins = [];
131
79
 
132
80
  for (let id of registeredPlugins) {
133
- if (!this._instances.has(id)) {
81
+ if (!this[kPluginManagerInstances].has(id)) {
134
82
  missingPlugins.push(id);
135
83
  }
136
84
  }
137
85
 
138
86
  if (missingPlugins.length > 0) {
139
- throw new Error(`Invalid plugin list, the following plugins registered client-side: [${missingPlugins.join(', ')}] have not been registered server-side. Registered server-side plugins are: [${Array.from(this._instances.keys()).join(', ')}].`);
87
+ throw new Error(`Invalid plugin list, the following plugins registered client-side: [${missingPlugins.join(', ')}] have not been registered server-side. Registered server-side plugins are: [${Array.from(this[kPluginManagerInstances].keys()).join(', ')}].`);
140
88
  }
141
89
  }
142
90
 
143
91
  /** @private */
144
- async addClient(client, registeredPlugins = []) {
92
+ async [kServerPluginManagerAddClient](client, registeredPlugins = []) {
145
93
  let promises = [];
146
94
 
147
95
  for (let pluginName of registeredPlugins) {
@@ -154,10 +102,10 @@ class PluginManager extends BasePluginManager {
154
102
  }
155
103
 
156
104
  /** @private */
157
- async removeClient(client) {
105
+ async [kServerPluginManagerRemoveClient](client) {
158
106
  let promises = [];
159
107
 
160
- for (let plugin of this._instances.values()) {
108
+ for (let plugin of this[kPluginManagerInstances].values()) {
161
109
  if (plugin.clients.has(client)) {
162
110
  promises.push(plugin.removeClient(client));
163
111
  }
@@ -165,6 +113,65 @@ class PluginManager extends BasePluginManager {
165
113
 
166
114
  await Promise.all(promises);
167
115
  }
116
+
117
+ /**
118
+ * Register a plugin into the manager.
119
+ *
120
+ * _A plugin must always be registered both on client-side and on server-side_
121
+ *
122
+ * Refer to the plugin documentation to check its options and proper way of
123
+ * registering it.
124
+ *
125
+ * @param {string} id - Unique id of the plugin. Enables the registration of the
126
+ * same plugin factory under different ids.
127
+ * @param {Function} factory - Factory function that returns the Plugin class.
128
+ * @param {object} [options={}] - Options to configure the plugin.
129
+ * @param {array} [deps=[]] - List of plugins' names the plugin depends on, i.e.
130
+ * the plugin initialization will start only after the plugins it depends on are
131
+ * fully started themselves.
132
+ * @see {@link ClientPluginManager#register}
133
+ * @see {@link ServerPluginManager#register}
134
+ * @example
135
+ * // client-side
136
+ * client.pluginManager.register('user-defined-id', pluginFactory);
137
+ * // server-side
138
+ * server.pluginManager.register('user-defined-id', pluginFactory);
139
+ */
140
+ register(id, factory = null, options = {}, deps = []) {
141
+ const ctor = factory(ServerPlugin);
142
+
143
+ if (!(ctor.prototype instanceof ServerPlugin)) {
144
+ throw new Error(`[soundworks.PluginManager] Invalid argument, "pluginManager.register" second argument should be a factory function returning a class extending the "ServerPlugin" base class`);
145
+ }
146
+
147
+ super.register(id, ctor, options, deps);
148
+ }
149
+
150
+ /**
151
+ * Retrieve a fully started instance of a registered plugin.
152
+ *
153
+ * Be aware that the `get` method resolves only when the plugin is fully 'started',
154
+ * which is what we want 99.99% of the time. As such, and to prevent the application
155
+ * to be stuck in some kind of Promise dead lock, this method will throw if
156
+ * used before `server.init()` (or `server.start()`).
157
+ *
158
+ * To handle the remaining 0.01% cases and access plugin instances during their
159
+ * initialization (e.g. to display initialization screen, etc.), you should rely
160
+ * on the `onStateChange` method.
161
+ *
162
+ * _Note: the async API is designed to enable the dynamic creation of plugins
163
+ * (hopefully without brealing changes) in a future release._
164
+ *
165
+ * @param {ServerPlugin#id} id - Id of the plugin as defined when registered.
166
+ * @returns {ServerPlugin}
167
+ */
168
+ async get(id) {
169
+ if (this.status !== 'started') {
170
+ throw new Error(`[soundworks.PluginManager] Cannot get plugin before "server.init()"`);
171
+ }
172
+
173
+ return super.getUnsafe(id);
174
+ }
168
175
  }
169
176
 
170
- export default PluginManager;
177
+ export default ServerPluginManager;
@@ -12,7 +12,7 @@ import {
12
12
  kSocketsLatencyStatsWorker,
13
13
  kSocketsDebugPreventHeartBeat,
14
14
  kSocketsRemoveFromAllRooms,
15
- } from './Sockets.js';
15
+ } from './ServerSockets.js';
16
16
 
17
17
  export const kSocketClientId = Symbol('soundworks:socket-client-id');
18
18
  export const kSocketTerminate = Symbol('soundworks:socket-terminate');
@@ -21,22 +21,15 @@ export const kSocketTerminate = Symbol('soundworks:socket-terminate');
21
21
  * Simple publish / subscribe wrapper built on top of the
22
22
  * [ws](https://github.com/websockets/ws) library.
23
23
  *
24
- * An instance of {@link server.Socket} is automatically created per client
25
- * when it connects (see {@link server.Client#socket}).
24
+ * An instance of {@link ServerSocket} is automatically created per client
25
+ * when it connects (see {@link SeverClient#socket}).
26
26
  *
27
- * _Important: In most cases, you should consider using a {@link client.SharedState}
27
+ * _Important: In most cases, you should consider using a {@link SharedState}
28
28
  * rather than directly using the Socket instance._
29
29
  *
30
- * The Socket class contains two different WebSockets:
31
- * - a socket configured with `binaryType = 'blob'` for JSON compatible data
32
- * types (i.e. string, number, boolean, object, array and null).
33
- * - a socket configured with `binaryType= 'arraybuffer'` for efficient streaming
34
- * of binary data.
35
- *
36
- * @memberof server
37
30
  * @hideconstructor
38
31
  */
39
- class Socket {
32
+ class ServerSocket {
40
33
  #socket = null;
41
34
  #sockets = null;
42
35
  #listeners = new Map();
@@ -53,7 +46,7 @@ class Socket {
53
46
  * Reference to the sockets object, is mainly dedicated to allow
54
47
  * broadcasting from a given socket instance.
55
48
  *
56
- * @type {server.Sockets}
49
+ * @type {ServerSockets}
57
50
  * @example
58
51
  * socket.sockets.broadcast('my-room', this, 'update-value', 1);
59
52
  */
@@ -94,7 +87,7 @@ class Socket {
94
87
  // client is busy, e.g. when loading large sound files so let's just warn
95
88
  // until we gather more feedback
96
89
  // cf. https://making.close.com/posts/reliable-websockets/
97
- console.warn(`[Socket] client (id: ${this[kSocketClientId]}) did not respond to ping message in time (missed: ${heartbeatMissed}, interval: ${PING_INTERVAL})`);
90
+ console.warn(`[ServerSocket] client (id: ${this[kSocketClientId]}) did not respond to ping message in time (missed: ${heartbeatMissed}, interval: ${PING_INTERVAL})`);
98
91
  // this.#dispatchEvent('close');
99
92
  // return;
100
93
  }
@@ -144,6 +137,8 @@ class Socket {
144
137
  *
145
138
  * Is automatically called when socket is closed on the client side or when
146
139
  * Server is stopped
140
+ *
141
+ * @private
147
142
  */
148
143
  [kSocketTerminate]() {
149
144
  // clear ping / pong interval
@@ -170,11 +165,11 @@ class Socket {
170
165
  }
171
166
 
172
167
  /**
173
- * Reference to the @link{server.Sockets} instance.
168
+ * Reference to the @link{ServerSockets} instance.
174
169
  *
175
170
  * Allows for broadcasting from a given socket instance.
176
171
  *
177
- * @type {server.Sockets}
172
+ * @type {ServerSockets}
178
173
  * @example
179
174
  * socket.sockets.broadcast('my-room', this, 'update-value', 1);
180
175
  */
@@ -182,6 +177,12 @@ class Socket {
182
177
  return this.#sockets;
183
178
  }
184
179
 
180
+ /**
181
+ * Reay state of the underlying socket instance.
182
+ *
183
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState}
184
+ * @type {number}
185
+ */
185
186
  get readyState() {
186
187
  return this.#socket.readyState;
187
188
  }
@@ -216,7 +217,7 @@ class Socket {
216
217
  * @param {string} channel - Channel name.
217
218
  * @param {Function} callback - Callback to execute when a message is received.
218
219
  * Arguments of the callback function will match the arguments sent using the
219
- * {@link server.Socket#send} method.
220
+ * {@link ServerSocket#send} method.
220
221
  */
221
222
  addListener(channel, callback) {
222
223
  if (!this.#listeners.has(channel)) {
@@ -275,4 +276,4 @@ class Socket {
275
276
 
276
277
  }
277
278
 
278
- export default Socket;
279
+ export default ServerSocket;
@@ -8,30 +8,39 @@ import {
8
8
  WebSocketServer,
9
9
  } from 'ws';
10
10
 
11
- import Socket, {
11
+ import {
12
+ kServerOnSocketConnection,
13
+ kServerIsProtectedRole,
14
+ } from './Server.js';
15
+ import ServerSocket, {
12
16
  kSocketTerminate,
13
- } from './Socket.js';
17
+ } from './ServerSocket.js';
14
18
 
15
19
  // @note - fs.readFileSync creates some cwd() issues...
16
20
  import networkLatencyWorker from './audit-network-latency.worker.js';
17
21
 
22
+ export const kSocketsStart = Symbol('soundworks:sockets-start');
23
+ export const kSocketsStop = Symbol('soundworks:sockets-stop');
24
+
18
25
  export const kSocketsRemoveFromAllRooms = Symbol('soundworks:sockets-remove-from-all-rooms');
19
26
  export const kSocketsLatencyStatsWorker = Symbol('soundworks:sockets-latency-stats-worker');
20
27
  export const kSocketsDebugPreventHeartBeat = Symbol('soundworks:sockets-debug-prevent-heartbeat');
21
28
 
22
29
  /**
23
- * Manage all {@link server.Socket} instances.
24
- *
25
- * _Important: In most cases, you should consider using a {@link client.SharedState}
26
- * rather than directly using the Socket instance._
30
+ * Manage all {@link ServerSocket} instances.
27
31
  *
28
- * @memberof server
32
+ * _Important: In most cases, you should consider using a {@link SharedState}
33
+ * rather than directly using the ServerSocket instance._
29
34
  */
30
- class Sockets {
35
+ class ServerSockets {
36
+ #server = null;
37
+ #config = null;
31
38
  #wsServer = null;
32
39
  #rooms = new Map();
33
40
 
34
- constructor() {
41
+ constructor(server, config) {
42
+ this.#server = server;
43
+ this.#config = config;
35
44
  // Init special `'*'` room which stores all current connections.
36
45
  this.#rooms.set('*', new Set());
37
46
 
@@ -43,15 +52,14 @@ class Sockets {
43
52
  * Initialize sockets, all sockets are added to two rooms by default:
44
53
  * - to the room corresponding to the client `role`
45
54
  * - to the '*' room that holds all connected sockets
46
- *
47
55
  * @private
48
56
  */
49
- async start(server, config, onConnectionCallback) {
57
+ async [kSocketsStart]() {
50
58
  // Audit for network latency estimation, the worker is written in cjs so that we
51
59
  // can make builds for Max, move back to modules once Max support modules
52
60
  this[kSocketsLatencyStatsWorker] = new Worker(networkLatencyWorker, { eval: true });
53
61
 
54
- const auditState = await server.getAuditState();
62
+ const auditState = await this.#server.getAuditState();
55
63
 
56
64
  auditState.onUpdate(updates => {
57
65
  if ('averageNetworkLatencyWindow' in updates || 'averageNetworkLatencyPeriod' in updates) {
@@ -74,27 +82,27 @@ class Sockets {
74
82
  // Init ws server
75
83
  this.#wsServer = new WebSocketServer({
76
84
  noServer: true,
77
- path: `/${config.path}`,
85
+ path: `/${this.#config.path}`,
78
86
  });
79
87
 
80
88
  this.#wsServer.on('connection', (ws, req) => {
81
89
  const { role, token } = querystring.parse(req.url.split('?')[1]);
82
- const socket = new Socket(ws, this);
90
+ const socket = new ServerSocket(ws, this);
83
91
 
84
92
  socket.addToRoom('*');
85
93
  socket.addToRoom(role);
86
94
 
87
- onConnectionCallback(role, socket, token);
95
+ this.#server[kServerOnSocketConnection](role, socket, token);
88
96
  });
89
97
 
90
- // Prevent socket with protected role to connect is token is invalid
91
- server.httpServer.on('upgrade', async (req, socket, head) => {
98
+ // Prevent socket with protected role to connect if token is invalid
99
+ this.#server.httpServer.on('upgrade', async (req, socket, head) => {
92
100
  const { role, token } = querystring.parse(req.url.split('?')[1]);
93
101
 
94
- if (server.isProtected(role)) {
102
+ if (this.#server[kServerIsProtectedRole](role)) {
95
103
  // we don't have any IP in the upgrade request object,
96
104
  // so we just check the connection token is pending and valid
97
- if (!server.isValidConnectionToken(token)) {
105
+ if (!this.#server[kServerIsValidConnectionToken](token)) {
98
106
  socket.destroy('not allowed');
99
107
  }
100
108
  }
@@ -109,7 +117,7 @@ class Sockets {
109
117
  * Terminate all existing sockets.
110
118
  * @private
111
119
  */
112
- terminate() {
120
+ [kSocketsStop]() {
113
121
  // terminate stat worker thread
114
122
  this[kSocketsLatencyStatsWorker].terminate();
115
123
  // clean sockets
@@ -119,6 +127,7 @@ class Sockets {
119
127
 
120
128
  /**
121
129
  * Remove given socket from all rooms.
130
+ * @private
122
131
  */
123
132
  [kSocketsRemoveFromAllRooms](socket) {
124
133
  for (let [_, room] of this.#rooms) {
@@ -129,9 +138,9 @@ class Sockets {
129
138
  /**
130
139
  * Add a socket to a room.
131
140
  *
132
- * _Note that in most cases, you should use a shared state instead_
141
+ * _Note that in most cases, you should use a {@link SharedState} instead_
133
142
  *
134
- * @param {server.Socket} socket - Socket to add to the room.
143
+ * @param {ServerSocket} socket - Socket to add to the room.
135
144
  * @param {String} roomId - Id of the room.
136
145
  */
137
146
  addToRoom(socket, roomId) {
@@ -146,9 +155,9 @@ class Sockets {
146
155
  /**
147
156
  * Remove a socket from a room.
148
157
  *
149
- * _Note that in most cases, you should use a shared state instead_
158
+ * _Note that in most cases, you should use a {@link SharedState} instead_
150
159
  *
151
- * @param {server.Socket} socket - Socket to remove from the room.
160
+ * @param {ServerSocket} socket - Socket to remove from the room.
152
161
  * @param {String} roomId - Id of the room.
153
162
  */
154
163
  removeFromRoom(socket, roomId) {
@@ -162,11 +171,11 @@ class Sockets {
162
171
  * Send a message to all clients os given room(s). If no room is specified,
163
172
  * the message is sent to all clients.
164
173
  *
165
- * _Note that in most cases, you should use a shared state instead_
174
+ * _Note that in most cases, you should use a {@link SharedState} instead_
166
175
  *
167
176
  * @param {String|Array} roomsIds - Ids of the rooms that must receive
168
177
  * the message. If `null` the message is sent to all clients.
169
- * @param {server.Socket} excludeSocket - Optionnal socket to ignore when
178
+ * @param {ServerSocket} excludeSocket - Optionnal socket to ignore when
170
179
  * broadcasting the message, typically the client at the origin of the message.
171
180
  * @param {String} channel - Channel name.
172
181
  * @param {...*} args - Payload of the message. As many arguments as needed, of
@@ -198,4 +207,4 @@ class Sockets {
198
207
  }
199
208
  }
200
209
 
201
- export default Sockets;
210
+ export default ServerSockets;