@bizjournals/js-storage 0.0.1 → 0.1.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.
package/.gitlab-ci.yml ADDED
@@ -0,0 +1,15 @@
1
+ npmrunner:
2
+ tags:
3
+ - php73
4
+ script:
5
+ - date
6
+ - node --version
7
+ - npm --version
8
+ - rm -f .npmrc
9
+ - mv build/.npmrc .npmrc
10
+ - npm install --loglevel=error
11
+ - npm test
12
+ - rm -rf node_modules
13
+ - rm -f .npmrc
14
+ except:
15
+ - tags
package/README.md CHANGED
@@ -0,0 +1,96 @@
1
+ # Storage
2
+ This bundle has helper classes to interact with browser storage options. At present we
3
+ support `localstorage` and `sessionstorage`. These share a common abstract parent.
4
+
5
+ Storage references are critical to the implementation of our architecture. A reference
6
+ is a named key that contains your data in the selected storage type.
7
+
8
+ ## Installing
9
+
10
+ Using npm:
11
+
12
+ ```bash
13
+ npm install @bizjournals/vue-core
14
+ ```
15
+
16
+ Using yarn:
17
+
18
+ ```bash
19
+ yarn add @bizjournals/vue-core
20
+ ```
21
+
22
+ **Configuring your environment:**
23
+
24
+ You will need to configure an `NPM_TOKEN` within your project to include these
25
+ private modules. The best idea is to use an existing project as an example.
26
+
27
+ _For simple setups the .gitlab-ci.yml file within this project as a guide to accessing
28
+ project variables via the .npmrc file_
29
+
30
+ ## Example
31
+
32
+ ```js
33
+ import { StorageReference, LocalStorage, SessionStorage } from "@bizjournals/js-storage";
34
+
35
+ // This will setup a reference that is namespaced to bizj
36
+ // The full key in localstorage will be bizj.mykey
37
+ // This key will have an expiration partner that by default will be one hour
38
+ const something = new StorageReference('mykey', new LocalStorage());
39
+
40
+ something.saveAs({
41
+ my: 'data'
42
+ });
43
+
44
+ // local storage has a configurable API as well, and this can be used in storage
45
+ // reference objects too.
46
+ const local = new LocalStorage({
47
+ // by changing the namespace what was bizj by default will now be notbizj
48
+ // Example: notbizj.mykey
49
+ namespace: 'notbizj',
50
+ expires: 3600 // one hour
51
+ });
52
+
53
+
54
+ // session storage uses the same api as local storage
55
+ const somethingElse = new StorageReference('difkey', new SessionStorage({
56
+ namespace: 'woa'
57
+ }));
58
+
59
+ const somethingElsesData = somethingElse.obtain();
60
+ ```
61
+
62
+ ## Storage Reference
63
+ A storage reference is a keyed object that exists within either local or session storage.
64
+ It may be prefixed with a namespace since of the respective storage container.
65
+
66
+ ### API
67
+
68
+ **constructor**(cacheKey : String, storageSystem : StorageAbstract)
69
+ **obtain**()
70
+ **bust**()
71
+ **saveAs**(data : Mixed)
72
+
73
+ ## Storage Abstract
74
+ The parent class for both local and session storage creates the API used by each of them.
75
+
76
+ ### API
77
+
78
+ **constructor**(options : Object : { namespace: String, expires: Number })
79
+ **getItem**(key: String)
80
+ **hasItem**(key : String)
81
+ **setItem**(key : String, value : Mixed, expires = true : Boolean)
82
+
83
+
84
+ ### Reference
85
+
86
+ #### getItem
87
+ Gets an item with a specified key. The namespace set in the construction of the object will
88
+ be pre-fixed to the beginning of the string, by default this is `bizj`.
89
+
90
+ #### hasItem
91
+ This checks to see if the item is available. If it is it'll cache it, so that if you need to
92
+ get the item later you don't need to worry about additional reads.
93
+
94
+ #### setItem
95
+ Sets the item in storage and updates the item in cache. It will automatically prefix itself
96
+ with the namespace, by default `bizj`.
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ transformIgnorePatterns: ["/node_modules/(?!(@bizjournals))/"]
3
+ };
@@ -14,11 +14,6 @@ describe('core:class >> storageabstract:clear', () => {
14
14
  }).not.toThrow();
