@soundworks/core 4.0.0-alpha.1 → 4.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "extends": [
3
3
  "@ircam",
4
- "plugin:jsdoc/recommended"
5
4
  ],
6
5
  "settings": {
7
6
  "jsdoc": {
@@ -0,0 +1,31 @@
1
+ name: GH Pages
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - '*'
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ jobs:
12
+ deploy:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Checkout code
16
+ uses: actions/checkout@v3
17
+
18
+ - name: 'Install Node'
19
+ uses: actions/setup-node@v3.6.0
20
+
21
+ - name: Install dependencies
22
+ run: npm install
23
+
24
+ - name: Build Docs
25
+ run: npm run doc
26
+
27
+ - name: Deploy
28
+ uses: JamesIves/github-pages-deploy-action@v4
29
+ with:
30
+ folder: docs
31
+
@@ -0,0 +1,18 @@
1
+ name: Unit Tests
2
+ on: push
3
+
4
+ jobs:
5
+ test:
6
+ runs-on: ubuntu-latest
7
+ steps:
8
+ - name: Checkout
9
+ uses: actions/checkout@v3
10
+
11
+ - name: 'Install Node'
12
+ uses: actions/setup-node@v3.6.0
13
+
14
+ - name: Install dependencies
15
+ run: npm install
16
+
17
+ - name: "Run Test"
18
+ run: npm test -- tests/**.spec.js
package/README.md CHANGED
@@ -1,24 +1,27 @@
1
- # `soundworks`
1
+ # soundworks
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/@soundworks%2Fcore.svg)](https://badge.fury.io/js/@soundworks%2Fcore)
4
+ [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
4
5
 
5
6
  ![soundworks-logo](./assets/logo-200x200.png)
6
7
 
7
8
  Open-source creative coding framework for distributed applications based on Web technologies.
8
9
 
9
- Primarily focused on music, `soundworks` aims at supporting rapid development of real-time distributed applications using _JavaScript_. It provides abstractions to hide the complexity of the network and to foster very rapid-prototyping and trial-and-error workflows that are typical in artistic practices.
10
+ Primarily focused on music, **soundworks** aims at supporting rapid development of real-time distributed applications using _JavaScript_. It provides abstractions to hide the complexity of the network and to foster very rapid-prototyping and trial-and-error workflows that are typical in artistic practices.
10
11
 
11
12
  *__WARNING: The version 4 of `@soundworks/core` is under heavy development.__*
12
13
 
13
14
  ## Getting Started
14
15
 
15
- The best and most simple way to start using `soundworks` is to use the `@soundworks/create` wizard.
16
+ The best and most simple way to start using **soundworks** is to use the `@soundworks/create` wizard.
16
17
 
17
18
  ```sh
18
19
  npx @soundworks/create@latest
19
20
  ```
20
21
 
21
- See [https://soundworks.dev/guides/getting-started.html](https://soundworks.dev/guides/getting-started.html) for more informations on the wizard and how to start with `soundworks`.
22
+ ![./assets/soundworks-create-min.gif](./assets/soundworks-create-min.gif)
23
+
24
+ See [https://soundworks.dev/tutorials/getting-started.html](https://soundworks.dev/tutorials/getting-started.html) for more informations on the wizard and how to start with **soundworks**.
22
25
 
23
26
  <!--
24
27
  ## Documentation
@@ -38,43 +41,31 @@ git checkout v4
38
41
  serve docs
39
42
  ```
40
43
 
44
+ Feel welcome to open an [issue](https://github.com/collective-soundworks/soundworks/issues) or a PR if you find any inconsistency, error or missing information in the documentation.
45
+
46
+ ## Share with Us
47
+
48
+ If you made an application using **soundworks** please let us know here: https://github.com/collective-soundworks/soundworks/discussions/61
49
+
41
50
  ## TypeScript Support
42
51
 
43
52
  Basic TypeScript support will be proposed in a (hopefully) near future.
44
53
 
45
- However, as we aim to follow the TC39 and W3C specifications as close as possible, we will wait for the https://github.com/tc39/proposal-type-annotations proposal to reach stage 3 to update the source code in a more integrated manner.
54
+ However, for maintenance reasons, we aim at following the TC39 and W3C specifications as close as possible. Therefore, we will wait for the https://github.com/tc39/proposal-type-annotations proposal to reach stage 3 to update the source code in a more integrated manner.
46
55
 
47
56
  ## Install
48
57
 
49
- Note that the `@soundworks/core` package is automatically installed when creating an application using the `@soundworks/create` wizard, so most of the time you should not have to install this package manually. See [https://soundworks.dev/guides/getting-started.html](https://soundworks.dev/guides/getting-started.html) for more informations on the `soundworks` wizard.
58
+ Note that the `@soundworks/core` package is automatically installed when creating an application using the `@soundworks/create` wizard, so most of the time you should not have to install this package manually. See [https://soundworks.dev/guides/getting-started.html](https://soundworks.dev/guides/getting-started.html) for more informations on the **soundworks** wizard.
50
59
 
51
60
  ```
52
61
  npm install @soundworks/core
53
62
  ```
54
63
 
55
- ## Share with Us
56
-
57
- If you made an application using `soundworks` please let us know here: https://github.com/collective-soundworks/soundworks/discussions/61
58
-
59
- ## Academic Papers
60
-
61
- - Benjamin Matuszewski. A Web-Based Framework for Distributed Music System Research and Creation. AES - Journal of the Audio Engineering Society Audio-Accoustics-Application, Audio Engineering Society Inc, 2020. <[hal-03033143](https://hal.archives-ouvertes.fr/hal-03033143)>
62
- - Benjamin Matuszewski. Soundworks - A Framework for Networked Music Systems on the Web - State of Affairs and New Developments. Proceedings of the Web Audio Conference (WAC) 2019, Dec 2019, Trondheim, Norway. <[hal-02387783](https://hal.archives-ouvertes.fr/hal-02387783)>
63
- - Benjamin Matuszewski, Norbert Schnell, Frédéric Bevilacqua. Interaction Topologies in Mobile-Based Situated Networked Music Systems. Wireless Communications and Mobile Computing, Hindawi Publishing Corporation, 2019, 2019, pp.9142490. ⟨10.1155/2019/9142490⟩. <[hal-02086673](https://hal.archives-ouvertes.fr/hal-02086673)>
64
- - Norbert Schnell, Sébastien Robaszkiewicz. Soundworks – A playground for artists and developers to create collaborative mobile web performances. `Proceedings of the Web Audio Conference (WAC'15), 2015, Paris, France. <[hal-01580797](https://hal.archives-ouvertes.fr/hal-01580797)>
65
-
66
64
  ## Credits
67
65
 
68
- `soundworks` has been initiated by [Norbert Schnell](https://github.com/NorbertSchnell), [Sébastien Robaszkiewicz](https://github.com/i-Robi), and [Benjamin Matuszewski](https://github.com/b-ma) at the [ISMM](http://ismm.ircam.fr/) team at [Ircam - Centre Pompidou](http://www.ircam.fr/) in the framework of the [*CoSiMa*](http://cosima.ircam.fr/) research project supported by the [French National Research Agency (ANR)](http://www.agence-nationale-recherche.fr/en/).
69
-
70
- Futher developments has been supported in the framework of:
71
- - The [RAPID-MIX project](http://rapidmix.goldsmithsdigital.com/), funded by the European Union’s Horizon 2020 research and innovation program
72
- - The Ircam projects _BeCoMe_ and _SO(a)P_
73
- - The _Constella(c)tions_ residency of the STARTS program of the European Commission.
74
-
75
- Development is pursued, led by Benjamin Matuszewski, in the [Interaction Music Movement Team](https://www.stms-lab.fr/team/interaction-son-musique-mouvement/) from the Ircam's STMS-LAB.
66
+ [https://soundworks.dev/credits.html](https://soundworks.dev/credits.html)
76
67
 
77
68
  ## License
78
69
 
79
- [BSD-3-Clause](https://github.com/collective-soundworks/soundworks/blob/master/LICENSE)
70
+ [BSD-3-Clause](./LICENSE)
80
71
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soundworks/core",
3
- "version": "4.0.0-alpha.1",
3
+ "version": "4.0.0-alpha.10",
4
4
  "description": "Open-source creative coding framework for distributed applications based on Web technologies",
5
5
  "authors": [
6
6
  "Benjamin Matuszewski",
@@ -43,52 +43,51 @@
43
43
  "node": ">=16.0.0"
44
44
  },
45
45
  "scripts": {
46
- "doc": "npm run jsdoc && npm run types",
47
- "jsdoc": "rm -Rf docs && jsdoc -c .jsdoc.json --verbose && cp -R assets docs/",
46
+ "doc": "rm -Rf docs && jsdoc -c .jsdoc.json --verbose && cp -R assets docs/",
48
47
  "lint": "npx eslint src",
49
48
  "test": "mocha",
50
49
  "toc": "markdown-toc -i README.md",
51
50
  "types": "rm -Rf types && tsc",
52
- "version": "npm run toc && npm run doc && git add docs"
51
+ "preversion": "npm run toc && git commit -am 'docs: build' --allow-empty"
53
52
  },
54
53
  "dependencies": {
55
- "@ircam/sc-gettime": "^1.0.0",
56
- "chalk": "^4.1.2",
54
+ "@ircam/sc-gettime": "^1.0.1",
55
+ "@ircam/sc-utils": "^1.1.1",
56
+ "chalk": "^5.3.0",
57
57
  "columnify": "^1.6.0",
58
58
  "compression": "^1.7.1",
59
+ "cross-fetch": "^3.1.8",
59
60
  "express": "^4.18.1",
60
61
  "fast-deep-equal": "^3.1.3",
61
62
  "fast-text-encoding": "^1.0.0",
62
- "is-plain-obj": "3.0.0",
63
- "isomorphic-ws": "^4.0.1",
63
+ "isomorphic-ws": "^5.0.0",
64
64
  "keyv": "^4.2.2",
65
65
  "keyv-file": "^0.2.0",
66
66
  "lodash.clonedeep": "^4.5.0",
67
67
  "lodash.merge": "^4.6.2",
68
- "pem": "^1.14.6",
69
- "serve-static": "^1.15.0",
68
+ "pem": "^1.14.8",
70
69
  "template-literal": "^1.0.4",
71
- "uuid": "^8.3.2",
70
+ "uuid": "^9.0.0",
72
71
  "window-or-global": "^1.0.1",
73
- "ws": "^8.11.0"
72
+ "ws": "^8.12.0"
74
73
  },
75
74
  "devDependencies": {
76
- "@ircam/eslint-config": "^1.0.0",
75
+ "@ircam/eslint-config": "^1.3.0",
77
76
  "chai": "^4.3.6",
78
77
  "chai-shallow-deep-equal": "^1.4.6",
79
78
  "commitizen": "^4.2.5",
80
79
  "cz-conventional-changelog": "^3.3.0",
81
- "docdash": "^1.2.0",
82
- "dotenv": "^16.0.3",
83
- "eslint": "^8.24.0",
84
- "eslint-plugin-jsdoc": "^39.6.4",
80
+ "docdash": "^2.0.1",
81
+ "dotenv": "^16.3.1",
82
+ "eslint": "^8.44.0",
83
+ "eslint-plugin-jsdoc": "^46.4.3",
85
84
  "generate-changelog": "^1.8.0",
86
- "jsdoc": "^3.6.10",
85
+ "jsdoc": "^4.0.0",
87
86
  "markdown-toc": "^1.2.0",
88
- "mocha": "^9.2.2",
89
- "puppeteer": "^18.0.5",
87
+ "mocha": "^10.2.0",
88
+ "puppeteer": "^20.7.4",
90
89
  "tcp-ping": "^0.1.1",
91
- "typescript": "^4.9.3"
90
+ "typescript": "^5.1.6"
92
91
  },
93
92
  "optionalDependencies": {
94
93
  "bufferutil": "^4.0.5",
@@ -1,4 +1,4 @@
1
- import isPlainObject from 'is-plain-obj';
1
+ import { isBrowser, isPlainObject } from '@ircam/sc-utils';
2
2
 
3
3
  import ContextManager from './ContextManager.js';
4
4
  import PluginManager from './PluginManager.js';
@@ -10,11 +10,43 @@ import {
10
10
  CLIENT_HANDSHAKE_ERROR,
11
11
  AUDIT_STATE_NAME,
12
12
  } from '../common/constants.js';
13
- import { isBrowser } from '../common/utils.js';
14
13
  import logger from '../common/logger.js';
15
14
 
16
15
  /**
17
- * The `Client` class is the main entry point for the client-side of soundworks
16
+ * Configuration object for a client running in a browser runtime.
17
+ *
18
+ * @typedef BrowserClientConfig
19
+ * @memberof client
20
+ * @type {object}
21
+ * @property {string} role - Role of the client in the application (e.g. 'player', 'controller').
22
+ * @property {object} [app] - Application configration object.
23
+ * @property {string} [app.name=''] - Name of the application.
24
+ * @property {string} [app.author=''] - Name of the author.
25
+ * @property {object} [env] - Environment configration object.
26
+ * @property {string} [env.websockets={}] - Configuration options for websockets.
27
+ * @property {string} [env.subpath=''] - If running behind a proxy, path to the application.
28
+ */
29
+
30
+ /**
31
+ * Configuration object for a client running in a node runtime.
32
+ *
33
+ * @typedef NodeClientConfig
34
+ * @memberof client
35
+ * @type {object}
36
+ * @property {string} role - Role of the client in the application (e.g. 'player', 'controller').
37
+ * @property {object} [app] - Application configration object.
38
+ * @property {string} [app.name=''] - Name of the application.
39
+ * @property {string} [app.author=''] - Name of the author.
40
+ * @property {object} env - Environment configration object.
41
+ * @property {boolean} env.serverAddress - Domain name or IP of the server.
42
+ * @property {boolean} env.useHttps - Define is the server run in http or in https.
43
+ * @property {boolean} env.port - Port on which the server is listening.
44
+ * @property {string} [env.websockets={}] - Configuration options for websockets.
45
+ * @property {string} [env.subpath=''] - If running behind a proxy, path to the application.
46
+ */
47
+
48
+ /**
49
+ * The `Client` class is the main entry point for the client-side of a soundworks
18
50
  * application.
19
51
  *
20
52
  * A `Client` instance allows to access soundworks components such as {@link client.StateManager},
@@ -166,6 +198,12 @@ class Client {
166
198
  */
167
199
  this.status = 'idle';
168
200
 
201
+ /**
202
+ * Token of the client if connected through HTTP authentication.
203
+ * @private
204
+ */
205
+ this.token = null;
206
+
169
207
  /** @private */
170
208
  this._onStatusChangeCallbacks = new Set();
171
209
  /** @private */
@@ -208,9 +246,10 @@ class Client {
208
246
  try {
209
247
  await new Promise((resolve, reject) => {
210
248
  // wait for handshake response before starting stateManager and pluginManager
211
- this.socket.addListener(CLIENT_HANDSHAKE_RESPONSE, async ({ id, uuid }) => {
249
+ this.socket.addListener(CLIENT_HANDSHAKE_RESPONSE, async ({ id, uuid, token }) => {
212
250
  this.id = id;
213
251
  this.uuid = uuid;
252
+ this.token = token;
214
253
 
215
254
  resolve();
216
255
  });
@@ -218,7 +257,7 @@ class Client {
218
257
  this.socket.addListener(CLIENT_HANDSHAKE_ERROR, (err) => {
219
258
  let msg = ``;
220
259
 
221
- switch(err.type) {
260
+ switch (err.type) {
222
261
  case 'invalid-client-type':
223
262
  msg = `[soundworks:Client] ${err.message}`;
224
263
  break;
@@ -242,7 +281,7 @@ class Client {
242
281
 
243
282
  this.socket.send(CLIENT_HANDSHAKE_REQUEST, payload);
244
283
  });
245
- } catch(err) {
284
+ } catch (err) {
246
285
  throw new Error(err);
247
286
  }
248
287
 
@@ -269,8 +308,9 @@ class Client {
269
308
  * method if it has not been called manually.
270
309
  *
271
310
  * What it does:
272
- * - optionnaly call {@link client.Client#init}
273
- * - starts all the already created contexts (see {@link client.Context})
311
+ * - implicitly call {@link client.Client#init} if not done manually
312
+ * - start all created contexts. For that to happen, you will have to call `client.init`
313
+ * manually and instantiate the contexts between `client.init()` and `client.start()`
274
314
  *
275
315
  * @example
276
316
  * import { Client } from '@soundworks/core/client.js'
@@ -69,11 +69,15 @@ class Context {
69
69
 
70
70
  /**
71
71
  * The soundworks client instance.
72
+ * @type {client.Client}
73
+ * @readonly
72
74
  */
73
75
  this.client = client;
74
76
 
75
77
  /**
76
78
  * Status of the context, i.e. 'idle', 'inited', 'started', 'errored'
79
+ * @type {string}
80
+ * @readonly
77
81
  */
78
82
  this.status = 'idle';
79
83
 
@@ -113,10 +117,16 @@ class Context {
113
117
  }
114
118
 
115
119
  /**
116
- * Name of the context. Defaults to the class name, override to use a user-defined name.
120
+ * Optionnal user-defined name of the context (defaults to the class name).
117
121
  *
118
- * @returns {string} - Name of the context.
122
+ * The context manager will match the client-side and server-side contexts based
123
+ * on this name. If the {@link server.ContextManager} don't find a corresponding
124
+ * user-defined context with the same name, it will use a default (noop) context.
125
+ *
126
+ * @readonly
127
+ * @type {string}
119
128
  * @example
129
+ * // server-side and client-side contexts are matched based on their respective `name`
120
130
  * class MyContext extends Context {
121
131
  * get name() {
122
132
  * return 'my-user-defined-context-name';
@@ -128,21 +138,38 @@ class Context {
128
138
  }
129
139
 
130
140
  /**
131
- * Start the context. This method is automatically called when `await client.start()`
132
- * is called, or lazilly called when entering the context (i.e. `context.enter()`)
133
- * if the context has been created after `client.start()`.
141
+ * Start the context. This method is lazilly called when the client enters the
142
+ * context for the first time (cf. ${client.Context#enter}). If you know some
143
+ * some heavy and/or potentially long job has to be done when starting the context
144
+ * (e.g. call to a web service) it may be a good practice to call it explicitely.
145
+ *
146
+ * This method should be implemented to perform operations that are valid for the
147
+ * whole lifetime of the context, regardless the client enters or exits the context.
148
+ *
149
+ * @example
150
+ * import { Context } from '@soundworks/core/client.js';
151
+ *
152
+ * class MyContext extends Context {
153
+ * async start() {
154
+ * await super.start();
155
+ * await this.doSomeLongJob();
156
+ * }
157
+ * }
134
158
  *
135
- * In some situation, you might want to implement this method to handle application
136
- * wise behavior regardeless the client enters or exists the context.
159
+ * // Instantiate the context
160
+ * const myContext = new Context(client);
161
+ * // manually start the context to perform the long operation before the client
162
+ * // enters the context.
163
+ * await myContext.start();
137
164
  */
138
165
  async start() {}
139
166
 
140
167
  /**
141
168
  * Stop the context. This method is automatically called when `await client.stop()`
142
- * is called.
169
+ * is called. It should be used to cleanup context wise operations made in `start()`
170
+ * (e.g. destroy the reusable audio graph).
143
171
  *
144
- * In some situation, you might want to implement this method to handle application
145
- * wise behavior regardeless the client enters or exists the context.
172
+ * _WARNING: this method should never be called manually._
146
173
  */
147
174
  async stop() {}
148
175
 
@@ -182,7 +209,7 @@ class Context {
182
209
  const reqId = storeRequestPromise(resolve, reject);
183
210
  this.client.socket.send(CONTEXT_ENTER_REQUEST, reqId, this.name);
184
211
  });
185
- } catch(err) {
212
+ } catch (err) {
186
213
  throw new Error(err);
187
214
  }
188
215
  }
@@ -216,7 +243,7 @@ class Context {
216
243
  const reqId = storeRequestPromise(resolve, reject);
217
244
  this.client.socket.send(CONTEXT_EXIT_REQUEST, reqId, this.name);
218
245
  });
219
- } catch(err) {
246
+ } catch (err) {
220
247
  throw new Error(err);
221
248
  }
222
249
  }
@@ -78,7 +78,7 @@ class ContextManager {
78
78
  this._contextStartPromises.set(contextName, startPromise);
79
79
  await startPromise;
80
80
  context.status = 'started';
81
- } catch(err) {
81
+ } catch (err) {
82
82
  context.status = 'errored';
83
83
  throw new Error(err);
84
84
  }
@@ -14,7 +14,8 @@ import BasePlugin from '../common/BasePlugin.js';
14
14
  */
15
15
 
16
16
  /**
17
- * Base class to extend in order to create new `soundworks` plugins.
17
+ * Base class to extend in order to create the client-side counterpart of a
18
+ * `soundworks` plugin.
18
19
  *
19
20
  * In the `soundworks` paradigm, a plugin is a component that allows to extend
20
21
  * the framework capabilities by encapsulating common and reusable logic in
@@ -23,7 +23,7 @@ import Client from './Client.js';
23
23
  *
24
24
  * Plugins should always be registered both client-side and server-side,
25
25
  * and before {@link client.Client#start} or {@link server.Server#start}
26
- * are called for proper initialization.
26
+ * to be properly initialized.
27
27
  *
28
28
  * In some sitautions, you might want to register the same plugin factory several times
29
29
  * using different ids (e.g. for watching several parts of the file system, etc.).
@@ -35,12 +35,13 @@ import Client from './Client.js';
35
35
  * See {@link client.Client#pluginManager}
36
36
  *
37
37
  * ```
38
+ * // client-side
38
39
  * import { Client } from '@soundworks/core/client.js';
39
- * import platformPlugin from '@soundworks/plugin-sync/client.js';
40
+ * import syncPlugin from '@soundworks/plugin-sync/client.js';
40
41
  *
41
42
  * const client = new Client(config);
42
43
  * // register the plugin before `client.start()`
43
- * client.pluginManager.register('sync', pluginSync);
44
+ * client.pluginManager.register('sync', syncPlugin);
44
45
  *
45
46
  * await client.start();
46
47
  *
@@ -52,6 +53,25 @@ import Client from './Client.js';
52
53
  * }, 1000);
53
54
  * ```
54
55
  *
56
+ * ```
57
+ * // server-side
58
+ * import { Server } from '@soundworks/core/server.js';
59
+ * import syncPlugin from '@soundworks/plugin-sync/server.js';
60
+ *
61
+ * const server = new Server(config);
62
+ * // register the plugin before `server.start()`
63
+ * server.pluginManager.register('sync', syncPlugin);
64
+ *
65
+ * await server.start();
66
+ *
67
+ * const sync = await server.pluginManager.get('sync');
68
+ *
69
+ * setInterval(() => {
70
+ * // log the estimated global synced clock alongside the local clock.
71
+ * console.log(sync.getSyncTime(), sync.getLocalTime());
72
+ * }, 1000);
73
+ * ```
74
+ *
55
75
  * @memberof client
56
76
  * @extends BasePluginManager
57
77
  * @inheritdoc
@@ -63,7 +83,7 @@ class PluginManager extends BasePluginManager {
63
83
  */
64
84
  constructor(client) {
65
85
  if (!(client instanceof Client)) {
66
- throw new Error(`[soundworks.PluginManager] Invalid argument, "new PluginManager(client)" should receive an instance of "soundworks.Client as argument"`);
86
+ throw new Error(`[soundworks.PluginManager] Invalid argument, "new PluginManager(client)" should receive an instance of "soundworks.Client" as argument`);
67
87
  }
68
88
 
69
89
  super(client);
@@ -91,8 +111,8 @@ class PluginManager extends BasePluginManager {
91
111
  * initialization (e.g. to display initialization screen, etc.), you should rely
92
112
  * on the `onStateChange` method.
93
113
  *
94
- * _Note: the async API is designed to enable the dynamic creation of plugins (hopefully
95
- * without brealing changes) in a future release._
114
+ * _Note: the async API is designed to enable the dynamic creation of plugins
115
+ * (hopefully without brealing changes) in a future release._
96
116
  *
97
117
  * @param {client.Plugin#id} id - Id of the plugin as defined when registered.
98
118
  * @returns {client.Plugin}
@@ -105,18 +125,7 @@ class PluginManager extends BasePluginManager {
105
125
  throw new Error(`[soundworks.PluginManager] Cannot get plugin before "client.init()"`);
106
126
  }
107
127
 
108
- return super.getUnsafe(id);
109
- }
110
-
111
- // client only methods
112
- // ------------------------------------------------------------
113
-
114
- /**
115
- * @protected
116
- * @ignore
117
- */
118
- getRegisteredPlugins() {
119
- return Array.from(this._registeredPlugins.keys());
128
+ return super.unsafeGet(id);
120
129
  }
121
130
  }
122
131
 
@@ -0,0 +1,35 @@
1
+ import BaseSharedStateCollection from '../common/BaseSharedStateCollection.js';
2
+
3
+ // this file exists only for documentation purposesSharedStateCollection.js
4
+
5
+ /**
6
+ * @callback client.SharedStateCollection~onUpdateCallback
7
+ * @param {client.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 client.stateManager.getCollection('my-schema');
23
+ * const allValues = collection.getValues();
24
+ * collection.onUpdate((state, newValues, oldValues, context) => {
25
+ * // do something
26
+ * });
27
+ * ```
28
+ * @memberof client
29
+ * @extends BaseSharedStateCollection
30
+ * @inheritdoc
31
+ * @hideconstructor
32
+ */
33
+ class SharedStateCollection extends BaseSharedStateCollection {}
34
+
35
+ export default SharedStateCollection;