Created
August 28, 2023 20:47
-
-
Save yairEO/89d0b42b67e708832a878f259eecb172 to your computer and use it in GitHub Desktop.
browserStorage.js - better reading/writings to localstorage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {isString} from 'utility/types'; | |
export const VERSION = 1; // current version of persisted data. if code change breaks persisted data, verison number should be bumped. | |
export const STORAGE_KEY_PREFIX = 'amdocs/catalog'; | |
/** | |
* checks arguments are as expected | |
* @param {string} keyName | |
* @param {string} type | |
* @returns boolean | |
*/ | |
const isValid = (keyName, type) => { | |
if (!window[`${type}Storage`]) { | |
console.warn('wrong storage type: ', type); | |
return false; | |
} | |
if (!keyName || !isString(keyName)) { | |
console.warn('missing keyName or invalid type'); | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* | |
* @param {string} keyName | |
* @returns full storage path name, conststing of pre-defined, base path prefix and a custom dynamic path suffix | |
*/ | |
export const getPathString = (keyName, version) => `${STORAGE_KEY_PREFIX}/${keyName}/v${version || VERSION}`; | |
/** | |
* extracts the storage path's version, which is at the end of the key | |
* @param {string} key | |
* @returns number | |
*/ | |
const getKeyVersion = key => +key.split('/v').pop(); | |
export function removeBrowserStorage(keyName, {type = 'local', version = VERSION} = {}) { | |
if (!isValid(keyName, type)) return; | |
window[`${type}Storage`].removeItem(getPathString(keyName, version)); | |
} | |
export function getBrowserStorage(keyName, {type = 'local'} = {}) { | |
if (!isValid(keyName, type)) return; | |
let value; | |
Object.keys(window[`${type}Storage`]) | |
.filter(key => key.includes('/' + keyName)) | |
.forEach(key => { | |
const keyVersion = getKeyVersion(key); | |
if (keyVersion === VERSION) { | |
try { value = JSON.parse(window[`${type}Storage`][key]); } | |
catch (err){ console.warn(err); } | |
} | |
// remove any previous version(s) | |
else | |
removeBrowserStorage(keyName, {version: keyVersion}); | |
}); | |
return value; | |
} | |
/** | |
* Sets a browser local/session storage key/value | |
* @param {string} keyName storage key name which gets concatenated to the base STORAGE_KEY_PREFIX | |
* @param {*} data any type of data which can be represented as string | |
* @param {string} type local/session storage type | |
* @returns | |
*/ | |
export function setBrowserStorage(keyName, data, {type = 'local'} = {}) { | |
if (!isValid(keyName, type)) return; | |
if (!data) { | |
console.warn('setBrowserStorage: no data (forgot?)'); | |
return false; | |
} | |
window[`${type}Storage`].setItem(getPathString(keyName), JSON.stringify(data)); | |
// go over all existing storage keys and find the one matching the keyName | |
const foundStorageKey = Object.keys(window[`${type}Storage`]).find(key => key.includes('/' + keyName)); | |
// gets the key's version, which is suffixed at the end | |
const storageKeyVersion = getKeyVersion(foundStorageKey); | |
// if found key has a deprecated version, remove that key | |
if (storageKeyVersion !== VERSION) | |
removeBrowserStorage(keyName, {version: storageKeyVersion}); | |
window[`${type}Storage`].setItem(getPathString(keyName), JSON.stringify(data)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sinon from 'sinon'; | |
import {expect} from 'chai'; | |
import {getPathString, getBrowserStorage, setBrowserStorage} from './browserStorage'; | |
describe('Browser storage', () => { | |
const sandbox = sinon.createSandbox(); | |
const data = {name: 'John Doe', age: 30}; | |
afterEach(() => { | |
sandbox.restore(); | |
}); | |
describe('setBrowserStorage', () => { | |
it('should call window.localStorage.setItem with the correct arguments', () => { | |
const setItemStub = sandbox.stub(window.localStorage, 'setItem'); | |
setBrowserStorage('user', data); | |
expect(setItemStub.calledOnceWith(getPathString('user'), JSON.stringify(data))).to.be.true; | |
}); | |
it('should not call window.localStorage.setItem when keyName is not a string', () => { | |
const setItemStub = sandbox.stub(window.localStorage, 'setItem'); | |
setBrowserStorage(null, data); | |
expect(setItemStub.notCalled).to.be.true; | |
}); | |
it('should not call window.localStorage.setItem when type is not "local" or "session"', () => { | |
const setItemStub = sandbox.stub(window.localStorage, 'setItem'); | |
setBrowserStorage('user', data, {type: 'invalid'}); | |
expect(setItemStub.notCalled).to.be.true; | |
}); | |
}); | |
describe('getBrowserStorage', () => { | |
it('should call window.localStorage.getItem with the correct arguments', () => { | |
const getItemStub = sandbox.stub(window.localStorage, 'getItem'); | |
const path = getPathString('user'); | |
getBrowserStorage('user'); | |
expect(getItemStub.calledWith(path)).to.be.true; | |
}); | |
it('should not call window.localStorage.getItem when keyName is not a string', () => { | |
const getItemStub = sandbox.stub(window.localStorage, 'getItem'); | |
expect(getBrowserStorage(null)).to.be.undefined; | |
expect(getItemStub.notCalled).to.be.true; | |
}); | |
it('should not call window.localStorage.getItem when type is not "local" or "session"', () => { | |
const getItemStub = sandbox.stub(window.localStorage, 'getItem'); | |
expect(getBrowserStorage('user', {type: 'invalid'})).to.be.undefined; | |
expect(getItemStub.notCalled).to.be.true; | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export * from './browserStorage'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment