jcgertig/betterstorage

View on GitHub
src/BetterStorage.js

Summary

Maintainability
C
1 day
Test Coverage
import { autobind } from 'core-decorators';

@autobind
export default class BetterStorage {
  constructor(prefix = '', kind = 'local', overrides = {}) {
    this.prefix = prefix;
    this.kind = kind;
    this.store = typeof kind === 'string' ? window[`${kind}Storage`] : kind;

    this.methods = Object.assign({
      doSet: this._doSet,
      doGet: this._doGet,
      doRemove: this._doRemove,
      doClear: this._doClear,
      doLength: this._doLength,
      doFullLength: this._doFullLength,
      doKey: this._doKey,
      doFullKey: this._doFullKey,
      doHas: this._doHas
    }, overrides);
  }

  _doSet(key, data) {
    return this.store.setItem(key, JSON.stringify({ value: data }));
  }

  _doGet(key) {
    try {
      return JSON.parse(this.store.getItem(key)).value;
    } catch (e) {
      return this.store.getItem(key);
    }
  }

  _doRemove(key) {
    return this.store.removeItem(key);
  }

  _doClear() {
    return this.store.clear();
  }

  _doLength() {
    return this.keys.length;
  }

  _doFullLength() {
    return this.store.length;
  }

  _doKey(n) {
    return this.keys[n];
  }

  _doFullKey(n) {
    return this.store.key(n);
  }

  _doHas(key) {
    return this.fullKeys.indexOf(key) > -1;
  }

  getStoreKey(key = '', prefix) {
    prefix = prefix || this.prefix;
    if (prefix === '') { return key; }
    return `${prefix}-${key}`;
  }

  setPrefix(prefix = '', changeExisting = false) {
    if (changeExisting && this.prefix !== '' && this.keys.length > 0) {
      this.keys.forEach((key) => {
        const val = this.store.getItem(this.getStoreKey(key));
        this.store.removeItem(this.getStoreKey(key));
        this.store.setItem(this.getStoreKey(key, prefix), val);
      });
    }
    this.prefix = prefix;
  }

  setKind(kind, migrateData = false) {
    const newStore = typeof kind === 'string' ? window[`${kind}Storage`] : kind;
    if (migrateData && this.prefix !== '' && this.keys.length > 0) {
      this.keys.forEach((key) => {
        const val = this.store.getItem(this.getStoreKey(key));
        this.store.removeItem(this.getStoreKey(key));
        newStore.setItem(this.getStoreKey(key), val);
      });
    }
    this.kind = kind;
    this.store = newStore;
  }

  /*
   * Set Item into Storage
   */
  set(key, value) {
    return this.methods.doSet(this.getStoreKey(key), value);
  }

  /*
   * Get Item from Storage
   */
  get(key) {
    return this.methods.doGet(this.getStoreKey(key));
  }

  /*
   * Removes an Item from Storage
   */
  remove(key) {
    return this.methods.doRemove(this.getStoreKey(key));
  }

  /*
   * If store has key
   */
  has(key) {
    return this.methods.doHas(this.getStoreKey(key));
  }

  /*
   * Clears the store
   */
  clear(full = false) {
    if (this.prefix === '' || full) {
      return this.methods.doClear();
    } else {
      return Promise.all(
        this.keys.map((key) => {
          return this.methods.doRemove(this.getStoreKey(key));
        })
      );
    }
  }

  /*
   * Number of items with prefix
   */
  getLength() {
    return this.methods.doLength();
  }

  /*
   * Number of items in the store
   */
  getFullLength() {
    return this.methods.doFullLength();
  }

  /*
   * Get prefix key at location
   */
  key(n) {
    return this.methods.doKey(n);
  }

  /*
   * Get key at location
   */
  fullKey(n) {
    return this.methods.doFullKey(n);
  }

  /*
   * List of prefixed keys in store
   */
  get keys() {
    if (this.prefix === '') { return this.fullKeys; }
    return Object.keys(this.store)
      .filter((item) => item.indexOf(`${this.prefix}-`) === 0)
      .map((item) => item.replace(`${this.prefix}-`, ''));
  }

  /*
   * List of all keys in store
   */
  get fullKeys() {
    return Object.keys(this.store);
  }
}