@soundworks/core 4.0.0-alpha.7 → 5.0.0

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 (144) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/README.md +16 -50
  3. package/package.json +26 -44
  4. package/src/client/Client.js +306 -256
  5. package/src/client/{Context.js → ClientContext.js} +63 -54
  6. package/src/client/ClientContextManager.js +115 -0
  7. package/src/client/{Plugin.js → ClientPlugin.js} +23 -19
  8. package/src/client/{PluginManager.js → ClientPluginManager.js} +43 -40
  9. package/src/client/ClientSocket.js +270 -0
  10. package/src/client/{StateManager.js → ClientStateManager.js} +13 -13
  11. package/src/client/index.js +36 -39
  12. package/src/common/BasePlugin.js +63 -58
  13. package/src/common/BasePluginManager.js +191 -142
  14. package/src/common/BaseStateManager.js +636 -143
  15. package/src/common/BatchedTransport.js +73 -0
  16. package/src/common/ParameterBag.js +90 -93
  17. package/src/common/PromiseStore.js +54 -0
  18. package/src/common/SharedState.js +821 -0
  19. package/src/common/SharedStateCollection.js +492 -0
  20. package/src/common/constants.js +14 -2
  21. package/src/common/logger.js +64 -68
  22. package/src/common/shared-state-types.js +82 -0
  23. package/src/common/sockets-utils.js +0 -64
  24. package/src/common/version.js +2 -0
  25. package/src/server/Server.js +559 -821
  26. package/src/server/ServerClient.js +74 -0
  27. package/src/server/{Context.js → ServerContext.js} +96 -77
  28. package/src/server/{ContextManager.js → ServerContextManager.js} +107 -87
  29. package/src/server/{Plugin.js → ServerPlugin.js} +30 -32
  30. package/src/server/ServerPluginManager.js +177 -0
  31. package/src/server/ServerSocket.js +256 -0
  32. package/src/server/ServerSockets.js +150 -0
  33. package/src/server/ServerStateManager.js +706 -0
  34. package/src/server/SharedStatePrivate.js +277 -0
  35. package/src/server/audit-network-latency.worker.js +19 -4
  36. package/src/server/{audit-schema.js → audit-state-class-description.js} +3 -2
  37. package/src/server/create-http-server.js +127 -0
  38. package/src/server/crypto.js +8 -7
  39. package/src/server/index.js +60 -17
  40. package/types/client/Client.d.ts +95 -70
  41. package/types/client/{Context.d.ts → ClientContext.d.ts} +59 -34
  42. package/types/client/{ContextManager.d.ts → ClientContextManager.d.ts} +19 -22
  43. package/types/client/ClientPlugin.d.ts +51 -0
  44. package/types/client/ClientPluginManager.d.ts +112 -0
  45. package/types/client/ClientSocket.d.ts +76 -0
  46. package/types/client/{StateManager.d.ts → ClientStateManager.d.ts} +18 -21
  47. package/types/client/index.d.ts +33 -6
  48. package/types/common/BasePlugin.d.ts +64 -53
  49. package/types/common/BasePluginManager.d.ts +84 -39
  50. package/types/common/BaseStateManager.d.ts +227 -49
  51. package/types/common/BatchedTransport.d.ts +17 -0
  52. package/types/common/ParameterBag.d.ts +73 -76
  53. package/types/common/PromiseStore.d.ts +11 -0
  54. package/types/common/SharedState.d.ts +291 -0
  55. package/types/common/SharedStateCollection.d.ts +311 -0
  56. package/types/common/constants.d.ts +10 -3
  57. package/types/common/logger.d.ts +8 -6
  58. package/types/common/shared-state-types.d.ts +95 -0
  59. package/types/common/sockets-utils.d.ts +0 -5
  60. package/types/common/version.d.ts +2 -0
  61. package/types/server/Server.d.ts +215 -136
  62. package/types/server/ServerClient.d.ts +45 -0
  63. package/types/server/ServerContext.d.ts +209 -0
  64. package/types/server/ServerContextManager.d.ts +75 -0
  65. package/types/server/ServerPlugin.d.ts +57 -0
  66. package/types/server/ServerPluginManager.d.ts +115 -0
  67. package/types/server/ServerSocket.d.ts +69 -0
  68. package/types/server/ServerSockets.d.ts +42 -0
  69. package/types/server/ServerStateManager.d.ts +284 -0
  70. package/types/server/SharedStatePrivate.d.ts +23 -0
  71. package/types/server/audit-network-latency.worker.d.ts +2 -2
  72. package/types/server/{audit-schema.d.ts → audit-state-class-description.d.ts} +8 -9
  73. package/types/server/create-http-server.d.ts +5 -0
  74. package/types/server/crypto.d.ts +4 -0
  75. package/types/server/index.d.ts +51 -3
  76. package/.eslintrc +0 -15
  77. package/.github/workflows/gh-pages.yml +0 -31
  78. package/.github/workflows/unit-tests.yml +0 -18
  79. package/src/client/ContextManager.js +0 -111
  80. package/src/client/SharedState.js +0 -84
  81. package/src/client/SharedStateCollection.js +0 -35
  82. package/src/client/Socket.js +0 -402
  83. package/src/common/BaseSharedState.js +0 -517
  84. package/src/common/BaseSharedStateCollection.js +0 -179
  85. package/src/common/SharedStatePrivate.js +0 -192
  86. package/src/common/promise-store.js +0 -25
  87. package/src/server/Client.js +0 -55
  88. package/src/server/PluginManager.js +0 -170
  89. package/src/server/SharedState.js +0 -85
  90. package/src/server/SharedStateCollection.js +0 -36
  91. package/src/server/Socket.js +0 -396
  92. package/src/server/Sockets.js +0 -224
  93. package/src/server/StateManager.js +0 -620
  94. package/tsconfig.json +0 -21
  95. package/types/client/Client.d.ts.map +0 -1
  96. package/types/client/Context.d.ts.map +0 -1
  97. package/types/client/ContextManager.d.ts.map +0 -1
  98. package/types/client/Plugin.d.ts +0 -53
  99. package/types/client/Plugin.d.ts.map +0 -1
  100. package/types/client/PluginManager.d.ts +0 -96
  101. package/types/client/PluginManager.d.ts.map +0 -1
  102. package/types/client/SharedState.d.ts +0 -85
  103. package/types/client/SharedState.d.ts.map +0 -1
  104. package/types/client/Socket.d.ts +0 -138
  105. package/types/client/Socket.d.ts.map +0 -1
  106. package/types/client/StateManager.d.ts.map +0 -1
  107. package/types/client/index.d.ts.map +0 -1
  108. package/types/common/BasePlugin.d.ts.map +0 -1
  109. package/types/common/BasePluginManager.d.ts.map +0 -1
  110. package/types/common/BaseSharedState.d.ts +0 -173
  111. package/types/common/BaseSharedState.d.ts.map +0 -1
  112. package/types/common/BaseStateManager.d.ts.map +0 -1
  113. package/types/common/ParameterBag.d.ts.map +0 -1
  114. package/types/common/SharedStatePrivate.d.ts +0 -20
  115. package/types/common/SharedStatePrivate.d.ts.map +0 -1
  116. package/types/common/constants.d.ts.map +0 -1
  117. package/types/common/logger.d.ts.map +0 -1
  118. package/types/common/promise-store.d.ts +0 -4
  119. package/types/common/promise-store.d.ts.map +0 -1
  120. package/types/common/sockets-utils.d.ts.map +0 -1
  121. package/types/common/utils.d.ts +0 -5
  122. package/types/common/utils.d.ts.map +0 -1
  123. package/types/server/Client.d.ts +0 -40
  124. package/types/server/Client.d.ts.map +0 -1
  125. package/types/server/Context.d.ts +0 -59
  126. package/types/server/Context.d.ts.map +0 -1
  127. package/types/server/ContextManager.d.ts +0 -69
  128. package/types/server/ContextManager.d.ts.map +0 -1
  129. package/types/server/Plugin.d.ts +0 -70
  130. package/types/server/Plugin.d.ts.map +0 -1
  131. package/types/server/PluginManager.d.ts +0 -91
  132. package/types/server/PluginManager.d.ts.map +0 -1
  133. package/types/server/Server.d.ts.map +0 -1
  134. package/types/server/SharedState.d.ts +0 -86
  135. package/types/server/SharedState.d.ts.map +0 -1
  136. package/types/server/Socket.d.ts +0 -128
  137. package/types/server/Socket.d.ts.map +0 -1
  138. package/types/server/Sockets.d.ts +0 -73
  139. package/types/server/Sockets.d.ts.map +0 -1
  140. package/types/server/StateManager.d.ts +0 -190
  141. package/types/server/StateManager.d.ts.map +0 -1
  142. package/types/server/audit-network-latency.worker.d.ts.map +0 -1
  143. package/types/server/audit-schema.d.ts.map +0 -1
  144. package/types/server/index.d.ts.map +0 -1
