@soundworks/core 5.4.3 → 5.6.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.
- package/.gitattributes +1 -0
- package/CHANGELOG.md +5 -0
- package/README.md +6 -0
- package/package.json +18 -12
- package/src/client/Client.js +7 -4
- package/src/client/ClientSocket.js +9 -3
- package/src/common/BasePlugin.js +2 -2
- package/src/common/BasePluginManager.js +2 -2
- package/src/common/BaseStateManager.js +8 -3
- package/src/common/ParameterBag.js +14 -14
- package/src/common/SharedState.js +40 -8
- package/src/common/SharedStateCollection.js +3 -3
- package/src/common/constants.js +2 -0
- package/src/common/isomorphic/colored-logger.browser.js +17 -0
- package/src/common/isomorphic/colored-logger.node.js +19 -0
- package/src/common/isomorphic/web-socket.browser.js +1 -0
- package/src/common/isomorphic/web-socket.node.js +3 -0
- package/src/common/logs/gated-logger.js +30 -0
- package/src/common/logs/warnings.js +36 -0
- package/src/common/version.js +1 -1
- package/src/server/Server.js +23 -35
- package/src/server/ServerClient.js +7 -3
- package/src/server/ServerStateManager.js +10 -6
- package/src/server/SharedStatePrivate.js +19 -0
- package/src/server/create-http-server.js +81 -39
- package/src/server/crypto.js +2 -3
- package/types/client/Client.d.ts.map +1 -1
- package/types/client/ClientPluginManager.d.ts +1 -1
- package/types/client/ClientPluginManager.d.ts.map +1 -1
- package/types/client/ClientSocket.d.ts +4 -0
- package/types/client/ClientSocket.d.ts.map +1 -1
- package/types/client/index.d.ts +3 -3
- package/types/client/index.d.ts.map +1 -1
- package/types/common/BasePluginManager.d.ts +1 -1
- package/types/common/BasePluginManager.d.ts.map +1 -1
- package/types/common/BaseStateManager.d.ts.map +1 -1
- package/types/common/BatchedTransport.d.ts +1 -1
- package/types/common/BatchedTransport.d.ts.map +1 -1
- package/types/common/ParameterBag.d.ts +30 -8
- package/types/common/ParameterBag.d.ts.map +1 -1
- package/types/common/PromiseStore.d.ts +1 -1
- package/types/common/PromiseStore.d.ts.map +1 -1
- package/types/common/SharedState.d.ts +11 -4
- package/types/common/SharedState.d.ts.map +1 -1
- package/types/common/SharedStateCollection.d.ts +7 -7
- package/types/common/SharedStateCollection.d.ts.map +1 -1
- package/types/common/constants.d.ts +1 -0
- package/types/common/constants.d.ts.map +1 -1
- package/types/common/isomorphic/colored-logger.browser.d.ts +8 -0
- package/types/common/isomorphic/colored-logger.browser.d.ts.map +1 -0
- package/types/common/isomorphic/colored-logger.node.d.ts +8 -0
- package/types/common/isomorphic/colored-logger.node.d.ts.map +1 -0
- package/types/common/isomorphic/web-socket.browser.d.ts +10 -0
- package/types/common/isomorphic/web-socket.browser.d.ts.map +1 -0
- package/types/common/isomorphic/web-socket.node.d.ts +2 -0
- package/types/common/isomorphic/web-socket.node.d.ts.map +1 -0
- package/types/common/logs/gated-logger.d.ts +9 -0
- package/types/common/logs/gated-logger.d.ts.map +1 -0
- package/types/common/logs/warnings.d.ts +7 -0
- package/types/common/logs/warnings.d.ts.map +1 -0
- package/types/common/shared-state-types.d.ts +11 -11
- package/types/common/shared-state-types.d.ts.map +1 -1
- package/types/common/version.d.ts +1 -1
- package/types/server/Server.d.ts +5 -5
- package/types/server/Server.d.ts.map +1 -1
- package/types/server/ServerClient.d.ts.map +1 -1
- package/types/server/ServerPluginManager.d.ts +1 -1
- package/types/server/ServerPluginManager.d.ts.map +1 -1
- package/types/server/ServerSocket.d.ts +1 -1
- package/types/server/ServerSocket.d.ts.map +1 -1
- package/types/server/ServerStateManager.d.ts.map +1 -1
- package/types/server/SharedStatePrivate.d.ts +5 -5
- package/types/server/SharedStatePrivate.d.ts.map +1 -1
- package/types/server/create-http-server.d.ts +1 -0
- package/types/server/create-http-server.d.ts.map +1 -1
- package/types/server/crypto.d.ts +1 -1
- package/types/server/crypto.d.ts.map +1 -1
- package/types/server/index.d.ts +3 -3
- package/types/server/index.d.ts.map +1 -1
- package/src/common/logger.js +0 -150
- package/types/common/logger.d.ts +0 -19
- package/types/common/logger.d.ts.map +0 -1
package/.gitattributes
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* text=auto eol=lf
|
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -42,6 +42,12 @@ Note that the `@soundworks/core` package is automatically installed when creatin
|
|
|
42
42
|
npm install @soundworks/core
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
## Developement Notes
|
|
46
|
+
|
|
47
|
+
### Windows
|
|
48
|
+
|
|
49
|
+
On windows machine, tests may fail when run in node.js command line, due to `openssl` not being found. This is fixed when run with git command line.
|
|
50
|
+
|
|
45
51
|
## Share with Us
|
|
46
52
|
|
|
47
53
|
If you made an application using **soundworks** please let us know here: https://github.com/collective-soundworks/soundworks/discussions/61
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soundworks/core",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.6.0",
|
|
4
4
|
"description": "Open-source creative coding framework for distributed applications based on Web technologies",
|
|
5
5
|
"collaborators": [
|
|
6
6
|
"Benjamin Matuszewski",
|
|
@@ -24,6 +24,16 @@
|
|
|
24
24
|
"types": "./types/server/index.d.ts"
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
|
+
"imports": {
|
|
28
|
+
"#isomorphic/colored-logger.js": {
|
|
29
|
+
"module": "./src/common/isomorphic/colored-logger.browser.js",
|
|
30
|
+
"node": "./src/common/isomorphic/colored-logger.node.js"
|
|
31
|
+
},
|
|
32
|
+
"#isomorphic/web-socket.js": {
|
|
33
|
+
"module": "./src/common/isomorphic/web-socket.browser.js",
|
|
34
|
+
"node": "./src/common/isomorphic/web-socket.node.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
27
37
|
"repository": {
|
|
28
38
|
"type": "git",
|
|
29
39
|
"url": "git+https://github.com/collective-soundworks/soundworks.git"
|
|
@@ -41,7 +51,7 @@
|
|
|
41
51
|
"distributed-system"
|
|
42
52
|
],
|
|
43
53
|
"engines": {
|
|
44
|
-
"node": ">=
|
|
54
|
+
"node": ">=22.0.0"
|
|
45
55
|
},
|
|
46
56
|
"scripts": {
|
|
47
57
|
"doc": "npm run types && rm -rf docs && jsdoc -c .jsdoc --verbose && cp -R misc/assets docs/",
|
|
@@ -56,14 +66,11 @@
|
|
|
56
66
|
"dependencies": {
|
|
57
67
|
"@ircam/sc-utils": "^1.13.0",
|
|
58
68
|
"cancelable-promise": "^4.3.1",
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"isomorphic-ws": "^5.0.0",
|
|
69
|
+
"defu": "^6.1.7",
|
|
70
|
+
"dequal": "^2.0.3",
|
|
62
71
|
"keyv": "^5.6.0",
|
|
63
72
|
"keyv-file": "^5.3.3",
|
|
64
|
-
"
|
|
65
|
-
"pem": "^1.14.8",
|
|
66
|
-
"uuid": "^13.0.0",
|
|
73
|
+
"selfsigned": "^5.5.0",
|
|
67
74
|
"ws": "^8.19.0"
|
|
68
75
|
},
|
|
69
76
|
"devDependencies": {
|
|
@@ -73,13 +80,12 @@
|
|
|
73
80
|
"dotenv": "^17.3.1",
|
|
74
81
|
"eslint": "^10.0.3",
|
|
75
82
|
"jsdoc": "^4.0.5",
|
|
76
|
-
"mocha": "^11.7.
|
|
83
|
+
"mocha": "^11.7.6",
|
|
77
84
|
"puppeteer": "^24.39.0",
|
|
78
85
|
"tcp-ping": "^0.1.1",
|
|
79
|
-
"typescript": "^
|
|
86
|
+
"typescript": "^6.0.2"
|
|
80
87
|
},
|
|
81
88
|
"optionalDependencies": {
|
|
82
|
-
"bufferutil": "^4.1.0"
|
|
83
|
-
"utf-8-validate": "^6.0.6"
|
|
89
|
+
"bufferutil": "^4.1.0"
|
|
84
90
|
}
|
|
85
91
|
}
|
package/src/client/Client.js
CHANGED
|
@@ -23,7 +23,10 @@ import {
|
|
|
23
23
|
CLIENT_HANDSHAKE_ERROR,
|
|
24
24
|
AUDIT_STATE_NAME,
|
|
25
25
|
} from '../common/constants.js';
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
import gatedLogger from '../common/logs/gated-logger.js';
|
|
28
|
+
import warnings from '../common/logs/warnings.js';
|
|
29
|
+
|
|
27
30
|
import VERSION from '../common/version.js';
|
|
28
31
|
|
|
29
32
|
// for testing purposes
|
|
@@ -132,7 +135,7 @@ class Client {
|
|
|
132
135
|
|
|
133
136
|
this[kClientOnStatusChangeCallbacks] = new Set();
|
|
134
137
|
|
|
135
|
-
|
|
138
|
+
gatedLogger.verbose = !!this.#config.env.verbose;
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
/**
|
|
@@ -209,7 +212,7 @@ class Client {
|
|
|
209
212
|
* @deprecated Use {@link Client#runtime} instead.
|
|
210
213
|
*/
|
|
211
214
|
get target() {
|
|
212
|
-
|
|
215
|
+
warnings.deprecated('Client#target', 'Client#runtime', '4.0.0-alpha.29');
|
|
213
216
|
return this.runtime;
|
|
214
217
|
}
|
|
215
218
|
|
|
@@ -335,7 +338,7 @@ class Client {
|
|
|
335
338
|
this.#token = token;
|
|
336
339
|
|
|
337
340
|
if (version !== this.#version) {
|
|
338
|
-
|
|
341
|
+
warnings.versionDiscrepancies(this.#role, this.#version, version);
|
|
339
342
|
}
|
|
340
343
|
|
|
341
344
|
resolve();
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { isBrowser } from '@ircam/sc-utils';
|
|
2
|
-
import WebSocket from 'isomorphic-ws';
|
|
3
2
|
|
|
3
|
+
import WebSocket from '#isomorphic/web-socket.js';
|
|
4
4
|
import {
|
|
5
5
|
PING_MESSAGE,
|
|
6
6
|
PONG_MESSAGE,
|
|
7
7
|
} from '../common/constants.js';
|
|
8
|
-
import logger from '../common/logger.js';
|
|
9
8
|
import {
|
|
10
9
|
packStringMessage,
|
|
11
10
|
unpackStringMessage,
|
|
@@ -167,7 +166,7 @@ class ClientSocket {
|
|
|
167
166
|
|
|
168
167
|
if (e.error) {
|
|
169
168
|
const msg = `ClientSocket error - code: ${e.error.code}, message: ${e.error.message}`;
|
|
170
|
-
|
|
169
|
+
console.log(msg);
|
|
171
170
|
}
|
|
172
171
|
|
|
173
172
|
// Try to reconnect in all cases. Note that if the socket has been connected,
|
|
@@ -274,6 +273,13 @@ class ClientSocket {
|
|
|
274
273
|
this.#listeners.delete(channel);
|
|
275
274
|
}
|
|
276
275
|
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Close the socket, will dispatch the close event. For debug testing purpose
|
|
279
|
+
*/
|
|
280
|
+
close() {
|
|
281
|
+
this.#socket.close();
|
|
282
|
+
}
|
|
277
283
|
}
|
|
278
284
|
|
|
279
285
|
export default ClientSocket;
|
package/src/common/BasePlugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { defu } from 'defu';
|
|
2
2
|
|
|
3
3
|
// Notes: we use Symbol.for because we need to override this in helpers test
|
|
4
4
|
export const kBasePluginStatus = Symbol.for('soundworks:base-plugin-status');
|
|
@@ -171,7 +171,7 @@ class BasePlugin {
|
|
|
171
171
|
* @see {@link BasePluginManager#onStateChange}
|
|
172
172
|
*/
|
|
173
173
|
propagateStateChange(updates) {
|
|
174
|
-
this.state =
|
|
174
|
+
this.state = defu(updates, this.state);
|
|
175
175
|
this.#onStateChangeCallbacks.forEach(callback => callback(this.state));
|
|
176
176
|
}
|
|
177
177
|
}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
kBasePluginStatus,
|
|
5
5
|
} from './BasePlugin.js';
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import gatedLogger from './logs/gated-logger.js';
|
|
8
8
|
|
|
9
9
|
export const kPluginManagerStart = Symbol('soundworks:plugin-manager-start');
|
|
10
10
|
export const kPluginManagerStop = Symbol('soundworks:plugin-manager-stop');
|
|
@@ -64,7 +64,7 @@ class BasePluginManager {
|
|
|
64
64
|
* @private
|
|
65
65
|
*/
|
|
66
66
|
async [kPluginManagerStart]() {
|
|
67
|
-
|
|
67
|
+
gatedLogger.title('starting registered plugins');
|
|
68
68
|
|
|
69
69
|
if (this.#status !== 'idle') {
|
|
70
70
|
throw new DOMException(`Cannot execute 'kPluginManagerStart' on BasePluginManager: Lifecycle methods must be called in following order: kPluginManagerStart, kPluginManagerStop`, 'InvalidAccessError');
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isString,
|
|
3
|
+
isFunction,
|
|
4
|
+
isPlainObject,
|
|
5
|
+
} from '@ircam/sc-utils';
|
|
6
|
+
|
|
2
7
|
import SharedState from './SharedState.js';
|
|
3
8
|
import SharedStateCollection, {
|
|
4
9
|
kSharedStateCollectionInit,
|
|
@@ -23,7 +28,7 @@ import {
|
|
|
23
28
|
GET_CLASS_DESCRIPTION_RESPONSE,
|
|
24
29
|
GET_CLASS_DESCRIPTION_ERROR,
|
|
25
30
|
} from './constants.js';
|
|
26
|
-
import
|
|
31
|
+
import warnings from './logs/warnings.js';
|
|
27
32
|
|
|
28
33
|
export const kStateManagerInit = Symbol('soundworks:state-manager-init');
|
|
29
34
|
export const kStateManagerDeleteState = Symbol('soundworks:state-manager-delete-state');
|
|
@@ -265,7 +270,7 @@ class BaseStateManager {
|
|
|
265
270
|
* @deprecated Use {@link BaseStateManager#getClassDescription} instead.
|
|
266
271
|
*/
|
|
267
272
|
async getSchema(className) {
|
|
268
|
-
|
|
273
|
+
warnings.deprecated('BaseStateManager#getSchema', 'BaseStateManager#getClassDescription', '4.0.0-alpha.29');
|
|
269
274
|
return this.getClassDescription(className);
|
|
270
275
|
}
|
|
271
276
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import cloneDeep from 'lodash/cloneDeep.js';
|
|
2
|
-
import equal from 'fast-deep-equal';
|
|
3
|
-
|
|
4
1
|
import {
|
|
5
2
|
isPlainObject,
|
|
6
3
|
} from '@ircam/sc-utils';
|
|
4
|
+
import {
|
|
5
|
+
dequal,
|
|
6
|
+
} from 'dequal/lite';
|
|
7
7
|
|
|
8
8
|
export const sharedOptions = {
|
|
9
9
|
nullable: false,
|
|
@@ -19,7 +19,7 @@ export const types = {
|
|
|
19
19
|
boolean: {
|
|
20
20
|
required: ['default'],
|
|
21
21
|
get defaultOptions() {
|
|
22
|
-
return Object.assign(
|
|
22
|
+
return Object.assign(structuredClone(sharedOptions), {});
|
|
23
23
|
},
|
|
24
24
|
coerceFunction: (name, def, value) => {
|
|
25
25
|
if (typeof value !== 'boolean') {
|
|
@@ -32,7 +32,7 @@ export const types = {
|
|
|
32
32
|
string: {
|
|
33
33
|
required: ['default'],
|
|
34
34
|
get defaultOptions() {
|
|
35
|
-
return Object.assign(
|
|
35
|
+
return Object.assign(structuredClone(sharedOptions), {});
|
|
36
36
|
},
|
|
37
37
|
coerceFunction: (name, def, value) => {
|
|
38
38
|
if (typeof value !== 'string') {
|
|
@@ -45,7 +45,7 @@ export const types = {
|
|
|
45
45
|
integer: {
|
|
46
46
|
required: ['default'],
|
|
47
47
|
get defaultOptions() {
|
|
48
|
-
return Object.assign(
|
|
48
|
+
return Object.assign(structuredClone(sharedOptions), {
|
|
49
49
|
min: -Infinity,
|
|
50
50
|
max: +Infinity,
|
|
51
51
|
});
|
|
@@ -78,7 +78,7 @@ export const types = {
|
|
|
78
78
|
float: {
|
|
79
79
|
required: ['default'],
|
|
80
80
|
get defaultOptions() {
|
|
81
|
-
return Object.assign(
|
|
81
|
+
return Object.assign(structuredClone(sharedOptions), {
|
|
82
82
|
min: -Infinity,
|
|
83
83
|
max: +Infinity,
|
|
84
84
|
});
|
|
@@ -111,7 +111,7 @@ export const types = {
|
|
|
111
111
|
enum: {
|
|
112
112
|
required: ['default', 'list'],
|
|
113
113
|
get defaultOptions() {
|
|
114
|
-
return Object.assign(
|
|
114
|
+
return Object.assign(structuredClone(sharedOptions), {});
|
|
115
115
|
},
|
|
116
116
|
coerceFunction: (name, def, value) => {
|
|
117
117
|
if (def.list.indexOf(value) === -1) {
|
|
@@ -125,7 +125,7 @@ export const types = {
|
|
|
125
125
|
any: {
|
|
126
126
|
required: ['default'],
|
|
127
127
|
get defaultOptions() {
|
|
128
|
-
return Object.assign(
|
|
128
|
+
return Object.assign(structuredClone(sharedOptions), {});
|
|
129
129
|
},
|
|
130
130
|
coerceFunction: (name, def, value) => {
|
|
131
131
|
// no check as it can have any type...
|
|
@@ -176,7 +176,7 @@ class ParameterBag {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
static getFullDescription(description) {
|
|
179
|
-
const fullDescription =
|
|
179
|
+
const fullDescription = structuredClone(description);
|
|
180
180
|
|
|
181
181
|
for (let [name, def] of Object.entries(fullDescription)) {
|
|
182
182
|
if (types[def.type].sanitizeDescription) {
|
|
@@ -213,7 +213,7 @@ class ParameterBag {
|
|
|
213
213
|
ParameterBag.validateDescription(description);
|
|
214
214
|
|
|
215
215
|
description = ParameterBag.getFullDescription(description);
|
|
216
|
-
initValues =
|
|
216
|
+
initValues = structuredClone(initValues);
|
|
217
217
|
|
|
218
218
|
// make sure initValues make sens according to the given description
|
|
219
219
|
for (let name in initValues) {
|
|
@@ -308,7 +308,7 @@ class ParameterBag {
|
|
|
308
308
|
if (this.#description[name].type === 'any') {
|
|
309
309
|
// we return a deep copy of the object as we don't want the client code to
|
|
310
310
|
// be able to modify our underlying data.
|
|
311
|
-
return
|
|
311
|
+
return structuredClone(this.#values[name]);
|
|
312
312
|
} else {
|
|
313
313
|
return this.#values[name];
|
|
314
314
|
}
|
|
@@ -369,7 +369,7 @@ class ParameterBag {
|
|
|
369
369
|
set(name, value) {
|
|
370
370
|
value = this.coerceValue(name, value);
|
|
371
371
|
const currentValue = this.#values[name];
|
|
372
|
-
const updated = !
|
|
372
|
+
const updated = !dequal(currentValue, value);
|
|
373
373
|
|
|
374
374
|
// we store a deep copy of the object as we don't want the client to be able
|
|
375
375
|
// to modify our underlying data, which leads to unexpected behavior where the
|
|
@@ -377,7 +377,7 @@ class ParameterBag {
|
|
|
377
377
|
// @see tests/common.state-manager.spec.js
|
|
378
378
|
// 'should copy stored value for "any" type to have a predictable behavior'
|
|
379
379
|
if (this.#description[name].type === 'any') {
|
|
380
|
-
value =
|
|
380
|
+
value = structuredClone(value);
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
this.#values[name] = value;
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
UPDATE_RESPONSE,
|
|
15
15
|
UPDATE_ABORT,
|
|
16
16
|
UPDATE_NOTIFICATION,
|
|
17
|
+
HAS_SIBLINGS_NOTIFICATION,
|
|
17
18
|
} from './constants.js';
|
|
18
19
|
|
|
19
20
|
import {
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
kStateManagerDeleteState,
|
|
22
23
|
} from './BaseStateManager.js';
|
|
23
24
|
|
|
24
|
-
import
|
|
25
|
+
import warnings from './logs/warnings.js';
|
|
25
26
|
|
|
26
27
|
// for testing purposes
|
|
27
28
|
export const kSharedStatePromiseStore = Symbol('soundworks:shared-state-promise-store');
|
|
@@ -108,6 +109,8 @@ class SharedState {
|
|
|
108
109
|
#filter = null;
|
|
109
110
|
// true is the state has been detached or deleted
|
|
110
111
|
#detached = false;
|
|
112
|
+
// only valid for owners
|
|
113
|
+
#hasSiblings = false;
|
|
111
114
|
#parameters = null;
|
|
112
115
|
#onUpdateCallbacks = new Set();
|
|
113
116
|
#onDetachCallbacks = new Set();
|
|
@@ -182,6 +185,8 @@ class SharedState {
|
|
|
182
185
|
// state has been deleted by its creator or the class has been deleted
|
|
183
186
|
// ---------------------------------------------
|
|
184
187
|
this.#client.transport.addListener(`${DELETE_NOTIFICATION}-${this.#id}-${this.#instanceId}`, async () => {
|
|
188
|
+
this.#detached = true;
|
|
189
|
+
|
|
185
190
|
this.#manager[kStateManagerDeleteState](this.#id);
|
|
186
191
|
this.#clearTransport();
|
|
187
192
|
|
|
@@ -239,6 +244,10 @@ class SharedState {
|
|
|
239
244
|
this[kSharedStatePromiseStore].reject(reqId, msg);
|
|
240
245
|
});
|
|
241
246
|
|
|
247
|
+
this.#client.transport.addListener(`${HAS_SIBLINGS_NOTIFICATION}-${this.#id}-${this.#instanceId}`, hasSiblings => {
|
|
248
|
+
this.#hasSiblings = hasSiblings;
|
|
249
|
+
});
|
|
250
|
+
|
|
242
251
|
} else {
|
|
243
252
|
// ---------------------------------------------
|
|
244
253
|
// the attached node has called `.detach()`
|
|
@@ -291,7 +300,7 @@ class SharedState {
|
|
|
291
300
|
* @deprecated Use {@link SharedState#className} instead.
|
|
292
301
|
*/
|
|
293
302
|
get schemaName() {
|
|
294
|
-
|
|
303
|
+
warnings.deprecated('SharedState#schemaName', 'SharedState#className', '4.0.0-alpha.29');
|
|
295
304
|
return this.className;
|
|
296
305
|
}
|
|
297
306
|
|
|
@@ -303,6 +312,24 @@ class SharedState {
|
|
|
303
312
|
return this.#isOwner;
|
|
304
313
|
}
|
|
305
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Indicates if the node as siblings, i.e. if several versions of the same state
|
|
317
|
+
* exists on the network
|
|
318
|
+
* Always return true if the state instance is attached
|
|
319
|
+
* @type {Boolean}
|
|
320
|
+
*/
|
|
321
|
+
get hasSiblings() {
|
|
322
|
+
if (this.#detached) {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (!this.isOwner) {
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return this.#hasSiblings;
|
|
331
|
+
}
|
|
332
|
+
|
|
306
333
|
#clearTransport() {
|
|
307
334
|
// remove listeners
|
|
308
335
|
this.#client.transport.removeAllListeners(`${UPDATE_RESPONSE}-${this.#id}-${this.#instanceId}`);
|
|
@@ -397,7 +424,7 @@ class SharedState {
|
|
|
397
424
|
* @deprecated Use {@link SharedState#getDescription} instead.
|
|
398
425
|
*/
|
|
399
426
|
getSchema(paramName = null) {
|
|
400
|
-
|
|
427
|
+
warnings.deprecated('SharedState#getSchema', 'SharedState#getDescription', '4.0.0-alpha.29');
|
|
401
428
|
return this.getDescription(paramName);
|
|
402
429
|
}
|
|
403
430
|
|
|
@@ -466,7 +493,7 @@ class SharedState {
|
|
|
466
493
|
}
|
|
467
494
|
|
|
468
495
|
if (isPlainObject(arguments[0]) && isPlainObject(arguments[1])) {
|
|
469
|
-
|
|
496
|
+
warnings.removed('`context` argument in SharedState.set(updates, context)', 'a regular parameter configured with `event=true`', '4.0.0-alpha.29');
|
|
470
497
|
}
|
|
471
498
|
|
|
472
499
|
if (arguments.length === 2 && isString(updates)) {
|
|
@@ -551,11 +578,14 @@ class SharedState {
|
|
|
551
578
|
hasLocalParam = true;
|
|
552
579
|
locallyResolvedParam[name] = this.#parameters.get(name);
|
|
553
580
|
} else if (acknowledge === false) {
|
|
554
|
-
//
|
|
555
|
-
//
|
|
581
|
+
// when acknowledge is false, e.g. streaming values, values are
|
|
582
|
+
// propagated on the network only if hasSiblings is true
|
|
556
583
|
hasNonAcknowledgedParams = true;
|
|
557
584
|
locallyResolvedParam[name] = this.#parameters.get(name);
|
|
558
|
-
|
|
585
|
+
// propagate only if there is an attached state somewhere
|
|
586
|
+
if (this.hasSiblings) {
|
|
587
|
+
networkPropagatedParams[name] = updates[name];
|
|
588
|
+
}
|
|
559
589
|
} else {
|
|
560
590
|
// note that immediate params are shared and acknowledged
|
|
561
591
|
hasRegularSharedParam = true;
|
|
@@ -580,7 +610,9 @@ class SharedState {
|
|
|
580
610
|
this[kSharedStatePromiseStore].associateResolveData(reqId, locallyResolvedParam);
|
|
581
611
|
}
|
|
582
612
|
|
|
583
|
-
|
|
613
|
+
if (Object.keys(networkPropagatedParams).length > 0) {
|
|
614
|
+
this.#client.transport.emit(`${UPDATE_REQUEST}-${this.#id}-${this.#instanceId}`, reqId, networkPropagatedParams);
|
|
615
|
+
}
|
|
584
616
|
|
|
585
617
|
// if we don't have regular shared params, we can resolve now
|
|
586
618
|
if (!hasRegularSharedParam) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import warnings from './logs/warnings.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Callback to execute when an update is triggered on one of the shared states
|
|
@@ -163,7 +163,7 @@ class SharedStateCollection {
|
|
|
163
163
|
* @deprecated Use {@link SharedStateCollection#className} instead.
|
|
164
164
|
*/
|
|
165
165
|
get schemaName() {
|
|
166
|
-
|
|
166
|
+
warnings.deprecated('SharedStateCollection#schemaName', 'SharedStateCollection#className', '4.0.0-alpha.29');
|
|
167
167
|
return this.className;
|
|
168
168
|
}
|
|
169
169
|
|
|
@@ -171,7 +171,7 @@ class SharedStateCollection {
|
|
|
171
171
|
* @deprecated Use {@link SharedStateCollection#getDescription} instead.
|
|
172
172
|
*/
|
|
173
173
|
getSchema(paramName = null) {
|
|
174
|
-
|
|
174
|
+
warnings.deprecated('SharedStateCollection#getSchema', 'SharedStateCollection#getDescription', '4.0.0-alpha.29');
|
|
175
175
|
return this.getDescription(paramName);
|
|
176
176
|
}
|
|
177
177
|
|
package/src/common/constants.js
CHANGED
|
@@ -44,6 +44,8 @@ export const GET_CLASS_DESCRIPTION_REQUEST = 's:s:req';
|
|
|
44
44
|
export const GET_CLASS_DESCRIPTION_RESPONSE = 's:s:res';
|
|
45
45
|
export const GET_CLASS_DESCRIPTION_ERROR = 's:s:err';
|
|
46
46
|
|
|
47
|
+
export const HAS_SIBLINGS_NOTIFICATION = 's:hs:not';
|
|
48
|
+
|
|
47
49
|
// context channels
|
|
48
50
|
export const CONTEXT_ENTER_REQUEST = 'c:en:req';
|
|
49
51
|
export const CONTEXT_ENTER_RESPONSE = 'c:en:res';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @private
|
|
3
|
+
*/
|
|
4
|
+
export default {
|
|
5
|
+
title(msg) {
|
|
6
|
+
console.log(`%c${msg}`, 'color: cyan');
|
|
7
|
+
},
|
|
8
|
+
log(msg) {
|
|
9
|
+
console.log(msg);
|
|
10
|
+
},
|
|
11
|
+
warn(msg) {
|
|
12
|
+
console.warn(`%c${msg}`, 'color: yellow');
|
|
13
|
+
},
|
|
14
|
+
error(msg) {
|
|
15
|
+
console.error(`%c${msg}`, 'color: red');
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { styleText } from 'node:util';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
6
|
+
export default {
|
|
7
|
+
title(msg) {
|
|
8
|
+
console.log(styleText('cyan', msg));
|
|
9
|
+
},
|
|
10
|
+
log(msg) {
|
|
11
|
+
console.log(msg);
|
|
12
|
+
},
|
|
13
|
+
warn(msg) {
|
|
14
|
+
console.warn(styleText('yellow', msg));
|
|
15
|
+
},
|
|
16
|
+
error(msg) {
|
|
17
|
+
console.error(styleText('red', msg));
|
|
18
|
+
},
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default globalThis.WebSocket;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import coloredLogger from '#isomorphic/colored-logger.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
6
|
+
export default {
|
|
7
|
+
// Note that setting verbose to false is mainly useful for tests
|
|
8
|
+
verbose: true,
|
|
9
|
+
|
|
10
|
+
title(msg) {
|
|
11
|
+
if (this.verbose) {
|
|
12
|
+
coloredLogger.title(msg);
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
log(msg) {
|
|
16
|
+
if (this.verbose) {
|
|
17
|
+
coloredLogger.log(msg);
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
warn(msg) {
|
|
21
|
+
if (this.verbose) {
|
|
22
|
+
coloredLogger.warn(msg);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
error(msg) {
|
|
26
|
+
if (this.verbose) {
|
|
27
|
+
coloredLogger.error(msg);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import coloredLogger from '#isomorphic/colored-logger.js';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
versionDiscrepancies(clientRole, clientVersion, serverVersion) {
|
|
5
|
+
coloredLogger.warn(`
|
|
6
|
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
7
|
+
|
|
8
|
+
WARNING
|
|
9
|
+
|
|
10
|
+
Version discrepancies between server and "${clientRole}" client:
|
|
11
|
+
+ server: ${serverVersion} | client: ${clientVersion}
|
|
12
|
+
|
|
13
|
+
This might lead to unexpected behavior, you should consider to re-install your
|
|
14
|
+
dependencies on both your server and clients.
|
|
15
|
+
|
|
16
|
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`);
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
deprecated(oldAPI, newAPI, lastSupportedVersion) {
|
|
20
|
+
if (!lastSupportedVersion) {
|
|
21
|
+
throw new Error(`Invalid 'logger.deprecated call: a deprecation version is required`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const msg = `DEPRECATION WARNING: \`${oldAPI}\` is deprecated (last supported version: ${lastSupportedVersion}) and will be removed in the next major revision, please use ${newAPI} instead.\n`;
|
|
25
|
+
coloredLogger.warn(msg);
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
removed(oldAPI, hint, lastSupportedVersion) {
|
|
29
|
+
if (!lastSupportedVersion) {
|
|
30
|
+
throw new Error(`Invalid 'logger.deprecated call: a deprecation version is required`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const msg = `"${oldAPI}" has been removed (last supported version: ${lastSupportedVersion}), please use "${hint}" instead.`;
|
|
34
|
+
throw new Error(msg);
|
|
35
|
+
},
|
|
36
|
+
};
|
package/src/common/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// [WARNING] This file is generated, do not edit
|
|
2
|
-
export default '5.
|
|
2
|
+
export default '5.6.0';
|