@soundworks/core 4.0.0-alpha.21 → 4.0.0-alpha.23
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/CHANGELOG.md +14 -3
- package/package.json +15 -15
- package/src/client/Client.js +233 -188
- package/src/client/Socket.js +84 -247
- package/src/client/index.js +6 -0
- package/src/common/constants.js +0 -1
- package/src/common/logger.js +15 -0
- package/src/common/sockets-utils.js +0 -63
- package/src/common/version.js +2 -0
- package/src/server/Plugin.js +22 -10
- package/src/server/Server.js +37 -36
- package/src/server/Socket.js +126 -250
- package/src/server/Sockets.js +103 -127
- package/src/server/audit-network-latency.worker.js +4 -3
- package/src/server/index.js +6 -0
- package/types/client/Client.d.ts +41 -8
- package/types/client/Client.d.ts.map +1 -1
- package/types/client/Context.d.ts +40 -14
- package/types/client/Context.d.ts.map +1 -1
- package/types/client/Plugin.d.ts +42 -41
- package/types/client/Plugin.d.ts.map +1 -1
- package/types/client/PluginManager.d.ts +26 -11
- package/types/client/PluginManager.d.ts.map +1 -1
- package/types/client/SharedState.d.ts +1 -1
- package/types/client/SharedState.d.ts.map +1 -1
- package/types/client/SharedStateCollection.d.ts +41 -0
- package/types/client/SharedStateCollection.d.ts.map +1 -0
- package/types/client/Socket.d.ts +41 -30
- package/types/client/Socket.d.ts.map +1 -1
- package/types/client/StateManager.d.ts +1 -1
- package/types/client/StateManager.d.ts.map +1 -1
- package/types/client/index.d.ts +0 -8
- package/types/common/BasePlugin.d.ts +24 -19
- package/types/common/BasePlugin.d.ts.map +1 -1
- package/types/common/BasePluginManager.d.ts +17 -5
- package/types/common/BasePluginManager.d.ts.map +1 -1
- package/types/common/BaseSharedState.d.ts +100 -29
- package/types/common/BaseSharedState.d.ts.map +1 -1
- package/types/common/BaseSharedStateCollection.d.ts +183 -0
- package/types/common/BaseSharedStateCollection.d.ts.map +1 -0
- package/types/common/BaseStateManager.d.ts +83 -18
- package/types/common/BaseStateManager.d.ts.map +1 -1
- package/types/common/BatchedTransport.d.ts +21 -0
- package/types/common/BatchedTransport.d.ts.map +1 -0
- package/types/common/ParameterBag.d.ts +61 -40
- package/types/common/ParameterBag.d.ts.map +1 -1
- package/types/common/PromiseStore.d.ts +11 -0
- package/types/common/PromiseStore.d.ts.map +1 -0
- package/types/common/SharedStatePrivate.d.ts +4 -3
- package/types/common/SharedStatePrivate.d.ts.map +1 -1
- package/types/common/constants.d.ts +10 -1
- package/types/common/constants.d.ts.map +1 -1
- package/types/common/logger.d.ts +1 -1
- package/types/common/sockets-utils.d.ts.map +1 -1
- package/types/common/version.d.ts +3 -0
- package/types/common/version.d.ts.map +1 -0
- package/types/server/Client.d.ts +5 -0
- package/types/server/Client.d.ts.map +1 -1
- package/types/server/Context.d.ts +162 -22
- package/types/server/Context.d.ts.map +1 -1
- package/types/server/ContextManager.d.ts +4 -4
- package/types/server/ContextManager.d.ts.map +1 -1
- package/types/server/Plugin.d.ts +56 -55
- package/types/server/Plugin.d.ts.map +1 -1
- package/types/server/PluginManager.d.ts +26 -6
- package/types/server/PluginManager.d.ts.map +1 -1
- package/types/server/Server.d.ts +207 -70
- package/types/server/Server.d.ts.map +1 -1
- package/types/server/SharedState.d.ts +1 -1
- package/types/server/SharedState.d.ts.map +1 -1
- package/types/server/SharedStateCollection.d.ts +41 -0
- package/types/server/SharedStateCollection.d.ts.map +1 -0
- package/types/server/Socket.d.ts +93 -57
- package/types/server/Socket.d.ts.map +1 -1
- package/types/server/Sockets.d.ts +32 -25
- package/types/server/Sockets.d.ts.map +1 -1
- package/types/server/StateManager.d.ts +242 -27
- package/types/server/StateManager.d.ts.map +1 -1
- package/types/server/audit-network-latency.worker.d.ts +2 -1
- package/types/server/audit-schema.d.ts +8 -8
- package/types/server/crypto.d.ts +3 -0
- package/types/server/crypto.d.ts.map +1 -0
- package/types/server/index.d.ts +0 -4
- package/types/common/promise-store.d.ts +0 -4
- package/types/common/promise-store.d.ts.map +0 -1
- package/types/common/utils.d.ts +0 -5
- package/types/common/utils.d.ts.map +0 -1
package/src/server/Sockets.js
CHANGED
|
@@ -1,39 +1,42 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
1
|
+
import querystring from 'node:querystring';
|
|
2
|
+
import {
|
|
3
|
+
Worker,
|
|
4
|
+
} from 'node:worker_threads';
|
|
4
5
|
|
|
5
|
-
import
|
|
6
|
+
import {
|
|
7
|
+
default as WebSocket,
|
|
8
|
+
WebSocketServer,
|
|
9
|
+
} from 'ws';
|
|
10
|
+
|
|
11
|
+
import Socket, {
|
|
12
|
+
kSocketTerminate,
|
|
13
|
+
} from './Socket.js';
|
|
14
|
+
|
|
15
|
+
// @note - fs.readFileSync creates some cwd() issues...
|
|
6
16
|
import networkLatencyWorker from './audit-network-latency.worker.js';
|
|
7
17
|
|
|
8
|
-
|
|
9
|
-
|
|
18
|
+
export const kSocketsRemoveFromAllRooms = Symbol('soundworks:sockets-remove-from-all-rooms');
|
|
19
|
+
export const kSocketsLatencyStatsWorker = Symbol('soundworks:sockets-latency-stats-worker');
|
|
20
|
+
export const kSocketsDebugPreventHeartBeat = Symbol('soundworks:sockets-debug-prevent-heartbeat');
|
|
10
21
|
|
|
11
22
|
/**
|
|
12
|
-
*
|
|
23
|
+
* Manage all {@link server.Socket} instances.
|
|
13
24
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
25
|
+
* _Important: In most cases, you should consider using a {@link client.SharedState}
|
|
26
|
+
* rather than directly using the Socket instance._
|
|
16
27
|
*
|
|
17
28
|
* @memberof server
|
|
18
29
|
*/
|
|
19
30
|
class Sockets {
|
|
31
|
+
#wsServer = null;
|
|
32
|
+
#rooms = new Map();
|
|
33
|
+
|
|
20
34
|
constructor() {
|
|
21
|
-
|
|
22
|
-
this.
|
|
23
|
-
|
|
24
|
-
this
|
|
25
|
-
|
|
26
|
-
this._rooms.set('*', new Set());
|
|
27
|
-
/** @private */
|
|
28
|
-
this._initializationCache = new Map();
|
|
29
|
-
|
|
30
|
-
/** @private */
|
|
31
|
-
this._latencyStatsWorker = null; // protected - used in Socket instances
|
|
32
|
-
/** @private */
|
|
33
|
-
this._auditState = null;
|
|
34
|
-
|
|
35
|
-
/** @private */
|
|
36
|
-
this._DEBUG_PREVENT_HEARTBEAT = false;
|
|
35
|
+
// Init special `'*'` room which stores all current connections.
|
|
36
|
+
this.#rooms.set('*', new Set());
|
|
37
|
+
|
|
38
|
+
this[kSocketsLatencyStatsWorker] = null;
|
|
39
|
+
this[kSocketsDebugPreventHeartBeat] = false;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
/**
|
|
@@ -44,15 +47,15 @@ class Sockets {
|
|
|
44
47
|
* @private
|
|
45
48
|
*/
|
|
46
49
|
async start(server, config, onConnectionCallback) {
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
this._latencyStatsWorker = new Worker(networkLatencyWorker, { eval: true });
|
|
51
|
-
this._auditState = await server.getAuditState();
|
|
50
|
+
// Audit for network latency estimation, the worker is written in cjs so that we
|
|
51
|
+
// can make builds for Max, move back to modules once Max support modules
|
|
52
|
+
this[kSocketsLatencyStatsWorker] = new Worker(networkLatencyWorker, { eval: true });
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
const auditState = await server.getAuditState();
|
|
55
|
+
|
|
56
|
+
auditState.onUpdate(updates => {
|
|
54
57
|
if ('averageNetworkLatencyWindow' in updates || 'averageNetworkLatencyPeriod' in updates) {
|
|
55
|
-
this.
|
|
58
|
+
this[kSocketsLatencyStatsWorker].postMessage({
|
|
56
59
|
type: 'config',
|
|
57
60
|
value: {
|
|
58
61
|
averageLatencyWindow: updates.averageNetworkLatencyWindow,
|
|
@@ -62,137 +65,104 @@ class Sockets {
|
|
|
62
65
|
}
|
|
63
66
|
}, true);
|
|
64
67
|
|
|
65
|
-
this.
|
|
68
|
+
this[kSocketsLatencyStatsWorker].on('message', msg => {
|
|
66
69
|
if (msg.type === 'computed-average-latency') {
|
|
67
|
-
|
|
70
|
+
auditState.set({ averageNetworkLatency: msg.value });
|
|
68
71
|
}
|
|
69
72
|
});
|
|
70
73
|
|
|
71
|
-
//
|
|
72
|
-
this
|
|
74
|
+
// Init ws server
|
|
75
|
+
this.#wsServer = new WebSocketServer({
|
|
73
76
|
noServer: true,
|
|
74
|
-
path: `/${config.path}`,
|
|
77
|
+
path: `/${config.path}`,
|
|
75
78
|
});
|
|
76
79
|
|
|
77
|
-
this.
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
const binary = !!(parseInt(queryString.binary));
|
|
81
|
-
|
|
82
|
-
if (binary) {
|
|
83
|
-
ws.binaryType = 'arraybuffer';
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (!this._initializationCache.has(key)) {
|
|
87
|
-
this._initializationCache.set(key, { ws, binary });
|
|
88
|
-
} else {
|
|
89
|
-
const cached = this._initializationCache.get(key);
|
|
90
|
-
this._initializationCache.delete(key);
|
|
80
|
+
this.#wsServer.on('connection', (ws, req) => {
|
|
81
|
+
const { role, token } = querystring.parse(req.url.split('?')[1]);
|
|
82
|
+
const socket = new Socket(ws, this);
|
|
91
83
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const binaryWs = cached.binary ? cached.ws : ws;
|
|
95
|
-
const socket = new Socket(stringWs, binaryWs, this._rooms, this, config);
|
|
84
|
+
socket.addToRoom('*');
|
|
85
|
+
socket.addToRoom(role);
|
|
96
86
|
|
|
97
|
-
|
|
98
|
-
socket.addToRoom(role);
|
|
99
|
-
|
|
100
|
-
onConnectionCallback(role, socket, token);
|
|
101
|
-
}
|
|
87
|
+
onConnectionCallback(role, socket, token);
|
|
102
88
|
});
|
|
103
89
|
|
|
104
|
-
//
|
|
90
|
+
// Prevent socket with protected role to connect is token is invalid
|
|
105
91
|
server.httpServer.on('upgrade', async (req, socket, head) => {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
const { role, token } = queryString;
|
|
92
|
+
const { role, token } = querystring.parse(req.url.split('?')[1]);
|
|
109
93
|
|
|
110
94
|
if (server.isProtected(role)) {
|
|
111
|
-
// we don't have any
|
|
112
|
-
// connection token is pending
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (!allowed) {
|
|
95
|
+
// we don't have any IP in the upgrade request object,
|
|
96
|
+
// so we just check the connection token is pending and valid
|
|
97
|
+
if (!server.isValidConnectionToken(token)) {
|
|
116
98
|
socket.destroy('not allowed');
|
|
117
99
|
}
|
|
118
100
|
}
|
|
119
101
|
|
|
120
|
-
this.
|
|
121
|
-
this.
|
|
102
|
+
this.#wsServer.handleUpgrade(req, socket, head, (ws) => {
|
|
103
|
+
this.#wsServer.emit('connection', ws, req);
|
|
122
104
|
});
|
|
123
105
|
});
|
|
124
106
|
}
|
|
125
107
|
|
|
126
108
|
/**
|
|
127
|
-
* Terminate all existing sockets
|
|
128
|
-
*
|
|
109
|
+
* Terminate all existing sockets.
|
|
129
110
|
* @private
|
|
130
111
|
*/
|
|
131
112
|
terminate() {
|
|
132
113
|
// terminate stat worker thread
|
|
133
|
-
this.
|
|
114
|
+
this[kSocketsLatencyStatsWorker].terminate();
|
|
134
115
|
// clean sockets
|
|
135
|
-
const sockets = this.
|
|
136
|
-
sockets.forEach(socket => socket
|
|
116
|
+
const sockets = this.#rooms.get('*');
|
|
117
|
+
sockets.forEach(socket => socket[kSocketTerminate]());
|
|
137
118
|
}
|
|
138
119
|
|
|
139
|
-
/**
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (typeof roomIds === 'string') {
|
|
146
|
-
roomIds = [roomIds];
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
roomIds.forEach(roomId => {
|
|
150
|
-
if (this._rooms.has(roomId)) {
|
|
151
|
-
const room = this._rooms.get(roomId);
|
|
152
|
-
room.forEach(socket => targets.add(socket));
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
} else {
|
|
156
|
-
targets = this._rooms.get('*');
|
|
120
|
+
/**
|
|
121
|
+
* Remove given socket from all rooms.
|
|
122
|
+
*/
|
|
123
|
+
[kSocketsRemoveFromAllRooms](socket) {
|
|
124
|
+
for (let [_, room] of this.#rooms) {
|
|
125
|
+
room.delete(socket);
|
|
157
126
|
}
|
|
158
|
-
|
|
159
|
-
targets.forEach(socket => {
|
|
160
|
-
if (socket.ws.readyState === WebSocket.OPEN) {
|
|
161
|
-
if (excludeSocket !== null) {
|
|
162
|
-
if (socket !== excludeSocket) {
|
|
163
|
-
socket[method](channel, ...args);
|
|
164
|
-
}
|
|
165
|
-
} else {
|
|
166
|
-
socket[method](channel, ...args);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
127
|
}
|
|
171
128
|
|
|
172
129
|
/**
|
|
173
|
-
* Add a socket to a room
|
|
130
|
+
* Add a socket to a room.
|
|
131
|
+
*
|
|
132
|
+
* _Note that in most cases, you should use a shared state instead_
|
|
174
133
|
*
|
|
175
134
|
* @param {server.Socket} socket - Socket to add to the room.
|
|
176
135
|
* @param {String} roomId - Id of the room.
|
|
177
136
|
*/
|
|
178
137
|
addToRoom(socket, roomId) {
|
|
179
|
-
|
|
138
|
+
if (!this.#rooms.has(roomId)) {
|
|
139
|
+
this.#rooms.set(roomId, new Set());
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const room = this.#rooms.get(roomId);
|
|
143
|
+
room.add(socket);
|
|
180
144
|
}
|
|
181
145
|
|
|
182
146
|
/**
|
|
183
|
-
* Remove a socket from a room
|
|
147
|
+
* Remove a socket from a room.
|
|
148
|
+
*
|
|
149
|
+
* _Note that in most cases, you should use a shared state instead_
|
|
184
150
|
*
|
|
185
151
|
* @param {server.Socket} socket - Socket to remove from the room.
|
|
186
152
|
* @param {String} roomId - Id of the room.
|
|
187
153
|
*/
|
|
188
154
|
removeFromRoom(socket, roomId) {
|
|
189
|
-
|
|
155
|
+
if (this.#rooms.has(roomId)) {
|
|
156
|
+
const room = this.#rooms.get(roomId);
|
|
157
|
+
room.delete(socket);
|
|
158
|
+
}
|
|
190
159
|
}
|
|
191
160
|
|
|
192
161
|
/**
|
|
193
|
-
* Send a message
|
|
194
|
-
*
|
|
162
|
+
* Send a message to all clients os given room(s). If no room is specified,
|
|
163
|
+
* the message is sent to all clients.
|
|
195
164
|
*
|
|
165
|
+
* _Note that in most cases, you should use a shared state instead_
|
|
196
166
|
*
|
|
197
167
|
* @param {String|Array} roomsIds - Ids of the rooms that must receive
|
|
198
168
|
* the message. If `null` the message is sent to all clients.
|
|
@@ -203,22 +173,28 @@ class Sockets {
|
|
|
203
173
|
* JSON compatible data types (i.e. string, number, boolean, object, array and null).
|
|
204
174
|
*/
|
|
205
175
|
broadcast(roomIds, excludeSocket, channel, ...args) {
|
|
206
|
-
|
|
207
|
-
}
|
|
176
|
+
const targets = new Set();
|
|
208
177
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
178
|
+
if (typeof roomIds === 'string' || Array.isArray(roomIds)) {
|
|
179
|
+
if (typeof roomIds === 'string') {
|
|
180
|
+
roomIds = [roomIds];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
roomIds.forEach(roomId => {
|
|
184
|
+
if (this.#rooms.has(roomId)) {
|
|
185
|
+
const room = this.#rooms.get(roomId);
|
|
186
|
+
room.forEach(socket => targets.add(socket));
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
} else {
|
|
190
|
+
targets = this.#rooms.get('*');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
targets.forEach(socket => {
|
|
194
|
+
if (socket.readyState === WebSocket.OPEN && socket !== excludeSocket) {
|
|
195
|
+
socket.send(channel, ...args);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
222
198
|
}
|
|
223
199
|
}
|
|
224
200
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// @note - We use this common js syntax so that the server can be bundled to cjs
|
|
2
|
+
// which allows to build a server that can be accepted by Max `node.script`
|
|
3
|
+
//
|
|
3
4
|
// Should move back to regular esm module once Max has fixed its loader
|
|
4
5
|
export default `
|
|
5
6
|
const { parentPort } = require('node:worker_threads');
|
|
@@ -11,6 +12,7 @@ let averageLatencyPeriod = 2;
|
|
|
11
12
|
let intervalId = null;
|
|
12
13
|
let meanLatency = 0;
|
|
13
14
|
|
|
15
|
+
// workaround that sc-utils is pure emascript module
|
|
14
16
|
let getTime;
|
|
15
17
|
let inited = new Promise(async (resolve) => {
|
|
16
18
|
module = await import('@ircam/sc-utils');
|
|
@@ -25,7 +27,6 @@ parentPort.on('message', async msg => {
|
|
|
25
27
|
averageLatencyPeriod = msg.value.averageLatencyPeriod;
|
|
26
28
|
|
|
27
29
|
await inited;
|
|
28
|
-
|
|
29
30
|
// launch compute in its own loop so that the number of computation is
|
|
30
31
|
// decoupled from the number of connected clients
|
|
31
32
|
clearInterval(intervalId);
|
package/src/server/index.js
CHANGED
package/types/client/Client.d.ts
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
export default Client;
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Configuration object for a client running in a browser runtime.
|
|
4
|
+
*/
|
|
5
|
+
export type ClientConfig = any;
|
|
6
|
+
/**
|
|
7
|
+
* Configuration object for a client running in a browser runtime.
|
|
8
|
+
*
|
|
9
|
+
* @typedef ClientConfig
|
|
10
|
+
* @memberof client
|
|
11
|
+
* @type {object}
|
|
12
|
+
* @property {string} role - Role of the client in the application (e.g. 'player', 'controller').
|
|
13
|
+
* @property {object} [app] - Application configration object.
|
|
14
|
+
* @property {string} [app.name=''] - Name of the application.
|
|
15
|
+
* @property {string} [app.author=''] - Name of the author.
|
|
16
|
+
* @property {object} [env] - Environment configration object.
|
|
17
|
+
* @property {boolean} env.useHttps - Define if the websocket should use secure connection.
|
|
18
|
+
* @property {boolean} [env.serverAddress=''] - Address the socket server. Mandatory for
|
|
19
|
+
* node clients. For browser clients, use `window.location.domain` as fallback if empty.
|
|
20
|
+
* @property {boolean} env.port - Port of the socket server.
|
|
21
|
+
* @property {string} [env.websockets={}] - Configuration options for websockets.
|
|
22
|
+
* @property {string} [env.subpath=''] - If running behind a proxy, path to the application.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* The `Client` class is the main entry point for the client-side of a soundworks
|
|
4
26
|
* application.
|
|
5
27
|
*
|
|
6
28
|
* A `Client` instance allows to access soundworks components such as {@link client.StateManager},
|
|
@@ -20,11 +42,16 @@ export default Client;
|
|
|
20
42
|
*/
|
|
21
43
|
declare class Client {
|
|
22
44
|
/**
|
|
23
|
-
* @param {client.
|
|
24
|
-
* Configuration of the soundworks client.
|
|
45
|
+
* @param {client.ClientConfig} config - Configuration of the soundworks client.
|
|
25
46
|
* @throws Will throw if the given config object is invalid.
|
|
26
47
|
*/
|
|
27
|
-
constructor(config: client.
|
|
48
|
+
constructor(config: client.ClientConfig);
|
|
49
|
+
/**
|
|
50
|
+
* package version
|
|
51
|
+
* @type string
|
|
52
|
+
* @readonly
|
|
53
|
+
*/
|
|
54
|
+
readonly version: string;
|
|
28
55
|
/**
|
|
29
56
|
* Role of the client in the application.
|
|
30
57
|
*
|
|
@@ -34,9 +61,9 @@ declare class Client {
|
|
|
34
61
|
/**
|
|
35
62
|
* Configuration object.
|
|
36
63
|
*
|
|
37
|
-
* @type {client.
|
|
64
|
+
* @type {client.ClientConfig}
|
|
38
65
|
*/
|
|
39
|
-
config: client.
|
|
66
|
+
config: client.ClientConfig;
|
|
40
67
|
/**
|
|
41
68
|
* Session id of the client (incremeted positive number), generated and
|
|
42
69
|
* retrieved by the server during `client.init`. The counter is reset when
|
|
@@ -99,6 +126,11 @@ declare class Client {
|
|
|
99
126
|
* @type {string}
|
|
100
127
|
*/
|
|
101
128
|
status: string;
|
|
129
|
+
/**
|
|
130
|
+
* Token of the client if connected through HTTP authentication.
|
|
131
|
+
* @private
|
|
132
|
+
*/
|
|
133
|
+
private token;
|
|
102
134
|
/** @private */
|
|
103
135
|
private _onStatusChangeCallbacks;
|
|
104
136
|
/** @private */
|
|
@@ -136,8 +168,9 @@ declare class Client {
|
|
|
136
168
|
* method if it has not been called manually.
|
|
137
169
|
*
|
|
138
170
|
* What it does:
|
|
139
|
-
* -
|
|
140
|
-
* -
|
|
171
|
+
* - implicitly call {@link client.Client#init} if not done manually
|
|
172
|
+
* - start all created contexts. For that to happen, you will have to call `client.init`
|
|
173
|
+
* manually and instantiate the contexts between `client.init()` and `client.start()`
|
|
141
174
|
*
|
|
142
175
|
* @example
|
|
143
176
|
* import { Client } from '@soundworks/core/client.js'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../../src/client/Client.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../../src/client/Client.js"],"names":[],"mappings":";;;;;AAeA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH;IACE;;;OAGG;IACH,yCAmJC;IAjHC;;;;OAIG;IACH,kBAHS,MAAM,CAGO;IAEtB;;;;OAIG;IACH,MAFU,MAAM,CAEO;IAEvB;;;;OAIG;IACH,4BAAoB;IAYpB;;;;;;OAMG;IACH,IAFU,MAAM,CAEF;IAEd;;;;;OAKG;IACH,MAFU,MAAM,CAEA;IAEhB;;;;;;OAMG;IACH,sBAA0B;IAE1B;;;;OAIG;IACH,QAFU,MAAM,CAE8B;IAE9C;;;;;;;OAOG;IACH,sCAA0C;IAE1C;;;;;;;OAOG;IACH,oCAA4C;IAE5C;;;;;;;OAOG;IACH,kCAAsC;IAEtC;;;;OAIG;IACH,QAFU,MAAM,CAEI;IAEpB;;;OAGG;IACH,cAAiB;IAEjB,eAAe;IACf,iCAAyC;IACzC,eAAe;IACf,oBAAuB;IAKzB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,sBA8EC;IAED;;;;;;;;;;;;;;;OAeG;IACH,uBAmBC;IAED;;;;;;;;;;;;;;;OAeG;IACH,sBAUC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,iBAPa,2BAA2B,CAiBvC;IAED;;;;;OAKG;IACH,6CAIC;IAED,eAAe;IACf,wBAgBC;CACF"}
|
|
@@ -51,39 +51,66 @@ declare class Context {
|
|
|
51
51
|
constructor(client: client.Client);
|
|
52
52
|
/**
|
|
53
53
|
* The soundworks client instance.
|
|
54
|
+
* @type {client.Client}
|
|
55
|
+
* @readonly
|
|
54
56
|
*/
|
|
55
|
-
client: Client;
|
|
57
|
+
readonly client: client.Client;
|
|
56
58
|
/**
|
|
57
59
|
* Status of the context, i.e. 'idle', 'inited', 'started', 'errored'
|
|
60
|
+
* @type {string}
|
|
61
|
+
* @readonly
|
|
58
62
|
*/
|
|
59
|
-
status: string;
|
|
63
|
+
readonly status: string;
|
|
60
64
|
/**
|
|
61
|
-
*
|
|
65
|
+
* Optionnal user-defined name of the context (defaults to the class name).
|
|
62
66
|
*
|
|
63
|
-
*
|
|
67
|
+
* The context manager will match the client-side and server-side contexts based
|
|
68
|
+
* on this name. If the {@link server.ContextManager} don't find a corresponding
|
|
69
|
+
* user-defined context with the same name, it will use a default (noop) context.
|
|
70
|
+
*
|
|
71
|
+
* @readonly
|
|
72
|
+
* @type {string}
|
|
64
73
|
* @example
|
|
74
|
+
* // server-side and client-side contexts are matched based on their respective `name`
|
|
65
75
|
* class MyContext extends Context {
|
|
66
76
|
* get name() {
|
|
67
77
|
* return 'my-user-defined-context-name';
|
|
68
78
|
* }
|
|
69
79
|
* }
|
|
70
80
|
*/
|
|
71
|
-
get name(): string;
|
|
81
|
+
readonly get name(): string;
|
|
72
82
|
/**
|
|
73
|
-
* Start the context. This method is
|
|
74
|
-
*
|
|
75
|
-
*
|
|
83
|
+
* Start the context. This method is lazilly called when the client enters the
|
|
84
|
+
* context for the first time (cf. ${client.Context#enter}). If you know some
|
|
85
|
+
* some heavy and/or potentially long job has to be done when starting the context
|
|
86
|
+
* (e.g. call to a web service) it may be a good practice to call it explicitely.
|
|
87
|
+
*
|
|
88
|
+
* This method should be implemented to perform operations that are valid for the
|
|
89
|
+
* whole lifetime of the context, regardless the client enters or exits the context.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* import { Context } from '@soundworks/core/client.js';
|
|
93
|
+
*
|
|
94
|
+
* class MyContext extends Context {
|
|
95
|
+
* async start() {
|
|
96
|
+
* await super.start();
|
|
97
|
+
* await this.doSomeLongJob();
|
|
98
|
+
* }
|
|
99
|
+
* }
|
|
76
100
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
101
|
+
* // Instantiate the context
|
|
102
|
+
* const myContext = new Context(client);
|
|
103
|
+
* // manually start the context to perform the long operation before the client
|
|
104
|
+
* // enters the context.
|
|
105
|
+
* await myContext.start();
|
|
79
106
|
*/
|
|
80
107
|
start(): Promise<void>;
|
|
81
108
|
/**
|
|
82
109
|
* Stop the context. This method is automatically called when `await client.stop()`
|
|
83
|
-
* is called.
|
|
110
|
+
* is called. It should be used to cleanup context wise operations made in `start()`
|
|
111
|
+
* (e.g. destroy the reusable audio graph).
|
|
84
112
|
*
|
|
85
|
-
*
|
|
86
|
-
* wise behavior regardeless the client enters or exists the context.
|
|
113
|
+
* _WARNING: this method should never be called manually._
|
|
87
114
|
*/
|
|
88
115
|
stop(): Promise<void>;
|
|
89
116
|
/**
|
|
@@ -135,5 +162,4 @@ declare class Context {
|
|
|
135
162
|
*/
|
|
136
163
|
exit(): Promise<any>;
|
|
137
164
|
}
|
|
138
|
-
import Client from "./Client.js";
|
|
139
165
|
//# sourceMappingURL=Context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Context.d.ts","sourceRoot":"","sources":["../../src/client/Context.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Context.d.ts","sourceRoot":"","sources":["../../src/client/Context.js"],"names":[],"mappings":";AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH;IACE;;;OAGG;IACH,mCAoDC;IA/CC;;;;OAIG;IACH,+BAAoB;IAEpB;;;;OAIG;IACH,iBAHU,MAAM,CAGI;IAqCtB;;;;;;;;;;;;;;;;OAgBG;IACH,4BAEC;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,uBAAgB;IAEhB;;;;;;OAMG;IACH,sBAAe;IAEf;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,sBAeC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,qBAUC;CACF"}
|
package/types/client/Plugin.d.ts
CHANGED
|
@@ -3,51 +3,52 @@ export namespace client {
|
|
|
3
3
|
/**
|
|
4
4
|
* ~onStateChangeCallback
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
type Plugin = (#state: client.Plugin) => any;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Callback executed when the plugin state is updated.
|
|
10
|
+
*
|
|
11
|
+
* @callback client.Plugin~onStateChangeCallback
|
|
12
|
+
* @param {client.Plugin#state} state - Current state of the plugin.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Delete the registered {@link client.Plugin~onStateChangeCallback}.
|
|
16
|
+
*
|
|
17
|
+
* @callback client.Plugin~deleteOnStateChangeCallback
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Base class to extend in order to create the client-side counterpart of a
|
|
21
|
+
* `soundworks` plugin.
|
|
22
|
+
*
|
|
23
|
+
* In the `soundworks` paradigm, a plugin is a component that allows to extend
|
|
24
|
+
* the framework capabilities by encapsulating common and reusable logic in
|
|
25
|
+
* an application wise perspective. For example, plugins are available to handle
|
|
26
|
+
* clock synchronization, to deal with the file system, etc. Plugin should always
|
|
27
|
+
* have both a client-side and a server-side part.
|
|
28
|
+
*
|
|
29
|
+
* See [https://soundworks.dev/guide/ecosystem](https://soundworks.dev/guide/ecosystem)
|
|
30
|
+
* for more informations on the available plugins.
|
|
31
|
+
*
|
|
32
|
+
* _Creating new plugins should be considered an advanced usage._
|
|
33
|
+
*
|
|
34
|
+
* @memberof client
|
|
35
|
+
* @extends BasePlugin
|
|
36
|
+
* @inheritdoc
|
|
37
|
+
*/
|
|
38
|
+
declare class Plugin extends BasePlugin {
|
|
13
39
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
40
|
+
* @param {client.Client} client - The soundworks client instance.
|
|
41
|
+
* @param {string} id - User defined id of the plugin as defined in
|
|
42
|
+
* {@link client.PluginManager#register}.
|
|
17
43
|
*/
|
|
44
|
+
constructor(client: client.Client, id: string);
|
|
18
45
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* In the `soundworks` paradigm, a plugin is a component that allows to extend
|
|
22
|
-
* the framework capabilities by encapsulating common and reusable logic in
|
|
23
|
-
* an application wise perspective. For example, plugins are available to handle
|
|
24
|
-
* clock synchronization, to deal with the file system, etc. Plugin should always
|
|
25
|
-
* have both a client-side and a server-side part.
|
|
26
|
-
*
|
|
27
|
-
* See [https://soundworks.dev/guide/ecosystem](https://soundworks.dev/guide/ecosystem)
|
|
28
|
-
* for more informations on the available plugins.
|
|
29
|
-
*
|
|
30
|
-
* _Creating new plugins should be considered an advanced usage._
|
|
46
|
+
* Instance of soundworks client.
|
|
31
47
|
*
|
|
32
|
-
* @
|
|
33
|
-
* @
|
|
34
|
-
* @inheritdoc
|
|
48
|
+
* @type {client.Client}
|
|
49
|
+
* @see {@link client.Client}
|
|
35
50
|
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @param {client.Client} client - The soundworks client instance.
|
|
39
|
-
* @param {string} id - User defined id of the plugin as defined in
|
|
40
|
-
* {@link client.PluginManager#register}.
|
|
41
|
-
*/
|
|
42
|
-
constructor(client: client.Client, id: string);
|
|
43
|
-
/**
|
|
44
|
-
* Instance of soundworks client.
|
|
45
|
-
*
|
|
46
|
-
* @type {client.Client}
|
|
47
|
-
* @see {@link client.Client}
|
|
48
|
-
*/
|
|
49
|
-
client: client.Client;
|
|
50
|
-
}
|
|
51
|
+
client: client.Client;
|
|
51
52
|
}
|
|
52
|
-
import BasePlugin from
|
|
53
|
+
import BasePlugin from '../common/BasePlugin.js';
|
|
53
54
|
//# sourceMappingURL=Plugin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Plugin.d.ts","sourceRoot":"","sources":["../../src/client/Plugin.js"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"Plugin.d.ts","sourceRoot":"","sources":["../../src/client/Plugin.js"],"names":[],"mappings":";;;;;2BAMW,aAAa;;AAJxB;;;;;GAKG;AAEH;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH;IACE;;;;OAIG;IACH,uCAHW,MAAM,EAahB;IAPC;;;;;OAKG;IACH,sBAAoB;CAevB;uBAhEsB,yBAAyB"}
|