@soundworks/core 3.7.0 → 4.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +16 -0
- package/LICENSE +1 -1
- package/README.md +32 -30
- package/package.json +48 -28
- package/src/client/Client.js +391 -0
- package/src/client/Context.js +225 -0
- package/src/client/ContextManager.js +111 -0
- package/src/client/Plugin.js +66 -0
- package/src/client/PluginManager.js +123 -0
- package/src/client/SharedState.js +84 -0
- package/src/client/Socket.js +389 -0
- package/src/client/StateManager.js +67 -0
- package/src/client/index.js +77 -0
- package/src/common/BasePlugin.js +163 -0
- package/src/common/BasePluginManager.js +227 -0
- package/{common/SharedState.js → src/common/BaseSharedState.js} +198 -234
- package/src/common/BaseStateManager.js +200 -0
- package/{common → src/common}/ParameterBag.js +74 -112
- package/{common → src/common}/SharedStatePrivate.js +56 -62
- package/src/common/constants.js +51 -0
- package/src/common/logger.js +154 -0
- package/src/common/promise-store.js +25 -0
- package/src/common/sockets-utils.js +73 -0
- package/src/common/utils.js +22 -0
- package/src/server/Client.js +50 -0
- package/src/server/Context.js +99 -0
- package/src/server/ContextManager.js +266 -0
- package/src/server/Plugin.js +77 -0
- package/src/server/PluginManager.js +150 -0
- package/src/server/Server.js +849 -0
- package/src/server/SharedState.js +86 -0
- package/{server → src/server}/Socket.js +114 -88
- package/{server → src/server}/Sockets.js +73 -60
- package/{common/SharedStateManagerServer.js → src/server/StateManager.js} +181 -129
- package/src/server/audit-network-latency.worker.js +57 -0
- package/src/server/audit-schema.js +42 -0
- package/src/server/index.js +45 -0
- package/tsconfig.json +21 -0
- package/types/client/Client.d.ts +194 -0
- package/types/client/Client.d.ts.map +1 -0
- package/types/client/Context.d.ts +139 -0
- package/types/client/Context.d.ts.map +1 -0
- package/types/client/ContextManager.d.ts +45 -0
- package/types/client/ContextManager.d.ts.map +1 -0
- package/types/client/Plugin.d.ts +53 -0
- package/types/client/Plugin.d.ts.map +1 -0
- package/types/client/PluginManager.d.ts +96 -0
- package/types/client/PluginManager.d.ts.map +1 -0
- package/types/client/SharedState.d.ts +85 -0
- package/types/client/SharedState.d.ts.map +1 -0
- package/types/client/Socket.d.ts +138 -0
- package/types/client/Socket.d.ts.map +1 -0
- package/types/client/StateManager.d.ts +72 -0
- package/types/client/StateManager.d.ts.map +1 -0
- package/types/client/index.d.ts +11 -0
- package/types/client/index.d.ts.map +1 -0
- package/types/common/BasePlugin.d.ts +145 -0
- package/types/common/BasePlugin.d.ts.map +1 -0
- package/types/common/BasePluginManager.d.ts +88 -0
- package/types/common/BasePluginManager.d.ts.map +1 -0
- package/types/common/BaseSharedState.d.ts +173 -0
- package/types/common/BaseSharedState.d.ts.map +1 -0
- package/types/common/BaseStateManager.d.ts +70 -0
- package/types/common/BaseStateManager.d.ts.map +1 -0
- package/types/common/ParameterBag.d.ts +143 -0
- package/types/common/ParameterBag.d.ts.map +1 -0
- package/types/common/SharedStatePrivate.d.ts +20 -0
- package/types/common/SharedStatePrivate.d.ts.map +1 -0
- package/types/common/constants.d.ts +35 -0
- package/types/common/constants.d.ts.map +1 -0
- package/types/common/logger.d.ts +16 -0
- package/types/common/logger.d.ts.map +1 -0
- package/types/common/promise-store.d.ts +4 -0
- package/types/common/promise-store.d.ts.map +1 -0
- package/types/common/sockets-utils.d.ts +9 -0
- package/types/common/sockets-utils.d.ts.map +1 -0
- package/types/common/utils.d.ts +5 -0
- package/types/common/utils.d.ts.map +1 -0
- package/types/server/Client.d.ts +40 -0
- package/types/server/Client.d.ts.map +1 -0
- package/types/server/Context.d.ts +59 -0
- package/types/server/Context.d.ts.map +1 -0
- package/types/server/ContextManager.d.ts +69 -0
- package/types/server/ContextManager.d.ts.map +1 -0
- package/types/server/Plugin.d.ts +70 -0
- package/types/server/Plugin.d.ts.map +1 -0
- package/types/server/PluginManager.d.ts +91 -0
- package/types/server/PluginManager.d.ts.map +1 -0
- package/types/server/Server.d.ts +223 -0
- package/types/server/Server.d.ts.map +1 -0
- package/types/server/SharedState.d.ts +86 -0
- package/types/server/SharedState.d.ts.map +1 -0
- package/types/server/Socket.d.ts +128 -0
- package/types/server/Socket.d.ts.map +1 -0
- package/types/server/Sockets.d.ts +73 -0
- package/types/server/Sockets.d.ts.map +1 -0
- package/types/server/StateManager.d.ts +190 -0
- package/types/server/StateManager.d.ts.map +1 -0
- package/types/server/audit-network-latency.worker.d.ts +2 -0
- package/types/server/audit-network-latency.worker.d.ts.map +1 -0
- package/types/server/audit-schema.d.ts +27 -0
- package/types/server/audit-schema.d.ts.map +1 -0
- package/types/server/index.d.ts +7 -0
- package/types/server/index.d.ts.map +1 -0
- package/client/AbstractExperience.js +0 -54
- package/client/AbstractPlugin.js +0 -230
- package/client/Client.js +0 -193
- package/client/PluginManager.js +0 -279
- package/client/Socket.js +0 -346
- package/client/index.js +0 -48
- package/client.js +0 -28
- package/common/SharedStateManagerClient.js +0 -194
- package/common/Signal.js +0 -40
- package/common/SignalAll.js +0 -44
- package/common/logger.js +0 -162
- package/common/shared-state-utils.js +0 -89
- package/common/sockets-encoder-decoder.js +0 -73
- package/server/AbstractExperience.js +0 -126
- package/server/AbstractPlugin.js +0 -214
- package/server/Client.js +0 -70
- package/server/PluginManager.js +0 -273
- package/server/Server.js +0 -785
- package/server/index.js +0 -49
- package/server.js +0 -28
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
export default StateManager;
|
|
2
|
+
export namespace server {
|
|
3
|
+
/**
|
|
4
|
+
* ~ObserveCallback
|
|
5
|
+
*/
|
|
6
|
+
type StateManager = () => any;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* @callback server.StateManager~ObserveCallback
|
|
10
|
+
* @async
|
|
11
|
+
* @param {String} schemaName - name of the schema
|
|
12
|
+
* @param {Number} stateId - id of the state
|
|
13
|
+
* @param {Number} nodeId - id of the node that created the state
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The `StateManager` allows to create new {@link server.SharedState}s, or attach
|
|
17
|
+
* to {@link server.SharedState}s created by other nodes (clients or server). It
|
|
18
|
+
* can also track all the {@link server.SharedState}s created by other nodes.
|
|
19
|
+
*
|
|
20
|
+
* An instance of `StateManager` is automatically created by the `soundworks.Server`
|
|
21
|
+
* at initialization (cf. {@link server.Server#stateManager}).
|
|
22
|
+
*
|
|
23
|
+
* Compared to the {@link client.StateManager}, the `server.StateManager` can also
|
|
24
|
+
* create and delete schemas, as well as register update hook that are executed when
|
|
25
|
+
* a state is updated.
|
|
26
|
+
*
|
|
27
|
+
* See {@link server.Server#stateManager}
|
|
28
|
+
*
|
|
29
|
+
* Tutorial: {@link https://soundworks.dev/guide/state-manager.html}
|
|
30
|
+
*
|
|
31
|
+
* ```
|
|
32
|
+
* // server-side
|
|
33
|
+
* import { Server } from '@soundworks/server/index.js';
|
|
34
|
+
*
|
|
35
|
+
* const server = new Server(config);
|
|
36
|
+
* // declare and register the schema of a shared state.
|
|
37
|
+
* server.stateManager.registerSchema('some-global-state', {
|
|
38
|
+
* myRandom: {
|
|
39
|
+
* type: 'float',
|
|
40
|
+
* default: 0,
|
|
41
|
+
* }
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* await server.start();
|
|
45
|
+
*
|
|
46
|
+
* // create a global state server-side
|
|
47
|
+
* const globalState = await server.stateManager.create('some-global-state');
|
|
48
|
+
* // listen and react to the changes made by the clients
|
|
49
|
+
* globalState.onUpdate(updates => console.log(updates));
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* ```
|
|
53
|
+
* // client-side
|
|
54
|
+
* import { Client } from '@soundworks/client.index.js';
|
|
55
|
+
*
|
|
56
|
+
* const client = new Client(config);
|
|
57
|
+
* await client.start();
|
|
58
|
+
*
|
|
59
|
+
* // attach to the global state created by the server
|
|
60
|
+
* const globalState = await client.stateManager.attach('some-global-state');
|
|
61
|
+
*
|
|
62
|
+
* // update the value of a `myRandom` parameter every seconds
|
|
63
|
+
* setInterval(() => {
|
|
64
|
+
* globalState.set({ myRandom: Math.random() });
|
|
65
|
+
* }, 1000);
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @memberof server
|
|
69
|
+
* @extends BaseStateManager
|
|
70
|
+
* @inheritdoc
|
|
71
|
+
* @hideconstructor
|
|
72
|
+
*/
|
|
73
|
+
declare class StateManager extends BaseStateManager {
|
|
74
|
+
constructor();
|
|
75
|
+
_clientByNodeId: Map<any, any>;
|
|
76
|
+
_serverStatesById: Map<any, any>;
|
|
77
|
+
_schemas: Map<any, any>;
|
|
78
|
+
_observers: Set<any>;
|
|
79
|
+
_hooksBySchemaName: Map<any, any>;
|
|
80
|
+
/**
|
|
81
|
+
* Add a client to the manager.
|
|
82
|
+
*
|
|
83
|
+
* This is automatically handled by the {@link server.Server} when a client connects.
|
|
84
|
+
*
|
|
85
|
+
* @param {Number} nodeId - Id of the client node, as given in
|
|
86
|
+
* {@link client.StateManager}
|
|
87
|
+
* @param {Object} transport - Tranpsort mecanism to communicate with the
|
|
88
|
+
* client. Should implement a basic EventEmitter API.
|
|
89
|
+
*
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
private addClient;
|
|
93
|
+
/**
|
|
94
|
+
* Remove a client from the manager. Clean all created or attached states.
|
|
95
|
+
*
|
|
96
|
+
* This is automatically handled by the {@link server.Server} when a client disconnects.
|
|
97
|
+
*
|
|
98
|
+
* @param {Number} nodeId - Id of the client node, as given in
|
|
99
|
+
* {@link client.StateManager}
|
|
100
|
+
*
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
private removeClient;
|
|
104
|
+
/**
|
|
105
|
+
* Register a schema from which shared states (cf. {@link common.SharedState})
|
|
106
|
+
* can be instanciated.
|
|
107
|
+
*
|
|
108
|
+
* @param {String} schemaName - Name of the schema.
|
|
109
|
+
* @param {server.StateManager~schema} schema - Data structure
|
|
110
|
+
* describing the states that will be created from this schema.
|
|
111
|
+
*
|
|
112
|
+
* @see {@link server.StateManager#create}
|
|
113
|
+
* @see {@link client.StateManager#create}
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* server.stateManager.registerSchema('my-schema', {
|
|
117
|
+
* myBoolean: {
|
|
118
|
+
* type: 'boolean'
|
|
119
|
+
* default: false,
|
|
120
|
+
* },
|
|
121
|
+
* myFloat: {
|
|
122
|
+
* type: 'float'
|
|
123
|
+
* default: 0.1,
|
|
124
|
+
* min: -1,
|
|
125
|
+
* max: 1
|
|
126
|
+
* }
|
|
127
|
+
* })
|
|
128
|
+
*/
|
|
129
|
+
registerSchema(schemaName: string, schema: any): void;
|
|
130
|
+
/**
|
|
131
|
+
* Delete a schema and all associated states.
|
|
132
|
+
* When a schema is deleted, all states created from this schema are deleted
|
|
133
|
+
* as well, therefore all attached clients are detached and the `onDetach`
|
|
134
|
+
* and `onDelete` callbacks are called on the related states.
|
|
135
|
+
*
|
|
136
|
+
* @param {String} schemaName - Name of the schema.
|
|
137
|
+
*/
|
|
138
|
+
deleteSchema(schemaName: string): void;
|
|
139
|
+
/**
|
|
140
|
+
* @callback server.StateManager~updateHook
|
|
141
|
+
* @async
|
|
142
|
+
*
|
|
143
|
+
* @param {Object} updates - Update object as given on a set callback, or
|
|
144
|
+
* result of the previous hook
|
|
145
|
+
* @param {Object} currentValues - Current values of the state.
|
|
146
|
+
* @param {Object} [context=null] - Optionnal context passed by the creator
|
|
147
|
+
* of the update.
|
|
148
|
+
*
|
|
149
|
+
* @return {Object} The "real" updates to be applied on the state.
|
|
150
|
+
*/
|
|
151
|
+
/**
|
|
152
|
+
* Register a function for a given schema (e.g. will be applied on all states
|
|
153
|
+
* created from this schema) that will be executed before the update values
|
|
154
|
+
* are propagated. For example, this could be used to implement a preset system
|
|
155
|
+
* where all the values of the state are updated from e.g. some data stored in
|
|
156
|
+
* filesystem while the consumer of the state only want to update the preset name.
|
|
157
|
+
*
|
|
158
|
+
* The hook is associated to every state of its kind (i.e. schemaName) and
|
|
159
|
+
* executed on every update (call of `set`). Note that the hooks are executed
|
|
160
|
+
* server-side regarless the node on which `set` has been called and before
|
|
161
|
+
* the "actual" update of the state (e.g. before the call of `onUpdate`).
|
|
162
|
+
*
|
|
163
|
+
* @param {String} schemaName - Kind of states on which applying the hook.
|
|
164
|
+
* @param {server.StateManager~updateHook} updateHook - Function
|
|
165
|
+
* called between the `set` call and the actual update.
|
|
166
|
+
*
|
|
167
|
+
* @returns {Fuction} deleteHook - Handler that deletes the hook when executed.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* server.stateManager.registerSchema('hooked', {
|
|
171
|
+
* name: { type: 'string', default: null, nullable: true },
|
|
172
|
+
* name: { numUpdates: 'integer', default: 0 },
|
|
173
|
+
* });
|
|
174
|
+
* server.stateManager.registerUpdateHook('hooked', updates => {
|
|
175
|
+
* return {
|
|
176
|
+
* ...updates
|
|
177
|
+
* numUpdates: currentValues.numUpdates + 1,
|
|
178
|
+
* };
|
|
179
|
+
* });
|
|
180
|
+
*
|
|
181
|
+
* const state = await server.stateManager.create('hooked');
|
|
182
|
+
*
|
|
183
|
+
* await state.set({ name: 'test' });
|
|
184
|
+
* const values = state.getValues();
|
|
185
|
+
* assert.deepEqual(result, { name: 'test', numUpdates: 1 });
|
|
186
|
+
*/
|
|
187
|
+
registerUpdateHook(schemaName: string, updateHook: any): Fuction;
|
|
188
|
+
}
|
|
189
|
+
import BaseStateManager from "../common/BaseStateManager.js";
|
|
190
|
+
//# sourceMappingURL=StateManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StateManager.d.ts","sourceRoot":"","sources":["../../src/server/StateManager.js"],"names":[],"mappings":";;;;;;;AA4BA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH;IACE,cAcC;IAPC,+BAAgC;IAChC,iCAAkC;IAClC,wBAAyB;IACzB,qBAA2B;IAC3B,kCAAmC;IAKrC;;;;;;;;;;;OAWG;IACH,kBA6GC;IAED;;;;;;;;;OASG;IACH,qBAgCC;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,sDAUC;IAED;;;;;;;OAOG;IACH,uCAqBC;IAED;;;;;;;;;;;OAWG;IAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,iEAUC;CAEF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-network-latency.worker.d.ts","sourceRoot":"","sources":["../../src/server/audit-network-latency.worker.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
declare namespace _default {
|
|
2
|
+
namespace numClients {
|
|
3
|
+
export const type: string;
|
|
4
|
+
const _default: {};
|
|
5
|
+
export { _default as default };
|
|
6
|
+
}
|
|
7
|
+
namespace averageNetworkLatency {
|
|
8
|
+
const type_1: string;
|
|
9
|
+
export { type_1 as type };
|
|
10
|
+
const _default_1: number;
|
|
11
|
+
export { _default_1 as default };
|
|
12
|
+
}
|
|
13
|
+
namespace averageNetworkLatencyWindow {
|
|
14
|
+
const type_2: string;
|
|
15
|
+
export { type_2 as type };
|
|
16
|
+
const _default_2: number;
|
|
17
|
+
export { _default_2 as default };
|
|
18
|
+
}
|
|
19
|
+
namespace averageNetworkLatencyPeriod {
|
|
20
|
+
const type_3: string;
|
|
21
|
+
export { type_3 as type };
|
|
22
|
+
const _default_3: number;
|
|
23
|
+
export { _default_3 as default };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export default _default;
|
|
27
|
+
//# sourceMappingURL=audit-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-schema.d.ts","sourceRoot":"","sources":["../../src/server/audit-schema.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.js"],"names":[],"mappings":""}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var _debug = _interopRequireDefault(require("debug"));
|
|
9
|
-
|
|
10
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
|
-
const log = (0, _debug.default)('soundworks:lifecycle');
|
|
13
|
-
/**
|
|
14
|
-
* Base class to extend for implementing a client of a soundworks application.
|
|
15
|
-
*
|
|
16
|
-
* @memberof client
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
class AbstractExperience {
|
|
20
|
-
constructor(client) {
|
|
21
|
-
// @todo - check that it's a soundworks instance
|
|
22
|
-
if (!client) {
|
|
23
|
-
throw new Error(`${this.constructor.name} should receive the "Client" instance as first argument`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
this.client = client;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Require a registered plugin.
|
|
30
|
-
* @see {client.PluginManager#register}
|
|
31
|
-
*
|
|
32
|
-
* @param {String} name - Name of the plugin as given when registered.
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
require(name) {
|
|
37
|
-
return this.client.pluginManager.get(name, true);
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Start the experience. This lifecycle method is called by the soundworks
|
|
41
|
-
* client when all the required plugins are `ready` and thus the `Experience``
|
|
42
|
-
* can start with all the necessary informations and plugins ready to be consumed.
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
start() {
|
|
47
|
-
log(`> experience "${this.constructor.name}" start`);
|
|
48
|
-
this.client.socket.send('s:exp:enter');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
var _default = AbstractExperience;
|
|
54
|
-
exports.default = _default;
|
package/client/AbstractPlugin.js
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var _debug = _interopRequireDefault(require("debug"));
|
|
9
|
-
|
|
10
|
-
var _lodash = _interopRequireDefault(require("lodash.merge"));
|
|
11
|
-
|
|
12
|
-
var _Signal = _interopRequireDefault(require("../common/Signal.js"));
|
|
13
|
-
|
|
14
|
-
var _SignalAll = _interopRequireDefault(require("../common/SignalAll.js"));
|
|
15
|
-
|
|
16
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
-
|
|
18
|
-
const log = (0, _debug.default)('soundworks:lifecycle');
|
|
19
|
-
/**
|
|
20
|
-
* Base class to extend for implementing a new plugin.
|
|
21
|
-
*
|
|
22
|
-
* A plugin should always be provided wrapped in a factory function to allow for
|
|
23
|
-
* dynamically extend this class and avoid circular dependencies.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* function myPluginFactory(AbstractPlugin) {
|
|
27
|
-
* class MyPlugin extends AbstractPlugin {
|
|
28
|
-
* constructor(client, name, options) {
|
|
29
|
-
* super(client, name);
|
|
30
|
-
* // ...
|
|
31
|
-
* }
|
|
32
|
-
*
|
|
33
|
-
* async start() {
|
|
34
|
-
* await ...
|
|
35
|
-
* this.started();
|
|
36
|
-
* await ...
|
|
37
|
-
* this.ready();
|
|
38
|
-
* }
|
|
39
|
-
* }
|
|
40
|
-
*
|
|
41
|
-
* return MyPlugin;
|
|
42
|
-
* }
|
|
43
|
-
* // then register the factory
|
|
44
|
-
* client.pluginManager.register('my-plugin', myPluginFactory, { options }, []);
|
|
45
|
-
*
|
|
46
|
-
* @param {client.Client} client - instance of the soundworks Client
|
|
47
|
-
* @param {String} name - user defined name of the plugin
|
|
48
|
-
*
|
|
49
|
-
* @memberof client
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
|
-
class AbstractPlugin {
|
|
53
|
-
constructor(client, name) {
|
|
54
|
-
if (!client) {
|
|
55
|
-
throw new Error(`[plugin] 1rst argument should be an instance of Client`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (!name) {
|
|
59
|
-
throw new Error(`[plugin] 2nd argument should be a valid name`);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Instance of the soundworks client
|
|
63
|
-
* @see {client.Client}
|
|
64
|
-
* @type {String}
|
|
65
|
-
*/
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.client = client;
|
|
69
|
-
/**
|
|
70
|
-
* Name of the plugin, as defined on registration.
|
|
71
|
-
* @type {String}
|
|
72
|
-
*/
|
|
73
|
-
|
|
74
|
-
this.name = name;
|
|
75
|
-
/**
|
|
76
|
-
* Options of the plugin.
|
|
77
|
-
* @type {Object}
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
this.options = {};
|
|
81
|
-
/**
|
|
82
|
-
* Signals defining the process state.
|
|
83
|
-
* @type {Object}
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
/** @private */
|
|
87
|
-
|
|
88
|
-
this.signals = {
|
|
89
|
-
start: new _SignalAll.default(),
|
|
90
|
-
started: new _Signal.default(),
|
|
91
|
-
ready: new _Signal.default(),
|
|
92
|
-
errored: new _Signal.default() // @needs a payload
|
|
93
|
-
|
|
94
|
-
}; // start when all required signals are fired
|
|
95
|
-
|
|
96
|
-
this.signals.start.addObserver(() => this.start());
|
|
97
|
-
this.started = this.started.bind(this);
|
|
98
|
-
this.ready = this.ready.bind(this);
|
|
99
|
-
this.error = this.error.bind(this);
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Helper function to merge default options and user-defined options.
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* this.options = this.configure(defaults, options);
|
|
106
|
-
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
configure(defaults, options) {
|
|
110
|
-
return (0, _lodash.default)({}, defaults, options);
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Interface method to override when implementing child class.
|
|
114
|
-
*
|
|
115
|
-
* _Important: the derived class MUST call {@link client.AbstractPlugin#started}
|
|
116
|
-
* and {@link client.AbstractPlugin#ready} to notify soundworks about the
|
|
117
|
-
* state of the plugin_
|
|
118
|
-
*
|
|
119
|
-
* @see {client.AbstractPlugin#started}
|
|
120
|
-
* @see {client.AbstractPlugin#ready}
|
|
121
|
-
*
|
|
122
|
-
* @example
|
|
123
|
-
* class MyDelayPlugin extends AbstractPlugin {
|
|
124
|
-
* // ...
|
|
125
|
-
* async start() {
|
|
126
|
-
* this.state = await this.client.stateManager.attach(`s:${this.name}`);
|
|
127
|
-
* this.started();
|
|
128
|
-
* // do [async] stuff
|
|
129
|
-
* setTimeout(() => this.ready(), 3000);
|
|
130
|
-
* }
|
|
131
|
-
* }
|
|
132
|
-
*/
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
start() {
|
|
136
|
-
throw new Error(`plugin "${this.name}": "start()" not implemented or "super.start()" called`);
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Lifecyle method to call in the {@link client.AbstractPlugin#start} method
|
|
140
|
-
* when the plugin is effectively started, as it may have to
|
|
141
|
-
* do some asynchonous job at start (e.g. creating a shared state, waiting for
|
|
142
|
-
* user input, etc.).
|
|
143
|
-
*
|
|
144
|
-
* _Must be called between before {@link client.AbstractPlugin#ready}._
|
|
145
|
-
*
|
|
146
|
-
* @see {client.AbstractPlugin#start}
|
|
147
|
-
* @see {client.AbstractPlugin#ready}
|
|
148
|
-
*
|
|
149
|
-
* @example
|
|
150
|
-
* class MyDelayPlugin extends AbstractPlugin {
|
|
151
|
-
* // start() is executed when the `start` signal pass to `true`
|
|
152
|
-
* async start() {
|
|
153
|
-
* this.state = await this.client.stateManager.attach(`s:${this.name}`);
|
|
154
|
-
* this.started();
|
|
155
|
-
* // do [async] stuff
|
|
156
|
-
* setTimeout(() => this.ready(), 3000);
|
|
157
|
-
* }
|
|
158
|
-
* }
|
|
159
|
-
*/
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
started() {
|
|
163
|
-
// @note - these check are mostly there for development help. Could be
|
|
164
|
-
// replaced with decorators.
|
|
165
|
-
if (this.signals.start.value === false) {
|
|
166
|
-
throw new Error(`plugin "${this.name}" cannot "started" before "start"`);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (this.signals.started.value === true) {
|
|
170
|
-
throw new Error(`plugin "${this.name}" cannot be "started" twice`);
|
|
171
|
-
} // @note - this as no strong incidence on the initialization lifecycle,
|
|
172
|
-
// maybe should be enforced
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
log(`> plugin "${this.name}" started`);
|
|
176
|
-
this.signals.started.value = true;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Lifecyle method to call in the {@link client.AbstractPlugin#start} method
|
|
180
|
-
* when the plugin has completely finished its initialization should be
|
|
181
|
-
* considered as ready. Calling this method notify soundworks that the
|
|
182
|
-
* initialization process can continue or that the application can start
|
|
183
|
-
* safely (cf. {@link client.AbstractExperience#start})
|
|
184
|
-
*
|
|
185
|
-
* @see {client.AbstractPlugin#start}
|
|
186
|
-
* @see {client.AbstractPlugin#started}
|
|
187
|
-
* @see {client.AbstractExperience#start}
|
|
188
|
-
*
|
|
189
|
-
* @example
|
|
190
|
-
* class MyDelayPlugin extends AbstractPlugin {
|
|
191
|
-
* // ...
|
|
192
|
-
* async start() {
|
|
193
|
-
* this.state = await this.client.stateManager.attach(`s:${this.name}`);
|
|
194
|
-
* this.started();
|
|
195
|
-
* // do [async] stuff
|
|
196
|
-
* setTimeout(() => this.ready(), 3000);
|
|
197
|
-
* }
|
|
198
|
-
* }
|
|
199
|
-
*/
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
ready() {
|
|
203
|
-
// @note - these check are mostly there for development help. Could be
|
|
204
|
-
// replaced with decorators.
|
|
205
|
-
if (this.signals.start.value === false) {
|
|
206
|
-
throw new Error(`plugin "${this.name}" cannot "ready" before "start"`);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (this.signals.started.value === false) {
|
|
210
|
-
throw new Error(`plugin "${this.name}" cannot "ready" before "started"`);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (this.signals.ready.value === true) {
|
|
214
|
-
throw new Error(`plugin "${this.name}" cannot be "ready" twice`);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
log(`> plugin "${this.name}" ready`);
|
|
218
|
-
this.signals.ready.value = true;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
error(msg) {
|
|
222
|
-
log(`> plugin "${this.name}" error: ${msg}`);
|
|
223
|
-
this.signals.errored.msg = msg;
|
|
224
|
-
this.signals.errored.value = true;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
var _default = AbstractPlugin;
|
|
230
|
-
exports.default = _default;
|