@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
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.types = exports.sharedOptions = exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _lodash = _interopRequireDefault(require("lodash.clonedeep"));
|
|
9
|
+
|
|
10
|
+
var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal"));
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
// import types from './types';
|
|
15
|
+
// import shallowClone from 'shallow-clone';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Object} server.SharedStateManagerServer~schema
|
|
19
|
+
*
|
|
20
|
+
* Description of a schema to be register by the {@link server.ServerStateManagerServer}
|
|
21
|
+
* A schema consists of a combinaison of key value pairs where the key is the
|
|
22
|
+
* name of the parameter, and the value is an object describing the parameter.
|
|
23
|
+
*
|
|
24
|
+
* Available types are:
|
|
25
|
+
* - {@link server.SharedStateManagerServer~schemaBooleanDef}
|
|
26
|
+
* - {@link server.SharedStateManagerServer~schemaStringDef}
|
|
27
|
+
* - {@link server.SharedStateManagerServer~schemaIntegerDef}
|
|
28
|
+
* - {@link server.SharedStateManagerServer~schemaFloatDef}
|
|
29
|
+
* - {@link server.SharedStateManagerServer~schemaEnumDef}
|
|
30
|
+
* - {@link server.SharedStateManagerServer~schemaAnyDef}
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* {
|
|
34
|
+
* myBoolean: {
|
|
35
|
+
* type: 'boolean'
|
|
36
|
+
* default: false,
|
|
37
|
+
* },
|
|
38
|
+
* myFloat: {
|
|
39
|
+
* type: 'float'
|
|
40
|
+
* default: 0.1,
|
|
41
|
+
* min: -1,
|
|
42
|
+
* max: 1,
|
|
43
|
+
* event: true,
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @typedef {Object} server.SharedStateManagerServer~schemaBooleanDef
|
|
50
|
+
*
|
|
51
|
+
* @property {String} type='boolean' - Define a boolean parameter.
|
|
52
|
+
* @property {Boolean} default - Default value of the parameter.
|
|
53
|
+
* @property {Boolean} [nullable=false] - Define if the parameter is nullable. If
|
|
54
|
+
* set to `true` the parameter `default` is set to `null`.
|
|
55
|
+
* @property {Boolean} [event=false] - Define if the parameter is a volatile, e.g.
|
|
56
|
+
* set its value back to `null` after propagation. When `true`, `nullable` is
|
|
57
|
+
* automatically set to `true` and `default` to `null`.
|
|
58
|
+
* @property {Boolean} [filterChange=true] - Setting this option to `false` forces
|
|
59
|
+
* the propagation of a parameter even when its value do not change. It
|
|
60
|
+
* offers a kind of middle ground between the default bahavior (e.g. where
|
|
61
|
+
* only changed values are propagated) and the behavior of the `event` option
|
|
62
|
+
* (which has no state per se). As such, setting this options to `false` if
|
|
63
|
+
* `event=true` does not make sens.
|
|
64
|
+
* @property {Boolean} [immediate=false] - Setting this option to `true` will
|
|
65
|
+
* trigger any change (e.g. call the subscribe listeners) immediately on the
|
|
66
|
+
* state that generate the update (i.e. calling `set`), before propagating the
|
|
67
|
+
* change on the network. This option can be usefull in cases the network
|
|
68
|
+
* would introduce a noticeable latency on the client. If for some reason
|
|
69
|
+
* the value is overriden server-side (e.g. in an updateHook) the listeners
|
|
70
|
+
* will be called again on when the "real" / final value will be received.
|
|
71
|
+
* @property {Object} [metas={}] - Optionnal metadata of the parameter.
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @typedef {Object} server.SharedStateManagerServer~schemaStringDef
|
|
76
|
+
*
|
|
77
|
+
* @property {String} type='string' - Define a boolean parameter.
|
|
78
|
+
* @property {Mixed} default - Default value of the parameter.
|
|
79
|
+
* @property {Boolean} [nullable=false] - Define if the parameter is nullable. If
|
|
80
|
+
* set to `true` the parameter `default` is set to `null`.
|
|
81
|
+
* @property {Boolean} [event=false] - Define if the parameter is a volatile, e.g.
|
|
82
|
+
* set its value back to `null` after propagation. When `true`, `nullable` is
|
|
83
|
+
* automatically set to `true` and `default` to `null`.
|
|
84
|
+
* @property {Boolean} [filterChange=true] - Setting this option to `false` forces
|
|
85
|
+
* the propagation of a parameter even when its value do not change. It
|
|
86
|
+
* offers a kind of middle ground between the default bahavior (e.g. where
|
|
87
|
+
* only changed values are propagated) and the behavior of the `event` option
|
|
88
|
+
* (which has no state per se). As such, setting this options to `false` if
|
|
89
|
+
* `event=true` does not make sens.
|
|
90
|
+
* @property {Boolean} [immediate=false] - Setting this option to `true` will
|
|
91
|
+
* trigger any change (e.g. call the subscribe listeners) immediately on the
|
|
92
|
+
* state that generate the update (i.e. calling `set`), before propagating the
|
|
93
|
+
* change on the network. This option can be usefull in cases the network
|
|
94
|
+
* would introduce a noticeable latency on the client. If for some reason
|
|
95
|
+
* the value is overriden server-side (e.g. in an updateHook) the listeners
|
|
96
|
+
* will be called again on when the "real" / final value will be received.
|
|
97
|
+
* @property {Object} [metas={}] - Optionnal metadata of the parameter.
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
@typedef {Object} server.SharedStateManagerServer~schemaIntegerDef
|
|
102
|
+
*
|
|
103
|
+
* @property {String} type='integer' - Define a boolean parameter.
|
|
104
|
+
* @property {Mixed} default - Default value of the parameter.
|
|
105
|
+
* @property {Number} [min=-Infinity] - Minimum value of the parameter.
|
|
106
|
+
* @property {Number} [max=+Infinity] - Maximum value of the parameter.
|
|
107
|
+
* @property {Boolean} [nullable=false] - Define if the parameter is nullable. If
|
|
108
|
+
* set to `true` the parameter `default` is set to `null`.
|
|
109
|
+
* @property {Boolean} [event=false] - Define if the parameter is a volatile, e.g.
|
|
110
|
+
* set its value back to `null` after propagation. When `true`, `nullable` is
|
|
111
|
+
* automatically set to `true` and `default` to `null`.
|
|
112
|
+
* @property {Boolean} [filterChange=true] - Setting this option to `false` forces
|
|
113
|
+
* the propagation of a parameter even when its value do not change. It
|
|
114
|
+
* offers a kind of middle ground between the default bahavior (e.g. where
|
|
115
|
+
* only changed values are propagated) and the behavior of the `event` option
|
|
116
|
+
* (which has no state per se). As such, setting this options to `false` if
|
|
117
|
+
* `event=true` does not make sens.
|
|
118
|
+
* @property {Boolean} [immediate=false] - Setting this option to `true` will
|
|
119
|
+
* trigger any change (e.g. call the subscribe listeners) immediately on the
|
|
120
|
+
* state that generate the update (i.e. calling `set`), before propagating the
|
|
121
|
+
* change on the network. This option can be usefull in cases the network
|
|
122
|
+
* would introduce a noticeable latency on the client. If for some reason
|
|
123
|
+
* the value is overriden server-side (e.g. in an updateHook) the listeners
|
|
124
|
+
* will be called again on when the "real" / final value will be received.
|
|
125
|
+
* @property {Object} [metas={}] - Optionnal metadata of the parameter.
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @typedef {Object} server.SharedStateManagerServer~schemaFloatDef
|
|
130
|
+
*
|
|
131
|
+
* @property {String} [type='float'] - Float parameter.
|
|
132
|
+
* @property {Mixed} default - Default value.
|
|
133
|
+
* @property {Number} [min=-Infinity] - Minimum value.
|
|
134
|
+
* @property {Number} [max=+Infinity] - Maximum value.
|
|
135
|
+
* @property {Boolean} [nullable=false] - Define if the parameter is nullable. If
|
|
136
|
+
* set to `true` the parameter `default` is set to `null`.
|
|
137
|
+
* @property {Boolean} [event=false] - Define if the parameter is a volatile, e.g.
|
|
138
|
+
* set its value back to `null` after propagation. When `true`, `nullable` is
|
|
139
|
+
* automatically set to `true` and `default` to `null`.
|
|
140
|
+
* @property {Boolean} [filterChange=true] - Setting this option to `false` forces
|
|
141
|
+
* the propagation of a parameter even when its value do not change. It
|
|
142
|
+
* offers a kind of middle ground between the default bahavior (e.g. where
|
|
143
|
+
* only changed values are propagated) and the behavior of the `event` option
|
|
144
|
+
* (which has no state per se). As such, setting this options to `false` if
|
|
145
|
+
* `event=true` does not make sens.
|
|
146
|
+
* @property {Boolean} [immediate=false] - Setting this option to `true` will
|
|
147
|
+
* trigger any change (e.g. call the subscribe listeners) immediately on the
|
|
148
|
+
* state that generate the update (i.e. calling `set`), before propagating the
|
|
149
|
+
* change on the network. This option can be usefull in cases the network
|
|
150
|
+
* would introduce a noticeable latency on the client. If for some reason
|
|
151
|
+
* the value is overriden server-side (e.g. in an updateHook) the listeners
|
|
152
|
+
* will be called again on when the "real" / final value will be received.
|
|
153
|
+
* @property {Object} [metas={}] - Optionnal metadata of the parameter.
|
|
154
|
+
*/
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @typedef {Object} server.SharedStateManagerServer~schemaEnumDef
|
|
158
|
+
*
|
|
159
|
+
* @property {String} [type='enum'] - Enum parameter.
|
|
160
|
+
* @property {Mixed} default - Default value of the parameter.
|
|
161
|
+
* @property {Array} list - Possible values of the parameter.
|
|
162
|
+
* @property {Boolean} [nullable=false] - Define if the parameter is nullable. If
|
|
163
|
+
* set to `true` the parameter `default` is set to `null`.
|
|
164
|
+
* @property {Boolean} [event=false] - Define if the parameter is a volatile, e.g.
|
|
165
|
+
* set its value back to `null` after propagation. When `true`, `nullable` is
|
|
166
|
+
* automatically set to `true` and `default` to `null`.
|
|
167
|
+
* @property {Boolean} [filterChange=true] - Setting this option to `false` forces
|
|
168
|
+
* the propagation of a parameter even when its value do not change. It
|
|
169
|
+
* offers a kind of middle ground between the default bahavior (e.g. where
|
|
170
|
+
* only changed values are propagated) and the behavior of the `event` option
|
|
171
|
+
* (which has no state per se). As such, setting this options to `false` if
|
|
172
|
+
* `event=true` does not make sens.
|
|
173
|
+
* @property {Boolean} [immediate=false] - Setting this option to `true` will
|
|
174
|
+
* trigger any change (e.g. call the subscribe listeners) immediately on the
|
|
175
|
+
* state that generate the update (i.e. calling `set`), before propagating the
|
|
176
|
+
* change on the network. This option can be usefull in cases the network
|
|
177
|
+
* would introduce a noticeable latency on the client. If for some reason
|
|
178
|
+
* the value is overriden server-side (e.g. in an updateHook) the listeners
|
|
179
|
+
* will be called again on when the "real" / final value will be received.
|
|
180
|
+
* @property {Object} [metas={}] - Optionnal metadata of the parameter.
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @typedef {Object} server.SharedStateManagerServer~schemaAnyDef
|
|
185
|
+
*
|
|
186
|
+
* Note that the `any` type always return a shallow copy of the state internal
|
|
187
|
+
* value. Mutating the returned value will not modify the internal state.
|
|
188
|
+
*
|
|
189
|
+
* @property {String} [type='any'] - Parameter of any type.
|
|
190
|
+
* @property {Mixed} default - Default value of the parameter.
|
|
191
|
+
* @property {Boolean} [nullable=false] - Define if the parameter is nullable. If
|
|
192
|
+
* set to `true` the parameter `default` is set to `null`.
|
|
193
|
+
* @property {Boolean} [event=false] - Define if the parameter is a volatile, e.g.
|
|
194
|
+
* set its value back to `null` after propagation. When `true`, `nullable` is
|
|
195
|
+
* automatically set to `true` and `default` to `null`.
|
|
196
|
+
* @property {Boolean} [filterChange=true] - Setting this option to `false` forces
|
|
197
|
+
* the propagation of a parameter even when its value do not change. It
|
|
198
|
+
* offers a kind of middle ground between the default bahavior (e.g. where
|
|
199
|
+
* only changed values are propagated) and the behavior of the `event` option
|
|
200
|
+
* (which has no state per se). As such, setting this options to `false` if
|
|
201
|
+
* `event=true` does not make sens.
|
|
202
|
+
* @property {Boolean} [immediate=false] - Setting this option to `true` will
|
|
203
|
+
* trigger any change (e.g. call the subscribe listeners) immediately on the
|
|
204
|
+
* state that generate the update (i.e. calling `set`), before propagating the
|
|
205
|
+
* change on the network. This option can be usefull in cases the network
|
|
206
|
+
* would introduce a noticeable latency on the client. If for some reason
|
|
207
|
+
* the value is overriden server-side (e.g. in an updateHook) the listeners
|
|
208
|
+
* will be called again on when the "real" / final value will be received.
|
|
209
|
+
* @property {Object} [metas={}] - Optionnal metadata of the parameter.
|
|
210
|
+
*/
|
|
211
|
+
const sharedOptions = {
|
|
212
|
+
nullable: false,
|
|
213
|
+
event: false,
|
|
214
|
+
// if event=true, nullable=true
|
|
215
|
+
metas: {},
|
|
216
|
+
filterChange: true,
|
|
217
|
+
immediate: false
|
|
218
|
+
};
|
|
219
|
+
exports.sharedOptions = sharedOptions;
|
|
220
|
+
const types = {
|
|
221
|
+
boolean: {
|
|
222
|
+
required: ['default'],
|
|
223
|
+
|
|
224
|
+
get defaultOptions() {
|
|
225
|
+
return Object.assign((0, _lodash.default)(sharedOptions), {});
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
coerceFunction: (name, def, value) => {
|
|
229
|
+
if (typeof value !== 'boolean') {
|
|
230
|
+
throw new TypeError(`[stateManager] Invalid value for boolean param "${name}": ${value}`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return value;
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
string: {
|
|
237
|
+
required: ['default'],
|
|
238
|
+
|
|
239
|
+
get defaultOptions() {
|
|
240
|
+
return Object.assign((0, _lodash.default)(sharedOptions), {});
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
coerceFunction: (name, def, value) => {
|
|
244
|
+
if (typeof value !== 'string') {
|
|
245
|
+
throw new TypeError(`[stateManager] Invalid value for string param "${name}": ${value}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return value;
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
integer: {
|
|
252
|
+
required: ['default'],
|
|
253
|
+
|
|
254
|
+
get defaultOptions() {
|
|
255
|
+
return Object.assign((0, _lodash.default)(sharedOptions), {
|
|
256
|
+
min: -Infinity,
|
|
257
|
+
max: +Infinity
|
|
258
|
+
});
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
coerceFunction: (name, def, value) => {
|
|
262
|
+
if (!(typeof value === 'number' && Math.floor(value) === value)) {
|
|
263
|
+
throw new TypeError(`[stateManager] Invalid value for integer param "${name}": ${value}`);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return Math.max(def.min, Math.min(def.max, value));
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
float: {
|
|
270
|
+
required: ['default'],
|
|
271
|
+
|
|
272
|
+
get defaultOptions() {
|
|
273
|
+
return Object.assign((0, _lodash.default)(sharedOptions), {
|
|
274
|
+
min: -Infinity,
|
|
275
|
+
max: +Infinity
|
|
276
|
+
});
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
coerceFunction: (name, def, value) => {
|
|
280
|
+
if (typeof value !== 'number' || value !== value) {
|
|
281
|
+
// reject NaN
|
|
282
|
+
throw new TypeError(`[stateManager] Invalid value for float param "${name}": ${value}`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return Math.max(def.min, Math.min(def.max, value));
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
enum: {
|
|
289
|
+
required: ['default', 'list'],
|
|
290
|
+
|
|
291
|
+
get defaultOptions() {
|
|
292
|
+
return Object.assign((0, _lodash.default)(sharedOptions), {});
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
coerceFunction: (name, def, value) => {
|
|
296
|
+
if (def.list.indexOf(value) === -1) {
|
|
297
|
+
throw new TypeError(`[stateManager] Invalid value for enum param "${name}": ${value}`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return value;
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
any: {
|
|
304
|
+
required: ['default'],
|
|
305
|
+
|
|
306
|
+
get defaultOptions() {
|
|
307
|
+
return Object.assign((0, _lodash.default)(sharedOptions), {});
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
coerceFunction: (name, def, value) => {
|
|
311
|
+
// no check as it can have any type...
|
|
312
|
+
return value;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
/**
|
|
317
|
+
* Bag of parameters.
|
|
318
|
+
* @private
|
|
319
|
+
*/
|
|
320
|
+
|
|
321
|
+
exports.types = types;
|
|
322
|
+
|
|
323
|
+
class ParameterBag {
|
|
324
|
+
static validateSchema(schema) {
|
|
325
|
+
for (let name in schema) {
|
|
326
|
+
const def = schema[name];
|
|
327
|
+
|
|
328
|
+
if (!def.hasOwnProperty('type')) {
|
|
329
|
+
throw new TypeError(`[stateManager] Invalid schema definition - param "${name}": "type" key is required`);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (!types.hasOwnProperty(def.type)) {
|
|
333
|
+
throw new TypeError(`[stateManager] Invalid schema definition - param "${name}": "{ type: '${def.type}' }" does not exists`);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const required = types[def.type].required;
|
|
337
|
+
required.forEach(function (key) {
|
|
338
|
+
if (def.event === true && key === 'default') {// do nothing, default is always null for `event` params
|
|
339
|
+
} else if (!def.hasOwnProperty(key)) {
|
|
340
|
+
throw new TypeError(`[stateManager] Invalid schema definition - param "${name}" (type "${def.type}"): "${key}" key is required`);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
constructor(schema, initValues = {}) {
|
|
347
|
+
if (!schema) {
|
|
348
|
+
throw new Error(`[stateManager] schema is mandatory`);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
schema = (0, _lodash.default)(schema);
|
|
352
|
+
initValues = (0, _lodash.default)(initValues);
|
|
353
|
+
/**
|
|
354
|
+
* List of parameters.
|
|
355
|
+
*
|
|
356
|
+
* @type {Object<String, Param>}
|
|
357
|
+
* @name _params
|
|
358
|
+
* @memberof ParameterBag
|
|
359
|
+
* @instance
|
|
360
|
+
* @private
|
|
361
|
+
*/
|
|
362
|
+
|
|
363
|
+
this._values = {};
|
|
364
|
+
/**
|
|
365
|
+
* List of schema with init values.
|
|
366
|
+
*
|
|
367
|
+
* @type {Object<String, paramDefinition>}
|
|
368
|
+
* @name _schema
|
|
369
|
+
* @memberof ParameterBag
|
|
370
|
+
* @instance
|
|
371
|
+
* @private
|
|
372
|
+
*/
|
|
373
|
+
|
|
374
|
+
this._schema = {};
|
|
375
|
+
ParameterBag.validateSchema(schema); // make shure initValues make sens according to the given schema
|
|
376
|
+
|
|
377
|
+
for (let name in initValues) {
|
|
378
|
+
if (!schema.hasOwnProperty(name)) {
|
|
379
|
+
throw new ReferenceError(`[stateManager] init value defined for undefined param "${name}"`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
for (let [name, def] of Object.entries(schema)) {
|
|
384
|
+
const {
|
|
385
|
+
defaultOptions,
|
|
386
|
+
coerceFunction
|
|
387
|
+
} = types[def.type];
|
|
388
|
+
def = Object.assign({}, defaultOptions, def); // if event property is set to true, the param must
|
|
389
|
+
// be nullable and its default value is `undefined`
|
|
390
|
+
|
|
391
|
+
if (def.event === true) {
|
|
392
|
+
def.nullable = true;
|
|
393
|
+
def.default = null;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
let initValue;
|
|
397
|
+
|
|
398
|
+
if (initValues.hasOwnProperty(name)) {
|
|
399
|
+
initValue = initValues[name];
|
|
400
|
+
} else {
|
|
401
|
+
initValue = def.default;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
this._schema[name] = def; // coerce init value and store in definition
|
|
405
|
+
|
|
406
|
+
initValue = this.set(name, initValue)[0];
|
|
407
|
+
this._schema[name].initValue = initValue;
|
|
408
|
+
this._values[name] = initValue;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Define if the parameter exists.
|
|
413
|
+
*
|
|
414
|
+
* @param {String} name - Name of the parameter.
|
|
415
|
+
* @return {Boolean}
|
|
416
|
+
*/
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
has(name) {
|
|
420
|
+
return this._schema.hasOwnProperty(name);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Return values of all parameters as a flat object.
|
|
424
|
+
*
|
|
425
|
+
* @return {Object}
|
|
426
|
+
*/
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
getValues() {
|
|
430
|
+
let values = {};
|
|
431
|
+
|
|
432
|
+
for (let name in this._values) {
|
|
433
|
+
values[name] = this.get(name);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return values;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Return the value of the given parameter. If the parameter is of `any` type,
|
|
440
|
+
* a deep copy is returned.
|
|
441
|
+
*
|
|
442
|
+
* @param {String} name - Name of the parameter.
|
|
443
|
+
* @return {Mixed} - Value of the parameter.
|
|
444
|
+
*/
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
get(name) {
|
|
448
|
+
if (!this.has(name)) {
|
|
449
|
+
throw new ReferenceError(`[stateManager] Cannot get value of undefined parameter "${name}"`);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (this._schema[name].type === 'any') {
|
|
453
|
+
return (0, _lodash.default)(this._values[name]);
|
|
454
|
+
} else {
|
|
455
|
+
return this._values[name];
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Set the value of a parameter. If the value of the parameter is updated
|
|
460
|
+
* (aka if previous value is different from new value) all registered
|
|
461
|
+
* callbacks are registered.
|
|
462
|
+
*
|
|
463
|
+
* @param {String} name - Name of the parameter.
|
|
464
|
+
* @param {Mixed} value - Value of the parameter.
|
|
465
|
+
* @param {Boolean} [forcePropagation=false] - if true, propagate value even
|
|
466
|
+
* if the value has not changed.
|
|
467
|
+
* @return {Array} - [new value, updated flag].
|
|
468
|
+
*/
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
set(name, value) {
|
|
472
|
+
if (!this.has(name)) {
|
|
473
|
+
throw new ReferenceError(`[stateManager] Cannot set value of undefined parameter "${name}"`);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const def = this._schema[name];
|
|
477
|
+
const {
|
|
478
|
+
coerceFunction
|
|
479
|
+
} = types[def.type];
|
|
480
|
+
|
|
481
|
+
if (value === null && def.nullable === false) {
|
|
482
|
+
throw new TypeError(`[stateManager] Invalid value for ${def.type} param "${name}": value is null and param is not nullable`);
|
|
483
|
+
} else if (value === null && def.nullable === true) {
|
|
484
|
+
value = value;
|
|
485
|
+
} else {
|
|
486
|
+
value = coerceFunction(name, def, value);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const currentValue = this._values[name];
|
|
490
|
+
const updated = !(0, _fastDeepEqual.default)(currentValue, value);
|
|
491
|
+
this._values[name] = value;
|
|
492
|
+
|
|
493
|
+
if (def.event === true) {
|
|
494
|
+
this._values[name] = null;
|
|
495
|
+
} // return tuple so that the state manager can handle the `filterChange` option
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
return [value, updated];
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Reset a parameter to its initialization values. Reset all parameters if no argument.
|
|
502
|
+
* @note - prefer `state.set(state.getInitValues())`
|
|
503
|
+
* or `state.set(state.getDefaultValues())`
|
|
504
|
+
*
|
|
505
|
+
* @param {String} [name=null] - Name of the parameter to reset.
|
|
506
|
+
*/
|
|
507
|
+
// reset(name = null) {
|
|
508
|
+
// if (name !== null) {
|
|
509
|
+
// this._params[name] = this._initValues[name];
|
|
510
|
+
// } else {
|
|
511
|
+
// for (let name in this.params) {
|
|
512
|
+
// this._params[name].reset();
|
|
513
|
+
// }
|
|
514
|
+
// }
|
|
515
|
+
// }
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Return the given schema along with the initialization values.
|
|
519
|
+
*
|
|
520
|
+
* @return {Object}
|
|
521
|
+
*/
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
getSchema(name = null) {
|
|
525
|
+
if (name === null) {
|
|
526
|
+
return this._schema;
|
|
527
|
+
} else {
|
|
528
|
+
if (!this.has(name)) {
|
|
529
|
+
throw new ReferenceError(`[stateManager] Cannot get schema description of undefined parameter "${name}"`);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
return this._schema[name];
|
|
533
|
+
}
|
|
534
|
+
} // return the default value, if initValue has been given, return init values
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
getInitValues() {
|
|
538
|
+
const initValues = {};
|
|
539
|
+
|
|
540
|
+
for (let [name, def] of Object.entries(this._schema)) {
|
|
541
|
+
initValues[name] = def.initValue;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
return initValues;
|
|
545
|
+
} // return the default value, if initValue has been given, return init values
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
getDefaults() {
|
|
549
|
+
const defaults = {};
|
|
550
|
+
|
|
551
|
+
for (let [name, def] of Object.entries(this._schema)) {
|
|
552
|
+
defaults[name] = def.defaults;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return defaults;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
var _default = ParameterBag;
|
|
561
|
+
exports.default = _default;
|