@onehat/data 1.21.15 → 1.21.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/data",
3
- "version": "1.21.15",
3
+ "version": "1.21.17",
4
4
  "description": "JS data modeling package with adapters for many storage mediums.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -21,12 +21,14 @@ export const MODE_REMOTE_WITH_OFFLINE = 'MODE_REMOTE_WITH_OFFLINE';
21
21
  * an AjaxRepository.
22
22
  *
23
23
  * Note: This is not a true subclass of Repository. Instead, its properties
24
- * and methods are Proxy'd from the "ActiveRepository", either the local or remote,
24
+ * and methods are Proxied from the "ActiveRepository", either the local or remote,
25
25
  * depending upon operating mode.
26
26
  *
27
27
  * Multiple operating modes:
28
- * - MODE_LOCAL_MIRROR
29
- * - This mode is for keeping local copies of data that doesn't change very often.
28
+ * - MODE_LOCAL_MIRROR (default mode)
29
+ * - This mode is for keeping local copies of data that don't change very often.
30
+ * - It's often used in apps for offline functionality--the app reads from this repository,
31
+ * and saves its commands to a CommandQueue repository.
30
32
  * - *Add/Edit/Delete operations are disabled.*
31
33
  * - First time in use, it loads its data from remote.
32
34
  * - From then on, it primarily depends upon local.
@@ -54,7 +56,7 @@ export const MODE_REMOTE_WITH_OFFLINE = 'MODE_REMOTE_WITH_OFFLINE';
54
56
  * Repository's remote repository type to be a CommandRepository.
55
57
  *
56
58
  *
57
- * - MODE_REMOTE_WITH_OFFLINE
59
+ * - MODE_REMOTE_WITH_OFFLINE (not currently implemented)
58
60
  * - This mode provides an offline backup to the normal operation of remote.
59
61
  * - Normally uses remote, but automatically switches to local if necessary (i.e. if offline).
60
62
  * - Any changes made while offline will be saved to a queue, and then replayed to remote
