@onehat/data 1.21.14 → 1.21.16

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.
@@ -147,6 +147,64 @@ describe('Repository Base', function() {
147
147
  expect(this.repository.isAutoSave).to.be.false;
148
148
  });
149
149
 
150
+ it('markLoaded', function() {
151
+
152
+ const repository = new this.Repository({
153
+ id: 'foo',
154
+ schema: this.schema,
155
+ isAutoLoad: false,
156
+ isAutoSave: true,
157
+ isPaginated: true,
158
+ data: [
159
+ { key: 1, value: 'one', },
160
+ { key: 2, value: 'two', },
161
+ { key: 3, value: 'three', },
162
+ { key: 4, value: 'four', },
163
+ { key: 5, value: 'five', },
164
+ ],
165
+ });
166
+ repository.initialize();
167
+
168
+ expect(repository.isLoading).to.be.false;
169
+ expect(repository.isLoaded).to.be.false;
170
+ expect(repository.lastLoaded).to.be.null;
171
+
172
+ repository.markLoaded();
173
+
174
+ expect(repository.isLoading).to.be.false;
175
+ expect(repository.isLoaded).to.be.true;
176
+ expect(repository.lastLoaded).to.be.not.null;
177
+ });
178
+
179
+ it('markUnloaded', function() {
180
+
181
+ const repository = new this.Repository({
182
+ id: 'foo',
183
+ schema: this.schema,
184
+ isAutoLoad: false,
185
+ isAutoSave: true,
186
+ isPaginated: true,
187
+ data: [
188
+ { key: 1, value: 'one', },
189
+ { key: 2, value: 'two', },
190
+ { key: 3, value: 'three', },
191
+ { key: 4, value: 'four', },
192
+ { key: 5, value: 'five', },
193
+ ],
194
+ });
195
+ repository.initialize();
196
+
197
+ repository.isLoading = true;
198
+ repository.isLoaded = true;
199
+ repository.lastLoaded = true;
200
+
201
+ repository.markUnloaded();
202
+
203
+ expect(repository.isLoading).to.be.false;
204
+ expect(repository.isLoaded).to.be.false;
205
+ expect(repository.lastLoaded).to.be.null;
206
+ });
207
+
150
208
  });
151
209
 
152
210
  describe('sorting', function() {
@@ -325,7 +383,7 @@ describe('Repository Base', function() {
325
383
  expect(filter.value).to.be.eq('1');
326
384
  });
327
385
 
328
- it.only('filter - object', function() {
386
+ it('filter - object', function() {
329
387
  // two possible ways to call filter with an object
330
388
  // 1. filter({ name: 'key', value: '1' });
331
389
  this.repository.filter({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/data",
3
- "version": "1.21.14",
3
+ "version": "1.21.16",
4
4
  "description": "JS data modeling package with adapters for many storage mediums.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -1097,6 +1097,18 @@ class AjaxRepository extends Repository {
1097
1097
  }));
1098
1098
  }
1099
1099
 
1100
+ /**
1101
+ * Clears all state and storage of entities, as though nothing was ever loaded.
1102
+ */
1103
+ clearAll() {
1104
+ this._destroyEntities();
1105
+ this.entities = [];
1106
+ this.total = 0;
1107
+ this._setPaginationVars();
1108
+ this.markUnloaded();
1109
+ this.emit('changeData', this.entities);
1110
+ }
1111
+
1100
1112
  setIsOnline(isOnline) {
1101
1113
  this.isOnline = !!isOnline; // force convert type to boolean
1102
1114
  }
@@ -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;
@@ -431,6 +431,15 @@ export default class Repository extends EventEmitter {
431
431
  await waitUntil(() => !this.isLoading, { timeout });
432
432
  }
433
433
 
434
+ /**
435
+ * Marks this repository as unloaded
436
+ */
437
+ markUnloaded() {
438
+ this.markLoading(false);
439
+ this.isLoaded = false;
440
+ this.lastLoaded = null;
441
+ }
442
+
434
443
  /**
435
444
  * Marks this repository as loaded
436
445
  */
@@ -833,9 +842,7 @@ export default class Repository extends EventEmitter {
833
842
  this.throwError('this._setFilters is no longer valid. Repository has been destroyed.');
834
843
  return;
835
844
  }
836
- let isChanged = false;
837
845
  if (!_.isEqual(this.filters, filters)) {
838
- isChanged = true;
839
846
  this.filters = filters;
840
847
  this.resetPagination();
841
848
  let ret;
@@ -845,7 +852,7 @@ export default class Repository extends EventEmitter {
845
852
  this.emit('changeFilters');
846
853
  return ret;
847
854
  }
848
- return isChanged;
855
+ return false; // no filters changed
849
856
  }
850
857
 
851
858