@soundworks/core 3.1.0-beta.2 → 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.
@@ -12,6 +12,7 @@ var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal"));
12
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
13
 
14
14
  // import types from './types';
15
+ // import shallowClone from 'shallow-clone';
15
16
 
16
17
  /**
17
18
  * @typedef {Object} server.SharedStateManagerServer~schema
@@ -182,6 +183,9 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
182
183
  /**
183
184
  * @typedef {Object} server.SharedStateManagerServer~schemaAnyDef
184
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
+ *
185
189
  * @property {String} [type='any'] - Parameter of any type.
186
190
  * @property {Mixed} default - Default value of the parameter.
187
191
  * @property {Boolean} [nullable=false] - Define if the parameter is nullable. If
@@ -209,8 +213,8 @@ const sharedOptions = {
209
213
  event: false,
210
214
  // if event=true, nullable=true
211
215
  metas: {},
212
- filterChange: true // immediate: false,
213
-
216
+ filterChange: true,
217
+ immediate: false
214
218
  };
215
219
  exports.sharedOptions = sharedOptions;
216
220
  const types = {
@@ -423,10 +427,17 @@ class ParameterBag {
423
427
 
424
428
 
425
429
  getValues() {
426
- return Object.assign({}, this._values);
430
+ let values = {};
431
+
432
+ for (let name in this._values) {
433
+ values[name] = this.get(name);
434
+ }
435
+
436
+ return values;
427
437
  }
428
438
  /**
429
- * Return the value of the given parameter.
439
+ * Return the value of the given parameter. If the parameter is of `any` type,
440
+ * a deep copy is returned.
430
441
  *
431
442
  * @param {String} name - Name of the parameter.
432
443
  * @return {Mixed} - Value of the parameter.
@@ -438,7 +449,11 @@ class ParameterBag {
438
449
  throw new ReferenceError(`[stateManager] Cannot get value of undefined parameter "${name}"`);
439
450
  }
440
451
 
441
- return this._values[name];
452
+ if (this._schema[name].type === 'any') {
453
+ return (0, _lodash.default)(this._values[name]);
454
+ } else {
455
+ return this._values[name];
456
+ }
442
457
  }
443
458
  /**
444
459
  * Set the value of a parameter. If the value of the parameter is updated
@@ -484,6 +499,8 @@ class ParameterBag {
484
499
  }
485
500
  /**
486
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())`
487
504
  *
488
505
  * @param {String} [name=null] - Name of the parameter to reset.
489
506
  */
@@ -46,20 +46,18 @@ ${JSON.stringify(initValues, null, 2)}`);
46
46
  this._onDetachCallbacks = new Set();
47
47
  this._onDeleteCallbacks = new Set(); // add listener for state updates
48
48
 
49
- client.transport.addListener(`${_sharedStateUtils.UPDATE_RESPONSE}-${id}-${this.remoteId}`, (reqId, updates, context) => {
50
- const updated = this._commit(updates, context, true, true);
51
-
49
+ client.transport.addListener(`${_sharedStateUtils.UPDATE_RESPONSE}-${id}-${this.remoteId}`, async (reqId, updates, context) => {
50
+ const updated = await this._commit(updates, context, true, true);
52
51
  (0, _sharedStateUtils.resolveRequest)(reqId, updated);
53
52
  }); // retrieve values but do not propagate to subscriptions
54
53
 
55
- client.transport.addListener(`${_sharedStateUtils.UPDATE_ABORT}-${id}-${this.remoteId}`, (reqId, updates, context) => {
56
- const updated = this._commit(updates, context, false, true);
57
-
54
+ client.transport.addListener(`${_sharedStateUtils.UPDATE_ABORT}-${id}-${this.remoteId}`, async (reqId, updates, context) => {
55
+ const updated = await this._commit(updates, context, false, true);
58
56
  (0, _sharedStateUtils.resolveRequest)(reqId, updated);
59
57
  });
60
- client.transport.addListener(`${_sharedStateUtils.UPDATE_NOTIFICATION}-${id}-${this.remoteId}`, (updates, context) => {
58
+ client.transport.addListener(`${_sharedStateUtils.UPDATE_NOTIFICATION}-${id}-${this.remoteId}`, async (updates, context) => {
61
59
  // cf. https://github.com/collective-soundworks/soundworks/issues/18
62
- this._commit(updates, context, true, false);
60
+ await this._commit(updates, context, true, false);
63
61
  }); // ---------------------------------------------
64
62
  // DELETE initiated by creator, or schema deleted
65
63
  // ---------------------------------------------
@@ -145,7 +143,7 @@ ${JSON.stringify(initValues, null, 2)}`);
145
143
  /** @private */
146
144
 
147
145
 
148
- _commit(updates, context, propagate = true, initiator = false) {
146
+ async _commit(updates, context, propagate = true, initiator = false) {
149
147
  const newValues = {};
150
148
  const oldValues = {};
151
149
 
@@ -154,7 +152,11 @@ ${JSON.stringify(initValues, null, 2)}`);
154
152
  immediate,
155
153
  filterChange,
156
154
  event
157
- } = this._parameters.getSchema(name);
155
+ } = this._parameters.getSchema(name); // @note 20211209 - we have an issue here server-side, because if the value
156
+ // is an object or an array, the reference is shared by everybody, therefore
157
+ // `changed` is always false and the new value is never propagated...
158
+ // FIXED - `state.get` now returns a deep copy when `type` is `any`
159
+
158
160
 
159
161
  const oldValue = this._parameters.get(name);
160
162
 
@@ -177,14 +179,37 @@ ${JSON.stringify(initValues, null, 2)}`);
177
179
  } // if the `UPDATE_REQUEST` as been aborted by the server, do not propagate
178
180
 
179
181
 
182
+ let promises = [];
183
+
180
184
  if (propagate && Object.keys(newValues).length > 0) {
181
- this._subscriptions.forEach(listener => listener(newValues, oldValues, context));
185
+ this._subscriptions.forEach(listener => {
186
+ promises.push(listener(newValues, oldValues, context));
187
+ });
182
188
  }
183
189
 
190
+ await Promise.all(promises);
184
191
  return newValues;
185
192
  }
186
193
  /**
187
- * Updates values of the state.
194
+ * Updates values of the state. Wait for all subscriptions to be resolved
195
+ * before resolving itself, i.e.:
196
+ *
197
+ * ```js
198
+ * const a = await server.stateManager.create('a');
199
+ * let asyncCallbackCalled = false;
200
+ *
201
+ * a.subscribe(updates => {
202
+ * return new Promise(resolve => {
203
+ * setTimeout(() => {
204
+ * asyncCallbackCalled = true;
205
+ * resolve();
206
+ * }, 100);
207
+ * });
208
+ * });
209
+ *
210
+ * await a.set({ bool: true });
211
+ * assert.equal(asyncCallbackCalled, true);
212
+ * ```
188
213
  *
189
214
  * @async
190
215
  * @param {Object} updates - key / value pairs of updates to apply to the state.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soundworks/core",
3
- "version": "3.1.0-beta.2",
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",
@@ -39,7 +39,6 @@
39
39
  "fast-deep-equal": "^3.1.3",
40
40
  "fast-text-encoding": "^1.0.0",
41
41
  "isomorphic-ws": "^4.0.1",
42
- "jsdoc-template": "^1.2.0",
43
42
  "keyv": "^4.0.3",
44
43
  "keyv-file": "^0.2.0",
45
44
  "lodash.clonedeep": "^4.5.0",