@soundworks/core 3.0.4 → 3.1.0-beta.3
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/README.md +1 -0
- package/client/Client.js +1 -1
- package/client/PluginManager.js +4 -3
- package/client/Socket.js +70 -39
- package/common/ParameterBag.js +561 -0
- package/common/SharedState.js +218 -50
- package/common/SharedStateManagerClient.js +7 -1
- package/common/SharedStateManagerServer.js +100 -17
- package/common/SharedStatePrivate.js +96 -55
- package/common/shared-state-utils.js +6 -5
- package/common/sockets-encoder-decoder.js +1 -1
- package/package.json +15 -14
- package/server/Client.js +2 -4
- package/server/PluginManager.js +4 -3
- package/server/Server.js +51 -7
- package/server/utils/Db.js +0 -67
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _ParameterBag = _interopRequireDefault(require("./ParameterBag.js"));
|
|
9
9
|
|
|
10
10
|
var _lodash = _interopRequireDefault(require("lodash.clonedeep"));
|
|
11
11
|
|
|
@@ -22,92 +22,133 @@ class SharedStatePrivate {
|
|
|
22
22
|
constructor(id, schemaName, schema, manager, initValues = {}) {
|
|
23
23
|
this.id = id;
|
|
24
24
|
this.schemaName = schemaName;
|
|
25
|
-
this._schema = (0, _lodash.default)(schema);
|
|
26
25
|
this._manager = manager;
|
|
27
|
-
this._parameters =
|
|
26
|
+
this._parameters = new _ParameterBag.default(schema, initValues);
|
|
28
27
|
this._attachedClients = new Map(); // other peers interested in watching / controlling the state
|
|
29
28
|
|
|
30
29
|
this._creatorRemoteId = null;
|
|
31
30
|
this._creatorId = null;
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
_attachClient(remoteId, client,
|
|
33
|
+
_attachClient(remoteId, client, isOwner = false) {
|
|
35
34
|
this._attachedClients.set(remoteId, client);
|
|
36
35
|
|
|
37
|
-
if (
|
|
36
|
+
if (isOwner) {
|
|
38
37
|
this._creatorRemoteId = remoteId;
|
|
39
38
|
this._creatorId = client.id;
|
|
40
39
|
} // attach client listeners
|
|
41
40
|
|
|
42
41
|
|
|
43
|
-
client.transport.addListener(`${_sharedStateUtils.UPDATE_REQUEST}-${this.id}-${remoteId}`, (reqId, updates) => {
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
client.transport.addListener(`${_sharedStateUtils.UPDATE_REQUEST}-${this.id}-${remoteId}`, async (reqId, updates, context) => {
|
|
43
|
+
// apply registered hooks
|
|
44
|
+
const hooks = this._manager._hooksBySchemaName.get(this.schemaName);
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
const currentValue = this._parameters.get(name); // get new value this way to store events return values
|
|
46
|
+
const values = this._parameters.getValues();
|
|
49
47
|
|
|
48
|
+
let hookAborted = false; // cf. https://github.com/collective-soundworks/soundworks/issues/45
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// compare the Object instances instead of their values.
|
|
54
|
-
// @todo - this should be made more robust but how?
|
|
50
|
+
for (let hook of hooks.values()) {
|
|
51
|
+
const result = await hook(updates, values, context);
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
if (result === null) {
|
|
54
|
+
// explicit abort if hook returns null
|
|
55
|
+
hookAborted = true;
|
|
56
|
+
break;
|
|
57
|
+
} else if (result === undefined) {
|
|
58
|
+
// implicit continue if hook returns undefined
|
|
59
|
+
continue;
|
|
60
|
+
} else {
|
|
61
|
+
// the hook returned an updates object
|
|
62
|
+
updates = result;
|
|
60
63
|
}
|
|
61
64
|
}
|
|
62
65
|
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (
|
|
85
|
-
|
|
66
|
+
if (hookAborted === false) {
|
|
67
|
+
const filteredUpdates = {};
|
|
68
|
+
let hasUpdates = false;
|
|
69
|
+
|
|
70
|
+
for (let name in updates) {
|
|
71
|
+
// from v3.1.0 - the `filteredUpdates` check is made using 'fast-deep-equal'
|
|
72
|
+
// cf. https://github.com/epoberezkin/fast-deep-equal
|
|
73
|
+
// therefore unchanged objects are not considered changed
|
|
74
|
+
// nor propagated anymore.
|
|
75
|
+
// until v3.0.4 - we checked the `schema[name].type === 'any'`, to always consider
|
|
76
|
+
// objects as dirty, because if the state is attached locally, we
|
|
77
|
+
// compare the Object instances instead of their values.
|
|
78
|
+
// @note - this should be made more robust but how?
|
|
79
|
+
const [newValue, changed] = this._parameters.set(name, updates[name]); // if `filterChange` is set to `false` we don't check if the value
|
|
80
|
+
// has been changed or not, it is always propagated to client states
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
const {
|
|
84
|
+
filterChange
|
|
85
|
+
} = this._parameters.getSchema(name);
|
|
86
|
+
|
|
87
|
+
if (filterChange && changed || !filterChange) {
|
|
88
|
+
filteredUpdates[name] = newValue;
|
|
89
|
+
hasUpdates = true;
|
|
86
90
|
}
|
|
87
91
|
}
|
|
88
92
|
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
if (hasUpdates) {
|
|
94
|
+
// send response to requester
|
|
95
|
+
// client.transport.emit(`${UPDATE_RESPONSE}-${this.id}-${remoteId}`, reqId, filteredUpdates);
|
|
96
|
+
// @note: we propagate server-side last, because as the server transport
|
|
97
|
+
// is synchronous it can break ordering if a subscription function makes
|
|
98
|
+
// itself an update in reaction to an update, therefore network messages
|
|
99
|
+
// order would be broken,
|
|
100
|
+
// we need to handle cases where:
|
|
101
|
+
// client state (client.id: 2) sends a request
|
|
102
|
+
// server attached state (client.id: -1) spot a problem and overrides the value
|
|
103
|
+
// we want the remote client (id: 2) to receive in the right order:
|
|
104
|
+
// * 1. the value it requested,
|
|
105
|
+
// * 2. the value overriden by the server-side attached state (id: -1)
|
|
106
|
+
// this problem could be solved properly with a reducer system:
|
|
107
|
+
// if (dirty) {
|
|
108
|
+
// -> call (async) reducer
|
|
109
|
+
// -> get values from reducer
|
|
110
|
+
//. -> dispatch to everybody
|
|
111
|
+
// }
|
|
112
|
+
for (let [peerRemoteId, peer] of this._attachedClients.entries()) {
|
|
113
|
+
// propagate notification to all other attached clients except server
|
|
114
|
+
if (remoteId !== peerRemoteId && peer.id !== -1) {
|
|
115
|
+
peer.transport.emit(`${_sharedStateUtils.UPDATE_NOTIFICATION}-${this.id}-${peerRemoteId}`, filteredUpdates, context);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
92
118
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
119
|
+
if (client.id !== -1) {
|
|
120
|
+
client.transport.emit(`${_sharedStateUtils.UPDATE_RESPONSE}-${this.id}-${remoteId}`, reqId, filteredUpdates, context);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
for (let [peerRemoteId, peer] of this._attachedClients.entries()) {
|
|
124
|
+
// propagate notification to server
|
|
125
|
+
if (remoteId !== peerRemoteId && peer.id === -1) {
|
|
126
|
+
peer.transport.emit(`${_sharedStateUtils.UPDATE_NOTIFICATION}-${this.id}-${peerRemoteId}`, filteredUpdates, context);
|
|
127
|
+
}
|
|
97
128
|
}
|
|
98
|
-
}
|
|
99
129
|
|
|
100
|
-
|
|
101
|
-
|
|
130
|
+
if (client.id === -1) {
|
|
131
|
+
client.transport.emit(`${_sharedStateUtils.UPDATE_RESPONSE}-${this.id}-${remoteId}`, reqId, filteredUpdates, context);
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
// propagate back to the requester that the update has been aborted
|
|
135
|
+
// ignore all other attached clients.
|
|
136
|
+
client.transport.emit(`${_sharedStateUtils.UPDATE_ABORT}-${this.id}-${remoteId}`, reqId, updates, context);
|
|
102
137
|
}
|
|
103
138
|
} else {
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
139
|
+
// retrieve values from inner state (also handle immediate approriately)
|
|
140
|
+
const oldValues = {};
|
|
141
|
+
|
|
142
|
+
for (let name in updates) {
|
|
143
|
+
oldValues[name] = this._parameters.get(name);
|
|
144
|
+
} // aborted by hook (updates have been overriden to {})
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
client.transport.emit(`${_sharedStateUtils.UPDATE_ABORT}-${this.id}-${remoteId}`, reqId, oldValues, context);
|
|
107
148
|
}
|
|
108
149
|
});
|
|
109
150
|
|
|
110
|
-
if (
|
|
151
|
+
if (isOwner) {
|
|
111
152
|
// delete only if creator
|
|
112
153
|
client.transport.addListener(`${_sharedStateUtils.DELETE_REQUEST}-${this.id}-${remoteId}`, reqId => {
|
|
113
154
|
this._manager._serverStatesById.delete(this.id); // --------------------------------------------------------------------
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.UPDATE_RESPONSE = exports.UPDATE_REQUEST = exports.UPDATE_NOTIFICATION = exports.UPDATE_ABORT = exports.SERVER_ID = exports.OBSERVE_RESPONSE = exports.OBSERVE_REQUEST = exports.OBSERVE_NOTIFICATION = exports.DETACH_RESPONSE = exports.DETACH_REQUEST = exports.DETACH_ERROR = exports.DELETE_SCHEMA = exports.DELETE_RESPONSE = exports.DELETE_REQUEST = exports.DELETE_NOTIFICATION = exports.DELETE_ERROR = exports.CREATE_RESPONSE = exports.CREATE_REQUEST = exports.CREATE_ERROR = exports.ATTACH_RESPONSE = exports.ATTACH_REQUEST = exports.ATTACH_ERROR = void 0;
|
|
6
7
|
exports.idGenerator = idGenerator;
|
|
7
|
-
exports.storeRequestPromise = storeRequestPromise;
|
|
8
|
-
exports.resolveRequest = resolveRequest;
|
|
9
8
|
exports.rejectRequest = rejectRequest;
|
|
10
|
-
exports.
|
|
9
|
+
exports.resolveRequest = resolveRequest;
|
|
10
|
+
exports.storeRequestPromise = storeRequestPromise;
|
|
11
11
|
// id of the server when owner of a state
|
|
12
12
|
const SERVER_ID = -1;
|
|
13
13
|
exports.SERVER_ID = SERVER_ID;
|
|
@@ -35,8 +35,7 @@ const DETACH_REQUEST = 's:dt:req';
|
|
|
35
35
|
exports.DETACH_REQUEST = DETACH_REQUEST;
|
|
36
36
|
const DETACH_RESPONSE = 's:dt:res';
|
|
37
37
|
exports.DETACH_RESPONSE = DETACH_RESPONSE;
|
|
38
|
-
const DETACH_ERROR = 's:dt:err';
|
|
39
|
-
|
|
38
|
+
const DETACH_ERROR = 's:dt:err';
|
|
40
39
|
exports.DETACH_ERROR = DETACH_ERROR;
|
|
41
40
|
const OBSERVE_REQUEST = 's:o:req';
|
|
42
41
|
exports.OBSERVE_REQUEST = OBSERVE_REQUEST;
|
|
@@ -52,6 +51,8 @@ const UPDATE_ABORT = 's:u:ab';
|
|
|
52
51
|
exports.UPDATE_ABORT = UPDATE_ABORT;
|
|
53
52
|
const UPDATE_NOTIFICATION = 's:u:not';
|
|
54
53
|
exports.UPDATE_NOTIFICATION = UPDATE_NOTIFICATION;
|
|
54
|
+
const DELETE_SCHEMA = 's:d:s';
|
|
55
|
+
exports.DELETE_SCHEMA = DELETE_SCHEMA;
|
|
55
56
|
|
|
56
57
|
function* idGenerator() {
|
|
57
58
|
for (let i = 0; true; i++) {
|
|
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.packBinaryMessage = packBinaryMessage;
|
|
7
|
-
exports.unpackBinaryMessage = unpackBinaryMessage;
|
|
8
7
|
exports.packStringMessage = packStringMessage;
|
|
8
|
+
exports.unpackBinaryMessage = unpackBinaryMessage;
|
|
9
9
|
exports.unpackStringMessage = unpackStringMessage;
|
|
10
10
|
|
|
11
11
|
require("fast-text-encoding");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soundworks/core",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.1.0-beta.3",
|
|
4
4
|
"description": "full-stack javascript framework for distributed audio visual experiences on the web",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Benjamin Matuszewski",
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
"main": "",
|
|
19
19
|
"scripts": {
|
|
20
20
|
"clean": "rm -Rf client && rm -Rf server && rm -Rf common",
|
|
21
|
-
"
|
|
21
|
+
"doc": "rm -Rf docs && jsdoc -c .jsdoc.json --verbose && cp -R assets docs/",
|
|
22
22
|
"prepublishOnly": "npm run build",
|
|
23
23
|
"toc": "markdown-toc -i README.md",
|
|
24
|
-
"version": "npm run toc && npm run
|
|
24
|
+
"version": "npm run toc && npm run doc && git add docs",
|
|
25
25
|
"build:client": "babel src/client --out-dir client",
|
|
26
26
|
"build:server": "babel src/server --out-dir server",
|
|
27
27
|
"build:common": "babel src/common --out-dir common",
|
|
@@ -32,37 +32,38 @@
|
|
|
32
32
|
"dev": "npm run build && (npm run dev:client & npm run dev:server & npm run dev:common)"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"
|
|
36
|
-
"braintree-jsdoc-template": "^3.3.0",
|
|
37
|
-
"chalk": "^2.4.2",
|
|
35
|
+
"chalk": "^4.1.2",
|
|
38
36
|
"columnify": "^1.5.4",
|
|
39
37
|
"compression": "^1.7.1",
|
|
40
38
|
"debug": "^4.1.1",
|
|
39
|
+
"fast-deep-equal": "^3.1.3",
|
|
41
40
|
"fast-text-encoding": "^1.0.0",
|
|
42
41
|
"isomorphic-ws": "^4.0.1",
|
|
43
|
-
"
|
|
44
|
-
"keyv": "^
|
|
45
|
-
"keyv-file": "^0.1.13",
|
|
42
|
+
"keyv": "^4.0.3",
|
|
43
|
+
"keyv-file": "^0.2.0",
|
|
46
44
|
"lodash.clonedeep": "^4.5.0",
|
|
47
45
|
"lodash.merge": "^4.6.2",
|
|
48
46
|
"pem": "^1.12.5",
|
|
49
47
|
"polka": "^0.5.2",
|
|
50
48
|
"serve-static": "^1.13.2",
|
|
51
|
-
"
|
|
49
|
+
"uuid": "^8.3.2",
|
|
52
50
|
"window-or-global": "^1.0.1",
|
|
53
|
-
"ws": "^
|
|
51
|
+
"ws": "^8.2.3"
|
|
54
52
|
},
|
|
55
53
|
"devDependencies": {
|
|
56
54
|
"@babel/cli": "^7.4.4",
|
|
57
55
|
"@babel/core": "^7.4.5",
|
|
58
|
-
"@babel/plugin-proposal-export-default-from": "^7.5.2",
|
|
59
56
|
"@babel/preset-env": "^7.4.5",
|
|
60
57
|
"chai": "^4.2.0",
|
|
61
58
|
"chokidar": "^3.0.1",
|
|
62
|
-
"chokidar-cli": "^
|
|
59
|
+
"chokidar-cli": "^3.0.0",
|
|
63
60
|
"docdash": "^1.2.0",
|
|
64
61
|
"jsdoc": "^3.6.2",
|
|
65
62
|
"markdown-toc": "^1.2.0",
|
|
66
|
-
"mocha": "^
|
|
63
|
+
"mocha": "^9.1.3"
|
|
64
|
+
},
|
|
65
|
+
"optionalDependencies": {
|
|
66
|
+
"bufferutil": "^4.0.5",
|
|
67
|
+
"utf-8-validate": "^5.0.7"
|
|
67
68
|
}
|
|
68
69
|
}
|
package/server/Client.js
CHANGED
|
@@ -5,9 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
8
|
+
var _uuid = require("uuid");
|
|
11
9
|
|
|
12
10
|
function* idGenerator() {
|
|
13
11
|
for (let i = 0; true; i++) {
|
|
@@ -47,7 +45,7 @@ class Client {
|
|
|
47
45
|
* @type {String}
|
|
48
46
|
*/
|
|
49
47
|
|
|
50
|
-
this.uuid = (0,
|
|
48
|
+
this.uuid = (0, _uuid.v4)();
|
|
51
49
|
/**
|
|
52
50
|
* Socket connection with the remote {@link client.Client}.
|
|
53
51
|
* @type {server.Socket}
|
package/server/PluginManager.js
CHANGED
|
@@ -86,7 +86,8 @@ class PluginManager {
|
|
|
86
86
|
|
|
87
87
|
register(name, factory = null, options = {}, deps = []) {
|
|
88
88
|
if (this._registeredPlugins[name]) {
|
|
89
|
-
|
|
89
|
+
const ctor = factory(_AbstractPlugin.default);
|
|
90
|
+
throw new Error(`[soundworks:core] Plugin "${name}" of type "${ctor.name}" already registered`);
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
const ctor = factory(_AbstractPlugin.default);
|
|
@@ -105,7 +106,7 @@ class PluginManager {
|
|
|
105
106
|
|
|
106
107
|
get(name, _experience = null) {
|
|
107
108
|
if (!this._registeredPlugins[name]) {
|
|
108
|
-
throw new Error(`Cannot get or require plugin "${name}", plugin is not registered
|
|
109
|
+
throw new Error(`[soundworks:core] Cannot get or require plugin "${name}", plugin is not registered
|
|
109
110
|
> registered plugins are:
|
|
110
111
|
${Object.keys(this._registeredPlugins).map(n => `> - ${n}\n`).join('')}
|
|
111
112
|
`);
|
|
@@ -113,7 +114,7 @@ ${Object.keys(this._registeredPlugins).map(n => `> - ${n}\n`).join('')}
|
|
|
113
114
|
|
|
114
115
|
|
|
115
116
|
if (_experience && this.signals.start.value === true) {
|
|
116
|
-
throw new Error(`Plugin "${name}" required after pluginManager start`);
|
|
117
|
+
throw new Error(`[soundworks:core] Plugin "${name}" required after pluginManager start`);
|
|
117
118
|
}
|
|
118
119
|
|
|
119
120
|
if (!this._instances[name]) {
|
package/server/Server.js
CHANGED
|
@@ -35,12 +35,17 @@ var _Sockets = _interopRequireDefault(require("./Sockets.js"));
|
|
|
35
35
|
|
|
36
36
|
var _SharedStateManagerServer = _interopRequireDefault(require("../common/SharedStateManagerServer.js"));
|
|
37
37
|
|
|
38
|
-
var _Db = _interopRequireDefault(require("./utils/Db.js"));
|
|
39
|
-
|
|
40
38
|
var _logger = _interopRequireDefault(require("./utils/logger.js"));
|
|
41
39
|
|
|
40
|
+
var _keyv = _interopRequireDefault(require("keyv"));
|
|
41
|
+
|
|
42
|
+
var _keyvFile = _interopRequireDefault(require("keyv-file"));
|
|
43
|
+
|
|
42
44
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
43
45
|
|
|
46
|
+
let _dbNamespaces = new Set();
|
|
47
|
+
|
|
48
|
+
let _dbStore = null;
|
|
44
49
|
/**
|
|
45
50
|
* Server side entry point for a `soundworks` application.
|
|
46
51
|
*
|
|
@@ -58,6 +63,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
58
63
|
* const myExperience = new MyExperience();
|
|
59
64
|
* soundworks.server.start();
|
|
60
65
|
*/
|
|
66
|
+
|
|
61
67
|
class Server {
|
|
62
68
|
constructor() {
|
|
63
69
|
/**
|
|
@@ -98,7 +104,7 @@ class Server {
|
|
|
98
104
|
* @private
|
|
99
105
|
*/
|
|
100
106
|
|
|
101
|
-
this.db =
|
|
107
|
+
this.db = this.createNamespacedDb('core');
|
|
102
108
|
/**
|
|
103
109
|
* The {@link server.Sockets} instance. A small wrapper around
|
|
104
110
|
* [`ws`](https://github.com/websockets/ws) server.
|
|
@@ -320,8 +326,8 @@ class Server {
|
|
|
320
326
|
}
|
|
321
327
|
} else {
|
|
322
328
|
return new Promise(async (resolve, reject) => {
|
|
323
|
-
const key = await this.db.get('
|
|
324
|
-
const cert = await this.db.get('
|
|
329
|
+
const key = await this.db.get('httpsKey');
|
|
330
|
+
const cert = await this.db.get('httpsCert');
|
|
325
331
|
|
|
326
332
|
if (key && cert) {
|
|
327
333
|
this._httpsInfos = {
|
|
@@ -346,8 +352,8 @@ class Server {
|
|
|
346
352
|
key: keys.serviceKey,
|
|
347
353
|
cert: keys.certificate
|
|
348
354
|
};
|
|
349
|
-
await this.db.set('
|
|
350
|
-
await this.db.set('
|
|
355
|
+
await this.db.set('httpsKey', this._httpsInfos.key);
|
|
356
|
+
await this.db.set('httpsCert', this._httpsInfos.cert);
|
|
351
357
|
|
|
352
358
|
const httpsServer = _https.default.createServer(this._httpsInfos);
|
|
353
359
|
|
|
@@ -566,6 +572,44 @@ class Server {
|
|
|
566
572
|
});
|
|
567
573
|
});
|
|
568
574
|
}
|
|
575
|
+
/**
|
|
576
|
+
* Create namespaced databases for core and plugins
|
|
577
|
+
* (kind of experiemental API do not expose in doc for now)
|
|
578
|
+
*
|
|
579
|
+
* @note - introduced in v3.1.0-beta.1
|
|
580
|
+
* @note - used by core and plugin-audio-streams
|
|
581
|
+
* @private
|
|
582
|
+
*/
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
createNamespacedDb(namespace = null) {
|
|
586
|
+
if (namespace === null || !(typeof namespace === 'string')) {
|
|
587
|
+
throw new Error(`[soundworks:core] Invalid namespace for ".createNamespacedDb(namespace)", namespace is mandatory and should be a string`);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
if (_dbNamespaces.has(namespace)) {
|
|
591
|
+
throw new Error(`[soundworks:core] Invalid namespace for ".createNamespacedDb(namespace)", namespace "${namespace}" already exists`);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
const dbDirectory = _path.default.join(process.cwd(), '.data');
|
|
595
|
+
|
|
596
|
+
if (!_fs.default.existsSync(dbDirectory)) {
|
|
597
|
+
_fs.default.mkdirSync(dbDirectory);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
const filename = _path.default.join(dbDirectory, `soundworks-${namespace}.db`); // at note keyv-file doesn't seems to works
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
const store = new _keyvFile.default({
|
|
604
|
+
filename
|
|
605
|
+
});
|
|
606
|
+
const db = new _keyv.default({
|
|
607
|
+
namespace,
|
|
608
|
+
store
|
|
609
|
+
});
|
|
610
|
+
db.on('error', err => console.log(chalk.red('[soundworks:core] db ${namespace} error:'), err));
|
|
611
|
+
return db;
|
|
612
|
+
}
|
|
569
613
|
|
|
570
614
|
}
|
|
571
615
|
|
package/server/utils/Db.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var _keyv = _interopRequireDefault(require("keyv"));
|
|
9
|
-
|
|
10
|
-
var _keyvFile = _interopRequireDefault(require("keyv-file"));
|
|
11
|
-
|
|
12
|
-
var _path = _interopRequireDefault(require("path"));
|
|
13
|
-
|
|
14
|
-
var _fs = _interopRequireDefault(require("fs"));
|
|
15
|
-
|
|
16
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Simple in file key / value database.
|
|
20
|
-
* Do not expose for now, may not be the right way to go...
|
|
21
|
-
*
|
|
22
|
-
* @todo - implement options to change storage solution.
|
|
23
|
-
* cf. https://github.com/lukechilds/keyv
|
|
24
|
-
*
|
|
25
|
-
* @memberof server
|
|
26
|
-
* @private
|
|
27
|
-
*/
|
|
28
|
-
class Db {
|
|
29
|
-
constructor(options = {}) {
|
|
30
|
-
const dbDirectory = _path.default.join(process.cwd(), '.data');
|
|
31
|
-
|
|
32
|
-
if (!_fs.default.existsSync(dbDirectory)) {
|
|
33
|
-
_fs.default.mkdirSync(dbDirectory);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const filename = _path.default.join(dbDirectory, 'soundworks.db');
|
|
37
|
-
|
|
38
|
-
this.keyv = new _keyv.default({
|
|
39
|
-
namespace: 'soundworks',
|
|
40
|
-
store: new _keyvFile.default({
|
|
41
|
-
filename
|
|
42
|
-
})
|
|
43
|
-
});
|
|
44
|
-
this.keyv.on('error', err => console.log('Connection Error', err));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async get(key) {
|
|
48
|
-
const value = await this.keyv.get(key);
|
|
49
|
-
return value;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async set(key, value, expireDelayMs = undefined) {
|
|
53
|
-
await this.keyv.set(key, value, expireDelayMs);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async delete(key) {
|
|
57
|
-
await this.keyv.delete(key);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async clear() {
|
|
61
|
-
await this.keyv.clear();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
var _default = Db;
|
|
67
|
-
exports.default = _default;
|