@@ -1,192 +0,0 @@
1
- import ParameterBag from '../common/ParameterBag.js';
2
- import {
3
- DELETE_REQUEST,
4
- DELETE_RESPONSE,
5
- DELETE_NOTIFICATION,
6
- DETACH_REQUEST,
7
- DETACH_RESPONSE,
8
- UPDATE_REQUEST,
9
- UPDATE_RESPONSE,
10
- UPDATE_ABORT,
11
- UPDATE_NOTIFICATION,
12
- } from '../common/constants.js';
13
-
14
- /**
15
- * The "real" state, this instance is kept private by the server.StateManager.
16
- * It cannot be accessed without a SharedState proxy
17
- * @private
18
- */
19
- class SharedStatePrivate {
20
- constructor(id, schemaName, schema, manager, initValues = {}) {
21
- this.id = id;
22
- this.schemaName = schemaName;
23
-
24
- this._manager = manager;
25
- this._parameters = new ParameterBag(schema, initValues);
26
- this._attachedClients = new Map(); // other peers interested in watching / controlling the state
27
-
28
- this._creatorRemoteId = null;
29
- this._creatorId = null;
30
- }
31
-
32
- _attachClient(remoteId, client, isOwner = false) {
33
- this._attachedClients.set(remoteId, client);
34
-
35
- if (isOwner) {
36
- this._creatorRemoteId = remoteId;
37
- this._creatorId = client.id;
38
- }
39
-
40
- // attach client listeners
41
- client.transport.addListener(`${UPDATE_REQUEST}-${this.id}-${remoteId}`, async (reqId, updates, context) => {
42
- // apply registered hooks
43
- const hooks = this._manager._hooksBySchemaName.get(this.schemaName);
44
- const values = this._parameters.getValues();
45
- let hookAborted = false;
46
-
47
- // cf. https://github.com/collective-soundworks/soundworks/issues/45
48
- for (let hook of hooks.values()) {
49
- const result = await hook(updates, values, context);
50
-
51
- if (result === null) { // explicit abort if hook returns null
52
- hookAborted = true;
53
- break;
54
- } else if (result === undefined) { // implicit continue if hook returns undefined
55
- continue;
56
- } else { // the hook returned an updates object
57
- updates = result;
58
- }
59
- }
60
-
61
- if (hookAborted === false) {
62
- const filteredUpdates = {};
63
- let hasUpdates = false;
64
-
65
- for (let name in updates) {
66
- // from v3.1.0 - the `filteredUpdates` check is made using 'fast-deep-equal'
67
- // cf. https://github.com/epoberezkin/fast-deep-equal
68
- // therefore unchanged objects are not considered changed
69
- // nor propagated anymore.
70
- // until v3.0.4 - we checked the `schema[name].type === 'any'`, to always consider
71
- // objects as dirty, because if the state is attached locally, we
72
- // compare the Object instances instead of their values.
73
- // @note - this should be made more robust but how?
74
- const [newValue, changed] = this._parameters.set(name, updates[name]);
75
-
76
- // if `filterChange` is set to `false` we don't check if the value
77
- // has been changed or not, it is always propagated to client states
78
- const { event, filterChange } = this._parameters.getSchema(name);
79
-
80
- // if event type reset internal value to null
81
- if (event) {
82
- this._parameters.set(name, null);
83
- }
84
-
85
- if ((filterChange && changed) || !filterChange) {
86
- filteredUpdates[name] = newValue;
87
- hasUpdates = true;
88
- }
89
- }
90
-
91
- if (hasUpdates) {
92
- // send response to requester
93
- // client.transport.emit(`${UPDATE_RESPONSE}-${this.id}-${remoteId}`, reqId, filteredUpdates);
94
-
95
- // @note: we propagate server-side last, because as the server transport
96
- // is synchronous it can break ordering if a subscription function makes
97
- // itself an update in reaction to an update, therefore network messages
98
- // order would be broken,
99
-
100
- // we need to handle cases where:
101
- // client state (client.id: 2) sends a request
102
- // server attached state (client.id: -1) spot a problem and overrides the value
103
- // we want the remote client (id: 2) to receive in the right order:
104
- // * 1. the value it requested,
105
- // * 2. the value overriden by the server-side attached state (id: -1)
106
-
107
- // this problem could be solved properly with a reducer system:
108
- // if (dirty) {
109
- // -> call (async) reducer
110
- // -> get values from reducer
111
- //. -> dispatch to everybody
112
- // }
113
-
114
- for (let [peerRemoteId, peer] of this._attachedClients.entries()) {
115
- // propagate notification to all other attached clients except server
116
- if (remoteId !== peerRemoteId && peer.id !== -1) {
117
- peer.transport.emit(`${UPDATE_NOTIFICATION}-${this.id}-${peerRemoteId}`, filteredUpdates, context);
118
- }
119
- }
120
-
121
- if (client.id !== -1) {
122
- client.transport.emit(`${UPDATE_RESPONSE}-${this.id}-${remoteId}`, reqId, filteredUpdates, context);
123
- }
124
-
125
- for (let [peerRemoteId, peer] of this._attachedClients.entries()) {
126
- // propagate notification to server
127
- if (remoteId !== peerRemoteId && peer.id === -1) {
128
- peer.transport.emit(`${UPDATE_NOTIFICATION}-${this.id}-${peerRemoteId}`, filteredUpdates, context);
129
- }
130
- }
131
-
132
- if (client.id === -1) {
133
- client.transport.emit(`${UPDATE_RESPONSE}-${this.id}-${remoteId}`, reqId, filteredUpdates, context);
134
- }
135
- } else {
136
- // propagate back to the requester that the update has been aborted
137
- // ignore all other attached clients.
138
- client.transport.emit(`${UPDATE_ABORT}-${this.id}-${remoteId}`, reqId, updates, context);
139
- }
140
- } else {
141
- // retrieve values from inner state (also handle immediate approriately)
142
- const oldValues = {};
143
-
144
- for (let name in updates) {
145
- oldValues[name] = this._parameters.get(name);
146
- }
147
- // aborted by hook (updates have been overriden to {})
148
- client.transport.emit(`${UPDATE_ABORT}-${this.id}-${remoteId}`, reqId, oldValues, context);
149
- }
150
- });
151
-
152
- if (isOwner) {
153
- // delete only if creator
154
- client.transport.addListener(`${DELETE_REQUEST}-${this.id}-${remoteId}`, (reqId) => {
155
- this._manager._serverStatesById.delete(this.id);
156
- // --------------------------------------------------------------------
157
- // WARNING - MAKE SURE WE DON'T HAVE PROBLEM W/ THAT
158
- // --------------------------------------------------------------------
159
- // @todo - propagate server-side last, because if a subscription function sends a
160
- // message to a client, network messages order are kept coherent
161
- // this._subscriptions.forEach(func => func(updated));
162
- for (let [remoteId, attached] of this._attachedClients.entries()) {
163
- this._detachClient(remoteId, attached);
164
-
165
- if (remoteId === this._creatorRemoteId) {
166
- attached.transport.emit(`${DELETE_RESPONSE}-${this.id}-${remoteId}`, reqId);
167
- } else {
168
- attached.transport.emit(`${DELETE_NOTIFICATION}-${this.id}-${remoteId}`);
169
- }
170
- }
171
- });
172
- } else {
173
- // detach only if not creator
174
- client.transport.addListener(`${DETACH_REQUEST}-${this.id}-${remoteId}`, (reqId) => {
175
- this._detachClient(remoteId, client);
176
- client.transport.emit(`${DETACH_RESPONSE}-${this.id}-${remoteId}`, reqId);
177
- });
178
- }
179
- }
180
-
181
- _detachClient(remoteId, client) {
182
- this._attachedClients.delete(remoteId);
183
- // delete listeners
184
- client.transport.removeAllListeners(`${UPDATE_REQUEST}-${this.id}-${remoteId}`);
185
- client.transport.removeAllListeners(`${DELETE_REQUEST}-${this.id}-${remoteId}`);
186
- client.transport.removeAllListeners(`${DETACH_REQUEST}-${this.id}-${remoteId}`);
187
- }
188
- }
189
-
190
- export default SharedStatePrivate;
191
-
192
-
@@ -1,25 +0,0 @@
1
- import { idGenerator } from '@ircam/sc-utils';
2
-
3
- const generateRequestId = idGenerator();
4
- const requestPromises = new Map();
5
-
6
- export function storeRequestPromise(resolve, reject) {
7
- const reqId = generateRequestId.next().value;
8
- requestPromises.set(reqId, { resolve, reject });
9
-
10
- return reqId;
11
- }
12
-
13
- export function resolveRequest(reqId, data) {
14
- const { resolve } = requestPromises.get(reqId);
15
- requestPromises.delete(reqId);
16
-
17
- resolve(data);
18
- }
19
-
20
- export function rejectRequest(reqId, data) {
21
- const { reject } = requestPromises.get(reqId);
22
- requestPromises.delete(reqId);
23
-
24
- reject(data);
25
- }
@@ -1,55 +0,0 @@
1
- import { idGenerator } from '@ircam/sc-utils';
2
- import { v4 as uuid } from 'uuid';
3
-
4
- const generateId = idGenerator();
5
-
6
- /**
7
- * Server-side representation of a `soundworks` client.
8
- *
9
- * @memberof server
10
- * @hideconstructor
11
- * @see {@link client.Client}
12
- */
13
- class Client {
14
- /**
15
- * @param {String} role - Role of the client
16
- * @param {server.Socket} socket - Socket connection with the client
17
- */
18
- constructor(role, socket) {
19
- /**
20
- * Client role, as specified in client side config {@link client.Client}.
21
- *
22
- * @type {String}
23
- */
24
- this.role = role;
25
-
26
- /**
27
- * Session Id (incremented positive number).
28
- *
29
- * @type {Number}
30
- */
31
- this.id = generateId.next().value;
32
-
33
- /**
34
- * Unique session Id (uuidv4).
35
- *
36
- * @type {String}
37
- */
38
- this.uuid = uuid();
39
-
40
- /**
41
- * Socket connection with the remote client {@link client.Client}.
42
- *
43
- * @type {server.Socket}
44
- */
45
- this.socket = socket;
46
-
47
- /**
48
- * Is set in server._onSocketConnection
49
- * @private
50
- */
51
- this.token = null;
52
- }
53
- }
54
-
55
- export default Client;
@@ -1,170 +0,0 @@
1
- import BasePluginManager from '../common/BasePluginManager.js';
2
- import Plugin from './Plugin.js';
3
- import Server from './Server.js';
4
-
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
- */
20
-
21
- /**
22
- * The `PluginManager` allows to register and retrieve `soundworks` plugins.
23
- *
24
- * Plugins should always be registered both client-side and server-side,
25
- * and before {@link client.Client#start} or {@link server.Server#start}
26
- * to be properly initialized.
27
- *
28
- * In some sitautions, you might want to register the same plugin factory several times
29
- * using different ids (e.g. for watching several parts of the file system, etc.).
30
- *
31
- * Refer to the plugins' documentation for more precise examples, and the specific API
32
- * they expose. See [https://soundworks.dev/guide/ecosystem](https://soundworks.dev/guide/ecosystem)
33
- * for more informations on the available plugins.
34
- *
35
- * ```
36
- * // client-side
37
- * import { Client } from '@soundworks/core/client.js';
38
- * import syncPlugin from '@soundworks/plugin-sync/client.js';
39
- *
40
- * const client = new Client(config);
41
- * // register the plugin before `client.start()`
42
- * client.pluginManager.register('sync', syncPlugin);
43
- *
44
- * await client.start();
45
- *
46
- * const sync = await client.pluginManager.get('sync');
47
- *
48
- * setInterval(() => {
49
- * // log the estimated global synced clock alongside the local clock.
50
- * console.log(sync.getSyncTime(), sync.getLocalTime());
51
- * }, 1000);
52
- * ```
53
- *
54
- * ```
55
- * // server-side
56
- * import { Server } from '@soundworks/core/server.js';
57
- * import syncPlugin from '@soundworks/plugin-sync/server.js';
58
- *
59
- * const server = new Server(config);
60
- * // register the plugin before `server.start()`
61
- * server.pluginManager.register('sync', syncPlugin);
62
- *
63
- * await server.start();
64
- *
65
- * const sync = await server.pluginManager.get('sync');
66
- *
67
- * setInterval(() => {
68
- * // log the estimated global synced clock alongside the local clock.
69
- * console.log(sync.getSyncTime(), sync.getLocalTime());
70
- * }, 1000);
71
- * ```
72
- *
73
- * @memberof server
74
- * @extends BasePluginManager
75
- * @inheritdoc
76
- * @hideconstructor
77
- */
78
- class PluginManager extends BasePluginManager {
79
- constructor(server) {
80
- if (!(server instanceof Server)) {
81
- throw new Error(`[soundworks.PluginManager] Invalid argument, "new PluginManager(server)" should receive an instance of "soundworks.Server" as argument`);
82
- }
83
-
84
- super(server);
85
- }
86
-
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) {
130
- let missingPlugins = [];
131
-
132
- for (let id of registeredPlugins) {
133
- if (!this._instances.has(id)) {
134
- missingPlugins.push(id);
135
- }
136
- }
137
-
138
- 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(', ')}].`);
140
- }
141
- }
142
-
143
- /** @private */
144
- async addClient(client, registeredPlugins = []) {
145
- let promises = [];
146
-
147
- for (let pluginName of registeredPlugins) {
148
- const plugin = await this.get(pluginName);
149
- const promise = plugin.addClient(client);
150
- promises.push(promise);
151
- }
152
-
153
- await Promise.all(promises);
154
- }
155
-
156
- /** @private */
157
- async removeClient(client) {
158
- let promises = [];
159
-
160
- for (let plugin of this._instances.values()) {
161
- if (plugin.clients.has(client)) {
162
- promises.push(plugin.removeClient(client));
163
- }
164
- }
165
-
166
- await Promise.all(promises);
167
- }
168
- }
169
-
170
- export default PluginManager;
@@ -1,85 +0,0 @@
1
- import BaseSharedState from '../common/BaseSharedState.js';
2
-
3
- // this file exists only for documentation purposes
4
-
5
- /**
6
- * @callback server.SharedState~onUpdateCallback
7
- * @param {Object} newValues - Key / value pairs of the updates that have been
8
- * applied to the state.
9
- * @param {Object} oldValues - Key / value pairs of the updated params before
10
- * the updates has been applied to the state.
11
- * @param {Mixed} [context=null] - Optionnal context object that has been passed
12
- * with the values updates in the `set` call.
13
- */
14
-
15
- /**
16
- * Delete the registered {@link server.SharedState~onUpdateCallback}.
17
- *
18
- * @callback server.SharedState~deleteOnUpdateCallback
19
- */
20
-
21
- /**
22
- * The `SharedState` is one of the most important and versatile abstraction provided
23
- * by `soundworks`. It represents a set of parameters that are synchronized accross
24
- * every nodes of the application (clients and server) that declared some interest
25
- * to the shared state.
26
- *
27
- * A `SharedState` is created according to a "schema" (in the sense of a database
28
- * schema) that must be declared and registered server-side. Any number of `SharedState`s
29
- * can be created from a single schema.
30
- *
31
- * A shared state can be created both by the clients or by the server (in which case
32
- * it is generally considered as a global state of the application). Similarly any
33
- * node of the application (clients or server) can declare interest and "attach" to
34
- * a state created by another node. All node attached to a state can modify its values
35
- * and/or react to the modifications applied by other nodes.
36
- *
37
- * Tutorial: {@link https://soundworks.dev/guide/state-manager.html}
38
- *
39
- * ```
40
- * // server-side
41
- * import { Server } from '@soundworks/server/index.js';
42
- *
43
- * const server = new Server(config);
44
- * // declare and register the schema of a shared state.
45
- * server.stateManager.registerSchema('some-global-state', {
46
- * myRandom: {
47
- * type: 'float',
48
- * default: 0,
49
- * }
50
- * });
51
- *
52
- * await server.start();
53
- *
54
- * // create a global state server-side
55
- * const globalState = await server.stateManager.create('some-global-state');
56
- * // listen and react to the changes made by the clients
57
- * globalState.onUpdate(updates => console.log(updates));
58
- * ```
59
- *
60
- * ```
61
- * // client-side
62
- * import { Client } from '@soundworks/client.index.js';
63
- *
64
- * const client = new Client(config);
65
- * await client.start();
66
- *
67
- * // attach to the global state created by the server
68
- * const globalState = await client.stateManager.attach('some-global-state');
69
- *
70
- * // update the value of a `myRandom` parameter every seconds
71
- * setInterval(() => {
72
- * globalState.set({ myRandom: Math.random() });
73
- * }, 1000);
74
- * ``
75
- *
76
- * @memberof server
77
- * @extends BaseSharedState
78
- * @inheritdoc
79
- * @hideconstructor
80
- * @see {server.StateManager}
81
- */
82
- class SharedState extends BaseSharedState {}
83
-
84
- export default SharedState;
85
-
@@ -1,36 +0,0 @@
1
- import BaseSharedStateCollection from '../common/BaseSharedStateCollection.js';
2
-
3
- // this file exists only for documentation purposesSharedStateCollection.js
4
-
5
- /**
6
- * @callback server.SharedStateCollection~onUpdateCallback
7
- * @param {server.SharedState} state - State that triggered the update.
8
- * @param {Object} newValues - Key / value pairs of the updates that have been
9
- * applied to the state.
10
- * @param {Object} oldValues - Key / value pairs of the updated params before
11
- * the updates has been applied to the state.
12
- * @param {Mixed} [context=null] - Optionnal context object that has been passed
13
- * with the values updates in the `set` call.
14
- */
15
-
16
- /**
17
- * The `SharedStateCollection` interface represent a collection of all states
18
- * created from a given schema name on the network, at the execption of the ones
19
- * created by the current node.
20
- *
21
- * ```
22
- * const collection = await server.stateManager.getCollection('my-schema');
23
- * const allValues = collection.getValues();
24
- * collection.onUpdate((state, newValues, oldValues, context) => {
25
- * // do something
26
- * });
27
- * ```
28
- * @memberof server
29
- * @extends BaseSharedStateCollection
30
- * @inheritdoc
31
- * @hideconstructor
32
- */
33
- class SharedStateCollection extends BaseSharedStateCollection {}
34
-
35
- export default SharedStateCollection;
36
-