@bizjournals/js-storage 0.1.2 → 0.2.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/lib/storage.js +1 -0
- package/lib/storage.js.map +1 -0
- package/package.json +19 -4
- package/.gitlab-ci.yml +0 -15
- package/babel.config.cjs +0 -12
- package/jest.config.cjs +0 -3
- package/lib/abstract/__mocks__/mock-storage.js +0 -19
- package/lib/abstract/__tests__/storage.clear.spec.js +0 -25
- package/lib/abstract/__tests__/storage.constructor.spec.js +0 -46
- package/lib/abstract/__tests__/storage.expirationkey.spec.js +0 -22
- package/lib/abstract/__tests__/storage.getitem.spec.js +0 -80
- package/lib/abstract/__tests__/storage.hasitem.spec.js +0 -25
- package/lib/abstract/__tests__/storage.issupported.spec.js +0 -36
- package/lib/abstract/__tests__/storage.namespacekey.spec.js +0 -54
- package/lib/abstract/__tests__/storage.parser.spec.js +0 -40
- package/lib/abstract/__tests__/storage.removeitem.spec.js +0 -63
- package/lib/abstract/__tests__/storage.setitem.spec.js +0 -75
- package/lib/abstract/__tests__/storage.translator.spec.js +0 -24
- package/lib/abstract/constants/index.js +0 -3
- package/lib/abstract/exceptions/index.js +0 -1
- package/lib/abstract/index.js +0 -254
- package/lib/abstract/store/index.js +0 -10
- package/lib/local/__mocks__/local-storage.js +0 -28
- package/lib/local/__tests__/storage.local.spec.js +0 -8
- package/lib/local/index.js +0 -24
- package/lib/main.js +0 -5
- package/lib/reference/__tests__/storagereference.general.spec.js +0 -47
- package/lib/reference/exceptions/index.js +0 -1
- package/lib/reference/index.js +0 -67
- package/lib/session/__tests__/storage.session.spec.js +0 -8
- package/lib/session/index.js +0 -24
package/lib/storage.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const store={supported:null};class StorageAbstract{constructor(options={}){this.namespace=options.namespace||"bizj",this.expires=options.expires||3600,this.namespace=this.namespace.toLowerCase(),this.storage={}}getItem(key,parse=!0){let response;if(this.isSupported()&&!this.isItemExpired(key)){try{if(response=this.storage.getItem(this.namespaceKey(key)),null===response)return;response=parse?this.parser(response):response}catch(e){}return response}}parser(data){try{"string"==typeof data&&(data=JSON.parse(data))}catch(e){}return data}translator(value){return"string"==typeof value?value:JSON.stringify(value)}setItem(key,value,expires=!0){if(!this.isSupported())return;const generatedKey=this.namespaceKey(key);try{this.storage.setItem(generatedKey,this.translator(value)),expires&&this.storage.setItem(this.expirationKey(key),String(this.timestamp(this.expires)))}catch(e){}}removeItem(key){if(this.isSupported())try{this.storage.removeItem(this.namespaceKey(key)),this.storage.removeItem(this.expirationKey(key))}catch(e){}}clear(){try{this.storage.clear()}catch(e){}}hasItem(key){return void 0!==this.getItem(key,!1)}timestamp(offset=0){return Math.ceil(Date.now()/1e3)+offset}namespaceKey(key){if("string"!=typeof key)throw new Error("A key must be provided to obtain data from the store.");return 0===key.indexOf(`${this.namespace}.`)&&(key=key.slice(this.namespace.length+1)),`${this.namespace}.${key.toLowerCase()}`}expirationKey(key){return`${this.namespaceKey(key)}.expires`}isItemExpired(key){if(!this.isSupported())return!1;try{let value=this.storage.getItem(this.expirationKey(key));if("string"==typeof value&&value.length>0){if(parseInt(value,10)-this.timestamp()<=0)return this.removeItem(key),!0}}catch(e){}return!1}isSupported(){if("boolean"==typeof store.supported)return store.supported;const test="biz.storage.test";try{this.storage.setItem(test,"1"),this.storage.removeItem(test),store.supported=!0}catch(e){store.supported=e instanceof DOMException&&(22===e.code||1014===e.code||"QuotaExceededError"===e.name||"NS_ERROR_DOM_QUOTA_REACHED"===e.name)&&this.storage&&0!==this.storage.length}return store.supported}}class LocalStorage extends StorageAbstract{constructor(options={}){super(options),this.storage=window.localStorage}}class SessionStorage extends StorageAbstract{constructor(options){super(options),this.storage=window.sessionStorage}}class StorageReference{constructor(cacheKey,storageSystem){if("string"!=typeof cacheKey||!(storageSystem instanceof StorageAbstract))throw new Error("Invalid construction of cache system. Please refer to documentation.");this.cacheKey=cacheKey,this.storageSystem=storageSystem}obtain(){return this.storageSystem.getItem(this.cacheKey)}bust(){this.storageSystem.removeItem(this.cacheKey)}saveAs(data){return data&&this.storageSystem.setItem(this.cacheKey,data),this}}export{LocalStorage,SessionStorage,StorageReference};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sources":["../src/abstract/constants/index.js","../src/abstract/exceptions/index.js","../src/abstract/store/index.js","../src/abstract/index.js","../src/local/index.js","../src/session/index.js","../src/reference/exceptions/index.js","../src/reference/index.js"],"sourcesContent":["export const DEFAULT_EXPIRATION = 3600;\nexport const DEFAULT_NAMESPACE = 'bizj';\nexport const EXPIRES_KEY_SUFFIX = 'expires';","export const KEY_IS_REQUIRED_TO_FETCH_DATA = 'A key must be provided to obtain data from the store.';\n","/**\n * The data store for global variables\n *\n */\nconst store = {\n supported: null,\n}\n\n// --\nexport default store;","import { DEFAULT_EXPIRATION, DEFAULT_NAMESPACE, EXPIRES_KEY_SUFFIX } from './constants';\nimport { KEY_IS_REQUIRED_TO_FETCH_DATA } from './exceptions';\nimport store from './store';\n\n/*\n|--------------------------------------------------------------------------\n| Storage Abstract / Contract\n|--------------------------------------------------------------------------\n|\n| This is the base storage class that is extended for localStorage and\n| sessionStorage. In time we may look to use this for InnoDB as well.\n|\n|\n*/\nexport default class StorageAbstract {\n /**\n * Constructor takes in options for namespace and expiration.\n * Session storage is the default storage type.\n *\n * @param {object} options\n * @constructor\n */\n constructor (options = {}) {\n this.namespace = options.namespace || DEFAULT_NAMESPACE;\n this.expires = options.expires || DEFAULT_EXPIRATION;\n\n this.namespace = this.namespace.toLowerCase();\n\n this.storage = {};\n }\n\n /**\n * Gets an item from storage and runs the parser unless explicitly\n * disabled in the method request.\n *\n * @param {String} key\n * @param {Boolean} parse\n * @returns {(Array|Number|Object|String|Null)}\n */\n getItem (key, parse = true) {\n let response;\n\n if (! this.isSupported() || this.isItemExpired(key)) {\n return undefined;\n }\n\n try {\n response = this.storage.getItem(this.namespaceKey(key));\n\n if (response === null) return undefined;\n\n response = parse ? this.parser(response) : response;\n } catch (e) {\n // fall through\n }\n\n return response;\n }\n\n /**\n * Parses the data returned from the storage system\n *\n * @param data\n * @returns {*}\n */\n parser (data) {\n try {\n if (typeof data === 'string') {\n data = JSON.parse(data);\n }\n } catch (e) {\n // fall through\n }\n\n return data;\n }\n\n /**\n * Translates the data before setting to the storage system\n *\n * @param value\n * @returns {any}\n */\n translator (value) {\n return typeof value === 'string' ? value : JSON.stringify(value);\n }\n\n /**\n * Sets an item in the storage system.\n *\n * @param {string} key\n * @param {(array|object|number|string)} value\n * @param {boolean} expires\n */\n setItem (key, value, expires = true) {\n if (! this.isSupported()) {\n return;\n }\n\n const generatedKey = this.namespaceKey(key);\n\n try {\n this.storage.setItem(generatedKey, this.translator(value));\n\n if (expires) {\n this.storage.setItem(\n this.expirationKey(key),\n String(this.timestamp(this.expires)),\n );\n }\n } catch (e) {\n // fall through\n }\n }\n\n /**\n * Removes an item from the storage system.\n *\n * @param {string} key\n */\n removeItem (key) {\n if (! this.isSupported()) {\n return;\n }\n\n try {\n this.storage.removeItem(this.namespaceKey(key));\n this.storage.removeItem(this.expirationKey(key));\n } catch (e) {\n // fall through\n }\n }\n\n /**\n * Clears all items from storage.\n */\n clear () {\n try {\n this.storage.clear();\n } catch (e) {\n // fall through\n }\n }\n\n /**\n * Checks to see if an item exists in local storage.\n *\n * @param {string} key\n * @returns {boolean}\n */\n hasItem (key) {\n return this.getItem(key, false) !== undefined;\n }\n\n /**\n * Calculates the expires for an item.\n *\n * @param {number} offset\n * @returns {number}\n */\n timestamp (offset = 0) {\n return Math.ceil(Date.now() / 1000) + offset;\n }\n\n /**\n * Creates the key used for storing information in the storage\n *\n * @param {string} key\n * @returns {string}\n */\n namespaceKey (key) {\n if (typeof key !== 'string') {\n throw new Error(KEY_IS_REQUIRED_TO_FETCH_DATA);\n }\n\n if (key.indexOf(`${ this.namespace }.`) === 0) {\n key = key.slice(this.namespace.length + 1);\n }\n\n return `${ this.namespace }.${ key.toLowerCase() }`;\n }\n\n /**\n * Creates the expires key used for testing storage usage\n *\n * @returns {string}\n */\n expirationKey (key) {\n return `${ this.namespaceKey(key) }.${ EXPIRES_KEY_SUFFIX }`;\n }\n\n /**\n * Checks to see if an item is expired and removes it if so.\n *\n * @param {string} key\n * @returns {boolean}\n */\n isItemExpired (key) {\n if (! this.isSupported()) {\n return false;\n }\n\n try {\n let value = this.storage.getItem(this.expirationKey(key));\n\n if (typeof value === 'string' && value.length > 0) {\n let expires = parseInt(value, 10);\n\n if (expires - this.timestamp() <= 0) {\n this.removeItem(key);\n return true;\n }\n }\n } catch (e) {\n // fall through\n }\n\n return false;\n }\n\n /**\n * Checks to see if the storage system is supported\n *\n * @returns {boolean}\n */\n isSupported () {\n if (typeof store.supported === 'boolean') {\n return store.supported;\n }\n\n const test = 'biz.storage.test';\n\n try {\n this.storage.setItem(test, '1');\n this.storage.removeItem(test);\n\n store.supported = true;\n } catch (e) {\n store.supported = e instanceof DOMException && (\n // everything except Firefox\n e.code === 22 ||\n // Firefox\n e.code === 1014 ||\n // test name field too, because code might not be present\n // everything except Firefox\n e.name === 'QuotaExceededError' ||\n // Firefox\n e.name === 'NS_ERROR_DOM_QUOTA_REACHED'\n ) && (this.storage && this.storage.length !== 0);\n }\n\n return store.supported;\n }\n}\n","import StorageAbstract from \"../abstract\";\n\n/*\n|--------------------------------------------------------------------------\n| Local Storage\n|--------------------------------------------------------------------------\n| This is the base class for hooking into local storage. There isn't much\n| overlap here if you just keep instantiating, so there isn't much need\n| to singleton this.\n|\n|\n*/\nexport default class LocalStorage extends StorageAbstract {\n /**\n * Create a local storage adapter.\n *\n * @param {object} [options]\n */\n constructor(options = {}) {\n super(options);\n\n this.storage = window.localStorage;\n }\n}\n","import StorageAbstract from \"../abstract\";\n\n/*\n|--------------------------------------------------------------------------\n| Session Storage\n|--------------------------------------------------------------------------\n| This is the base class for hooking into session storage. There isn't much\n| overlap here if you just keep instantiating, so there isn't much need\n| to singleton this.\n|\n|\n*/\nexport default class SessionStorage extends StorageAbstract {\n /**\n * Create a session storage adapter.\n *\n * @param {object} [options]\n */\n constructor(options) {\n super(options);\n\n this.storage = window.sessionStorage;\n }\n}\n","export const INVALID_CONSTRUCTOR_PARAMETERS = 'Invalid construction of cache system. Please refer to documentation.';\n","import StorageAbstract from \"../abstract\";\nimport { INVALID_CONSTRUCTOR_PARAMETERS } from \"./exceptions\";\n\n/*\n|--------------------------------------------------------------------------\n| Storage Reference\n|--------------------------------------------------------------------------\n| This is a reference to something in storage. Each item has a key\n| belonging to a specific storage system. These storage systems have a\n| common abstract / contract that gives them the same expected pattern.\n| This is the adapter.\n|\n|\n*/\nexport default class StorageReference {\n /**\n * Creates an instance of a StorageReference system, which needs a cacheKey and\n * a Storage system (StorageAbstract).\n *\n * @param {string} cacheKey\n * @param {StorageAbstract} storageSystem\n * @constructor\n * @return {StorageReference}\n */\n constructor(cacheKey, storageSystem) {\n if (typeof cacheKey !== \"string\" || !(storageSystem instanceof StorageAbstract)) {\n throw new Error(INVALID_CONSTRUCTOR_PARAMETERS);\n }\n\n this.cacheKey = cacheKey;\n this.storageSystem = storageSystem;\n }\n\n /**\n * Pulls data from the local store or cached resource.\n *\n * @returns {*}\n */\n obtain() {\n return this.storageSystem.getItem(this.cacheKey);\n }\n\n /**\n * Destroys the cache reference with the cache key\n *\n * @returns {void}\n */\n bust() {\n this.storageSystem.removeItem(this.cacheKey);\n }\n\n /**\n * Saves the locally stored cache to the caching system. This is\n * differed via a Promise because the timing of this can be\n * performed asynchronously.\n *\n * @param data\n * @returns {StorageReference}\n */\n saveAs(data) {\n if (data) {\n this.storageSystem.setItem(this.cacheKey, data);\n }\n\n return this;\n }\n}\n"],"names":["DEFAULT_EXPIRATION","DEFAULT_NAMESPACE","EXPIRES_KEY_SUFFIX","KEY_IS_REQUIRED_TO_FETCH_DATA","store","supported","StorageAbstract","constructor","options","namespace","expires","toLowerCase","storage","getItem","key","parse","response","isSupported","isItemExpired","undefined","namespaceKey","parser","e","data","JSON","translator","value","stringify","setItem","generatedKey","expirationKey","String","timestamp","removeItem","clear","hasItem","offset","Math","ceil","Date","now","Error","indexOf","slice","length","parseInt","test","DOMException","code","name","LocalStorage","window","localStorage","SessionStorage","sessionStorage","INVALID_CONSTRUCTOR_PARAMETERS","StorageReference","cacheKey","storageSystem","obtain","bust","saveAs"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bizjournals/js-storage",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "ACBJ javascript storage classes",
|
|
5
5
|
"repository": {
|
|
6
6
|
"git": "https://gitlab.bizjournals.com/bizjournals/js-storage"
|
|
7
7
|
},
|
|
8
|
-
"main": "lib/
|
|
9
|
-
"type": "module",
|
|
8
|
+
"main": "lib/storage.js",
|
|
10
9
|
"sideEffects": false,
|
|
10
|
+
"files": [
|
|
11
|
+
"lib/**"
|
|
12
|
+
],
|
|
11
13
|
"scripts": {
|
|
12
14
|
"test": "jest",
|
|
15
|
+
"dev": "npm-run-all --parallel link watch",
|
|
16
|
+
"link": "npm link",
|
|
17
|
+
"build": "rollup -c",
|
|
18
|
+
"watch": "rollup -c -w",
|
|
13
19
|
"preversion": "npm test",
|
|
20
|
+
"version": "npm run build",
|
|
14
21
|
"postversion": "git push && git push --tags && npm publish"
|
|
15
22
|
},
|
|
16
23
|
"keywords": [],
|
|
@@ -18,8 +25,16 @@
|
|
|
18
25
|
"license": "UNLICENSED",
|
|
19
26
|
"devDependencies": {
|
|
20
27
|
"@babel/preset-env": "^7.10.3",
|
|
28
|
+
"@rollup/plugin-babel": "^5.3.0",
|
|
29
|
+
"@rollup/plugin-commonjs": "^17.0.0",
|
|
30
|
+
"@rollup/plugin-node-resolve": "^11.1.0",
|
|
21
31
|
"babel-jest": "^25.4.0",
|
|
22
|
-
"jest": "^25.4.0"
|
|
32
|
+
"jest": "^25.4.0",
|
|
33
|
+
"npm-run-all": "^4.1.5",
|
|
34
|
+
"rollup": "^2.36.2",
|
|
35
|
+
"rollup-plugin-delete": "^2.0.0",
|
|
36
|
+
"rollup-plugin-terser": "^7.0.2",
|
|
37
|
+
"serve": "^11.3.2"
|
|
23
38
|
},
|
|
24
39
|
"dependencies": {}
|
|
25
40
|
}
|
package/.gitlab-ci.yml
DELETED
package/babel.config.cjs
DELETED
package/jest.config.cjs
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
let store = {};
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
clear: jest.fn().mockImplementation(() => {
|
|
5
|
-
store = {};
|
|
6
|
-
}),
|
|
7
|
-
|
|
8
|
-
getItem: jest.fn().mockImplementation((key) => {
|
|
9
|
-
return store[key];
|
|
10
|
-
}),
|
|
11
|
-
|
|
12
|
-
setItem: jest.fn().mockImplementation((key, value) => {
|
|
13
|
-
store[key] = value;
|
|
14
|
-
}),
|
|
15
|
-
|
|
16
|
-
removeItem: jest.fn().mockImplementation((key) => {
|
|
17
|
-
delete store[key];
|
|
18
|
-
})
|
|
19
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
|
|
3
|
-
describe('core:class >> storageabstract:clear', () => {
|
|
4
|
-
let storageAbstract;
|
|
5
|
-
|
|
6
|
-
beforeAll(() => {
|
|
7
|
-
storageAbstract = new StorageAbstract();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('never fails or throws when storage is not set', () => {
|
|
11
|
-
delete storageAbstract.storage;
|
|
12
|
-
expect(() => {
|
|
13
|
-
storageAbstract.clear();
|
|
14
|
-
}).not.toThrow();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('runs the clear method on the storage system when defined', () => {
|
|
18
|
-
storageAbstract.storage = {
|
|
19
|
-
clear: jest.fn()
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
storageAbstract.clear();
|
|
23
|
-
expect(storageAbstract.storage.clear).toHaveBeenCalledTimes(1);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
import { DEFAULT_EXPIRATION, DEFAULT_NAMESPACE } from '../constants';
|
|
3
|
-
|
|
4
|
-
describe('core:class >> storageabstract:constructor', () => {
|
|
5
|
-
it('defaults to constant as it\'s namespace when none provided', () => {
|
|
6
|
-
const storageAbstract = new StorageAbstract();
|
|
7
|
-
expect(storageAbstract.namespace).toMatch(DEFAULT_NAMESPACE);
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('accepts an object parameter with key namespace and sets it to this.namespace', () => {
|
|
11
|
-
const namespace = 'test';
|
|
12
|
-
const storageAbstract = new StorageAbstract({ namespace });
|
|
13
|
-
expect(storageAbstract.namespace).toMatch(namespace);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('coercies the namespace to lower case before setting', () => {
|
|
17
|
-
const namespace = 'TeSt';
|
|
18
|
-
const storageAbstract = new StorageAbstract({ namespace });
|
|
19
|
-
expect(storageAbstract.namespace).toMatch(namespace.toLowerCase());
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('throws error when namespace provided is not a string', () => {
|
|
23
|
-
const namespaces = [true, {}, [], 12];
|
|
24
|
-
for (const namespace of namespaces) {
|
|
25
|
-
expect(() => {
|
|
26
|
-
new StorageAbstract({ namespace });
|
|
27
|
-
}).toThrow();
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('defaults to constant as it\'s expiration when none provided', () => {
|
|
32
|
-
const storageAbstract = new StorageAbstract();
|
|
33
|
-
expect(storageAbstract.expires).toEqual(DEFAULT_EXPIRATION);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('accepts an object parameter with key expires and sets it to this.expires', () => {
|
|
37
|
-
const expires = 3600 * 4;
|
|
38
|
-
const storageAbstract = new StorageAbstract({ expires });
|
|
39
|
-
expect(storageAbstract.expires).toEqual(expires);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('sets the storage to a default of null', () => {
|
|
43
|
-
const storageAbstract = new StorageAbstract();
|
|
44
|
-
expect(storageAbstract.storage).toEqual({});
|
|
45
|
-
});
|
|
46
|
-
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
import { EXPIRES_KEY_SUFFIX } from '../constants';
|
|
3
|
-
|
|
4
|
-
describe('core:class >> storageabstract:namespacekey', () => {
|
|
5
|
-
let storageAbstract;
|
|
6
|
-
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
storageAbstract = new StorageAbstract();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('calls the namespaceKey to generate the prefix', () => {
|
|
12
|
-
storageAbstract.namespaceKey = jest.fn();
|
|
13
|
-
storageAbstract.expirationKey('hey');
|
|
14
|
-
expect(storageAbstract.namespaceKey).toHaveBeenCalledTimes(1);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('returns a concatenated variation of the namespace and string key', () => {
|
|
18
|
-
let key = 'key';
|
|
19
|
-
expect(storageAbstract.expirationKey(key))
|
|
20
|
-
.toEqual(`${ storageAbstract.namespaceKey(key) }.${ EXPIRES_KEY_SUFFIX }`);
|
|
21
|
-
});
|
|
22
|
-
});
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
|
|
3
|
-
describe('core:class >> storageabstract:getitem', () => {
|
|
4
|
-
let storageClassMock, mockStorage, key = 'test';
|
|
5
|
-
|
|
6
|
-
beforeAll(() => {
|
|
7
|
-
storageClassMock = new StorageAbstract();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
storageClassMock.namespaceKey = jest.fn().mockImplementation(key => key);
|
|
12
|
-
storageClassMock.parser = jest.fn().mockImplementation(data => data);
|
|
13
|
-
storageClassMock.cache = jest.fn().mockImplementation(data => data);
|
|
14
|
-
storageClassMock.isSupported = jest.fn().mockImplementation(() => true);
|
|
15
|
-
storageClassMock.isItemExpired = jest.fn().mockImplementation(() => false);
|
|
16
|
-
|
|
17
|
-
mockStorage = {
|
|
18
|
-
getItem: jest.fn()
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
storageClassMock.storage = mockStorage;
|
|
22
|
-
StorageAbstract.supported = undefined;
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('returns undefined when it is not supported', () => {
|
|
26
|
-
storageClassMock.isSupported = jest.fn().mockImplementation(() => false);
|
|
27
|
-
|
|
28
|
-
expect(storageClassMock.getItem()).toEqual(undefined);
|
|
29
|
-
expect(storageClassMock.namespaceKey).not.toHaveBeenCalled();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('returns undefined when the item is expired', () => {
|
|
33
|
-
storageClassMock.isItemExpired = jest.fn().mockImplementation(() => true);
|
|
34
|
-
|
|
35
|
-
expect(storageClassMock.getItem()).toEqual(undefined);
|
|
36
|
-
expect(storageClassMock.namespaceKey).not.toHaveBeenCalled();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('calls `namespace` key to get a dynamically generated key', () => {
|
|
40
|
-
storageClassMock.namespaceKey = jest.fn().mockImplementation(() => {
|
|
41
|
-
throw new Error('Just a test fall through.');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
storageClassMock.getItem();
|
|
45
|
-
expect(storageClassMock.namespaceKey).toHaveBeenCalledTimes(1);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('calls getItem on the storage system when suspended data not available', () => {
|
|
49
|
-
storageClassMock.getItem(key);
|
|
50
|
-
expect(storageClassMock.storage.getItem).toHaveBeenCalledTimes(1);
|
|
51
|
-
expect(storageClassMock.storage.getItem).toHaveBeenCalledWith(key);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('calls the `parser` method with the data fetched from suspend or getItem', () => {
|
|
55
|
-
const data = { hey: 'you' };
|
|
56
|
-
|
|
57
|
-
const localStorage = {
|
|
58
|
-
getItem: jest.fn().mockImplementation(() => data)
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
storageClassMock.storage = localStorage;
|
|
62
|
-
|
|
63
|
-
storageClassMock.getItem(key);
|
|
64
|
-
expect(storageClassMock.parser).toHaveBeenCalled();
|
|
65
|
-
expect(storageClassMock.parser).toHaveBeenCalledWith(data);
|
|
66
|
-
});
|
|
67
|
-
|
|
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();
|
|
79
|
-
});
|
|
80
|
-
});
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
|
|
3
|
-
describe('core:class >> storageabstract:hasitem', () => {
|
|
4
|
-
let storageClassMock, key = 'test';
|
|
5
|
-
|
|
6
|
-
beforeAll(() => {
|
|
7
|
-
storageClassMock = new StorageAbstract();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
storageClassMock.getItem = jest.fn().mockImplementation(key => key);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('calls getItem to fetch the item from the storage system', () => {
|
|
15
|
-
storageClassMock.hasItem(key);
|
|
16
|
-
|
|
17
|
-
expect(storageClassMock.getItem).toHaveBeenCalledTimes(1);
|
|
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
|
-
});
|
|
25
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
import mockStorage from '../__mocks__/mock-storage';
|
|
3
|
-
import store from '../store';
|
|
4
|
-
|
|
5
|
-
describe('core:class >> storageabstract:issupported', () => {
|
|
6
|
-
let storageAbstract;
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
storageAbstract = new StorageAbstract();
|
|
10
|
-
mockStorage.setItem.mockClear();
|
|
11
|
-
mockStorage.removeItem.mockClear();
|
|
12
|
-
|
|
13
|
-
storageAbstract.storage = mockStorage;
|
|
14
|
-
store.supported = undefined;
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('returns false when the storage system is defaulted', () => {
|
|
18
|
-
storageAbstract.storage = {};
|
|
19
|
-
expect(storageAbstract.isSupported()).toBeFalsy();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('returns true when the storage system is valid and usable', () => {
|
|
23
|
-
storageAbstract.storage = mockStorage;
|
|
24
|
-
expect(storageAbstract.isSupported()).toBeTruthy();
|
|
25
|
-
expect(mockStorage.setItem).toHaveBeenCalledTimes(1);
|
|
26
|
-
expect(mockStorage.removeItem).toHaveBeenCalledTimes(1);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('returns a stored answer once the storage system has been checked', () => {
|
|
30
|
-
storageAbstract.storage = mockStorage;
|
|
31
|
-
let isSupported = storageAbstract.isSupported();
|
|
32
|
-
isSupported = storageAbstract.isSupported();
|
|
33
|
-
expect(mockStorage.setItem).toHaveBeenCalledTimes(1);
|
|
34
|
-
expect(mockStorage.removeItem).toHaveBeenCalledTimes(1);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
import { KEY_IS_REQUIRED_TO_FETCH_DATA } from '../exceptions';
|
|
3
|
-
|
|
4
|
-
describe('core:class >> storageabstract:namespacekey', () => {
|
|
5
|
-
let storageAbstract;
|
|
6
|
-
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
storageAbstract = new StorageAbstract();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('throws an exception when a non-string is passed', () => {
|
|
12
|
-
let keys = [true, [], {}, 1];
|
|
13
|
-
for (const key of keys) {
|
|
14
|
-
expect(() => {
|
|
15
|
-
storageAbstract.namespaceKey(key);
|
|
16
|
-
}).toThrow(KEY_IS_REQUIRED_TO_FETCH_DATA);
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('returns a concatenated variation of the namespace and string key', () => {
|
|
21
|
-
let key = 'key';
|
|
22
|
-
expect(storageAbstract.namespaceKey(key))
|
|
23
|
-
.toEqual(`${ storageAbstract.namespace }.${ key }`);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('coerces the key to lower case before returning', () => {
|
|
27
|
-
let key = 'KEy';
|
|
28
|
-
expect(storageAbstract.namespaceKey(key))
|
|
29
|
-
.toEqual(`${ storageAbstract.namespace }.${ key.toLowerCase() }`);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('extracts the namespace and key separator when present at the beginning of the string', () => {
|
|
33
|
-
const theRealKey = 'myrealkey';
|
|
34
|
-
let key = `${ storageAbstract.namespace }.${ theRealKey }`;
|
|
35
|
-
expect(storageAbstract.namespaceKey(key))
|
|
36
|
-
.toEqual(`${ storageAbstract.namespace }.${ theRealKey.toLowerCase() }`);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('does not extract the namespace and key separator when present anywhere else in the string', () => {
|
|
40
|
-
const theRealKey = 'myrealkey';
|
|
41
|
-
let key = `a${ storageAbstract.namespace }.${ theRealKey }`;
|
|
42
|
-
expect(storageAbstract.namespaceKey(key))
|
|
43
|
-
.not.toEqual(`${ storageAbstract.namespace }.${ theRealKey.toLowerCase() }`);
|
|
44
|
-
expect(storageAbstract.namespaceKey(key))
|
|
45
|
-
.toEqual(`${ storageAbstract.namespace }.${ key.toLowerCase() }`);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('does not extract the namespace when missing the key separator', () => {
|
|
49
|
-
const theRealKey = 'myrealkey';
|
|
50
|
-
let key = `${ storageAbstract.namespace }${ theRealKey }`;
|
|
51
|
-
expect(storageAbstract.namespaceKey(key))
|
|
52
|
-
.toEqual(`${ storageAbstract.namespace }.${ key.toLowerCase() }`);
|
|
53
|
-
});
|
|
54
|
-
});
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
|
|
3
|
-
describe('core:class >> storageabstract:parser', () => {
|
|
4
|
-
let storageAbstract;
|
|
5
|
-
const copyParse = JSON.parse;
|
|
6
|
-
delete JSON.parse;
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
storageAbstract = new StorageAbstract();
|
|
10
|
-
JSON.parse = jest.fn();
|
|
11
|
-
JSON.parse.mockClear();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('returns the raw data when not a string', () => {
|
|
15
|
-
const data = {
|
|
16
|
-
my: 'value'
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
expect(storageAbstract.parser(data)).toEqual(data);
|
|
20
|
-
expect(JSON.parse).not.toBeCalled();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('attempts to parse the item when it is a string', () => {
|
|
24
|
-
const data = 'somestuff';
|
|
25
|
-
|
|
26
|
-
storageAbstract.parser(data);
|
|
27
|
-
expect(JSON.parse).toHaveBeenCalledTimes(1);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('returns the provided string if it could not be JSON parsed', () => {
|
|
31
|
-
JSON.parse = copyParse;
|
|
32
|
-
let response;
|
|
33
|
-
|
|
34
|
-
expect(() => {
|
|
35
|
-
response = storageAbstract.parser('wowowow');
|
|
36
|
-
}).not.toThrow();
|
|
37
|
-
|
|
38
|
-
expect(response).toEqual('wowowow');
|
|
39
|
-
});
|
|
40
|
-
});
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
|
|
3
|
-
import store from '../store';
|
|
4
|
-
|
|
5
|
-
describe('core:class >> storageabstract:removeitem', () => {
|
|
6
|
-
let storageClassMock, mockStorage, key = 'test';
|
|
7
|
-
|
|
8
|
-
beforeAll(() => {
|
|
9
|
-
storageClassMock = new StorageAbstract();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
storageClassMock.isSupported = jest.fn().mockImplementation(() => true);
|
|
14
|
-
storageClassMock.namespaceKey = jest.fn().mockImplementation(key => key);
|
|
15
|
-
storageClassMock.expirationKey = jest.fn().mockImplementation(key => `${key}.expires`);
|
|
16
|
-
storageClassMock.resetAttempts = jest.fn().mockImplementation(() => {
|
|
17
|
-
storageClassMock.attempts = 0;
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
mockStorage = {
|
|
21
|
-
removeItem: jest.fn()
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
storageClassMock.storage = mockStorage;
|
|
25
|
-
store.supported = undefined;
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('halts when it is not supported', () => {
|
|
29
|
-
storageClassMock.isSupported = jest.fn().mockImplementation(() => false);
|
|
30
|
-
|
|
31
|
-
storageClassMock.removeItem(key);
|
|
32
|
-
|
|
33
|
-
expect(storageClassMock.isSupported).toHaveBeenCalledTimes(1);
|
|
34
|
-
expect(storageClassMock.storage.removeItem).not.toHaveBeenCalled();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('falls through when encountering an exception', () => {
|
|
38
|
-
store.supported = true;
|
|
39
|
-
|
|
40
|
-
const badStorage = {
|
|
41
|
-
removeItem: jest.fn().mockImplementation(() => {
|
|
42
|
-
throw new Error('testing code');
|
|
43
|
-
})
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
storageClassMock.storage = badStorage;
|
|
47
|
-
|
|
48
|
-
expect(() => {
|
|
49
|
-
storageClassMock.removeItem();
|
|
50
|
-
}).not.toThrow();
|
|
51
|
-
|
|
52
|
-
expect(storageClassMock.storage.removeItem).toHaveBeenCalledTimes(1);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('removes both the item at namespace and expiration keys', () => {
|
|
56
|
-
store.supported = true;
|
|
57
|
-
storageClassMock.removeItem();
|
|
58
|
-
|
|
59
|
-
expect(storageClassMock.namespaceKey).toHaveBeenCalledTimes(1);
|
|
60
|
-
expect(storageClassMock.expirationKey).toHaveBeenCalledTimes(1);
|
|
61
|
-
expect(storageClassMock.storage.removeItem).toHaveBeenCalledTimes(2);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
import store from '../store';
|
|
3
|
-
|
|
4
|
-
describe('core:class >> storageabstract:setitem', () => {
|
|
5
|
-
let storageClassMock, mockStorage, key = 'test';
|
|
6
|
-
|
|
7
|
-
beforeAll(() => {
|
|
8
|
-
storageClassMock = new StorageAbstract();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
storageClassMock.isSupported = jest.fn().mockImplementation(() => true);
|
|
13
|
-
storageClassMock.namespaceKey = jest.fn().mockImplementation(key => key);
|
|
14
|
-
storageClassMock.expirationKey = jest.fn().mockImplementation(key => key);
|
|
15
|
-
storageClassMock.translator = jest.fn().mockImplementation(data => data);
|
|
16
|
-
storageClassMock.timestamp = jest.fn().mockImplementation(() => 12345);
|
|
17
|
-
storageClassMock.cache = jest.fn().mockImplementation(data => data);
|
|
18
|
-
storageClassMock.clear = jest.fn().mockImplementation(() => storageClassMock);
|
|
19
|
-
storageClassMock.resetAttempts = jest.fn().mockImplementation(() => {
|
|
20
|
-
storageClassMock.attempts = 0;
|
|
21
|
-
return storageClassMock;
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
mockStorage = {
|
|
25
|
-
setItem: jest.fn()
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
storageClassMock.attempts = 0;
|
|
29
|
-
storageClassMock.storage = mockStorage;
|
|
30
|
-
store.supported = undefined;
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('resets the attempts and returns when it is not supported without continuing', () => {
|
|
34
|
-
storageClassMock.isSupported = jest.fn().mockImplementation(() => false);
|
|
35
|
-
storageClassMock.setItem();
|
|
36
|
-
|
|
37
|
-
expect(storageClassMock.isSupported).toHaveBeenCalledTimes(1);
|
|
38
|
-
expect(storageClassMock.namespaceKey).not.toHaveBeenCalled();
|
|
39
|
-
expect(mockStorage.setItem).not.toHaveBeenCalled();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('uses a dynamically generated namespaceKey to set the item', () => {
|
|
43
|
-
storageClassMock.setItem(key, { data: true });
|
|
44
|
-
expect(storageClassMock.namespaceKey).toHaveBeenCalledTimes(1);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('calls the translator prior to attempting to set the item', () => {
|
|
48
|
-
storageClassMock.translator = jest.fn().mockImplementation(() => {
|
|
49
|
-
throw new Error('testing script error');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
storageClassMock.setItem(key, { data: true });
|
|
53
|
-
expect(storageClassMock.translator).toHaveBeenCalled();
|
|
54
|
-
expect(storageClassMock.storage.setItem).not.toHaveBeenCalled();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('calls to set the item one time when not expiring', () => {
|
|
58
|
-
const data = { it: true };
|
|
59
|
-
|
|
60
|
-
storageClassMock.setItem(key, data, false);
|
|
61
|
-
|
|
62
|
-
expect(storageClassMock.storage.setItem).toHaveBeenCalledTimes(1);
|
|
63
|
-
expect(storageClassMock.storage.setItem).toHaveBeenCalledWith(key, data);
|
|
64
|
-
expect(storageClassMock.expirationKey).not.toHaveBeenCalled();
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('calls set item again with the expiration key if defaulted to expire', () => {
|
|
68
|
-
const data = { it: true };
|
|
69
|
-
|
|
70
|
-
storageClassMock.setItem(key, data);
|
|
71
|
-
|
|
72
|
-
expect(storageClassMock.storage.setItem).toHaveBeenCalledTimes(2);
|
|
73
|
-
expect(storageClassMock.expirationKey).toHaveBeenCalledTimes(1);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../';
|
|
2
|
-
|
|
3
|
-
describe('core:class >> storageabstract:translator', () => {
|
|
4
|
-
let storageAbstract;
|
|
5
|
-
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
storageAbstract = new StorageAbstract();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('calls json stringify when passed an object', () => {
|
|
11
|
-
const data = {
|
|
12
|
-
my: 'value'
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
expect(storageAbstract.translator(data))
|
|
16
|
-
.toEqual(JSON.stringify(data));
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('returns a string back exactly as is', () => {
|
|
20
|
-
const data = 'somestuff';
|
|
21
|
-
|
|
22
|
-
expect(storageAbstract.translator(data)).toEqual(data);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const KEY_IS_REQUIRED_TO_FETCH_DATA = 'A key must be provided to obtain data from the store.';
|
package/lib/abstract/index.js
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_EXPIRATION, DEFAULT_NAMESPACE, EXPIRES_KEY_SUFFIX } from './constants';
|
|
2
|
-
import { KEY_IS_REQUIRED_TO_FETCH_DATA } from './exceptions';
|
|
3
|
-
import store from './store';
|
|
4
|
-
|
|
5
|
-
/*
|
|
6
|
-
|--------------------------------------------------------------------------
|
|
7
|
-
| Storage Abstract / Contract
|
|
8
|
-
|--------------------------------------------------------------------------
|
|
9
|
-
|
|
|
10
|
-
| This is the base storage class that is extended for localStorage and
|
|
11
|
-
| sessionStorage. In time we may look to use this for InnoDB as well.
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
*/
|
|
15
|
-
export default class StorageAbstract {
|
|
16
|
-
/**
|
|
17
|
-
* Constructor takes in options for namespace and expiration.
|
|
18
|
-
* Session storage is the default storage type.
|
|
19
|
-
*
|
|
20
|
-
* @param {object} options
|
|
21
|
-
* @constructor
|
|
22
|
-
*/
|
|
23
|
-
constructor (options = {}) {
|
|
24
|
-
this.namespace = options.namespace || DEFAULT_NAMESPACE;
|
|
25
|
-
this.expires = options.expires || DEFAULT_EXPIRATION;
|
|
26
|
-
|
|
27
|
-
this.namespace = this.namespace.toLowerCase();
|
|
28
|
-
|
|
29
|
-
this.storage = {};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Gets an item from storage and runs the parser unless explicitly
|
|
34
|
-
* disabled in the method request.
|
|
35
|
-
*
|
|
36
|
-
* @param {String} key
|
|
37
|
-
* @param {Boolean} parse
|
|
38
|
-
* @returns {(Array|Number|Object|String|Null)}
|
|
39
|
-
*/
|
|
40
|
-
getItem (key, parse = true) {
|
|
41
|
-
let response;
|
|
42
|
-
|
|
43
|
-
if (! this.isSupported() || this.isItemExpired(key)) {
|
|
44
|
-
return undefined;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
response = this.storage.getItem(this.namespaceKey(key));
|
|
49
|
-
|
|
50
|
-
if (response === null) return undefined;
|
|
51
|
-
|
|
52
|
-
response = parse ? this.parser(response) : response;
|
|
53
|
-
} catch (e) {
|
|
54
|
-
// fall through
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return response;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Parses the data returned from the storage system
|
|
62
|
-
*
|
|
63
|
-
* @param data
|
|
64
|
-
* @returns {*}
|
|
65
|
-
*/
|
|
66
|
-
parser (data) {
|
|
67
|
-
try {
|
|
68
|
-
if (typeof data === 'string') {
|
|
69
|
-
data = JSON.parse(data);
|
|
70
|
-
}
|
|
71
|
-
} catch (e) {
|
|
72
|
-
// fall through
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return data;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Translates the data before setting to the storage system
|
|
80
|
-
*
|
|
81
|
-
* @param value
|
|
82
|
-
* @returns {any}
|
|
83
|
-
*/
|
|
84
|
-
translator (value) {
|
|
85
|
-
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Sets an item in the storage system.
|
|
90
|
-
*
|
|
91
|
-
* @param {string} key
|
|
92
|
-
* @param {(array|object|number|string)} value
|
|
93
|
-
* @param {boolean} expires
|
|
94
|
-
*/
|
|
95
|
-
setItem (key, value, expires = true) {
|
|
96
|
-
if (! this.isSupported()) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const generatedKey = this.namespaceKey(key);
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
this.storage.setItem(generatedKey, this.translator(value));
|
|
104
|
-
|
|
105
|
-
if (expires) {
|
|
106
|
-
this.storage.setItem(
|
|
107
|
-
this.expirationKey(key),
|
|
108
|
-
String(this.timestamp(this.expires)),
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
} catch (e) {
|
|
112
|
-
// fall through
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Removes an item from the storage system.
|
|
118
|
-
*
|
|
119
|
-
* @param {string} key
|
|
120
|
-
*/
|
|
121
|
-
removeItem (key) {
|
|
122
|
-
if (! this.isSupported()) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
this.storage.removeItem(this.namespaceKey(key));
|
|
128
|
-
this.storage.removeItem(this.expirationKey(key));
|
|
129
|
-
} catch (e) {
|
|
130
|
-
// fall through
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Clears all items from storage.
|
|
136
|
-
*/
|
|
137
|
-
clear () {
|
|
138
|
-
try {
|
|
139
|
-
this.storage.clear();
|
|
140
|
-
} catch (e) {
|
|
141
|
-
// fall through
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Checks to see if an item exists in local storage.
|
|
147
|
-
*
|
|
148
|
-
* @param {string} key
|
|
149
|
-
* @returns {boolean}
|
|
150
|
-
*/
|
|
151
|
-
hasItem (key) {
|
|
152
|
-
return this.getItem(key, false) !== undefined;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Calculates the expires for an item.
|
|
157
|
-
*
|
|
158
|
-
* @param {number} offset
|
|
159
|
-
* @returns {number}
|
|
160
|
-
*/
|
|
161
|
-
timestamp (offset = 0) {
|
|
162
|
-
return Math.ceil(Date.now() / 1000) + offset;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Creates the key used for storing information in the storage
|
|
167
|
-
*
|
|
168
|
-
* @param {string} key
|
|
169
|
-
* @returns {string}
|
|
170
|
-
*/
|
|
171
|
-
namespaceKey (key) {
|
|
172
|
-
if (typeof key !== 'string') {
|
|
173
|
-
throw new Error(KEY_IS_REQUIRED_TO_FETCH_DATA);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (key.indexOf(`${ this.namespace }.`) === 0) {
|
|
177
|
-
key = key.slice(this.namespace.length + 1);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return `${ this.namespace }.${ key.toLowerCase() }`;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Creates the expires key used for testing storage usage
|
|
185
|
-
*
|
|
186
|
-
* @returns {string}
|
|
187
|
-
*/
|
|
188
|
-
expirationKey (key) {
|
|
189
|
-
return `${ this.namespaceKey(key) }.${ EXPIRES_KEY_SUFFIX }`;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Checks to see if an item is expired and removes it if so.
|
|
194
|
-
*
|
|
195
|
-
* @param {string} key
|
|
196
|
-
* @returns {boolean}
|
|
197
|
-
*/
|
|
198
|
-
isItemExpired (key) {
|
|
199
|
-
if (! this.isSupported()) {
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
try {
|
|
204
|
-
let value = this.storage.getItem(this.expirationKey(key));
|
|
205
|
-
|
|
206
|
-
if (typeof value === 'string' && value.length > 0) {
|
|
207
|
-
let expires = parseInt(value, 10);
|
|
208
|
-
|
|
209
|
-
if (expires - this.timestamp() <= 0) {
|
|
210
|
-
this.removeItem(key);
|
|
211
|
-
return true;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
} catch (e) {
|
|
215
|
-
// fall through
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return false;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Checks to see if the storage system is supported
|
|
223
|
-
*
|
|
224
|
-
* @returns {boolean}
|
|
225
|
-
*/
|
|
226
|
-
isSupported () {
|
|
227
|
-
if (typeof store.supported === 'boolean') {
|
|
228
|
-
return store.supported;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const test = 'biz.storage.test';
|
|
232
|
-
|
|
233
|
-
try {
|
|
234
|
-
this.storage.setItem(test, '1');
|
|
235
|
-
this.storage.removeItem(test);
|
|
236
|
-
|
|
237
|
-
store.supported = true;
|
|
238
|
-
} catch (e) {
|
|
239
|
-
store.supported = e instanceof DOMException && (
|
|
240
|
-
// everything except Firefox
|
|
241
|
-
e.code === 22 ||
|
|
242
|
-
// Firefox
|
|
243
|
-
e.code === 1014 ||
|
|
244
|
-
// test name field too, because code might not be present
|
|
245
|
-
// everything except Firefox
|
|
246
|
-
e.name === 'QuotaExceededError' ||
|
|
247
|
-
// Firefox
|
|
248
|
-
e.name === 'NS_ERROR_DOM_QUOTA_REACHED'
|
|
249
|
-
) && (this.storage && this.storage.length !== 0);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return store.supported;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from '../../abstract';
|
|
2
|
-
|
|
3
|
-
export default class LocalStorageMock extends StorageAbstract {
|
|
4
|
-
constructor (options) {
|
|
5
|
-
super(options);
|
|
6
|
-
this.store = {};
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
clear () {
|
|
10
|
-
this.store = {};
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
getItem (key) {
|
|
14
|
-
return this.store[key] || null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
setItem (key, value, expires = true) {
|
|
18
|
-
this.store[key] = value;
|
|
19
|
-
return this;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
removeItem (key) {
|
|
23
|
-
delete this.store[key];
|
|
24
|
-
return this;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export class InvalidStorageMock {}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import LocalStorage from '../';
|
|
2
|
-
|
|
3
|
-
describe('bizjournals / core:class >> localstorage:constructor', () => {
|
|
4
|
-
it('builds the object with localStorage set as the storage system', () => {
|
|
5
|
-
const localStorage = new LocalStorage();
|
|
6
|
-
expect(localStorage.storage).toEqual(window.localStorage);
|
|
7
|
-
});
|
|
8
|
-
});
|
package/lib/local/index.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from "../abstract";
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
|--------------------------------------------------------------------------
|
|
5
|
-
| Local Storage
|
|
6
|
-
|--------------------------------------------------------------------------
|
|
7
|
-
| This is the base class for hooking into local storage. There isn't much
|
|
8
|
-
| overlap here if you just keep instantiating, so there isn't much need
|
|
9
|
-
| to singleton this.
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
*/
|
|
13
|
-
export default class LocalStorage extends StorageAbstract {
|
|
14
|
-
/**
|
|
15
|
-
* Create a local storage adapter.
|
|
16
|
-
*
|
|
17
|
-
* @param {object} [options]
|
|
18
|
-
*/
|
|
19
|
-
constructor(options = {}) {
|
|
20
|
-
super(options);
|
|
21
|
-
|
|
22
|
-
this.storage = window.localStorage;
|
|
23
|
-
}
|
|
24
|
-
}
|
package/lib/main.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import StorageReference from '../';
|
|
2
|
-
import LocalStorageMock, { InvalidStorageMock } from '../../local/__mocks__/local-storage';
|
|
3
|
-
import { INVALID_CONSTRUCTOR_PARAMETERS } from '../exceptions';
|
|
4
|
-
|
|
5
|
-
describe('bizjournals / core:class >> storagereference', () => {
|
|
6
|
-
it('throws error when the cachekey is not a string', () => {
|
|
7
|
-
expect(() => {
|
|
8
|
-
new StorageReference([], new LocalStorageMock());
|
|
9
|
-
}).toThrow(INVALID_CONSTRUCTOR_PARAMETERS);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('throws an error when the storage system does not adhere to contract', () => {
|
|
13
|
-
expect(() => {
|
|
14
|
-
new StorageReference('astring', new InvalidStorageMock());
|
|
15
|
-
}).toThrow(INVALID_CONSTRUCTOR_PARAMETERS);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('does not throw an error when constructor parameters are valid', () => {
|
|
19
|
-
expect(() => {
|
|
20
|
-
new StorageReference('astring', new LocalStorageMock());
|
|
21
|
-
}).not.toThrow();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('assigns the constructor parameters to variables for reference', () => {
|
|
25
|
-
const cacheKey = 'astring';
|
|
26
|
-
const localStorage = new LocalStorageMock();
|
|
27
|
-
|
|
28
|
-
const storage = new StorageReference(cacheKey, localStorage);
|
|
29
|
-
|
|
30
|
-
expect(storage.cacheKey).toEqual(cacheKey);
|
|
31
|
-
expect(storage.storageSystem).toEqual(localStorage);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('can save and obtain the data using the key from storage', () => {
|
|
35
|
-
const cacheKey = 'astring';
|
|
36
|
-
const localStorage = new LocalStorageMock();
|
|
37
|
-
const mockData = { luke: 'skywalker', plot: 'ruined' };
|
|
38
|
-
|
|
39
|
-
const storage = new StorageReference(cacheKey, localStorage);
|
|
40
|
-
|
|
41
|
-
expect(() => {
|
|
42
|
-
storage.saveAs(mockData);
|
|
43
|
-
}).not.toThrow();
|
|
44
|
-
|
|
45
|
-
expect(storage.obtain()).toEqual(mockData);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const INVALID_CONSTRUCTOR_PARAMETERS = 'Invalid construction of cache system. Please refer to documentation.';
|
package/lib/reference/index.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from "../abstract";
|
|
2
|
-
import { INVALID_CONSTRUCTOR_PARAMETERS } from "./exceptions";
|
|
3
|
-
|
|
4
|
-
/*
|
|
5
|
-
|--------------------------------------------------------------------------
|
|
6
|
-
| Storage Reference
|
|
7
|
-
|--------------------------------------------------------------------------
|
|
8
|
-
| This is a reference to something in storage. Each item has a key
|
|
9
|
-
| belonging to a specific storage system. These storage systems have a
|
|
10
|
-
| common abstract / contract that gives them the same expected pattern.
|
|
11
|
-
| This is the adapter.
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
*/
|
|
15
|
-
export default class StorageReference {
|
|
16
|
-
/**
|
|
17
|
-
* Creates an instance of a StorageReference system, which needs a cacheKey and
|
|
18
|
-
* a Storage system (StorageAbstract).
|
|
19
|
-
*
|
|
20
|
-
* @param {string} cacheKey
|
|
21
|
-
* @param {StorageAbstract} storageSystem
|
|
22
|
-
* @constructor
|
|
23
|
-
* @return {StorageReference}
|
|
24
|
-
*/
|
|
25
|
-
constructor(cacheKey, storageSystem) {
|
|
26
|
-
if (typeof cacheKey !== "string" || !(storageSystem instanceof StorageAbstract)) {
|
|
27
|
-
throw new Error(INVALID_CONSTRUCTOR_PARAMETERS);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
this.cacheKey = cacheKey;
|
|
31
|
-
this.storageSystem = storageSystem;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Pulls data from the local store or cached resource.
|
|
36
|
-
*
|
|
37
|
-
* @returns {*}
|
|
38
|
-
*/
|
|
39
|
-
obtain() {
|
|
40
|
-
return this.storageSystem.getItem(this.cacheKey);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Destroys the cache reference with the cache key
|
|
45
|
-
*
|
|
46
|
-
* @returns {void}
|
|
47
|
-
*/
|
|
48
|
-
bust() {
|
|
49
|
-
this.storageSystem.removeItem(this.cacheKey);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Saves the locally stored cache to the caching system. This is
|
|
54
|
-
* differed via a Promise because the timing of this can be
|
|
55
|
-
* performed asynchronously.
|
|
56
|
-
*
|
|
57
|
-
* @param data
|
|
58
|
-
* @returns {StorageReference}
|
|
59
|
-
*/
|
|
60
|
-
saveAs(data) {
|
|
61
|
-
if (data) {
|
|
62
|
-
this.storageSystem.setItem(this.cacheKey, data);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return this;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import SessionStorage from "../";
|
|
2
|
-
|
|
3
|
-
describe("bizjournals / core:class >> sessionstorage:constructor", () => {
|
|
4
|
-
it("builds the object with sessionStorage set as the storage system", () => {
|
|
5
|
-
const sessionStorage = new SessionStorage();
|
|
6
|
-
expect(sessionStorage.storage).toEqual(window.sessionStorage);
|
|
7
|
-
});
|
|
8
|
-
});
|
package/lib/session/index.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import StorageAbstract from "../abstract";
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
|--------------------------------------------------------------------------
|
|
5
|
-
| Session Storage
|
|
6
|
-
|--------------------------------------------------------------------------
|
|
7
|
-
| This is the base class for hooking into session storage. There isn't much
|
|
8
|
-
| overlap here if you just keep instantiating, so there isn't much need
|
|
9
|
-
| to singleton this.
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
*/
|
|
13
|
-
export default class SessionStorage extends StorageAbstract {
|
|
14
|
-
/**
|
|
15
|
-
* Create a session storage adapter.
|
|
16
|
-
*
|
|
17
|
-
* @param {object} [options]
|
|
18
|
-
*/
|
|
19
|
-
constructor(options) {
|
|
20
|
-
super(options);
|
|
21
|
-
|
|
22
|
-
this.storage = window.sessionStorage;
|
|
23
|
-
}
|
|
24
|
-
}
|