@soundworks/core 3.7.0 → 4.0.0-alpha.0

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.
Files changed (124) hide show
  1. package/.eslintrc +16 -0
  2. package/LICENSE +1 -1
  3. package/README.md +32 -30
  4. package/package.json +48 -28
  5. package/src/client/Client.js +391 -0
  6. package/src/client/Context.js +225 -0
  7. package/src/client/ContextManager.js +111 -0
  8. package/src/client/Plugin.js +66 -0
  9. package/src/client/PluginManager.js +123 -0
  10. package/src/client/SharedState.js +84 -0
  11. package/src/client/Socket.js +389 -0
  12. package/src/client/StateManager.js +67 -0
  13. package/src/client/index.js +77 -0
  14. package/src/common/BasePlugin.js +163 -0
  15. package/src/common/BasePluginManager.js +227 -0
  16. package/{common/SharedState.js → src/common/BaseSharedState.js} +198 -234
  17. package/src/common/BaseStateManager.js +200 -0
  18. package/{common → src/common}/ParameterBag.js +74 -112
  19. package/{common → src/common}/SharedStatePrivate.js +56 -62
  20. package/src/common/constants.js +51 -0
  21. package/src/common/logger.js +154 -0
  22. package/src/common/promise-store.js +25 -0
  23. package/src/common/sockets-utils.js +73 -0
  24. package/src/common/utils.js +22 -0
  25. package/src/server/Client.js +50 -0
  26. package/src/server/Context.js +99 -0
  27. package/src/server/ContextManager.js +266 -0
  28. package/src/server/Plugin.js +77 -0
  29. package/src/server/PluginManager.js +150 -0
  30. package/src/server/Server.js +849 -0
  31. package/src/server/SharedState.js +86 -0
  32. package/{server → src/server}/Socket.js +114 -88
  33. package/{server → src/server}/Sockets.js +73 -60
  34. package/{common/SharedStateManagerServer.js → src/server/StateManager.js} +181 -129
  35. package/src/server/audit-network-latency.worker.js +57 -0
  36. package/src/server/audit-schema.js +42 -0
  37. package/src/server/index.js +45 -0
  38. package/tsconfig.json +21 -0
  39. package/types/client/Client.d.ts +194 -0
  40. package/types/client/Client.d.ts.map +1 -0
  41. package/types/client/Context.d.ts +139 -0
  42. package/types/client/Context.d.ts.map +1 -0
  43. package/types/client/ContextManager.d.ts +45 -0
  44. package/types/client/ContextManager.d.ts.map +1 -0
  45. package/types/client/Plugin.d.ts +53 -0
  46. package/types/client/Plugin.d.ts.map +1 -0
  47. package/types/client/PluginManager.d.ts +96 -0
  48. package/types/client/PluginManager.d.ts.map +1 -0
  49. package/types/client/SharedState.d.ts +85 -0
  50. package/types/client/SharedState.d.ts.map +1 -0
  51. package/types/client/Socket.d.ts +138 -0
  52. package/types/client/Socket.d.ts.map +1 -0
  53. package/types/client/StateManager.d.ts +72 -0
  54. package/types/client/StateManager.d.ts.map +1 -0
  55. package/types/client/index.d.ts +11 -0
  56. package/types/client/index.d.ts.map +1 -0
  57. package/types/common/BasePlugin.d.ts +145 -0
  58. package/types/common/BasePlugin.d.ts.map +1 -0
  59. package/types/common/BasePluginManager.d.ts +88 -0
  60. package/types/common/BasePluginManager.d.ts.map +1 -0
  61. package/types/common/BaseSharedState.d.ts +173 -0
  62. package/types/common/BaseSharedState.d.ts.map +1 -0
  63. package/types/common/BaseStateManager.d.ts +70 -0
  64. package/types/common/BaseStateManager.d.ts.map +1 -0
  65. package/types/common/ParameterBag.d.ts +143 -0
  66. package/types/common/ParameterBag.d.ts.map +1 -0
  67. package/types/common/SharedStatePrivate.d.ts +20 -0
  68. package/types/common/SharedStatePrivate.d.ts.map +1 -0
  69. package/types/common/constants.d.ts +35 -0
  70. package/types/common/constants.d.ts.map +1 -0
  71. package/types/common/logger.d.ts +16 -0
  72. package/types/common/logger.d.ts.map +1 -0
  73. package/types/common/promise-store.d.ts +4 -0
  74. package/types/common/promise-store.d.ts.map +1 -0
  75. package/types/common/sockets-utils.d.ts +9 -0
  76. package/types/common/sockets-utils.d.ts.map +1 -0
  77. package/types/common/utils.d.ts +5 -0
  78. package/types/common/utils.d.ts.map +1 -0
  79. package/types/server/Client.d.ts +40 -0
  80. package/types/server/Client.d.ts.map +1 -0
  81. package/types/server/Context.d.ts +59 -0
  82. package/types/server/Context.d.ts.map +1 -0
  83. package/types/server/ContextManager.d.ts +69 -0
  84. package/types/server/ContextManager.d.ts.map +1 -0
  85. package/types/server/Plugin.d.ts +70 -0
  86. package/types/server/Plugin.d.ts.map +1 -0
  87. package/types/server/PluginManager.d.ts +91 -0
  88. package/types/server/PluginManager.d.ts.map +1 -0
  89. package/types/server/Server.d.ts +223 -0
  90. package/types/server/Server.d.ts.map +1 -0
  91. package/types/server/SharedState.d.ts +86 -0
  92. package/types/server/SharedState.d.ts.map +1 -0
  93. package/types/server/Socket.d.ts +128 -0
  94. package/types/server/Socket.d.ts.map +1 -0
  95. package/types/server/Sockets.d.ts +73 -0
  96. package/types/server/Sockets.d.ts.map +1 -0
  97. package/types/server/StateManager.d.ts +190 -0
  98. package/types/server/StateManager.d.ts.map +1 -0
  99. package/types/server/audit-network-latency.worker.d.ts +2 -0
  100. package/types/server/audit-network-latency.worker.d.ts.map +1 -0
  101. package/types/server/audit-schema.d.ts +27 -0
  102. package/types/server/audit-schema.d.ts.map +1 -0
  103. package/types/server/index.d.ts +7 -0
  104. package/types/server/index.d.ts.map +1 -0
  105. package/client/AbstractExperience.js +0 -54
  106. package/client/AbstractPlugin.js +0 -230
  107. package/client/Client.js +0 -193
  108. package/client/PluginManager.js +0 -279
  109. package/client/Socket.js +0 -346
  110. package/client/index.js +0 -48
  111. package/client.js +0 -28
  112. package/common/SharedStateManagerClient.js +0 -194
  113. package/common/Signal.js +0 -40
  114. package/common/SignalAll.js +0 -44
  115. package/common/logger.js +0 -162
  116. package/common/shared-state-utils.js +0 -89
  117. package/common/sockets-encoder-decoder.js +0 -73
  118. package/server/AbstractExperience.js +0 -126
  119. package/server/AbstractPlugin.js +0 -214
  120. package/server/Client.js +0 -70
  121. package/server/PluginManager.js +0 -273
  122. package/server/Server.js +0 -785
  123. package/server/index.js +0 -49
  124. package/server.js +0 -28
