@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
|
@@ -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
|
|
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
|
|
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
|
-
//
|
|
171
|
-
//
|
|
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
|
-
//
|
|
198
|
-
|
|
199
|
-
this.relayEventsFrom(
|
|
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
|
|
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
|
-
|
|
462
|
+
localItem.response = remoteItem.response;
|
|
361
463
|
this.remote.clear();
|
|
362
464
|
|
|
363
465
|
// Handle the server's response
|
package/src/Repository/Memory.js
CHANGED
|
@@ -449,10 +449,11 @@ class MemoryRepository extends Repository {
|
|
|
449
449
|
return;
|
|
450
450
|
}
|
|
451
451
|
|
|
452
|
-
|
|
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
|
|
604
|
-
|
|
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
|
-
//
|
|
257
|
-
|
|
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
|
|
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.
|
|
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
|
/**
|