@@ -67,6 +69,8 @@ class LocalFromRemoteRepository extends EventEmitter {
67
69
  constructor(config = {}) {
68
70
  super(...arguments);
69
71
 
72
+ // OneHatData._createRepository has already created the local and remote repositories
73
+
70
74
  if (!config.local || !(config.local instanceof Repository)) {
71
75
  this.throwError('No local repository defined.');
72
76
  return;
@@ -138,7 +142,6 @@ class LocalFromRemoteRepository extends EventEmitter {
138
142
 
139
143
  };
140
144
  _.merge(this, defaults, config);
141
-
142
145
 
143
146
  if (this.mode !== MODE_LOCAL_MIRROR &&
144
147
  this.mode !== MODE_REMOTE_WITH_OFFLINE &&
@@ -166,9 +169,9 @@ class LocalFromRemoteRepository extends EventEmitter {
166
169
  */
167
170
  this.lastSync = null;
168
171
 
169
-
170
- // This ES6 Proxy allows us to create magic getters for all properties and methods
171
- // of the active Repository (local or remote)
172
+ // This ES6 Proxy allows us to create magic getters and setters for all properties and methods
173
+ // of the active Repository (local or remote). If they exist on the LocalFromRemote, those are used.
174
+ // Otherwise, the Proxy will pass the getter or setter to the active Repository.
172
175
  const oThis = this;
173
176
  this._proxy = new Proxy(this, {
174
177
  get (target, name, receiver) {
@@ -181,6 +184,14 @@ class LocalFromRemoteRepository extends EventEmitter {
181
184
  }
182
185
  return Reflect.get(target, name, receiver);
183
186
  },
187
+ set(target, name, value, receiver) {
188
+ if (Reflect.has(target, name)) {
189
+ return Reflect.set(target, name, value, receiver);
190
+ } else {
191
+ const activeRepo = oThis._getActiveRepository();
192
+ return Reflect.set(activeRepo, name, value);
193
+ }
194
+ },
184
195
  });
185
196
 
186
197
  return this._proxy; // Return the Proxy, not 'this'
@@ -191,12 +202,14 @@ class LocalFromRemoteRepository extends EventEmitter {
191
202
  * - Relays all events from sub-repositories
192
203
  */
193
204
  async initialize() {
194
- this.relayEventsFrom(this.remote, this.remote.getRegisteredEvents(), 'remote_');
195
- this.relayEventsFrom(this.local, this.local.getRegisteredEvents(), 'local_');
196
205
 
197
- // Relay events from activeRepository directly, without prefix
198
- const activeRepository = this._getActiveRepository();
199
- this.relayEventsFrom(activeRepository, activeRepository.getRegisteredEvents());
206
+ // // This is going to relay the events, but add a prefix to each
207
+ // this.relayEventsFrom(this.remote, this.remote.getRegisteredEvents(), 'remote_');
208
+ // this.relayEventsFrom(this.local, this.local.getRegisteredEvents(), 'local_');
209
+
210
+ // // Relay events from activeRepository directly, without prefix
211
+ // const activeRepository = this._getActiveRepository();
212
+ // this.relayEventsFrom(activeRepository, activeRepository.getRegisteredEvents());
200
213
 
201
214
  // Set up and initialize commands
202
215
  if (this.mode === MODE_COMMAND_QUEUE) {
@@ -211,6 +224,96 @@ class LocalFromRemoteRepository extends EventEmitter {
211
224
  }
212
225
  }
213
226
 
227
+ // ____ __ __
228
+ // / __ \_ _____ _____/ /___ ____ _____/ /____
229
+ // / / / / | / / _ \/ ___/ / __ \/ __ `/ __ / ___/
230
+ // / /_/ /| |/ / __/ / / / /_/ / /_/ / /_/ (__ )
231
+ // \____/ |___/\___/_/ /_/\____/\__,_/\__,_/____/
232
+
233
+ // The following methods are all overloads of EventEmitter methods.
234
+ // They determine whether the events they pertain to are registered on this
235
+ // LocalFromRemote class, or if they should be relayed to the active repository.
236
+
237
+ emit(name) { // NOTE: Purposefully do not use an arrow-function, so we have access to arguments
238
+ if (_.indexOf(this._registeredEvents, name) === -1) {
239
+ return this._getActiveRepository().emit(...arguments);
240
+ }
241
+ return super.emit(...arguments);
242
+ }
243
+ _emitAlt(name) {
244
+ if (_.indexOf(this._registeredEvents, name) === -1) {
245
+ return this._getActiveRepository()._emitAlt(...arguments);
246
+ }
247
+ return super._emitAlt(...arguments);
248
+ }
249
+ addListeners(names) {
250
+ const
251
+ registeredEvents = this._registeredEvents,
252
+ activeRepository = this._getActiveRepository();
253
+ _.each(names, (name) => {
254
+ if (_.indexOf(registeredEvents, name) === -1) {
255
+ activeRepository.on(...arguments);
256
+ } else {
257
+ super.on(...arguments);
258
+ }
259
+ });
260
+ }
261
+ addListener(name) {
262
+ if (_.indexOf(this._registeredEvents, name) === -1) {
263
+ return this._getActiveRepository().addListener(...arguments);
264
+ }
265
+ return super.addListener(...arguments);
266
+ }
267
+ on(name) {
268
+ if (_.indexOf(this._registeredEvents, name) === -1) {
269
+ return this._getActiveRepository().on(...arguments);
270
+ }
271
+ return super.on(...arguments);
272
+ }
273
+ once(name) {
274
+ if (_.indexOf(this._registeredEvents, name) === -1) {
275
+ return this._getActiveRepository().once(...arguments);
276
+ }
277
+ return super.once(...arguments);
278
+ }
279
+ removeListener(name) {
280
+ if (_.indexOf(this._registeredEvents, name) === -1) {
281
+ return this._getActiveRepository().removeListener(...arguments);
282
+ }
283
+ return super.removeListener(...arguments);
284
+ }
285
+ off(name) {
286
+ if (_.indexOf(this._registeredEvents, name) === -1) {
287
+ return this._getActiveRepository().off(...arguments);
288
+ }
289
+ return super.off(...arguments);
290
+ }
291
+ removeListeners(names) {
292
+ const
293
+ registeredEvents = this._registeredEvents,
294
+ activeRepository = this._getActiveRepository();
295
+ _.each(names, (name) => {
296
+ if (_.indexOf(registeredEvents, name) === -1) {
297
+ activeRepository.off(...arguments);
298
+ } else {
299
+ super.off(...arguments);
300
+ }
301
+ });
302
+ }
303
+ isRegisteredEvent(name) {
304
+ if (_.indexOf(this._registeredEvents, name) === -1) {
305
+ return this._getActiveRepository().isRegisteredEvent(...arguments);
306
+ }
307
+ return super.isRegisteredEvent(...arguments);
308
+ }
309
+
310
+
311
+ // ________ __ ___ __ __ __
312
+ // / ____/ /___ ___________ / |/ /__ / /_/ /_ ____ ____/ /____
313
+ // / / / / __ `/ ___/ ___/ / /|_/ / _ \/ __/ __ \/ __ \/ __ / ___/
314
+ // / /___/ / /_/ (__ |__ ) / / / / __/ /_/ / / / /_/ / /_/ (__ )
315
+ // \____/_/\__,_/____/____/ /_/ /_/\___/\__/_/ /_/\____/\__,_/____/
316
+
214
317
  /**
215
318
  * Registers multiple commands for when syncing in MODE_COMMAND_QUEUE mode.
216
319
  */
@@ -279,9 +382,8 @@ class LocalFromRemoteRepository extends EventEmitter {
279
382
  * so we can sync immediately after add for MODE_COMMAND_QUEUE mode.
280
383
  */
281
384
  async add(data) {
282
- // NORMAL PROCESS, basically call super()
283
- // This adds to the local repository, so we can sync later,
284
- // if needed.
385
+ // NORMAL PROCESS
386
+ // This adds to the local repository, so we can sync later, if needed.
285
387
  const normalAdd = await this._getActiveRepository().add(data);
286
388
  if (this.mode !== MODE_COMMAND_QUEUE || !this.isOnline) {
287
389
  return normalAdd;
@@ -357,7 +459,7 @@ class LocalFromRemoteRepository extends EventEmitter {
357
459
  }
358
460
 
359
461
  // local <-- remote
360
- await localItem.loadOriginalData(remoteItem.getOriginalData());
462
+ localItem.response = remoteItem.response;
361
463
  this.remote.clear();
362
464
 
363
465
  // Handle the server's response
@@ -449,10 +449,11 @@ class MemoryRepository extends Repository {
449
449
  return;
450
450
  }
451
451
 
452
- delete this._keyedEntities[entity.id];
452
+ if (!entity.isDestroyed) {
453
+ delete this._keyedEntities[entity.id];
454
+ entity.destroy();
455
+ }
453
456
  this.entities = _.filter(this.entities, (x) => x.id !== entity.id);
454
-
455
- entity.destroy();
456
457
  return entity;
457
458
  }
458
459
 
@@ -600,8 +601,9 @@ class MemoryRepository extends Repository {
600
601
 
601
602
  this._setPaginationVars();
602
603
 
603
- const nextEntities = this._paginate(entities),
604
- nextValues = _.map(nextEntities, (entity) => entity.getSubmitValues());
604
+ const
605
+ nextEntities = this._paginate(entities),
606
+ nextValues = _.map(nextEntities, (entity) => entity.isDestroyed ? null : entity.getSubmitValues());
605
607
  if (!_.isEqual(this._previousValues, nextValues)) {
606
608
  this.entities = nextEntities;
607
609
  this._previousValues = nextValues;
@@ -214,6 +214,10 @@ class OfflineRepository extends MemoryRepository {
214
214
  }
215
215
 
216
216
  // Get a clone, in case we need to revert back to it later
217
+ if (entity.isDestroyed) {
218
+ return await this._storageDeleteValue(entity.id);
219
+ }
220
+
217
221
  const clone = entity.clone();
218
222
 
219
223
  // Attempt to edit
@@ -242,7 +246,7 @@ class OfflineRepository extends MemoryRepository {
242
246
  }
243
247
 
244
248
  // Get a clone, in case we need to revert back to it later
245
- const clone = entity.clone();
249
+ const clone = entity.isDestroyed ? null : entity.clone();
246
250
 
247
251
  // Attempt to delete
248
252
  super._doDelete(entity);
@@ -253,8 +257,12 @@ class OfflineRepository extends MemoryRepository {
253
257
  storageResult = await this._storageDeleteValue(entity.id);
254
258
  await this._deleteFromIndex(entity.id);
255
259
  } catch (e) {
256
- // Revert to clone
257
- this._keyedEntities[clone.id] = clone;
260
+ // try to revert to clone
261
+ if (clone) {
262
+ this._keyedEntities[clone.id] = clone;
263
+ } else {
264
+ delete this._keyedEntities[entity.id];
265
+ }
258
266
  }
259
267
 
260
268
  return storageResult;
@@ -842,9 +842,7 @@ export default class Repository extends EventEmitter {
842
842
  this.throwError('this._setFilters is no longer valid. Repository has been destroyed.');
843
843
  return;
844
844
  }
845
- let isChanged = false;
846
845
  if (!_.isEqual(this.filters, filters)) {
847
- isChanged = true;
848
846
  this.filters = filters;
849
847
  this.resetPagination();
850
848
  let ret;
@@ -854,7 +852,7 @@ export default class Repository extends EventEmitter {
854
852
  this.emit('changeFilters');
855
853
  return ret;
856
854
  }
857
- return isChanged;
855
+ return false; // no filters changed
858
856
  }
859
857
 
860
858
 
@@ -1525,7 +1523,7 @@ export default class Repository extends EventEmitter {
1525
1523
  if (!entities) {
1526
1524
  entities = this.entities;
1527
1525
  }
1528
- return _.filter(entities, entity => entity.isDirty && !entity.isSaving);
1526
+ return _.filter(entities, entity => !entity.isSaving && (entity.isDestroyed || entity.isDirty));
1529
1527
  }
1530
1528
 
1531
1529
  /**
@@ -1541,7 +1539,7 @@ export default class Repository extends EventEmitter {
1541
1539
  if (!entities) {
1542
1540
  entities = this.entities;
1543
1541
  }
1544
- return _.filter(entities, entity => entity.isDeleted);
1542
+ return _.filter(entities, entity => entity.isDestroyed || entity.isDeleted);
1545
1543
  }
1546
1544
 
1547
1545
  /**