@@ -0,0 +1,200 @@
1
+ import SharedState from './BaseSharedState.js';
2
+ import {
3
+ CREATE_REQUEST,
4
+ CREATE_RESPONSE,
5
+ CREATE_ERROR,
6
+ ATTACH_REQUEST,
7
+ ATTACH_RESPONSE,
8
+ ATTACH_ERROR,
9
+ OBSERVE_REQUEST,
10
+ OBSERVE_RESPONSE,
11
+ OBSERVE_NOTIFICATION,
12
+ UNOBSERVE_NOTIFICATION,
13
+ DELETE_SCHEMA,
14
+ } from './constants.js';
15
+ import {
16
+ storeRequestPromise,
17
+ resolveRequest,
18
+ rejectRequest,
19
+ } from './promise-store.js';
20
+
21
+ /**
22
+ * @private
23
+ */
24
+ class BaseStateManager {
25
+ /**
26
+ * @param {Number} id - Id of the node.
27
+ * @param {Object} transport - Transport to use for synchronizing the state.
28
+ * Must implement a basic EventEmitter API.
29
+ */
30
+ constructor(id, transport) {
31
+ this.client = { id, transport };
32
+
33
+ this._statesById = new Map();
34
+ this._observeListeners = new Set();
35
+ this._cachedSchemas = new Map();
36
+ this._observeRequestCallbacks = new Map();
37
+
38
+ // ---------------------------------------------
39
+ // CREATE
40
+ // ---------------------------------------------
41
+
42
+ this.client.transport.addListener(CREATE_RESPONSE, (reqId, stateId, remoteId, schemaName, schema, initValues) => {
43
+
44
+ // cache schema when first dealing it to save some bandwidth
45
+ if (!this._cachedSchemas.has(schemaName)) {
46
+ this._cachedSchemas.set(schemaName, schema);
47
+ }
48
+
49
+ schema = this._cachedSchemas.get(schemaName);
50
+
51
+ const state = new SharedState(stateId, remoteId, schemaName, schema, this.client, true, this, initValues);
52
+ this._statesById.set(state.id, state);
53
+
54
+ resolveRequest(reqId, state);
55
+ });
56
+
57
+ this.client.transport.addListener(CREATE_ERROR, (reqId, msg) => {
58
+ rejectRequest(reqId, msg);
59
+ });
60
+
61
+ // ---------------------------------------------
62
+ // ATTACH (when creator, is attached by default)
63
+ // ---------------------------------------------
64
+ this.client.transport.addListener(ATTACH_RESPONSE, (reqId, stateId, remoteId, schemaName, schema, currentValues) => {
65
+ // cache schema when first dealing with it to save some bandwidth
66
+ // note: when we make the schemas dynamic at some point
67
+ // the server should be able to invalidate the schema and send
68
+ // it again despite the caching.
69
+ if (!this._cachedSchemas.has(schemaName)) {
70
+ this._cachedSchemas.set(schemaName, schema);
71
+ }
72
+
73
+ schema = this._cachedSchemas.get(schemaName);
74
+
75
+ const state = new SharedState(stateId, remoteId, schemaName, schema, this.client, false, this, currentValues);
76
+ this._statesById.set(state.id, state);
77
+
78
+ resolveRequest(reqId, state);
79
+ });
80
+
81
+ this.client.transport.addListener(ATTACH_ERROR, (reqId, msg) => {
82
+ rejectRequest(reqId, msg);
83
+ });
84
+
85
+ // ---------------------------------------------
86
+ // OBSERVE PEERS (be notified when a state is created, lazy)
87
+ // ---------------------------------------------
88
+ this.client.transport.addListener(OBSERVE_RESPONSE, async (reqId, ...list) => {
89
+ // retrieve the callback that have been stored in observe to make sure
90
+ // we don't call another callback that may have been registered earlier.
91
+ const callback = this._observeRequestCallbacks.get(reqId);
92
+ this._observeRequestCallbacks.delete(reqId);
93
+
94
+ const promises = list.map(([schemaName, stateId, nodeId]) => {
95
+ return callback(schemaName, stateId, nodeId);
96
+ });
97
+
98
+ await Promise.all(promises);
99
+
100
+ const unsubscribe = () => {
101
+ this._observeListeners.delete(callback);
102
+
103
+ if (this._observeListeners.size === 0) {
104
+ this.client.transport.emit(UNOBSERVE_NOTIFICATION);
105
+ }
106
+ };
107
+ resolveRequest(reqId, unsubscribe);
108
+ });
109
+
110
+ this.client.transport.addListener(OBSERVE_NOTIFICATION, (...list) => {
111
+ list.forEach(([schemaName, stateId, nodeId]) => {
112
+ this._observeListeners.forEach(callback => callback(schemaName, stateId, nodeId));
113
+ });
114
+ });
115
+
116
+ // ---------------------------------------------
117
+ // Clear cache when schema is deleted
118
+ // ---------------------------------------------
119
+ this.client.transport.addListener(DELETE_SCHEMA, schemaName => {
120
+ this._cachedSchemas.delete(schemaName);
121
+ });
122
+ }
123
+
124
+ /**
125
+ * Create a `SharedState` instance from a registered schema.
126
+ *
127
+ * @param {String} schemaName - Name of the schema as given on registration
128
+ * (cf. ServerStateManager)
129
+ * @param {Object} [initValues={}] - Default values for the state.
130
+ * @returns {client.SharedState|server.SharedState}
131
+ * @see {@link client.SharedState}
132
+ * @see {@link server.SharedState}
133
+ * @example
134
+ * const state = await client.stateManager.create('my-schema');
135
+ */
136
+ async create(schemaName, initValues = {}) {
137
+ return new Promise((resolve, reject) => {
138
+ const reqId = storeRequestPromise(resolve, reject);
139
+ const requireSchema = this._cachedSchemas.has(schemaName) ? false : true;
140
+ this.client.transport.emit(CREATE_REQUEST, reqId, schemaName, requireSchema, initValues);
141
+ });
142
+ }
143
+
144
+ /**
145
+ * Attach to an existing `SharedState` instance.
146
+ *
147
+ * @param {String} schemaName - Name of the schema as given on registration
148
+ * (cf. ServerStateManager)
149
+ * @param {Object} [stateId=null] - Id of the state to attach to. If `null`,
150
+ * attach to the first state found with the given schema name (usefull for
151
+ * globally shared states owned by the server).
152
+ * @returns {client.SharedState|server.SharedState}
153
+ * @see {@link client.SharedState}
154
+ * @see {@link server.SharedState}
155
+ * @example
156
+ * const state = await client.stateManager.attach('my-schema');
157
+ */
158
+ async attach(schemaName, stateId = null) {
159
+ return new Promise((resolve, reject) => {
160
+ // @todo - add a timeout
161
+ const reqId = storeRequestPromise(resolve, reject);
162
+ const requireSchema = this._cachedSchemas.has(schemaName) ? false : true;
163
+ this.client.transport.emit(ATTACH_REQUEST, reqId, schemaName, stateId, requireSchema);
164
+ });
165
+ }
166
+
167
+ /**
168
+ * Observe all the `SharedState` instances that are created on the network.
169
+ * This can be usefull for clients with some controller role that might want to track
170
+ * the state of all other clients of the application, to monitor them and/or take
171
+ * control over them from a single point.
172
+ *
173
+ * @todo Optionnal schema name
174
+ * @param {server.StateManager~ObserveCallback|client.StateManager~ObserveCallback}
175
+ * callback - Function to be called when a new state is created on the network.
176
+ * @returns {Promise<Function>} - Return a Promise that resolves when the callback
177
+ * as been executed for the first time. The promise value is a function which
178
+ * allows to stop observing the network.
179
+ * @example
180
+ * client.stateManager.observe(async (schemaName, stateId, nodeId) => {
181
+ * if (schemaName === 'something') {
182
+ * const state = await this.client.stateManager.attach(schemaName, stateId);
183
+ * console.log(state.getValues());
184
+ * }
185
+ * });
186
+ */
187
+ async observe(callback) {
188
+ this._observeListeners.add(callback);
189
+ // store function
190
+ return new Promise((resolve, reject) => {
191
+ const reqId = storeRequestPromise(resolve, reject);
192
+ // store the callback to be executed on the response
193
+ this._observeRequestCallbacks.set(reqId, callback);
194
+ this.client.transport.emit(OBSERVE_REQUEST, reqId);
195
+ });
196
+ }
197
+ }
198
+
199
+ export default BaseStateManager;
200
+
@@ -1,18 +1,5 @@
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';
1
+ import cloneDeep from 'lodash.clonedeep';
2
+ import equal from 'fast-deep-equal';
16
3
 
