diff --git a/README.md b/README.md index 4edd216..7f550ce 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ app.use('/messages', service({ storage, id, startId, name, store, paginate })); __Options:__ - `storage` (**required**) - The local storage engine. You can pass in the browsers `window.localStorage`, React Native's `AsyncStorage` or a NodeJS localstorage module. -- `throttle` (*optional*, default `200`) - The minimum time (ms) before in-memory data is written to `storage`. Data is only written if changed since last write. +- `throttle` (*optional*, default `200`) - The minimum time (ms) before in-memory data is written to `storage`. - `id` (*optional*, default: `'id'`) - The name of the id field property. - `startId` (*optional*, default: `0`) - An id number to start with that will be incremented for new record. - `name` (*optional*, default: `'feathers'`) - The key to store data under in local or async storage. @@ -43,6 +43,7 @@ __Options:__ - `whitelist` (*optional*) - A list of additional query parameters to allow. - `multi` (*optional*) - Allow `create` with arrays and `update` and `remove` with `id` `null` to change multiple items. Can be `true` for all methods or an array of allowed methods (e.g. `[ 'remove', 'create' ]`). - `reuseKeys` (*optional*, default: `false`) Allow duplicate keys i.e. last definition wins. Mostly useful for demonstration and testing purposes. +- `strictStorage` (*optional*, default false) - When false, all storage data is held in memory after initialization. When true, the storage data is get/set on each method. ## Example diff --git a/lib/index.js b/lib/index.js index 85da79c..5c02f75 100644 --- a/lib/index.js +++ b/lib/index.js @@ -8,6 +8,7 @@ class LocalStorage extends Service { this._storageKey = options.name || 'feathers'; this._storage = options.storage || (typeof window !== 'undefined' && window.localStorage); this._throttle = options.throttle || 200; + this._strictStorage = options.strictStorage || false; this._reuseKeys = options.reuseKeys || false; this.store = null; @@ -49,6 +50,9 @@ class LocalStorage extends Service { this._timeout = setTimeout(() => { this._storage.setItem(this._storageKey, JSON.stringify(this.store)); delete this._timeout; + if (this._strictStorage) { + this.store = null; + } }, this._throttle); } @@ -61,11 +65,13 @@ class LocalStorage extends Service { } find (...args) { - return this.execute('find', ...args); + return this.execute('find', ...args) + .then(data => this._strictStorage ? this.flush(data) : data); } get (...args) { - return this.execute('get', ...args); + return this.execute('get', ...args) + .then(data => this._strictStorage ? this.flush(data) : data); } create (...args) { diff --git a/test/index.test.js b/test/index.test.js index 0fdf2a1..06dec19 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -205,6 +205,33 @@ describe('Feathers Localstorage Service', () => { done(); }); + it('clears memory when using strictStorage', () => { + const name = 'test-storage-8'; + + storage.setItem(name, '{ "0": { "id": 0, "text": "test 0" } }'); + + const app = feathers() + .use('/messages', service({ name, storage, strictStorage: true })); + + return app.service('messages').find() + .then(() => { + return new Promise((resolve) => { + setTimeout(() => { + assert.notStrictEqual(app.service('messages').store, null); + resolve(); + }, 100); + }); + }) + .then(() => { + return new Promise((resolve) => { + setTimeout(() => { + assert.strictEqual(app.service('messages').store, null); + resolve(); + }, 150); + }); + }); + }); + testSuite(app, errors, 'people'); testSuite(app, errors, 'people-customid', 'customid'); }); diff --git a/types/index.d.ts b/types/index.d.ts index 34866fc..e092096 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -6,6 +6,7 @@ import { Service as MemoryService, MemoryServiceOptions, MemoryServiceStore } fr export interface LocalStorageServiceOptions extends MemoryServiceOptions { name: string; throttle: number; + strictStorage: boolean; } export class Service extends MemoryService {