@soundworks/core 4.0.0-alpha.2 → 4.0.0-alpha.21

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": {
package/.jsdoc ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "source": {
3
+ "include": [
4
+ "misc/assets/DOC.md",
5
+ "src/client",
6
+ "src/server",
7
+ "src/common"
8
+ ]
9
+ },
10
+ "plugins": [
11
+ "plugins/markdown"
12
+ ],
13
+ "opts": {
14
+ "projectTitle": "Soundworks",
15
+ "destination": "./docs",
16
+ "encoding": "utf8",
17
+ "template": "./node_modules/docdash"
18
+ },
19
+ "templates": {
20
+ "default": {
21
+ "useLongnameInNav": true
22
+ },
23
+ "footer": ""
24
+ },
25
+ "docdash": {
26
+ "sectionOrder": [
27
+ "Namespaces",
28
+ "Classes",
29
+ "Modules",
30
+ "Externals",
31
+ "Events",
32
+ "Mixins",
33
+ "Tutorials",
34
+ "Interfaces"
35
+ ],
36
+ "scripts": [
37
+ "assets/custom.css"
38
+ ],
39
+ "meta": {
40
+ "title": "soundworks",
41
+ "description": "Documentation of soundworks, a full-stack JavaScript framework for distributed WebAudio and multimedia applications"
42
+ },
43
+ "search": true,
44
+ "menu": {
45
+ "Website": {
46
+ "href":"http://soundworks.dev/",
47
+ "target":"_blank",
48
+ "class":"menu-item"
49
+ },
50
+ "Github": {
51
+ "href": "https://github.com/collective-soundworks/soundworks",
52
+ "target":"_blank",
53
+ "class":"menu-item"
54
+ }
55
+ }
56
+ }
57
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ ## v4.0.0-alpha.21 - 19/02/2025
2
+
3
+ - Fix: prevent multiple 'close' events
4
+ - Fix: disable heartbeat check on client-side, was unstable
5
+ - Feat(SharedState): introduce 'local' option for parameters
6
+ - Feat(SharedState): ability to filter parameters of interest
7
+
8
+ ## v4.0.0-alpha.20 - 19/02/2024
9
+
10
+ - Refactor heartbeat - #86
11
+ - Refactor state collection - #85
12
+ - Fix issue with self signed certs and config generated by wizard - #84
13
+
14
+ ## v4.0.0-alpha.19 - 17/01/2024
15
+
16
+ - Hotfix for #85
17
+
18
+ ## v4.0.0-alpha.18 - 15/01/2024
19
+
20
+ - Batch network message for SharedStates
21
+
22
+ ## v4.0.0-alpha.17 - 16/12/2023
23
+
24
+ - Support bundling the server to cjs for Max externals
25
+
26
+ ## v4.0.0-alpha.16 - 15/12/2023
27
+
28
+ - Improve StateCollection performances
29
+
30
+ ## v4.0.0-alpha.15 - 13/12/2023
31
+
32
+ - Fix several issues with shared states
33
+ - **Breaking Change**: by default, `StateManager::observe` and `SharedStateCollection` now retrieve locally created states
package/README.md CHANGED
@@ -1,90 +1,56 @@
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
4
  [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
5
5
 
6
- ![soundworks-logo](./assets/logo-200x200.png)
6
+ ![soundworks-logo](./misc/assets/logo-200x200.png)
7
7
 
8
8
  Open-source creative coding framework for distributed applications based on Web technologies.
9
9
 
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
+ 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.
11
11
 
12
- *__WARNING: The version 4 of `@soundworks/core` is under heavy development.__*
13
-
14
- ## Getting Started
15
-
16
- The best and most simple way to start using `soundworks` is to use the `@soundworks/create` wizard.
17
-
18
- ```sh
19
- npx @soundworks/create@latest
20
- ```
21
-
22
- ![./assets/soundworks-create-min.gif](./assets/soundworks-create-min.gif)
23
-
24
- 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`.
25
-
26
- <!--
27
12
  ## Documentation
28
13
 
29
14
  - Guides and Tutorials: [https://soundworks.dev](https://soundworks.dev)
30
15
  - API: [https://soundworks.dev/api](https://soundworks.dev/api)
31
- -->
32
16
 
33
- ## API
17
+ ## Getting started
34
18
 
35
- The API is not publicly published for now. To access the API documentation locally, just clone this repository, go to the v4 branch and launch some http server in the docs directory. For example, using the [serve](https://www.npmjs.com/package/serve) package:
19
+ The best and most simple way to start using **soundworks** is to use the `@soundworks/create` wizard.
36
20
 
37
21
  ```sh
38
- git clone https://github.com/collective-soundworks/soundworks.git
39
- cd soundworks
40
- git checkout v4
41
- serve docs
22
+ npx @soundworks/create@latest
42
23
  ```
43
24
 
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.
25
+ ![soundworks-create](./misc/assets/soundworks-create-min.gif)
45
26
 
46
- ## Share with Us
27
+ See [https://soundworks.dev/tutorials/getting-started.html](https://soundworks.dev/tutorials/getting-started.html) for more information on the wizard and how to start using **soundworks**.
47
28
 
48
- If you made an application using `soundworks` please let us know here: https://github.com/collective-soundworks/soundworks/discussions/61
29
+ ## Misc
49
30
 
50
- ## TypeScript Support
31
+ ### TypeScript support
51
32
 
52
33
  Basic TypeScript support will be proposed in a (hopefully) near future.
53
34
 
54
35
  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.
55
36
 
56
- ## Install
37
+ ### Manual install
57
38
 
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.
39
+ 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 information on the **soundworks** wizard.
59
40
 
60
41
  ```
61
42
  npm install @soundworks/core
62
43
  ```
63
44
 
64
- ## Credits
65
-
66
- `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 context of the [CoSiMa](http://cosima.ircam.fr/) research project founded by the French National Research Agency (ANR).
67
-
68
- Development is now led by Benjamin Matuszewski, in the [Sound Music Movement Interaction Team](https://www.stms-lab.fr/team/interaction-son-musique-mouvement/) from the Ircam's STMS-LAB.
69
-
70
- ### Supporting Research Projects
71
-
72
- Initial and futher developments has been supported by the following research projects:
45
+ ## Share with Us
73
46
 
74
- - The [DOTS](http://dots.ircam.fr/) project, funded by the French National Research Agency (ANR)
75
- - The Ircam projects _BeCoMe_ and _SO(a)P_
76
- - The _Constella(c)tions_ residency, funded by the STARTS program of the European Commission
77
- - The [RAPID-MIX project](http://rapidmix.goldsmithsdigital.com/), funded by the European Union’s Horizon 2020 research and innovation program
78
- - The [CoSiMa](http://cosima.ircam.fr/) project, funded by the French National Research Agency (ANR)
47
+ If you made an application using **soundworks** please let us know here: https://github.com/collective-soundworks/soundworks/discussions/61
79
48
 
80
- ### Academic Papers
49
+ ## Credits
81
50
 
82
- - 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)>
83
- - 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)>
84
- - 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)>
85
- - 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)>
51
+ [https://soundworks.dev/credits.html](https://soundworks.dev/credits.html)
86
52
 
87
53
  ## License
88
54
 
89
- [BSD-3-Clause](https://github.com/collective-soundworks/soundworks/blob/master/LICENSE)
55
+ [BSD-3-Clause](./LICENSE)
90
56
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soundworks/core",
3
- "version": "4.0.0-alpha.2",
3
+ "version": "4.0.0-alpha.21",
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,45 @@
43
43
  "node": ">=16.0.0"
44
44
  },
45
45
  "scripts": {
46
- "doc": "npm run jsdoc",
47
- "jsdoc": "rm -Rf docs && jsdoc -c .jsdoc.json --verbose && cp -R assets docs/",
46
+ "doc": "rm -Rf docs && jsdoc -c .jsdoc --verbose && cp -R misc/assets docs/",
48
47
  "lint": "npx eslint src",
49
- "test": "mocha",
50
- "toc": "markdown-toc -i README.md",
48
+ "test": "npx mocha",
49
+ "test:all": "npx mocha tests/*/*.spec.js",
51
50
  "types": "rm -Rf types && tsc",
52
- "version": "npm run toc && npm run doc && git add docs"
51
+ "postversion": "node ./misc/scripts/check-changelog.js"
53
52
  },
54
53
  "dependencies": {
55
- "@ircam/sc-gettime": "^1.0.0",
56
- "chalk": "^4.1.2",
54
+ "@ircam/sc-utils": "^1.3.2",
55
+ "chalk": "^5.3.0",
57
56
  "columnify": "^1.6.0",
58
57
  "compression": "^1.7.1",
59
58
  "express": "^4.18.1",
60
59
  "fast-deep-equal": "^3.1.3",
61
60
  "fast-text-encoding": "^1.0.0",
62
- "is-plain-obj": "3.0.0",
63
- "isomorphic-ws": "^4.0.1",
64
- "keyv": "^4.2.2",
65
- "keyv-file": "^0.2.0",
66
- "lodash.clonedeep": "^4.5.0",
67
- "lodash.merge": "^4.6.2",
68
- "pem": "^1.14.6",
69
- "serve-static": "^1.15.0",
61
+ "isomorphic-ws": "^5.0.0",
62
+ "keyv": "^4.5.4",
63
+ "keyv-file": "^0.3.0",
64
+ "lodash": "^4.17.21",
65
+ "pem": "^1.14.8",
70
66
  "template-literal": "^1.0.4",
71
- "uuid": "^8.3.2",
72
- "window-or-global": "^1.0.1",
73
- "ws": "^8.11.0"
67
+ "uuid": "^9.0.1",
68
+ "ws": "^8.15.0"
74
69
  },
75
70
  "devDependencies": {
76
- "@ircam/eslint-config": "^1.0.0",
77
- "chai": "^4.3.6",
71
+ "@ircam/eslint-config": "^1.3.0",
72
+ "chai": "^4.3.10",
78
73
  "chai-shallow-deep-equal": "^1.4.6",
79
74
  "commitizen": "^4.2.5",
80
75
  "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",
85
- "generate-changelog": "^1.8.0",
86
- "jsdoc": "^3.6.10",
87
- "markdown-toc": "^1.2.0",
88
- "mocha": "^9.2.2",
89
- "puppeteer": "^18.0.5",
76
+ "docdash": "^2.0.2",
77
+ "dotenv": "^16.3.1",
78
+ "eslint": "^8.55.0",
79
+ "eslint-plugin-jsdoc": "^46.9.0",
80
+ "jsdoc": "^4.0.0",
81
+ "mocha": "^10.2.0",
82
+ "puppeteer": "^21.6.0",
90
83
  "tcp-ping": "^0.1.1",
91
- "typescript": "^4.9.3"
84
+ "typescript": "^5.3.3"
92
85
  },
93
86
  "optionalDependencies": {
94
87
  "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,7 +10,6 @@ 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
  /**
@@ -190,7 +189,7 @@ class Client {
190
189
  * @see {@link client.StateManager}
191
190
  * @type {client.StateManager}
192
191
  */
193
- this.stateManager = null;
192
+ this.stateManager = new StateManager();
194
193
 
195
194
  /**
196
195
  * Status of the client, 'idle', 'inited', 'started' or 'errored'.
@@ -199,6 +198,12 @@ class Client {
199
198
  */
200
199
  this.status = 'idle';
201
200
 
201
+ /**
202
+ * Token of the client if connected through HTTP authentication.
203
+ * @private
204
+ */
205
+ this.token = null;
206
+
202
207
  /** @private */
203
208
  this._onStatusChangeCallbacks = new Set();
204
209
  /** @private */
@@ -241,9 +246,10 @@ class Client {
241
246
  try {
242
247
  await new Promise((resolve, reject) => {
243
248
  // wait for handshake response before starting stateManager and pluginManager
244
- this.socket.addListener(CLIENT_HANDSHAKE_RESPONSE, async ({ id, uuid }) => {
249
+ this.socket.addListener(CLIENT_HANDSHAKE_RESPONSE, async ({ id, uuid, token }) => {
245
250
  this.id = id;
246
251
  this.uuid = uuid;
252
+ this.token = token;
247
253
 
248
254
  resolve();
249
255
  });
@@ -251,7 +257,7 @@ class Client {
251
257
  this.socket.addListener(CLIENT_HANDSHAKE_ERROR, (err) => {
252
258
  let msg = ``;
253
259
 
254
- switch(err.type) {
260
+ switch (err.type) {
255
261
  case 'invalid-client-type':
256
262
  msg = `[soundworks:Client] ${err.message}`;
257
263
  break;
@@ -275,14 +281,14 @@ class Client {
275
281
 
276
282
  this.socket.send(CLIENT_HANDSHAKE_REQUEST, payload);
277
283
  });
278
- } catch(err) {
284
+ } catch (err) {
279
285
  throw new Error(err);
280
286
  }
281
287
 
282
288
  // ------------------------------------------------------------
283
289
  // CREATE STATE MANAGER
284
290
  // ------------------------------------------------------------
285
- this.stateManager = new StateManager(this.id, {
291
+ this.stateManager.init(this.id, {
286
292
  emit: this.socket.send.bind(this.socket), // need to alias this
287
293
  addListener: this.socket.addListener.bind(this.socket),
288
294
  removeAllListeners: this.socket.removeAllListeners.bind(this.socket),
@@ -1,4 +1,5 @@
1
1
  import Client from './Client.js';
2
+ import PromiseStore from '../common/PromiseStore.js';
2
3
  import {
3
4
  CONTEXT_ENTER_REQUEST,
4
5
  CONTEXT_ENTER_RESPONSE,
@@ -7,11 +8,9 @@ import {
7
8
  CONTEXT_EXIT_RESPONSE,
8
9
  CONTEXT_EXIT_ERROR,
9
10
  } from '../common/constants.js';
10
- import {
11
- storeRequestPromise,
12
- resolveRequest,
13
- rejectRequest,
14
- } from '../common/promise-store.js';
11
+
12
+ // share between all context, as channels are common to all contexts
13
+ const promiseStore = new PromiseStore('Context');
15
14
 
16
15
  /**
17
16
  * Base class to extend in order to implement a new Context.
@@ -86,7 +85,7 @@ class Context {
86
85
  return;
87
86
  }
88
87
 
89
- resolveRequest(reqId);
88
+ promiseStore.resolve(reqId);
90
89
  });
91
90
 
92
91
  this.client.socket.addListener(CONTEXT_ENTER_ERROR, (reqId, contextName, msg) => {
@@ -94,7 +93,7 @@ class Context {
94
93
  return;
95
94
  }
96
95
 
97
- rejectRequest(reqId, msg);
96
+ promiseStore.reject(reqId, msg);
98
97
  });
99
98
 
100
99
  this.client.socket.addListener(CONTEXT_EXIT_RESPONSE, (reqId, contextName) => {
@@ -102,7 +101,7 @@ class Context {
102
101
  return;
103
102
  }
104
103
 
105
- resolveRequest(reqId);
104
+ promiseStore.resolve(reqId);
106
105
  });
107
106
 
108
107
  this.client.socket.addListener(CONTEXT_EXIT_ERROR, (reqId, contextName, msg) => {
@@ -110,7 +109,7 @@ class Context {
110
109
  return;
111
110
  }
112
111
 
113
- rejectRequest(reqId, msg);
112
+ promiseStore.reject(reqId, msg);
114
113
  });
115
114
 
116
115
  this.client.contextManager.register(this);
@@ -206,10 +205,10 @@ class Context {
206
205
  // we need the try/catch block to change the promise rejection into proper error
207
206
  try {
208
207
  await new Promise((resolve, reject) => {
209
- const reqId = storeRequestPromise(resolve, reject);
208
+ const reqId = promiseStore.add(resolve, reject, 'enter-context');
210
209
  this.client.socket.send(CONTEXT_ENTER_REQUEST, reqId, this.name);
211
210
  });
212
- } catch(err) {
211
+ } catch (err) {
213
212
  throw new Error(err);
214
213
  }
215
214
  }
@@ -240,10 +239,10 @@ class Context {
240
239
  // we need the try/catch block to change the promise rejection into proper error
241
240
  try {
242
241
  await new Promise((resolve, reject) => {
243
- const reqId = storeRequestPromise(resolve, reject);
242
+ const reqId = promiseStore.add(resolve, reject, 'exit-context');
244
243
  this.client.socket.send(CONTEXT_EXIT_REQUEST, reqId, this.name);
245
244
  });
246
- } catch(err) {
245
+ } catch (err) {
247
246
  throw new Error(err);
248
247
  }
249
248
  }
@@ -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
  }
@@ -83,7 +83,7 @@ class PluginManager extends BasePluginManager {
83
83
  */
84
84
  constructor(client) {
85
85
  if (!(client instanceof Client)) {
86
- 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`);
87
87
  }
88
88
 
89
89
  super(client);
@@ -0,0 +1,38 @@
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.
19
+ *
20
+ * It can optionnaly exclude the states created by the current node.
21
+ *
22
+ * See {@link client.StateManager#getCollection} for factory method API
23
+ *
24
+ * ```
25
+ * const collection = await client.stateManager.getCollection('my-schema');
26
+ * const allValues = collection.getValues();
27
+ * collection.onUpdate((state, newValues, oldValues, context) => {
28
+ * // do something
29
+ * });
30
+ * ```
31
+ * @memberof client
32
+ * @extends BaseSharedStateCollection
33
+ * @inheritdoc
34
+ * @hideconstructor
35
+ */
36
+ class SharedStateCollection extends BaseSharedStateCollection {}
37
+
38
+ export default SharedStateCollection;