17
4
  /**
18
5
  * @typedef {Object} server.SharedStateManagerServer~schema
@@ -44,7 +31,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
44
31
  * }
45
32
  * }
46
33
  */
47
-
48
34
  /**
49
35
  * @typedef {Object} server.SharedStateManagerServer~schemaBooleanDef
50
36
  *
@@ -62,15 +48,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
62
48
  * (which has no state per se). As such, setting this options to `false` if
63
49
  * `event=true` does not make sens.
64
50
  * @property {Boolean} [immediate=false] - Setting this option to `true` will
65
- * trigger any change (e.g. call the subscribe listeners) immediately on the
51
+ * trigger any change (e.g. call the `onUpdate` listeners) immediately on the
66
52
  * state that generate the update (i.e. calling `set`), before propagating the
67
53
  * change on the network. This option can be usefull in cases the network
68
54
  * 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
55
+ * the value is overriden server-side (e.g. in an `updateHook`) the listeners
70
56
  * will be called again on when the "real" / final value will be received.
71
57
  * @property {Object} [metas={}] - Optionnal metadata of the parameter.
72
58
  */
73
-
74
59
  /**
75
60
  * @typedef {Object} server.SharedStateManagerServer~schemaStringDef
76
61
  *
@@ -88,15 +73,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
88
73
  * (which has no state per se). As such, setting this options to `false` if
89
74
  * `event=true` does not make sens.
90
75
  * @property {Boolean} [immediate=false] - Setting this option to `true` will
91
- * trigger any change (e.g. call the subscribe listeners) immediately on the
76
+ * trigger any change (e.g. call the `onUpdate` listeners) immediately on the
92
77
  * state that generate the update (i.e. calling `set`), before propagating the
93
78
  * change on the network. This option can be usefull in cases the network
94
79
  * 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
80
+ * the value is overriden server-side (e.g. in an `updateHook`) the listeners
96
81
  * will be called again on when the "real" / final value will be received.
97
82
  * @property {Object} [metas={}] - Optionnal metadata of the parameter.
98
83
  */
