@soundworks/core 4.0.0-alpha.2 → 4.0.0-alpha.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/.eslintrc CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "extends": [
3
3
  "@ircam",
4
- "plugin:jsdoc/recommended"
5
4
  ],
6
5
  "settings": {
7
6
  "jsdoc": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soundworks/core",
3
- "version": "4.0.0-alpha.2",
3
+ "version": "4.0.0-alpha.3",
4
4
  "description": "Open-source creative coding framework for distributed applications based on Web technologies",
5
5
  "authors": [
6
6
  "Benjamin Matuszewski",
@@ -17,7 +17,7 @@ export const types = {
17
17
  },
18
18
  coerceFunction: (name, def, value) => {
19
19
  if (typeof value !== 'boolean') {
20
- throw new TypeError(`[stateManager] Invalid value for boolean param "${name}": ${value}`);
20
+ throw new TypeError(`[SharedState] Invalid value for boolean param "${name}": ${value}`);
21
21
  }
22
22
 
23
23
  return value;
@@ -30,7 +30,7 @@ export const types = {
30
30
  },
31
31
  coerceFunction: (name, def, value) => {
32
32
  if (typeof value !== 'string') {
33
- throw new TypeError(`[stateManager] Invalid value for string param "${name}": ${value}`);
33
+ throw new TypeError(`[SharedState] Invalid value for string param "${name}": ${value}`);
34
34
  }
35
35
 
36
36
  return value;
@@ -63,7 +63,7 @@ export const types = {
63
63
  },
64
64
  coerceFunction: (name, def, value) => {
65
65
  if (!(typeof value === 'number' && Math.floor(value) === value)) {
66
- throw new TypeError(`[stateManager] Invalid value for integer param "${name}": ${value}`);
66
+ throw new TypeError(`[SharedState] Invalid value for integer param "${name}": ${value}`);
67
67
  }
68
68
 
69
69
  return Math.max(def.min, Math.min(def.max, value));
@@ -96,7 +96,7 @@ export const types = {
96
96
  },
97
97
  coerceFunction: (name, def, value) => {
98
98
  if (typeof value !== 'number' || value !== value) { // reject NaN
99
- throw new TypeError(`[stateManager] Invalid value for float param "${name}": ${value}`);
99
+ throw new TypeError(`[SharedState] Invalid value for float param "${name}": ${value}`);
100
100
  }
101
101
 
102
102
  return Math.max(def.min, Math.min(def.max, value));
@@ -109,7 +109,7 @@ export const types = {
109
109
  },
110
110
  coerceFunction: (name, def, value) => {
111
111
  if (def.list.indexOf(value) === -1) {
112
- throw new TypeError(`[stateManager] Invalid value for enum param "${name}": ${value}`);
112
+ throw new TypeError(`[SharedState] Invalid value for enum param "${name}": ${value}`);
113
113
  }
114
114
 
115
115
 
@@ -139,11 +139,11 @@ class ParameterBag {
139
139
  const def = schema[name];
140
140
 
141
141
  if (!Object.prototype.hasOwnProperty.call(def, 'type')) {
142
- throw new TypeError(`[stateManager] Invalid schema definition - param "${name}": "type" key is required`);
142
+ throw new TypeError(`[StateManager.registerSchema] Invalid schema definition - param "${name}": "type" key is required`);
143
143
  }
144
144
 
145
145
  if (!Object.prototype.hasOwnProperty.call(types, def.type)) {
146
- throw new TypeError(`[stateManager] Invalid schema definition - param "${name}": "{ type: '${def.type}' }" does not exists`);
146
+ throw new TypeError(`[StateManager.registerSchema] Invalid schema definition - param "${name}": "{ type: '${def.type}' }" does not exists`);
147
147
  }
148
148
 
149
149
  const required = types[def.type].required;
@@ -152,7 +152,7 @@ class ParameterBag {
152
152
  if (def.event === true && key === 'default') {
153
153
  // do nothing, default is always null for `event` params
154
154
  } else if (!Object.prototype.hasOwnProperty.call(def, key)) {
155
- throw new TypeError(`[stateManager] Invalid schema definition - param "${name}" (type "${def.type}"): "${key}" key is required`);
155
+ throw new TypeError(`[StateManager.registerSchema] Invalid schema definition - param "${name}" (type "${def.type}"): "${key}" key is required`);
156
156
  }
157
157
  });
158
158
  }
@@ -160,7 +160,7 @@ class ParameterBag {
160
160
 
161
161
  constructor(schema, initValues = {}) {
162
162
  if (!schema) {
163
- throw new Error(`[stateManager] schema is mandatory`);
163
+ throw new Error(`[ParameterBag] schema is mandatory`);
164
164
  }
165
165
 
166
166
  schema = cloneDeep(schema);
@@ -193,7 +193,7 @@ class ParameterBag {
193
193
  // make shure initValues make sens according to the given schema
194
194
  for (let name in initValues) {
195
195
  if (!Object.prototype.hasOwnProperty.call(schema, name)) {
196
- throw new ReferenceError(`[stateManager] init value defined for undefined param "${name}"`);
196
+ throw new ReferenceError(`[StateManager.create] init value defined for undefined param "${name}"`);
197
197
  }
198
198
  }
199
199
 
@@ -264,10 +264,12 @@ class ParameterBag {
264
264
  */
265
265
  get(name) {
266
266
  if (!this.has(name)) {
267
- throw new ReferenceError(`[stateManager] Cannot get value of undefined parameter "${name}"`);
267
+ throw new ReferenceError(`[SharedState] Cannot get value of undefined parameter "${name}"`);
268
268
  }
269
269
 
270
270
  if (this._schema[name].type === 'any') {
271
+ // we return a deep copy of the object as we don't want the client code to
272
+ // be able to modify our underlying data.
271
273
  return cloneDeep(this._values[name]);
272
274
  } else {
273
275
  return this._values[name];
@@ -287,14 +289,14 @@ class ParameterBag {
287
289
  */
288
290
  set(name, value) {
289
291
  if (!this.has(name)) {
290
- throw new ReferenceError(`[stateManager] Cannot set value of undefined parameter "${name}"`);
292
+ throw new ReferenceError(`[SharedState] Cannot set value of undefined parameter "${name}"`);
291
293
  }
292
294
 
293
295
  const def = this._schema[name];
294
296
  const { coerceFunction } = types[def.type];
295
297
 
296
298
  if (value === null && def.nullable === false) {
297
- throw new TypeError(`[stateManager] Invalid value for ${def.type} param "${name}": value is null and param is not nullable`);
299
+ throw new TypeError(`[SharedState] Invalid value for ${def.type} param "${name}": value is null and param is not nullable`);
298
300
  } else if (value === null && def.nullable === true) {
299
301
  value = null;
300
302
  } else {
@@ -304,6 +306,16 @@ class ParameterBag {
304
306
  const currentValue = this._values[name];
305
307
  const updated = !equal(currentValue, value);
306
308
 
309
+ // we store a deep copy of the object as we don't want the client to be able
310
+ // to modify our underlying data, which leads unexpected behavior where the
311
+ // deep equal check to returns true, and therefore the update is not triggered.
312
+ //
313
+ // @see tests/common.state-manager.spec.js
314
+ // 'should copy stored value for "any" type to have a predictable behavior'
315
+ if (this._schema[name].type === 'any') {
316
+ value = cloneDeep(value);
317
+ }
318
+
307
319
  this._values[name] = value;
308
320
 
309
321
  // return tuple so that the state manager can handle the `filterChange` option
@@ -337,7 +349,7 @@ class ParameterBag {
337
349
  return this._schema;
338
350
  } else {
339
351
  if (!this.has(name)) {
340
- throw new ReferenceError(`[stateManager] Cannot get schema description of undefined parameter "${name}"`);
352
+ throw new ReferenceError(`[SharedState] Cannot get schema description of undefined parameter "${name}"`);
341
353
  }
342
354
 
343
355
  return this._schema[name];
@@ -1,3 +1,5 @@
1
+ import isPlainObj from 'is-plain-obj';
2
+
1
3
  // https://stackoverflow.com/questions/17575790/environment-detection-node-js-or-browser
2
4
  export const isBrowser = new Function('try {return this===window;}catch(e){ return false;}');
3
5
 
@@ -20,3 +22,7 @@ export function isFunction(func) {
20
22
  Object.prototype.toString.call(func) == '[object AsyncFunction]';
21
23
  }
22
24
 
25
+ export function isPlainObject(obj) {
26
+ return isPlainObj(obj);
27
+ }
28
+
@@ -648,6 +648,10 @@ Invalid certificate files, please check your:
648
648
 
649
649
  await this._dispatchStatus('started');
650
650
 
651
+ if (this.config.env.type === 'development') {
652
+ logger.log(`\n> press "${chalk.bold('Ctrl + C')}" to exit`);
653
+ }
654
+
651
655
  resolve();
652
656
  });
653
657
  });
@@ -5,6 +5,7 @@ import clonedeep from 'lodash.clonedeep';
5
5
  import BaseStateManager from '../common/BaseStateManager.js';
6
6
  import ParameterBag from '../common/ParameterBag.js';
7
7
  import SharedStatePrivate from '../common/SharedStatePrivate.js';
8
+ import { isString, isPlainObject } from '../common/utils.js';
8
9
  import {
9
10
  SERVER_ID,
10
11
  CREATE_REQUEST,
@@ -514,10 +515,18 @@ class StateManager extends BaseStateManager {
514
515
  * })
515
516
  */
516
517
  registerSchema(schemaName, schema) {
518
+ if (!isString(schemaName)) {
519
+ throw new Error(`[stateManager.registerSchema] Invalid schema name "${schemaName}", should be a string`);
520
+ }
521
+
517
522
  if (this._schemas.has(schemaName)) {
518
523
  throw new Error(`[stateManager.registerSchema] cannot register schema with name: "${schemaName}", schema name already exists`);
519
524
  }
520
525
 
526
+ if (!isPlainObject(schema)) {
527
+ throw new Error(`[stateManager.registerSchema] Invalid schema, should be an object`);
528
+ }
529
+
521
530
  ParameterBag.validateSchema(schema);
522
531
 
523
532
  this._schemas.set(schemaName, clonedeep(schema));