@soundworks/core 4.0.0-alpha.1 → 4.0.0-alpha.11
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 +0 -1
- package/README.md +17 -26
- package/package.json +20 -21
- package/src/client/Client.js +48 -8
- package/src/client/Context.js +39 -12
- package/src/client/ContextManager.js +1 -1
- package/src/client/Plugin.js +2 -1
- package/src/client/PluginManager.js +27 -18
- package/src/client/SharedStateCollection.js +35 -0
- package/src/client/Socket.js +61 -48
- package/src/client/index.js +0 -33
- package/src/common/BasePlugin.js +30 -20
- package/src/common/BasePluginManager.js +44 -20
- package/src/common/BaseSharedState.js +151 -41
- package/src/common/BaseSharedStateCollection.js +191 -0
- package/src/common/BaseStateManager.js +73 -16
- package/src/common/ParameterBag.js +87 -217
- package/src/common/promise-store.js +1 -1
- package/src/server/Client.js +7 -2
- package/src/server/Context.js +162 -18
- package/src/server/ContextManager.js +8 -9
- package/src/server/Plugin.js +2 -1
- package/src/server/PluginManager.js +27 -7
- package/src/server/Server.js +428 -101
- package/src/server/SharedState.js +0 -1
- package/src/server/SharedStateCollection.js +36 -0
- package/src/server/Socket.js +105 -62
- package/src/server/Sockets.js +52 -26
- package/src/server/StateManager.js +238 -28
- package/src/server/crypto.js +38 -0
- package/src/server/index.js +0 -20
- package/src/common/utils.js +0 -22
package/.eslintrc
CHANGED
package/README.md
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
#
|
|
1
|
+
# soundworks
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/@soundworks%2Fcore)
|
|
4
|
+
[](http://commitizen.github.io/cz-cli/)
|
|
4
5
|
|
|
5
6
|

|
|
6
7
|
|
|
7
8
|
Open-source creative coding framework for distributed applications based on Web technologies.
|
|
8
9
|
|
|
9
|
-
Primarily focused on music,
|
|
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
|
|
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
|
-
|
|
22
|
+

|
|
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,
|
|
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
|
|
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
|
-
|
|
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](
|
|
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.
|
|
3
|
+
"version": "4.0.0-alpha.11",
|
|
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": "
|
|
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
|
-
"
|
|
51
|
+
"preversion": "npm run toc && git commit -am 'docs: build' --allow-empty"
|
|
53
52
|
},
|
|
54
53
|
"dependencies": {
|
|
55
|
-
"@ircam/sc-gettime": "^1.0.
|
|
56
|
-
"
|
|
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
|
-
"
|
|
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.
|
|
69
|
-
"serve-static": "^1.15.0",
|
|
68
|
+
"pem": "^1.14.8",
|
|
70
69
|
"template-literal": "^1.0.4",
|
|
71
|
-
"uuid": "^
|
|
70
|
+
"uuid": "^9.0.0",
|
|
72
71
|
"window-or-global": "^1.0.1",
|
|
73
|
-
"ws": "^8.
|
|
72
|
+
"ws": "^8.12.0"
|
|
74
73
|
},
|
|
75
74
|
"devDependencies": {
|
|
76
|
-
"@ircam/eslint-config": "^1.
|
|
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": "^
|
|
82
|
-
"dotenv": "^16.
|
|
83
|
-
"eslint": "^8.
|
|
84
|
-
"eslint-plugin-jsdoc": "^
|
|
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": "^
|
|
85
|
+
"jsdoc": "^4.0.0",
|
|
87
86
|
"markdown-toc": "^1.2.0",
|
|
88
|
-
"mocha": "^
|
|
89
|
-
"puppeteer": "^
|
|
87
|
+
"mocha": "^10.2.0",
|
|
88
|
+
"puppeteer": "^20.7.4",
|
|
90
89
|
"tcp-ping": "^0.1.1",
|
|
91
|
-
"typescript": "^
|
|
90
|
+
"typescript": "^5.1.6"
|
|
92
91
|
},
|
|
93
92
|
"optionalDependencies": {
|
|
94
93
|
"bufferutil": "^4.0.5",
|
package/src/client/Client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import isPlainObject from '
|
|
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
|
-
*
|
|
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
|
-
* -
|
|
273
|
-
* -
|
|
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'
|
package/src/client/Context.js
CHANGED
|
@@ -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
|
-
*
|
|
120
|
+
* Optionnal user-defined name of the context (defaults to the class name).
|
|
117
121
|
*
|
|
118
|
-
*
|
|
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
|
|
132
|
-
*
|
|
133
|
-
*
|
|
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
|
-
*
|
|
136
|
-
*
|
|
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
|
-
*
|
|
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
|
}
|
package/src/client/Plugin.js
CHANGED
|
@@ -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
|
|
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
|
-
*
|
|
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
|
|
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',
|
|
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
|
|
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.
|
|
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;
|