99
-
100
84
  /**
101
85
  @typedef {Object} server.SharedStateManagerServer~schemaIntegerDef
102
86
  *
@@ -116,15 +100,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
116
100
  * (which has no state per se). As such, setting this options to `false` if
117
101
  * `event=true` does not make sens.
118
102
  * @property {Boolean} [immediate=false] - Setting this option to `true` will
119
- * trigger any change (e.g. call the subscribe listeners) immediately on the
103
+ * trigger any change (e.g. call the `onUpdate` listeners) immediately on the
120
104
  * state that generate the update (i.e. calling `set`), before propagating the
121
105
  * change on the network. This option can be usefull in cases the network
122
106
  * 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
107
+ * the value is overriden server-side (e.g. in an `updateHook`) the listeners
124
108
  * will be called again on when the "real" / final value will be received.
125
109
  * @property {Object} [metas={}] - Optionnal metadata of the parameter.
126
110
  */
127
-
128
111
  /**
129
112
  * @typedef {Object} server.SharedStateManagerServer~schemaFloatDef
130
113
  *
@@ -144,15 +127,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
144
127
  * (which has no state per se). As such, setting this options to `false` if
145
128
  * `event=true` does not make sens.
146
129
  * @property {Boolean} [immediate=false] - Setting this option to `true` will
147
- * trigger any change (e.g. call the subscribe listeners) immediately on the
130
+ * trigger any change (e.g. call the `onUpdate` listeners) immediately on the
148
131
  * state that generate the update (i.e. calling `set`), before propagating the
149
132
  * change on the network. This option can be usefull in cases the network
150
133
  * 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
134
+ * the value is overriden server-side (e.g. in an `updateHook`) the listeners
152
135
  * will be called again on when the "real" / final value will be received.
153
136
  * @property {Object} [metas={}] - Optionnal metadata of the parameter.
154
137
  */
