js/src/services/data.service.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * Save and Retrieve Session or Local Web storage data.
 */
class DataService {
    constructor() {
        this.hasStorage = this.storageAvailable('localStorage') && this.storageAvailable('sessionStorage');
        this.storage = { session: sessionStorage, local: localStorage };
    }

    /**
     * Check if storage is available.
     *
     * @returns {boolean|*}
     */
    storageAvailable(type) {
        let storage;
        try {
            storage = window[type];
            const x = '__storage_test__';
            storage.setItem(x, x);
            storage.removeItem(x);

            return true;
        } catch (e) {
            return e instanceof DOMException
                && (
                    e.code === 22 // everything except Firefox
                    || e.code === 1014 // Firefox
                    || e.name === 'QuotaExceededError' // test name field too, because code might not be present, everything except Firefox
                    || e.name === 'NS_ERROR_DOM_QUOTA_REACHED' // Firefox
                )
                // acknowledge QuotaExceededError only if there's something already stored
                && (storage && storage.length > 0);
        }
    }

    /**
     * Check for valid JSON string.
     *
     * @returns {boolean}
     */
    isJsonString(str) {
        try {
            JSON.parse(str);
        } catch (e) {
            console.error('JSON string parse failed: ' + e.message);

            return false;
        }

        return true;
    }

    /**
     * Set Item data value to local or web storage.
     * The item is the key associated with the data value in web or local storage.
     * Will add item value or replace it if already exist.
     */
    setData(item, value, type = 'local') {
        if (this.hasStorage) {
            this.storage[type].setItem(item, value);
        } else {
            console.error('Session storage is not available in your browser');
        }
    }

    /**
     * Get data value using an item as key.
     */
    getData(item, type = 'local') {
        let value = null;
        if (this.hasStorage) {
            value = this.storage[type].getItem(item);
        }

        return value;
    }

    /**
     * Clear associated data using item as key.
     */
    clearData(item, type = 'local') {
        if (this.hasStorage) {
            this.storage[type].removeItem(item);
        }
    }

    /**
     * Return store data for an item or empty object.
     *
     * @returns {{ session: *, local: * }}
     */
    getStoreData(name) {
        const store = {};
        if (name) {
            const localData = this.getData(name, 'local');
            if (localData) {
                store[name + '_local_store'] = localData;
            }
            const sessionData = this.getData(name, 'session');
            if (sessionData) {
                store[name + '_session_store'] = sessionData;
            }
        }

        return store;
    }

    /**
     * Similar to set data but make sure that value is
     * a valid JSON string prior to set data.
     */
    setJsonData(item, value, type = 'local') {
        if (!this.isJsonString(value)) {
            return;
        }
        this.setData(item, value, type);
    }

    /**
     * Will either create or merge with existing data.
     * Merging is done with Object assign, prioritizing new value.
     * Previous data, if exist, and value must be a valid JSON string.
     */
    addJsonData(item, value, type = 'local') {
        const previous = this.getData(item, type);
        if (!this.isJsonString(value) || !this.isJsonString(previous)) {
            return;
        }

        if (previous) {
            this.setData(item, JSON.stringify(Object.assign(JSON.parse(previous), JSON.parse(value))), type);
        } else {
            this.setData(item, value, type);
        }
    }
}

export default Object.freeze(new DataService());