@soundworks/core 5.5.0 → 5.7.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/CHANGELOG.md +13 -0
- package/README.md +6 -0
- package/package.json +17 -11
- package/src/client/Client.js +7 -4
- package/src/client/ClientSocket.js +2 -3
- package/src/common/BasePlugin.js +2 -2
- package/src/common/BasePluginManager.js +2 -2
- package/src/common/BaseStateManager.js +253 -221
- package/src/common/ParameterBag.js +14 -14
- package/src/common/SharedState.js +405 -247
- package/src/common/SharedStateCollection.js +82 -32
- 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/shared-state-utils.js +102 -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 +242 -227
- package/src/server/SharedStatePrivate.js +105 -68
- 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/ClientSocket.d.ts.map +1 -1
- package/types/common/BaseStateManager.d.ts +34 -47
- package/types/common/BaseStateManager.d.ts.map +1 -1
- package/types/common/ParameterBag.d.ts +28 -6
- package/types/common/ParameterBag.d.ts.map +1 -1
- package/types/common/SharedState.d.ts +55 -29
- package/types/common/SharedState.d.ts.map +1 -1
- package/types/common/SharedStateCollection.d.ts +26 -8
- 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-utils.d.ts +12 -0
- package/types/common/shared-state-utils.d.ts.map +1 -0
- package/types/common/version.d.ts +1 -1
- package/types/server/Server.d.ts.map +1 -1
- package/types/server/ServerClient.d.ts.map +1 -1
- package/types/server/ServerStateManager.d.ts +10 -10
- package/types/server/ServerStateManager.d.ts.map +1 -1
- package/types/server/SharedStatePrivate.d.ts +2 -3
- 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.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
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
UPDATE_RESPONSE,
|
|
10
10
|
UPDATE_ABORT,
|
|
11
11
|
UPDATE_NOTIFICATION,
|
|
12
|
+
HAS_SIBLINGS_NOTIFICATION,
|
|
12
13
|
} from '../common/constants.js';
|
|
13
14
|
import {
|
|
14
15
|
kServerStateManagerDeletePrivateState,
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
* @private
|
|
24
25
|
*/
|
|
25
26
|
function whiteListFilterUpdates(updates, whiteList) {
|
|
26
|
-
if (whiteList
|
|
27
|
+
if (!Array.isArray(whiteList)) {
|
|
27
28
|
return updates;
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -43,7 +44,7 @@ function whiteListFilterUpdates(updates, whiteList) {
|
|
|
43
44
|
* @private
|
|
44
45
|
*/
|
|
45
46
|
function blackListFilterUpdates(updates, blackList) {
|
|
46
|
-
if (blackList
|
|
47
|
+
if (!Array.isArray(blackList)) {
|
|
47
48
|
return updates;
|
|
48
49
|
}
|
|
49
50
|
// create a shallow copy so we can have multiple filters applied on same source
|
|
@@ -58,6 +59,22 @@ function blackListFilterUpdates(updates, blackList) {
|
|
|
58
59
|
return filtered;
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
function applyFilters(updates, options) {
|
|
63
|
+
if (options === null) {
|
|
64
|
+
return updates;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const { whiteList, blackList } = options;
|
|
68
|
+
// precedence to white list
|
|
69
|
+
if (Array.isArray(whiteList)) {
|
|
70
|
+
updates = whiteListFilterUpdates(updates, whiteList);
|
|
71
|
+
} else if (Array.isArray(blackList)) {
|
|
72
|
+
updates = blackListFilterUpdates(updates, blackList);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return updates;
|
|
76
|
+
}
|
|
77
|
+
|
|
61
78
|
export const kSharedStatePrivateAttachClient = Symbol('soundworks:shared-state-private-attach-client');
|
|
62
79
|
export const kSharedStatePrivateDetachClient = Symbol('soundworks:shared-state-private-detach-client');
|
|
63
80
|
export const kSharedStatePrivateGetValues = Symbol('soundworks:shared-state-private-get-values');
|
|
@@ -73,8 +90,7 @@ class SharedStatePrivate {
|
|
|
73
90
|
#className = null;
|
|
74
91
|
#manager = null;
|
|
75
92
|
#parameters = null;
|
|
76
|
-
#
|
|
77
|
-
#creatorInstanceId = null;
|
|
93
|
+
#ownerId = null;
|
|
78
94
|
#attachedClients = new Map();
|
|
79
95
|
|
|
80
96
|
constructor(manager, className, classDefinition, id, initValues = {}) {
|
|
@@ -93,12 +109,8 @@ class SharedStatePrivate {
|
|
|
93
109
|
return this.#className;
|
|
94
110
|
}
|
|
95
111
|
|
|
96
|
-
get
|
|
97
|
-
return this.#
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
get creatorInstanceId() {
|
|
101
|
-
return this.#creatorInstanceId;
|
|
112
|
+
get ownerId() {
|
|
113
|
+
return this.#ownerId;
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
get attachedClients() {
|
|
@@ -113,21 +125,53 @@ class SharedStatePrivate {
|
|
|
113
125
|
return this.#parameters.getValues();
|
|
114
126
|
}
|
|
115
127
|
|
|
116
|
-
[kSharedStatePrivateAttachClient](instanceId, client, isOwner,
|
|
117
|
-
|
|
128
|
+
[kSharedStatePrivateAttachClient](instanceId, client, isOwner, options) {
|
|
129
|
+
if (isOwner) {
|
|
130
|
+
this.#ownerId = client.id;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const clientInfos = { client, isOwner, options };
|
|
118
134
|
this.#attachedClients.set(instanceId, clientInfos);
|
|
119
135
|
|
|
136
|
+
client.transport.addListener(`${UPDATE_REQUEST}-${this.id}-${instanceId}`, this.#onUpdateRequest(instanceId, client));
|
|
137
|
+
|
|
120
138
|
if (isOwner) {
|
|
121
|
-
|
|
122
|
-
|
|
139
|
+
client.transport.addListener(`${DELETE_REQUEST}-${this.id}-${instanceId}`, this.#onDeleteRequest);
|
|
140
|
+
} else {
|
|
141
|
+
client.transport.addListener(`${DETACH_REQUEST}-${this.id}-${instanceId}`, this.#onDetachRequest(instanceId, client));
|
|
142
|
+
this.#updateHasSiblings();
|
|
123
143
|
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
[kSharedStatePrivateDetachClient](instanceId, client) {
|
|
147
|
+
this.#attachedClients.delete(instanceId);
|
|
148
|
+
|
|
149
|
+
client.transport.removeAllListeners(`${UPDATE_REQUEST}-${this.id}-${instanceId}`);
|
|
150
|
+
client.transport.removeAllListeners(`${DELETE_REQUEST}-${this.id}-${instanceId}`);
|
|
151
|
+
client.transport.removeAllListeners(`${DETACH_REQUEST}-${this.id}-${instanceId}`);
|
|
152
|
+
|
|
153
|
+
this.#updateHasSiblings();
|
|
154
|
+
}
|
|
124
155
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Update hasSiblings property on owner
|
|
158
|
+
*/
|
|
159
|
+
#updateHasSiblings() {
|
|
160
|
+
for (let [instanceId, clientInfos] of this.attachedClients) {
|
|
161
|
+
const { client, isOwner } = clientInfos;
|
|
162
|
+
|
|
163
|
+
if (isOwner) {
|
|
164
|
+
const hasSiblings = this.attachedClients.size > 1;
|
|
165
|
+
client.transport.emit(`${HAS_SIBLINGS_NOTIFICATION}-${this.id}-${instanceId}`, hasSiblings);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#onUpdateRequest = (instanceId, client) => {
|
|
171
|
+
return async (reqId, updates) => {
|
|
128
172
|
const hooks = this.#manager[kServerStateManagerGetUpdateHooks](this.className);
|
|
129
173
|
const values = this.#parameters.getValues();
|
|
130
|
-
//
|
|
174
|
+
// Do not propagate back to the requester, params that are marked as `acknowledge=false`
|
|
131
175
|
const acknowledgeFilter = this.#parameters.getParamListByDescriptor('acknowledge', false);
|
|
132
176
|
|
|
133
177
|
let hookAborted = false;
|
|
@@ -185,8 +229,9 @@ class SharedStatePrivate {
|
|
|
185
229
|
//
|
|
186
230
|
// @note - instanceId correspond to unique remote state id
|
|
187
231
|
|
|
188
|
-
//
|
|
189
|
-
//
|
|
232
|
+
// Apply acknowledge filter on `acknowledgedUpdates`
|
|
233
|
+
// Note that, We don't need to apply the whiteList / blackList filters
|
|
234
|
+
// for the requester, as they are blocked early on client-side
|
|
190
235
|
const requesterFilteredUpdates = blackListFilterUpdates(acknowledgedUpdates, acknowledgeFilter);
|
|
191
236
|
|
|
192
237
|
// propagate RESPONSE to the client that originates the request if not the server
|
|
@@ -203,11 +248,12 @@ class SharedStatePrivate {
|
|
|
203
248
|
|
|
204
249
|
// propagate NOTIFICATION to all peer states except on server-side
|
|
205
250
|
for (let [peerInstanceId, clientInfos] of this.#attachedClients) {
|
|
206
|
-
const { client: peer,
|
|
251
|
+
const { client: peer, options } = clientInfos;
|
|
207
252
|
|
|
208
253
|
if (instanceId !== peerInstanceId && peer.id !== -1) {
|
|
209
|
-
const filteredUpdates =
|
|
210
|
-
|
|
254
|
+
const filteredUpdates = applyFilters(acknowledgedUpdates, options);
|
|
255
|
+
|
|
256
|
+
// propagate only if there something left after applying the whiteList/blackList filters
|
|
211
257
|
if (Object.keys(filteredUpdates).length > 0) {
|
|
212
258
|
peer.transport.emit(
|
|
213
259
|
`${UPDATE_NOTIFICATION}-${this.id}-${peerInstanceId}`,
|
|
@@ -231,11 +277,12 @@ class SharedStatePrivate {
|
|
|
231
277
|
|
|
232
278
|
// propagate NOTIFICATION to all peer states on the server-side
|
|
233
279
|
for (let [peerInstanceId, clientInfos] of this.#attachedClients) {
|
|
234
|
-
const { client: peer,
|
|
280
|
+
const { client: peer, options } = clientInfos;
|
|
235
281
|
|
|
236
282
|
if (instanceId !== peerInstanceId && peer.id === -1) {
|
|
237
|
-
const filteredUpdates =
|
|
238
|
-
|
|
283
|
+
const filteredUpdates = applyFilters(acknowledgedUpdates, options);
|
|
284
|
+
|
|
285
|
+
// propagate only if there something left after applying the whiteList/blackList filters
|
|
239
286
|
if (Object.keys(filteredUpdates).length > 0) {
|
|
240
287
|
peer.transport.emit(
|
|
241
288
|
`${UPDATE_NOTIFICATION}-${this.id}-${peerInstanceId}`,
|
|
@@ -253,9 +300,9 @@ class SharedStatePrivate {
|
|
|
253
300
|
client.transport.emit(`${UPDATE_ABORT}-${this.id}-${instanceId}`, reqId, requesterFilteredUpdates);
|
|
254
301
|
}
|
|
255
302
|
}
|
|
256
|
-
} else {
|
|
257
|
-
//
|
|
258
|
-
//
|
|
303
|
+
} else { // hookAborted === true
|
|
304
|
+
// when explicitly aborted by a hook (return `null`), we only send
|
|
305
|
+
// back the current values to the requester
|
|
259
306
|
const currentValues = {};
|
|
260
307
|
|
|
261
308
|
for (let name in updates) {
|
|
@@ -267,46 +314,36 @@ class SharedStatePrivate {
|
|
|
267
314
|
client.transport.emit(`${UPDATE_ABORT}-${this.id}-${instanceId}`, reqId, requesterFilteredUpdates);
|
|
268
315
|
}
|
|
269
316
|
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
});
|
|
294
|
-
} else {
|
|
295
|
-
// detach only if not creator
|
|
296
|
-
client.transport.addListener(`${DETACH_REQUEST}-${this.id}-${instanceId}`, (reqId) => {
|
|
297
|
-
this[kSharedStatePrivateDetachClient](instanceId, client);
|
|
298
|
-
client.transport.emit(`${DETACH_RESPONSE}-${this.id}-${instanceId}`, reqId);
|
|
299
|
-
});
|
|
317
|
+
};
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
#onDeleteRequest = async reqId => {
|
|
321
|
+
// make sure hooks have been called when `delete()` fulfills
|
|
322
|
+
await this.#manager[kServerStateManagerDeletePrivateState](this);
|
|
323
|
+
// --------------------------------------------------------------------
|
|
324
|
+
// WARNING - MAKE SURE WE DON'T HAVE PROBLEM W/ THAT
|
|
325
|
+
// --------------------------------------------------------------------
|
|
326
|
+
// @todo - propagate server-side last, because if a subscription function sends a
|
|
327
|
+
// message to a client, network messages order are kept coherent
|
|
328
|
+
// this._subscriptions.forEach(func => func(updated));
|
|
329
|
+
for (let [instanceId, clientInfos] of this.#attachedClients) {
|
|
330
|
+
const { client, isOwner } = clientInfos;
|
|
331
|
+
this[kSharedStatePrivateDetachClient](instanceId, client);
|
|
332
|
+
|
|
333
|
+
if (isOwner) {
|
|
334
|
+
client.transport.emit(`${DELETE_RESPONSE}-${this.id}-${instanceId}`, reqId);
|
|
335
|
+
} else {
|
|
336
|
+
client.transport.emit(`${DELETE_NOTIFICATION}-${this.id}-${instanceId}`);
|
|
337
|
+
}
|
|
300
338
|
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
#onDetachRequest = (instanceId, client) => {
|
|
342
|
+
return reqId => {
|
|
343
|
+
this[kSharedStatePrivateDetachClient](instanceId, client);
|
|
344
|
+
client.transport.emit(`${DETACH_RESPONSE}-${this.id}-${instanceId}`, reqId);
|
|
345
|
+
};
|
|
346
|
+
};
|
|
310
347
|
}
|
|
311
348
|
|
|
312
349
|
export default SharedStatePrivate;
|
|
@@ -1,32 +1,26 @@
|
|
|
1
|
-
import http from 'node:http';
|
|
2
|
-
import https from 'node:https';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
1
|
import {
|
|
5
2
|
X509Certificate,
|
|
6
3
|
createPrivateKey,
|
|
7
4
|
} from 'node:crypto';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import http from 'node:http';
|
|
7
|
+
import https from 'node:https';
|
|
8
|
+
import os from 'node:os';
|
|
9
|
+
import {
|
|
10
|
+
styleText,
|
|
11
|
+
} from 'node:util';
|
|
8
12
|
|
|
9
|
-
import
|
|
10
|
-
import equal from 'fast-deep-equal';
|
|
11
|
-
|
|
12
|
-
import logger from '../common/logger.js';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @private
|
|
16
|
-
* @return {HttpServer|HttpsServer}
|
|
17
|
-
*/
|
|
18
|
-
export async function createHttpServer(server) {
|
|
19
|
-
const serverConfig = server.config;
|
|
20
|
-
|
|
21
|
-
if (serverConfig.env.useHttps !== true) {
|
|
22
|
-
return http.createServer();
|
|
23
|
-
}
|
|
13
|
+
import selfsigned from 'selfsigned';
|
|
24
14
|
|
|
15
|
+
async function createHttpsServer(server) {
|
|
25
16
|
// https is more tricky
|
|
26
|
-
const httpsInfos =
|
|
17
|
+
const httpsInfos = server.config.env.httpsInfos;
|
|
27
18
|
let useSelfSigned = false;
|
|
28
19
|
|
|
29
|
-
if (!httpsInfos
|
|
20
|
+
if (!httpsInfos
|
|
21
|
+
|| !fs.existsSync(httpsInfos.cert)
|
|
22
|
+
|| !fs.existsSync(httpsInfos.key)
|
|
23
|
+
) {
|
|
30
24
|
useSelfSigned = true;
|
|
31
25
|
}
|
|
32
26
|
|
|
@@ -77,7 +71,7 @@ export async function createHttpServer(server) {
|
|
|
77
71
|
|
|
78
72
|
httpsServer = https.createServer({ key, cert });
|
|
79
73
|
} catch (err) {
|
|
80
|
-
|
|
74
|
+
console.error(`
|
|
81
75
|
Invalid certificate files, please check your:
|
|
82
76
|
- key file: ${httpsInfos.key}
|
|
83
77
|
- cert file: ${httpsInfos.cert}
|
|
@@ -86,33 +80,23 @@ Invalid certificate files, please check your:
|
|
|
86
80
|
throw err;
|
|
87
81
|
}
|
|
88
82
|
} else {
|
|
83
|
+
|
|
89
84
|
// generate self signed certs or reused already existing ones
|
|
90
85
|
let cert = await server.db.get('httpsCert');
|
|
91
86
|
let key = await server.db.get('httpsKey');
|
|
92
87
|
|
|
93
88
|
if (!cert || !key) {
|
|
94
89
|
try {
|
|
95
|
-
const result = await
|
|
96
|
-
pem.createCertificate({ days: 1, selfSigned: true }, async (err, keys) => {
|
|
97
|
-
if (err) {
|
|
98
|
-
reject(err);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
resolve({
|
|
103
|
-
cert: keys.certificate,
|
|
104
|
-
key: keys.serviceKey,
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
});
|
|
90
|
+
const result = await selfsigned.generate(null);
|
|
108
91
|
|
|
109
92
|
cert = result.cert;
|
|
110
|
-
key = result.
|
|
93
|
+
key = result.private;
|
|
94
|
+
|
|
111
95
|
// store the generated certs to reuse on next start
|
|
112
|
-
await server.db.set('httpsCert', cert);
|
|
113
|
-
await server.db.set('httpsKey', key);
|
|
96
|
+
await server.db.set('httpsCert', cert); // -----BEGIN CERTIFICATE-----
|
|
97
|
+
await server.db.set('httpsKey', key); // -----BEGIN RSA PRIVATE KEY-----
|
|
114
98
|
} catch (err) {
|
|
115
|
-
|
|
99
|
+
console.error(err.stack);
|
|
116
100
|
throw err;
|
|
117
101
|
}
|
|
118
102
|
}
|
|
@@ -121,7 +105,65 @@ Invalid certificate files, please check your:
|
|
|
121
105
|
httpsServer = https.createServer({ cert, key });
|
|
122
106
|
}
|
|
123
107
|
|
|
124
|
-
|
|
108
|
+
// Log certificate information, just be verbose
|
|
109
|
+
console.log(styleText('cyan', `https certificates infos`));
|
|
110
|
+
|
|
111
|
+
if (httpsCertsInfos.selfSigned) {
|
|
112
|
+
console.warn(styleText('yellow', ` -------------------------------------------`));
|
|
113
|
+
console.warn(styleText('yellow', ` > USING SELF-SIGNED CERTIFICATE. `));
|
|
114
|
+
console.warn(styleText('yellow', ` users will face a unsafe web page warning `));
|
|
115
|
+
console.warn(styleText('yellow', ` -------------------------------------------`));
|
|
116
|
+
} else {
|
|
117
|
+
console.log(` valid from: ${httpsCertsInfos.validFrom}`);
|
|
118
|
+
console.log(` valid to: ${httpsCertsInfos.validTo}`);
|
|
119
|
+
|
|
120
|
+
if (!httpsCertsInfos.isValid) {
|
|
121
|
+
console.error(styleText('red', ` -------------------------------------------`));
|
|
122
|
+
console.error(styleText('red', ` > INVALID CERTIFICATE `));
|
|
123
|
+
console.error(styleText('red', ` i.e. you pretend to be safe but you are not`));
|
|
124
|
+
console.error(styleText('red', ` -------------------------------------------`));
|
|
125
|
+
} else {
|
|
126
|
+
if (httpsCertsInfos.daysRemaining < 5) {
|
|
127
|
+
console.log(styleText('red', ` > CERTIFICATE IS VALID... BUT ONLY ${httpsCertsInfos.daysRemaining} DAYS LEFT, PLEASE CONSIDER UPDATING YOUR CERTS!`));
|
|
128
|
+
} else if (httpsCertsInfos.daysRemaining < 15) {
|
|
129
|
+
console.log(styleText('yellow', ` > CERTIFICATE IS VALID - only ${httpsCertsInfos.daysRemaining} days left, be careful...`));
|
|
130
|
+
} else {
|
|
131
|
+
console.log(styleText('green', ` > CERTIFICATE IS VALID (${httpsCertsInfos.daysRemaining} days left)`));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
125
135
|
|
|
126
136
|
return httpsServer;
|
|
127
137
|
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @private
|
|
141
|
+
* @return {HttpServer|HttpsServer}
|
|
142
|
+
*/
|
|
143
|
+
export async function createHttpServer(server) {
|
|
144
|
+
const serverConfig = server.config;
|
|
145
|
+
|
|
146
|
+
const httpServer = serverConfig.env.useHttps !== true
|
|
147
|
+
? http.createServer()
|
|
148
|
+
: await createHttpsServer(server);
|
|
149
|
+
|
|
150
|
+
return httpServer;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function logServerInfos(envConfig) {
|
|
154
|
+
const protocol = envConfig.useHttps ? 'https' : 'http';
|
|
155
|
+
const port = envConfig.port;
|
|
156
|
+
const interfaces = os.networkInterfaces();
|
|
157
|
+
|
|
158
|
+
console.log(styleText('cyan', `${protocol} server listening on`));
|
|
159
|
+
|
|
160
|
+
Object.keys(interfaces).forEach(dev => {
|
|
161
|
+
interfaces[dev].forEach(details => {
|
|
162
|
+
if (details.family === 'IPv4') {
|
|
163
|
+
console.log(` ${protocol}://${details.address}:${styleText('green', `${port}`)}`);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
console.log(`\n> press "${styleText('bold', 'Ctrl + C')}" to exit`);
|
|
169
|
+
}
|
package/src/server/crypto.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
3
2
|
|
|
4
3
|
// adapted from https://dev.to/jobizil/encrypt-and-decrypt-data-in-nodejs-using-aes-256-cbc-2l6d
|
|
5
4
|
// generate a new key and init vector each time the server restart, we don't need
|
|
6
5
|
// any persistency here
|
|
7
|
-
const secretKey =
|
|
8
|
-
const secretIv =
|
|
6
|
+
const secretKey = crypto.randomUUID();
|
|
7
|
+
const secretIv = crypto.randomUUID();
|
|
9
8
|
const encryptionMethod = 'aes-256-cbc';
|
|
10
9
|
|
|
11
10
|
const key = crypto
|
|
@@ -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":"AAgCA,+CAA2E;AAC3E,2DAAqG;;AAErG;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;IAeE;;;OAGG;IACH,oBAHW,YAAY,EA+DtB;IAED;;;;OAIG;IACH,eAFU,MAAM,CAIf;IAED;;;;OAIG;IACH,YAFU,MAAM,CAIf;IAED;;;;OAIG;IACH,cAFU,YAAY,CAIrB;IAED;;;;;;;OAOG;IACH,UAFU,MAAM,CAIf;IAED;;;;;OAKG;IACH,YAFU,MAAM,CAIf;IAED;;;;;;;OAOG;IACH,aAFU,MAAM,CAIf;IAED;;;;OAIG;IACH,eAFU,MAAM,GAAC,SAAS,CAIzB;IAED;;OAEG;IACH,iCAGC;IAED;;;;;OAKG;IACH,cAFU,YAAY,CAIrB;IAED;;;;;;;OAOG;IACH,sBAFU,oBAAoB,CAI7B;IAED;;;;;;;OAOG;IACH,8CAEC;IAED;;;;;;;OAOG;IACH,oBAFU,kBAAkB,CAI3B;IAED;;;;OAIG;IACH,cAFU,MAAM,GAAC,QAAQ,GAAC,SAAS,GAAC,SAAS,CAI5C;IAqBD;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,sBA0DC;IAED;;;;;;;;;;;;;;;OAeG;IACH,uBAgBC;IAED;;;;;;;;;;;;;;;OAeG;IACH,sBAcC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,iBAPa,OAAO,CAAC,WAAW,CAAC,CAiBhC;IAED;;;;;OAKG;IACH,6CAGC;IA3VC,2CAAgD;;CA4VnD;yBAtdM,mBAAmB;iCARnB,2BAA2B;gCACF,0BAA0B;+BAQ3B,yBAAyB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientSocket.d.ts","sourceRoot":"","sources":["../../src/client/ClientSocket.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ClientSocket.d.ts","sourceRoot":"","sources":["../../src/client/ClientSocket.js"],"names":[],"mappings":"AAYA,6CAAsE;;AAEtE;;;;;;;;;;;;;;;;;;;GAmBG;AACH;IAOE,wDAIC;IAED;;;;;;;OAOG;IACH,aA4HC;IAoCD;;;;;;OAMG;IACH,cAJW,MAAM,WACH,GAAC,EAAA,QAQd;IAED;;;;;;;OAOG;IACH,qBALW,MAAM,4BAYhB;IAED;;;;;OAKG;IACH,wBAHW,MAAM,4BAYhB;IAED;;;;OAIG;IACH,6BAFW,MAAM,QAQhB;IAED;;OAEG;IACH,cAEC;IApGD;;;;;;;;;OASG;IACH,2BAWC;;CAgFF"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const kStateManagerInit: unique symbol;
|
|
2
2
|
export const kStateManagerDeleteState: unique symbol;
|
|
3
|
+
export const kPendingSharedStateConstructionData: unique symbol;
|
|
3
4
|
export const kStateManagerClient: unique symbol;
|
|
4
5
|
export default BaseStateManager;
|
|
5
6
|
/**
|
|
@@ -46,10 +47,6 @@ declare class BaseStateManager {
|
|
|
46
47
|
* const classDescription = await client.stateManager.getClassDescription('my-class');
|
|
47
48
|
*/
|
|
48
49
|
getClassDescription(className: SharedStateClassName): SharedStateClassDescription;
|
|
49
|
-
/**
|
|
50
|
-
* @deprecated Use {@link BaseStateManager#getClassDescription} instead.
|
|
51
|
-
*/
|
|
52
|
-
getSchema(className: any): Promise<any>;
|
|
53
50
|
/**
|
|
54
51
|
* Create a {@link SharedState} instance from a registered class.
|
|
55
52
|
*
|
|
@@ -90,26 +87,36 @@ declare class BaseStateManager {
|
|
|
90
87
|
*
|
|
91
88
|
* @overload
|
|
92
89
|
* @param {SharedStateClassName} className - Name of the class.
|
|
93
|
-
* @param {
|
|
90
|
+
* @param {Object} [options={}]
|
|
91
|
+
* @param {string[]} [options.whiteList] - White list of parameter names to track (as precedence over `blackList`).
|
|
92
|
+
* @param {string[]} [options.blackList] - Black list of parameter names to ignore.
|
|
94
93
|
* @returns {Promise<SharedState>}
|
|
95
94
|
*
|
|
96
95
|
* @example
|
|
97
96
|
* const state = await client.stateManager.attach('my-class', ['some-param']);
|
|
98
97
|
*/
|
|
99
|
-
attach(className: SharedStateClassName,
|
|
98
|
+
attach(className: SharedStateClassName, options?: {
|
|
99
|
+
whiteList?: string[] | undefined;
|
|
100
|
+
blackList?: string[] | undefined;
|
|
101
|
+
} | undefined): Promise<SharedState>;
|
|
100
102
|
/**
|
|
101
103
|
* Attach to an existing {@link SharedState} instance.
|
|
102
104
|
*
|
|
103
105
|
* @overload
|
|
104
106
|
* @param {SharedStateClassName} className - Name of the class.
|
|
105
107
|
* @param {number} stateId - Id of the state
|
|
106
|
-
* @param {
|
|
108
|
+
* @param {object} [options={}]
|
|
109
|
+
* @param {string[]} [options.whiteList] - White list of parameter names to track (as precedence over `blackList`).
|
|
110
|
+
* @param {string[]} [options.blackList] - Black list of parameter names to ignore.
|
|
107
111
|
* @returns {Promise<SharedState>}
|
|
108
112
|
*
|
|
109
113
|
* @example
|
|
110
114
|
* const state = await client.stateManager.attach('my-class', stateId, ['some-param']);
|
|
111
115
|
*/
|
|
112
|
-
attach(className: SharedStateClassName, stateId: number,
|
|
116
|
+
attach(className: SharedStateClassName, stateId: number, options?: {
|
|
117
|
+
whiteList?: string[] | undefined;
|
|
118
|
+
blackList?: string[] | undefined;
|
|
119
|
+
} | undefined): Promise<SharedState>;
|
|
113
120
|
/**
|
|
114
121
|
* Observe all the {@link SharedState} instances that are created on the network.
|
|
115
122
|
*
|
|
@@ -147,7 +154,7 @@ declare class BaseStateManager {
|
|
|
147
154
|
* @param {stateManagerObserveCallback} callback - Function to execute when a
|
|
148
155
|
* new {@link SharedState} is created on the network.
|
|
149
156
|
* @param {object} options - Options.
|
|
150
|
-
* @param {boolean} options.excludeLocal=false - If set to true, exclude states
|
|
157
|
+
* @param {boolean} [options.excludeLocal=false] - If set to true, exclude states
|
|
151
158
|
* created by the same node from the collection.
|
|
152
159
|
* @example
|
|
153
160
|
* client.stateManager.observe(async (className, stateId) => {
|
|
@@ -157,7 +164,7 @@ declare class BaseStateManager {
|
|
|
157
164
|
* }, { excludeLocal: true });
|
|
158
165
|
*/
|
|
159
166
|
observe(callback: stateManagerObserveCallback, options: {
|
|
160
|
-
excludeLocal
|
|
167
|
+
excludeLocal?: boolean | undefined;
|
|
161
168
|
}): any;
|
|
162
169
|
/**
|
|
163
170
|
* Observe all the {@link SharedState} instances of given {@link SharedStateClassName}
|
|
@@ -169,7 +176,7 @@ declare class BaseStateManager {
|
|
|
169
176
|
* @param {stateManagerObserveCallback} callback - Function to execute when a
|
|
170
177
|
* new {@link SharedState} is created on the network.
|
|
171
178
|
* @param {object} options - Options.
|
|
172
|
-
* @param {boolean} options.excludeLocal=false - If set to true, exclude states
|
|
179
|
+
* @param {boolean} [options.excludeLocal=false] - If set to true, exclude states
|
|
173
180
|
* created by the same node from the collection.
|
|
174
181
|
* @example
|
|
175
182
|
* client.stateManager.observe('my-shared-state-class', async (className, stateId) => {
|
|
@@ -177,7 +184,7 @@ declare class BaseStateManager {
|
|
|
177
184
|
* }, { excludeLocal: true });
|
|
178
185
|
*/
|
|
179
186
|
observe(className: SharedStateClassName, callback: stateManagerObserveCallback, options: {
|
|
180
|
-
excludeLocal
|
|
187
|
+
excludeLocal?: boolean | undefined;
|
|
181
188
|
}): any;
|
|
182
189
|
/**
|
|
183
190
|
* Returns a collection of all the states created from a given shared state class.
|
|
@@ -195,48 +202,28 @@ declare class BaseStateManager {
|
|
|
195
202
|
*
|
|
196
203
|
* @overload
|
|
197
204
|
* @param {SharedStateClassName} className - Name of the shared state class.
|
|
198
|
-
* @param {
|
|
199
|
-
*
|
|
200
|
-
* @returns {Promise<SharedStateCollection>}
|
|
201
|
-
*
|
|
202
|
-
* @example
|
|
203
|
-
* const collection = await client.stateManager.getCollection(className, ['my-param']);
|
|
204
|
-
*/
|
|
205
|
-
getCollection(className: SharedStateClassName, filter: SharedStateParameterName[]): Promise<SharedStateCollection>;
|
|
206
|
-
/**
|
|
207
|
-
* Returns a collection of all the states created from a given shared state class.
|
|
208
|
-
*
|
|
209
|
-
* @overload
|
|
210
|
-
* @param {SharedStateClassName} className - Name of the shared state class.
|
|
211
|
-
* @param {object} options - Options.
|
|
212
|
-
* @param {boolean} options.excludeLocal=false - If set to true, exclude states
|
|
205
|
+
* @param {object} [options={}] - Options.
|
|
206
|
+
* @param {boolean} [options.excludeLocal=false] - If set to true, exclude states
|
|
213
207
|
* created by the same node from the collection.
|
|
208
|
+
* @param {string[]} [options.whiteList] - White list of parameter names to track (as precedence over `blackList`).
|
|
209
|
+
* @param {string[]} [options.blackList] - Black list of parameter names to ignore.
|
|
214
210
|
* @returns {Promise<SharedStateCollection>}
|
|
215
211
|
*
|
|
216
212
|
* @example
|
|
217
|
-
* const collection = await client.stateManager.getCollection(className, {
|
|
213
|
+
* const collection = await client.stateManager.getCollection(className, {
|
|
214
|
+
* blackList: ['my-param'],
|
|
215
|
+
* excludeLocal: true,
|
|
216
|
+
* });
|
|
218
217
|
*/
|
|
219
|
-
getCollection(className: SharedStateClassName, options
|
|
220
|
-
excludeLocal
|
|
221
|
-
|
|
218
|
+
getCollection(className: SharedStateClassName, options?: {
|
|
219
|
+
excludeLocal?: boolean | undefined;
|
|
220
|
+
whiteList?: string[] | undefined;
|
|
221
|
+
blackList?: string[] | undefined;
|
|
222
|
+
} | undefined): Promise<SharedStateCollection>;
|
|
222
223
|
/**
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* @overload
|
|
226
|
-
* @param {SharedStateClassName} className - Name of the shared state class.
|
|
227
|
-
* @param {SharedStateParameterName[]} filter - Filter parameter of interest for each
|
|
228
|
-
* state of the collection.
|
|
229
|
-
* @param {object} options - Options.
|
|
230
|
-
* @param {boolean} options.excludeLocal=false - If set to true, exclude states
|
|
231
|
-
* created by the same node from the collection.
|
|
232
|
-
* @returns {Promise<SharedStateCollection>}
|
|
233
|
-
*
|
|
234
|
-
* @example
|
|
235
|
-
* const collection = await client.stateManager.getCollection(className, ['my-param'], { excludeLocal: true });
|
|
224
|
+
* @deprecated Use {@link BaseStateManager#getClassDescription} instead.
|
|
236
225
|
*/
|
|
237
|
-
|
|
238
|
-
excludeLocal: boolean;
|
|
239
|
-
}): Promise<SharedStateCollection>;
|
|
226
|
+
getSchema(className: any): Promise<any>;
|
|
240
227
|
/** @private */
|
|
241
228
|
private [kStateManagerDeleteState];
|
|
242
229
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseStateManager.d.ts","sourceRoot":"","sources":["../../src/common/BaseStateManager.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BaseStateManager.d.ts","sourceRoot":"","sources":["../../src/common/BaseStateManager.js"],"names":[],"mappings":"AA+BA,8CAAyE;AACzE,qDAAwF;AACxF,gEAA6H;AAE7H,gDAA6E;;;;;;;;;;;AAG7E;;;;;;;;GAQG;AACH;;;;;GAKG;AAEH,eAAe;AACf;IA6EE;;;;;;OAMG;IACH,2CAHW,GAAC,QAKX;IAED;;;;;;;;OAQG;IACH,+BANW,oBAAoB,GAEnB,2BAA2B,CAatC;IAYD;;;;;;;;OAQG;IACH,kBANW,oBAAoB;;QAElB,OAAO,CAAC,WAAW,CAAC,CAahC;;;;;;;;;;;IAyBE,kBACQ,oBAAoB,GAClB,OAAO,CAAC,WAAW,CAAC,CAE9B;;;;;;;;;;;;IAMA,kBACQ,oBAAoB,WACpB,MAAM,GACJ,OAAO,CAAC,WAAW,CAAC,CAE9B;;;;;;;;;;;;;;IAMA,kBACQ,oBAAoB;;;oBAIlB,OAAO,CAAC,WAAW,CAAC,CAE9B;;;;;;;;;;;;;;;IAMA,kBACQ,oBAAoB,WACpB,MAAM;;;oBAIJ,OAAO,CAAC,WAAW,CAAC,CAE9B;;;;;;;;;;;;;;IAgHA,kBACQ,2BAA2B,OAEnC;;;;;;;;;;;;;;;IAWA,mBACQ,oBAAoB,YAEpB,2BAA2B,OAEnC;;;;;;;;;;;;;;;;;;IASA,kBACQ,2BAA2B,WAGnC;QAA0B,YAAY;KAEtC,OAAA;;;;;;;;;;;;;;;;;;IAWA,mBACQ,oBAAoB,YAEpB,2BAA2B,WAGnC;QAA0B,YAAY;KAEtC,OAAA;;;;;;;;;;;IA4NA,yBACQ,oBAAoB,GAClB,OAAO,CAAC,qBAAqB,CAAC,CAExC;;;;;;;;;;;;;;;;;;;IAMA,yBACQ,oBAAoB;;;;oBAMlB,OAAO,CAAC,qBAAqB,CAAC,CAExC;IAqFH;;OAEG;IACH,wCAGC;IA5qBD,eAAe;IACf,mCAEC;IAED;;;;;;;OAOG;IACH,4BAyBC;IA3CC,eAAe;IACf,8BAAgC;;CAirBnC;wBA5uBuB,kBAAkB;kCAGnC,4BAA4B"}
|