155
-
156
138
  /**
157
139
  * @typedef {Object} server.SharedStateManagerServer~schemaEnumDef
158
140
  *
@@ -171,15 +153,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
171
153
  * (which has no state per se). As such, setting this options to `false` if
172
154
  * `event=true` does not make sens.
173
155
  * @property {Boolean} [immediate=false] - Setting this option to `true` will
174
- * trigger any change (e.g. call the subscribe listeners) immediately on the
156
+ * trigger any change (e.g. call the `onUpdate` listeners) immediately on the
175
157
  * state that generate the update (i.e. calling `set`), before propagating the
176
158
  * change on the network. This option can be usefull in cases the network
177
159
  * 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
160
+ * the value is overriden server-side (e.g. in an `updateHook`) the listeners
179
161
  * will be called again on when the "real" / final value will be received.
180
162
  * @property {Object} [metas={}] - Optionnal metadata of the parameter.
181
163
  */
182
-
183
164
  /**
184
165
  * @typedef {Object} server.SharedStateManagerServer~schemaAnyDef
185
166
  *
@@ -200,65 +181,59 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
200
181
  * (which has no state per se). As such, setting this options to `false` if
201
182
  * `event=true` does not make sens.
202
183
  * @property {Boolean} [immediate=false] - Setting this option to `true` will
203
- * trigger any change (e.g. call the subscribe listeners) immediately on the
184
+ * trigger any change (e.g. call the `onUpdate` listeners) immediately on the
204
185
  * state that generate the update (i.e. calling `set`), before propagating the
205
186
  * change on the network. This option can be usefull in cases the network
206
187
  * 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
188
+ * the value is overriden server-side (e.g. in an `updateHook`) the listeners
208
189
  * will be called again on when the "real" / final value will be received.
209
190
  * @property {Object} [metas={}] - Optionnal metadata of the parameter.
210
191
  */