15
15
  });
16
16
 
17
- it('always returns `this`', () => {
18
- const test = storageAbstract.clear();
19
- expect(test).toEqual(storageAbstract);
20
- });
21
-
22
17
  it('runs the clear method on the storage system when defined', () => {
23
18
  storageAbstract.storage = {
24
19
  clear: jest.fn()
@@ -1,6 +1,5 @@
1
1
  import StorageAbstract from '../';
2
2
  import { DEFAULT_EXPIRATION, DEFAULT_NAMESPACE } from '../constants';
3
- import { NAMESPACE_MUST_BE_STRING, EXPIRATION_MUST_BE_POSITIVE_INTEGER } from '../exceptions';
4
3
 
5
4
  describe('core:class >> storageabstract:constructor', () => {
6
5
  it('defaults to constant as it\'s namespace when none provided', () => {
@@ -25,7 +24,7 @@ describe('core:class >> storageabstract:constructor', () => {
25
24
  for (const namespace of namespaces) {
26
25
  expect(() => {
27
26
  new StorageAbstract({ namespace });
28
- }).toThrow(NAMESPACE_MUST_BE_STRING);
27
+ }).toThrow();
29
28
  }
30
29
  });
31
30
 
@@ -40,11 +39,6 @@ describe('core:class >> storageabstract:constructor', () => {
40
39
  expect(storageAbstract.expires).toEqual(expires);
41
40
  });
42
41
 
43
- it('defaults the number of attempts to zero', () => {
44
- const storageAbstract = new StorageAbstract();
45
- expect(storageAbstract.attempts).toEqual(0);
46
- });
47
-
48
42
  it('sets the storage to a default of null', () => {
49
43
  const storageAbstract = new StorageAbstract();
50
44
  expect(storageAbstract.storage).toEqual({});
@@ -19,19 +19,20 @@ describe('core:class >> storageabstract:getitem', () => {
19
19
  };
20
20
 
21
21
  storageClassMock.storage = mockStorage;
22
+ StorageAbstract.supported = undefined;
22
23
  });
23
24
 
24
- it('returns null when it is not supported', () => {
25
+ it('returns undefined when it is not supported', () => {
25
26
  storageClassMock.isSupported = jest.fn().mockImplementation(() => false);
26
27
 
27
- expect(storageClassMock.getItem()).toEqual(null);
28
+ expect(storageClassMock.getItem()).toEqual(undefined);
28
29
  expect(storageClassMock.namespaceKey).not.toHaveBeenCalled();
29
30
  });
30
31
 
31
- it('returns null when the item is expired', () => {
32
+ it('returns undefined when the item is expired', () => {
32
33
  storageClassMock.isItemExpired = jest.fn().mockImplementation(() => true);
33
34
 
34
- expect(storageClassMock.getItem()).toEqual(null);
35
+ expect(storageClassMock.getItem()).toEqual(undefined);
35
36
  expect(storageClassMock.namespaceKey).not.toHaveBeenCalled();
36
37
  });
37
38
 
@@ -64,8 +65,16 @@ describe('core:class >> storageabstract:getitem', () => {
64
65
  expect(storageClassMock.parser).toHaveBeenCalledWith(data);
65
66
  });
66
67
 
67
- it('caches the response data once obtained', () => {
68
- storageClassMock.getItem(key);
69
- expect(storageClassMock.cache).toHaveBeenCalledTimes(1);
68
+ it('does not call the `parser` method with the data fetched from suspend or getItem', () => {
69
+ const data = { hey: 'you' };
70
+
71
+ const localStorage = {
72
+ getItem: jest.fn().mockImplementation(() => data)
73
+ };
74
+
75
+ storageClassMock.storage = localStorage;
76
+
77
+ storageClassMock.getItem(key, false);
78
+ expect(storageClassMock.parser).not.toHaveBeenCalled();
70
79
  });
71
80
  });
@@ -16,4 +16,10 @@ describe('core:class >> storageabstract:hasitem', () => {
16
16
 
17
17
  expect(storageClassMock.getItem).toHaveBeenCalledTimes(1);
18
18
  });
19
+
20
+ it('returns false when the obtained item is undefined', () => {
21
+ storageClassMock.getItem = jest.fn().mockImplementation(() => undefined);
22
+
23
+ expect(storageClassMock.hasItem(key)).toBeFalsy();
24
+ });
19
25
  });
@@ -9,10 +9,8 @@ describe('core:class >> storageabstract:issupported', () => {
9
9
  mockStorage.setItem.mockClear();
10
10
  mockStorage.removeItem.mockClear();
11
11
 
12
- if (mockStorage._supported) {
13
- delete mockStorage._supported;
14
- }
15
12
  storageAbstract.storage = mockStorage;
13
+ StorageAbstract.supported = undefined;
16
14
  });
17
15
 
18
16
  it('returns false when the storage system is defaulted', () => {
@@ -27,10 +27,14 @@ describe('core:class >> storageabstract:parser', () => {
27
27
  expect(JSON.parse).toHaveBeenCalledTimes(1);
28
28
  });
29
29
 
30
- it('throws an exception when string is not valid json', () => {
30
+ it('returns the provided string if it could not be JSON parsed', () => {
31
31
  JSON.parse = copyParse;
32
+ let response;
33
+
32
34
  expect(() => {
33
- storageAbstract.parser('wowowow');
34
- }).toThrow();
35
+ response = storageAbstract.parser('wowowow');
36
+ }).not.toThrow();
37
+
38
+ expect(response).toEqual('wowowow');
35
39
  });
36
40
  });
@@ -19,28 +19,22 @@ describe('core:class >> storageabstract:removeitem', () => {
19
19
  removeItem: jest.fn()
20
20
  };
21
21
 
22
- storageClassMock.attempts = 0;
23
22
  storageClassMock.storage = mockStorage;
23
+ StorageAbstract.supported = undefined;
24
24
  });
25
25
 
26
- it('resets the attempts and halts when it is not supported', () => {
26
+ it('halts when it is not supported', () => {
27
27
  storageClassMock.isSupported = jest.fn().mockImplementation(() => false);
28
- storageClassMock.removeItem(key);
29
-
30
- expect(storageClassMock.resetAttempts).toHaveBeenCalledTimes(1);
31
- expect(storageClassMock.storage.removeItem).not.toHaveBeenCalled();
32
- });
33
28
 
34
- it('resets the attempts and halts when attempts are >= 2', () => {
35
- storageClassMock.attempts = 2;
36
29
  storageClassMock.removeItem(key);
37
30
 
38
- expect(storageClassMock.resetAttempts).toHaveBeenCalledTimes(1);
31
+ expect(storageClassMock.isSupported).toHaveBeenCalledTimes(1);
39
32
  expect(storageClassMock.storage.removeItem).not.toHaveBeenCalled();
40
-
41
33
  });
42
34
 
43
- it('attempts two times when encountering an error', () => {
35
+ it('falls through when encountering an exception', () => {
36
+ StorageAbstract.supported = true;
37
+
44
38
  const badStorage = {
45
39
  removeItem: jest.fn().mockImplementation(() => {
46
40
  throw new Error('testing code');
@@ -48,23 +42,20 @@ describe('core:class >> storageabstract:removeitem', () => {
48
42
  };
49
43
 
50
44
  storageClassMock.storage = badStorage;
51
- storageClassMock.removeItem();
52
45
 
53
- expect(storageClassMock.storage.removeItem).toHaveBeenCalledTimes(2);
46
+ expect(() => {
47
+ storageClassMock.removeItem();
48
+ }).not.toThrow();
49
+
50
+ expect(storageClassMock.storage.removeItem).toHaveBeenCalledTimes(1);
54
51
  });
55
52
 
56
53
  it('removes both the item at namespace and expiration keys', () => {
54
+ StorageAbstract.supported = true;
57
55
  storageClassMock.removeItem();
58
56
 
59
57
  expect(storageClassMock.namespaceKey).toHaveBeenCalledTimes(1);
60
58
  expect(storageClassMock.expirationKey).toHaveBeenCalledTimes(1);
61
59
  expect(storageClassMock.storage.removeItem).toHaveBeenCalledTimes(2);
62
60
  });
63
-
64
- it('resets attempts to zero on successful return', () => {
65
- storageClassMock.removeItem();
66
-
67
- expect(storageClassMock.storage.removeItem).toHaveBeenCalledTimes(2);
68
- expect(storageClassMock.resetAttempts).toHaveBeenCalledTimes(1);
69
- });
70
61
  });
@@ -26,22 +26,16 @@ describe('core:class >> storageabstract:setitem', () => {
26
26
 
27
27
  storageClassMock.attempts = 0;
28
28
  storageClassMock.storage = mockStorage;
29
+ StorageAbstract.supported = undefined;
29
30
  });
30
31
 
31
32
  it('resets the attempts and returns when it is not supported without continuing', () => {
32
33
  storageClassMock.isSupported = jest.fn().mockImplementation(() => false);
33
34
  storageClassMock.setItem();
34
35
 
35
- expect(storageClassMock.resetAttempts).toHaveBeenCalledTimes(1);
36
- expect(storageClassMock.namespaceKey).not.toHaveBeenCalled();
37
- });
38
-
39
- it('resets the attempts and returns when attempts is >= 2 without continuing', () => {
40
- storageClassMock.attempts = 3;
41
- storageClassMock.setItem();
42
-
43
- expect(storageClassMock.resetAttempts).toHaveBeenCalledTimes(1);
36
+ expect(storageClassMock.isSupported).toHaveBeenCalledTimes(1);
44
37
  expect(storageClassMock.namespaceKey).not.toHaveBeenCalled();
38
+ expect(mockStorage.setItem).not.toHaveBeenCalled();
45
39
  });
46
40
 
47
41
  it('uses a dynamically generated namespaceKey to set the item', () => {
@@ -59,7 +53,7 @@ describe('core:class >> storageabstract:setitem', () => {
59
53
  expect(storageClassMock.storage.setItem).not.toHaveBeenCalled();
60
54
  });
61
55
 
62
- it('calls to set the item one time when not expired', () => {
56
+ it('calls to set the item one time when not expiring', () => {
63
57
  const data = { it: true };
64
58
 
65
59
  storageClassMock.setItem(key, data, false);
@@ -77,25 +71,4 @@ describe('core:class >> storageabstract:setitem', () => {
77
71
  expect(storageClassMock.storage.setItem).toHaveBeenCalledTimes(2);
78
72
  expect(storageClassMock.expirationKey).toHaveBeenCalledTimes(1);
79
73
  });
80
-
81
- it('calls to cache the data with the key', () => {
82
- const data = { it: true };
83
-
84
- storageClassMock.setItem(key, data);
85
- expect(storageClassMock.cache).toHaveBeenCalledTimes(1);
86
- });
87
-
88
- it('calls clear when there is an error and attempts up to 2 times', () => {
89
- storageClassMock.translator = jest.fn().mockImplementation(() => {
90
- throw new Error('testing script error');
91
- });
92
-
93
- storageClassMock.setItem(key, { data: true });
94
- expect(storageClassMock.translator).toHaveBeenCalledTimes(2);
95
- });
96
-
97
- it('calls to reset attempts to zero once completed', () => {
98
- storageClassMock.setItem(key, { data: true });
99
- expect(storageClassMock.resetAttempts).toHaveBeenCalledTimes(1);
100
- });
101
74
  });
@@ -1,6 +1,5 @@
1
1
  import StorageAbstract from '../';
2
2
 
3
- // Mocking JSON.parse failed in this version of Jest
4
3
  describe('core:class >> storageabstract:translator', () => {
5
4
  let storageAbstract;
6
5
 
@@ -1,12 +1,6 @@
1
- import { empty } from "@bizjournals/js-utilities";
2
1
  import { DEFAULT_EXPIRATION, DEFAULT_NAMESPACE, EXPIRES_KEY_SUFFIX } from "./constants";
3
2
  import { KEY_IS_REQUIRED_TO_FETCH_DATA } from "./exceptions";
4
3
 
5
- // module scoped caching object
6
- // does share data between session / local / any other
7
- // If this becomes necessary attach it to the storage object
8
- const cache = {};
9
-
10
4
  /*
11
5
  |--------------------------------------------------------------------------
12
6
  | Storage Abstract / Contract
@@ -18,6 +12,13 @@ const cache = {};
18
12
  |
19
13
  */
20
14
  export default class StorageAbstract {
15
+ /**
16
+ * Extensions to this abstraction share an enabled state.
17
+ *
18
+ * @type {boolean}
19
+ */
20
+ static supported;
21
+
21
22
  /**
22
23
  * Constructor takes in options for namespace and expiration.
23
24
  * Session storage is the default storage type.
@@ -25,41 +26,36 @@ export default class StorageAbstract {
25
26
  * @param {object} options
26
27
  * @constructor
27
28
  */
28
- constructor(options = {}) {
29
+ constructor (options = {}) {
29
30
  this.namespace = options.namespace || DEFAULT_NAMESPACE;
30
31
  this.expires = options.expires || DEFAULT_EXPIRATION;
31
- this.attempts = 0;
32
32
 
33
33
  this.namespace = this.namespace.toLowerCase();
34
34
 
35
- cache[this.namespace] = cache[this.namespace] || {};
36
-
37
35
  this.storage = {};
38
36
  }
39
37
 
40
38
  /**
41
- * Gets an item from storage.
39
+ * Gets an item from storage and runs the parser unless explicitly
40
+ * disabled in the method request.
42
41
  *
43
- * @param {string} key
44
- * @returns {(Array|Number|Object|String)}
42
+ * @param {String} key
43
+ * @param {Boolean} parse
44
+ * @returns {(Array|Number|Object|String|Null)}
45
45
  */
46
- getItem(key) {
47
- if (!this.isSupported() || this.isItemExpired(key)) {
48
- return null;
49
- }
50
-
51
- let response = null;
46
+ getItem (key, parse = true) {
47
+ let response;
52
48
 
53
- if (cache[this.namespace][key]) {
54
- return cache[this.namespace][key];
49
+ if (!this.isSupported() || this.isItemExpired(key)) {
50
+ return response;
55
51
  }
56
52
 
57
53
  try {
58
- const generatedKey = this.namespaceKey(key);
54
+ response = this.storage.getItem(this.namespaceKey(key));
59
55
 
60
- response = this.parser(cache[generatedKey] || this.storage.getItem(generatedKey));
56
+ if (response === null) return undefined;
61
57
 
62
- this.cache(key, response);
58
+ response = parse ? this.parser(response) : response;
63
59
  } catch (e) {
64
60
  // fall through
65
61
  }
@@ -71,10 +67,18 @@ export default class StorageAbstract {
71
67
  * Parses the data returned from the storage system
72
68
  *
73
69
  * @param data
74
- * @returns {any}
70
+ * @returns {*}
75
71
  */
76
- parser(data) {
77
- return typeof data === "string" ? JSON.parse(data) : data;
72
+ parser (data) {
73
+ try {
74
+ if (typeof data === "string") {
75
+ data = JSON.parse(data);
76
+ }
77
+ } catch (e) {
78
+ // fall through
79
+ }
80
+
81
+ return data;
78
82
  }
79
83
 
80
84
  /**
@@ -83,8 +87,8 @@ export default class StorageAbstract {
83
87
  * @param value
84
88
  * @returns {any}
85
89
  */
86
- translator(value) {
87
- return typeof value === "string" ? value : JSON.stringify(value);
90
+ translator (value) {
91
+ return typeof value === 'string' ? value : JSON.stringify(value);
88
92
  }
89
93
 
90
94
  /**
@@ -94,9 +98,9 @@ export default class StorageAbstract {
94
98
  * @param {(array|object|number|string)} value
95
99
  * @param {boolean} expires
96
100
  */
97
- setItem(key, value, expires = true) {
98
- if (!this.isSupported() || this.attempts >= 2) {
99
- return this.resetAttempts();
101
+ setItem (key, value, expires = true) {
102
+ if (!this.isSupported()) {
103
+ return;
100
104
  }
101
105
 
102
106
  const generatedKey = this.namespaceKey(key);
@@ -105,16 +109,14 @@ export default class StorageAbstract {
105
109
  this.storage.setItem(generatedKey, this.translator(value));
106
110
 
107
111
  if (expires) {
108
- this.storage.setItem(this.expirationKey(key), String(this.timestamp(this.expires)));
112
+ this.storage.setItem(
113
+ this.expirationKey(key),
114
+ String(this.timestamp(this.expires))
115
+ );
109
116
  }
110
-
111
- this.cache(key, value);
112
117
  } catch (e) {
113
- this.attempts++;
114
- this.setItem(key, value, expires);
118
+ // fall through
115
119
  }
116
-
117
- return this.resetAttempts();
118
120
  }
119
121
 
120
122
  /**
@@ -122,48 +124,28 @@ export default class StorageAbstract {
122
124
  *
123
125
  * @param {string} key
124
126
  */
125
- removeItem(key) {
126
- if (!this.isSupported() || this.attempts >= 2) {
127
- return this.resetAttempts();
127
+ removeItem (key) {
128
+ if (!this.isSupported()) {
129
+ return;
128
130
  }
129
131
 
130
132
  try {
131
133
  this.storage.removeItem(this.namespaceKey(key));
132
134
  this.storage.removeItem(this.expirationKey(key));
133
-
134
- this.free(key);
135
135
  } catch (e) {
136
- this.attempts++;
137
- this.removeItem(key);
136
+ // fall through
138
137
  }
139
-
140
- return this.resetAttempts();
141
- }
142
-
143
- /**
144
- * Resets the number of attempt operations to zero.
145
- *
146
- * @returns {StorageAbstract}
147
- */
148
- resetAttempts() {
149
- this.attempts = 0;
150
-
151
- return this;
152
138
  }
153
139
 
154
140
  /**
155
141
  * Clears all items from storage.
156
142
  */
157
- clear() {
143
+ clear () {
158
144
  try {
159
145
  this.storage.clear();
160
-
161
- cache[this.namespace] = {};
162
146
  } catch (e) {
163
147
  // fall through
164
148
  }
165
-
166
- return this;
167
149
  }
168
150
 
169
151
  /**
@@ -172,8 +154,8 @@ export default class StorageAbstract {
172
154
  * @param {string} key
173
155
  * @returns {boolean}
174
156
  */
175
- hasItem(key) {
176
- return !empty(this.getItem(key));
157
+ hasItem (key) {
158
+ return this.getItem(key, false) !== undefined;
177
159
  }
178
160
 
179
161
  /**
@@ -182,7 +164,7 @@ export default class StorageAbstract {
182
164
  * @param {number} offset
183
165
  * @returns {number}
184
166
  */
185
- timestamp(offset = 0) {
167
+ timestamp (offset = 0) {
186
168
  return Math.ceil(Date.now() / 1000) + offset;
187
169
  }
188
170
 
@@ -192,16 +174,16 @@ export default class StorageAbstract {
192
174
  * @param {string} key
193
175
  * @returns {string}
194
176
  */
195
- namespaceKey(key) {
177
+ namespaceKey (key) {
196
178
  if (typeof key !== "string") {
197
179
  throw new Error(KEY_IS_REQUIRED_TO_FETCH_DATA);
198
180
  }
199
181
 
200
- if (key.indexOf(`${this.namespace}.`) === 0) {
182
+ if (key.indexOf(`${ this.namespace }.`) === 0) {
201
183
  key = key.slice(this.namespace.length + 1);
202
184
  }
203
185
 
204
- return `${this.namespace}.${key.toLowerCase()}`;
186
+ return `${ this.namespace }.${ key.toLowerCase() }`;
205
187
  }
206
188
 
207
189
  /**
@@ -209,8 +191,8 @@ export default class StorageAbstract {
209
191
  *
210
192
  * @returns {string}
211
193
  */
212
- expirationKey(key) {
213
- return `${this.namespaceKey(key)}.${EXPIRES_KEY_SUFFIX}`;
194
+ expirationKey (key) {
195
+ return `${ this.namespaceKey(key) }.${ EXPIRES_KEY_SUFFIX }`;
214
196
  }
215
197
 
216
198
  /**
@@ -219,7 +201,7 @@ export default class StorageAbstract {
219
201
  * @param {string} key
220
202
  * @returns {boolean}
221
203
  */
222
- isItemExpired(key) {
204
+ isItemExpired (key) {
223
205
  if (!this.isSupported()) {
224
206
  return false;
225
207
  }
@@ -242,52 +224,38 @@ export default class StorageAbstract {
242
224
  return false;
243
225
  }
244
226
 
245
- /**
246
- * Stores the data in memory.
247
- *
248
- * @param key
249
- * @param value
250
- */
251
- cache(key, value) {
252
- cache[this.namespace][key] = value;
253
-
254
- return this;
255
- }
256
-
257
- /**
258
- * Frees the data from memory.
259
- *
260
- * @param key
261
- * @param value
262
- */
263
- free(key) {
264
- if (cache[this.namespace][key]) {
265
- delete cache[this.namespace][key];
266
- }
267
-
268
- return this;
269
- }
270
-
271
227
  /**
272
228
  * Checks to see if the storage system is supported
273
229
  *
274
230
  * @returns {boolean}
275
231
  */
276
- isSupported() {
277
- if (typeof this.storage._supported === "boolean") {
278
- return this.storage._supported;
232
+ isSupported () {
233
+ if (typeof StorageAbstract.supported === "boolean") {
234
+ return StorageAbstract.supported;
279
235
  }
280
236
 
281
- const test = `${this.namespaceKey("storage")}.test`;
237
+ const test = 'biz.storage.test';
282
238
 
283
239
  try {
284
- this.storage.setItem(test, test);
240
+ this.storage.setItem(test, '1');
285
241
  this.storage.removeItem(test);
286
- this.storage._supported = true;
242
+
243
+ StorageAbstract.supported = true;
287
244
  } catch (e) {
288
- this.storage._supported = false;
245
+ StorageAbstract.supported = e instanceof DOMException &&
246
+ (
247
+ // everything except Firefox
248
+ e.code === 22 ||
249
+ // Firefox
250
+ e.code === 1014 ||
251
+ // test name field too, because code might not be present
252
+ // everything except Firefox
253
+ e.name === 'QuotaExceededError' ||
254
+ // Firefox
255
+ e.name === 'NS_ERROR_DOM_QUOTA_REACHED'
256
+ ) && (this.storage && this.storage.length !== 0);
289
257
  }
290
258
 
291
- return this.storage._supported;
259
+ return StorageAbstract.supported;
292
260
  }
293
261
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bizjournals/js-storage",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "ACBJ javascript storage classes",
5
5
  "repository": {
6
6
  "git": "https://gitlab.bizjournals.com/bizjournals/js-storage"
@@ -9,17 +9,17 @@
9
9
  "type": "module",
10
10
  "sideEffects": false,
11
11
  "scripts": {
12
- "test": "jest --transformIgnorePatterns \"node_modules/(?!(@bizjournals))/\""
12
+ "test": "jest",
13
+ "preversion": "npm test",
14
+ "postversion": "git push && git push --tags && npm publish"
13
15
  },
14
16
  "keywords": [],
15
17
  "author": "DPD",
16
18
  "license": "UNLICENSED",
17
19
  "devDependencies": {
18
- "@babel/preset-env": "^7.9.5",
20
+ "@babel/preset-env": "^7.10.3",
19
21
  "babel-jest": "^25.4.0",
20
22
  "jest": "^25.4.0"
21
23
  },
22
- "dependencies": {
23
- "@bizjournals/js-utilities": "0.0.1"
24
- }
24
+ "dependencies": {}
25
25
  }
@@ -1,20 +0,0 @@
1
- import StorageAbstract from '../';
2
-
3
- describe('core:class >> storageabstract:resetattempts', () => {
4
- let storageAbstract;
5
-
6
- beforeAll(() => {
7
- storageAbstract = new StorageAbstract();
8
- });
9
-
10
- it('resets the attempts to 0 when called', () => {
11
- storageAbstract.attempts = 2;
12
-
13
- storageAbstract.resetAttempts();
14
- expect(storageAbstract.attempts).toEqual(0);
15
- });
16
-
17
- it('returns `this`', () => {
18
- expect(storageAbstract.resetAttempts()).toEqual(storageAbstract);
19
- });
20
- });
File without changes