211
- const sharedOptions = {
192
+
193
+ export const sharedOptions = {
212
194
  nullable: false,
213
- event: false,
214
- // if event=true, nullable=true
195
+ event: false, // if event=true, nullable=true
215
196
  metas: {},
216
197
  filterChange: true,
217
- immediate: false
198
+ immediate: false,
218
199
  };
219
- exports.sharedOptions = sharedOptions;
220
- const types = {
200
+
201
+ export const types = {
221
202
  boolean: {
222
203
  required: ['default'],
223
-
224
204
  get defaultOptions() {
225
- return Object.assign((0, _lodash.default)(sharedOptions), {});
205
+ return Object.assign(cloneDeep(sharedOptions), {});
226
206
  },
227
-
228
207
  coerceFunction: (name, def, value) => {
229
208
  if (typeof value !== 'boolean') {
230
209
  throw new TypeError(`[stateManager] Invalid value for boolean param "${name}": ${value}`);
231
210
  }
232
211
 
233
212
  return value;
234
- }
213
+ },
235
214
  },
236
215
  string: {
237
216
  required: ['default'],
238
-
239
217
  get defaultOptions() {
240
- return Object.assign((0, _lodash.default)(sharedOptions), {});
218
+ return Object.assign(cloneDeep(sharedOptions), {});
241
219
  },
242
-
243
220
  coerceFunction: (name, def, value) => {
244
221
  if (typeof value !== 'string') {
245
222
  throw new TypeError(`[stateManager] Invalid value for string param "${name}": ${value}`);
246
223
  }
247
224
 
248
225
  return value;
249
- }
226
+ },
250
227
  },
251
228
  integer: {
252
229
  required: ['default'],
253
-
254
230
  get defaultOptions() {
255
- return Object.assign((0, _lodash.default)(sharedOptions), {
231
+ return Object.assign(cloneDeep(sharedOptions), {
256
232
  min: -Infinity,
257
- max: +Infinity
233
+ max: +Infinity,
258
234
  });
259
235
  },
260
-
261
- sanitizeSchema: def => {
236
+ sanitizeSchema: (def) => {
262
237
  // sanitize `null` values in received schema, this prevent a bug when
263
238
  // `min` and `max` are explicitely set to `±Infinity`, the schema is stringified
264
239
  // when sent over the network and therefore Infinity is transformed to `null`
@@ -281,19 +256,17 @@ const types = {
281
256
  }
282
257
 
283
258
  return Math.max(def.min, Math.min(def.max, value));
284
- }
259
+ },
285
260
  },
286
261
  float: {
287
262
  required: ['default'],
288
-
289
263
  get defaultOptions() {
290
- return Object.assign((0, _lodash.default)(sharedOptions), {
264
+ return Object.assign(cloneDeep(sharedOptions), {
291
265
  min: -Infinity,
292
- max: +Infinity
266
+ max: +Infinity,
293
267
  });
294
268
  },
295
-
296
- sanitizeSchema: def => {
269
+ sanitizeSchema: (def) => {
297
270
  // sanitize `null` values in received schema, this prevent a bug when
298
271
  // `min` and `max` are explicitely set to `±Infinity`, the schema is stringified
299
272
  // when sent over the network and therefore Infinity is transformed to `null`
@@ -311,49 +284,44 @@ const types = {
311
284
  return def;
312
285
  },
313
286
  coerceFunction: (name, def, value) => {
314
- if (typeof value !== 'number' || value !== value) {
315
- // reject NaN
287
+ if (typeof value !== 'number' || value !== value) { // reject NaN
316
288
  throw new TypeError(`[stateManager] Invalid value for float param "${name}": ${value}`);
317
289
  }
318
290
 
319
291
  return Math.max(def.min, Math.min(def.max, value));
320
- }
292
+ },
321
293
  },
322
294
  enum: {
323
295
  required: ['default', 'list'],
324
-
325
296
  get defaultOptions() {
326
- return Object.assign((0, _lodash.default)(sharedOptions), {});
297
+ return Object.assign(cloneDeep(sharedOptions), {});
327
298
  },
328
-
329
299
  coerceFunction: (name, def, value) => {
330
300
  if (def.list.indexOf(value) === -1) {
331
301
  throw new TypeError(`[stateManager] Invalid value for enum param "${name}": ${value}`);
332
302
  }
333
303
 
304
+
334
305
  return value;
335
- }
306
+ },
336
307
  },
337
308
  any: {
338
309
  required: ['default'],
339
-
340
310
  get defaultOptions() {
341
- return Object.assign((0, _lodash.default)(sharedOptions), {});
311
+ return Object.assign(cloneDeep(sharedOptions), {});
342
312
  },
343
-
344
313
  coerceFunction: (name, def, value) => {
345
314
  // no check as it can have any type...
346
315
  return value;
347
- }
348
- }
316
+ },
317
+ },
349
318
  };
319
+
320
+
350
321
  /**
351
322
  * Bag of parameters.
352
323
  * @private
353
324
  */
354
-
355
- exports.types = types;
356
-
357
325
  class ParameterBag {
358
326
  static validateSchema(schema) {
359
327
  for (let name in schema) {
@@ -368,8 +336,10 @@ class ParameterBag {
368
336
  }
369
337
 
370
338
  const required = types[def.type].required;
339
+
371
340
  required.forEach(key => {
372
- if (def.event === true && key === 'default') {// do nothing, default is always null for `event` params
341
+ if (def.event === true && key === 'default') {
342
+ // do nothing, default is always null for `event` params
373
343
  } else if (!Object.prototype.hasOwnProperty.call(def, key)) {
374
344
  throw new TypeError(`[stateManager] Invalid schema definition - param "${name}" (type "${def.type}"): "${key}" key is required`);
375
345
  }
@@ -382,8 +352,9 @@ class ParameterBag {
382
352
  throw new Error(`[stateManager] schema is mandatory`);
383
353
  }
384
354
 
385
- schema = (0, _lodash.default)(schema);
386
- initValues = (0, _lodash.default)(initValues);
355
+ schema = cloneDeep(schema);
356
+ initValues = cloneDeep(initValues);
357
+
387
358
  /**
388
359
  * List of parameters.
389
360
  *
@@ -393,8 +364,8 @@ class ParameterBag {
393
364
  * @instance
394
365
  * @private
395
366
  */
396
-
397
367
  this._values = {};
368
+
398
369
  /**
399
370
  * List of schema with init values.
400
371
  *
@@ -404,10 +375,11 @@ class ParameterBag {
404
375
  * @instance
405
376
  * @private
406
377
  */
407
-
408
378
  this._schema = {};
409
- ParameterBag.validateSchema(schema); // make shure initValues make sens according to the given schema
410
379
 
380
+ ParameterBag.validateSchema(schema);
381
+
382
+ // make shure initValues make sens according to the given schema
411
383
  for (let name in initValues) {
412
384
  if (!Object.prototype.hasOwnProperty.call(schema, name)) {
413
385
  throw new ReferenceError(`[stateManager] init value defined for undefined param "${name}"`);
@@ -419,12 +391,10 @@ class ParameterBag {
419
391
  def = types[def.type].sanitizeSchema(def);
420
392
  }
421
393
 
422
- const {
423
- defaultOptions
424
- } = types[def.type];
425
- def = Object.assign({}, defaultOptions, def); // if event property is set to true, the param must
394
+ const { defaultOptions } = types[def.type];
395
+ def = Object.assign({}, defaultOptions, def);
396
+ // if event property is set to true, the param must
426
397
  // be nullable and its default value is `undefined`
427
-
428
398
  if (def.event === true) {
429
399
  def.nullable = true;
430
400
  def.default = null;
@@ -438,31 +408,32 @@ class ParameterBag {
438
408
  initValue = def.default;
439
409
  }
440
410
 
441
- this._schema[name] = def; // coerce init value and store in definition
442
411
 
412
+ this._schema[name] = def;
413
+ // coerce init value and store in definition
443
414
  initValue = this.set(name, initValue)[0];
415
+
444
416
  this._schema[name].initValue = initValue;
445
417
  this._values[name] = initValue;
418
+
446
419
  }
447
420
  }
421
+
448
422
  /**
449
423
  * Define if the parameter exists.
450
424
  *
451
425
  * @param {String} name - Name of the parameter.
452
426
  * @return {Boolean}
453
427
  */
454
-
455
-
456
428
  has(name) {
457
429
  return Object.prototype.hasOwnProperty.call(this._schema, name);
458
430
  }
431
+
459
432
  /**
460
433
  * Return values of all parameters as a flat object.
461
434
  *
462
435
  * @return {Object}
463
436
  */
464
-
465
-
466
437
  getValues() {
467
438
  let values = {};
468
439
 
@@ -472,6 +443,7 @@ class ParameterBag {
472
443
 
473
444
  return values;
474
445
  }
446
+
475
447
  /**
476
448
  * Return the value of the given parameter. If the parameter is of `any` type,
477
449
  * a deep copy is returned.
@@ -479,19 +451,18 @@ class ParameterBag {
479
451
  * @param {String} name - Name of the parameter.
480
452
  * @return {Mixed} - Value of the parameter.
481
453
  */
482
-
483
-
484
454
  get(name) {
485
455
  if (!this.has(name)) {
486
456
  throw new ReferenceError(`[stateManager] Cannot get value of undefined parameter "${name}"`);
487
457
  }
488
458
 
489
459
  if (this._schema[name].type === 'any') {
490
- return (0, _lodash.default)(this._values[name]);
460
+ return cloneDeep(this._values[name]);
491
461
  } else {
492
462
  return this._values[name];
493
463
  }
494
464
  }
465
+
495
466
  /**
496
467
  * Set the value of a parameter. If the value of the parameter is updated
497
468
  * (aka if previous value is different from new value) all registered
@@ -503,17 +474,13 @@ class ParameterBag {
503
474
  * if the value has not changed.
504
475
  * @return {Array} - [new value, updated flag].
505
476
  */
506
-
507
-
508
477
  set(name, value) {
509
478
  if (!this.has(name)) {
510
479
  throw new ReferenceError(`[stateManager] Cannot set value of undefined parameter "${name}"`);
511
480
  }
512
481
 
513
482
  const def = this._schema[name];
514
- const {
515
- coerceFunction
516
- } = types[def.type];
483
+ const { coerceFunction } = types[def.type];
517
484
 
518
485
  if (value === null && def.nullable === false) {
519
486
  throw new TypeError(`[stateManager] Invalid value for ${def.type} param "${name}": value is null and param is not nullable`);
@@ -524,11 +491,14 @@ class ParameterBag {
524
491
  }
525
492
 
526
493
  const currentValue = this._values[name];
527
- const updated = !(0, _fastDeepEqual.default)(currentValue, value);
528
- this._values[name] = value; // return tuple so that the state manager can handle the `filterChange` option
494
+ const updated = !equal(currentValue, value);
495
+
496
+ this._values[name] = value;
529
497
 
498
+ // return tuple so that the state manager can handle the `filterChange` option
530
499
  return [value, updated];
531
500
  }
501
+
532
502
  /**
533
503
  * Reset a parameter to its initialization values. Reset all parameters if no argument.
534
504
  * @note - prefer `state.set(state.getInitValues())`
@@ -551,8 +521,6 @@ class ParameterBag {
551
521
  *
552
522
  * @return {Object}
553
523
  */
554
-
555
-
556
524
  getSchema(name = null) {
557
525
  if (name === null) {
558
526
  return this._schema;
@@ -563,31 +531,25 @@ class ParameterBag {
563
531
 
564
532
  return this._schema[name];
565
533
  }
566
- } // return the default value, if initValue has been given, return init values
567
-
534
+ }
568
535
 
536
+ // return the default value, if initValue has been given, return init values
569
537
  getInitValues() {
570
538
  const initValues = {};
571
-
572
539
  for (let [name, def] of Object.entries(this._schema)) {
573
540
  initValues[name] = def.initValue;
574
541
  }
575
-
576
542
  return initValues;
577
- } // return the default value, if initValue has been given, return init values
578
-
543
+ }
579
544
 
545
+ // return the default value, if initValue has been given, return init values
580
546
  getDefaults() {
581
547
  const defaults = {};
582
-
583
548
  for (let [name, def] of Object.entries(this._schema)) {
584
549
  defaults[name] = def.defaults;
585
550
  }
586
-
587
551
  return defaults;
588
552
  }
589
-
590
553
  }
591
554
 
592
- var _default = ParameterBag;
593
- exports.default = _default;
555
+ export default ParameterBag;