Home Reference Source

core/datastore/persisters/browser/browser-key-value-persister.js

import { Promise } from 'es6-promise';

import { Client } from '../../../client';

import { KeyValuePersister } from '../key-value-persister';
import { browserStorageCollectionsMaster } from '../utils';

/**
 * @private
 * @typedef BrowserStore
 * @property {Function} getItem
 * @property {Function} setItem
 * @property {Function} removeItem
 * @property {Function} clear
 */
export class BrowserKeyValuePersister extends KeyValuePersister {
  /** @type {BrowserStore} */
  _store;

  constructor(store, cacheEnabled, cacheTtl) {
    super(cacheEnabled, cacheTtl);
    this._store = store;
  }

  getKeys() {
    return Promise.resolve(Object.keys(this._store));
  }

  _readFromPersistance(collection) {
    const serialized = this._store.getItem(collection);
    return this._deserialize(serialized);
  }

  _writeToPersistance(collection, entities) {
    return this._ensureCollectionExists(collection)
      .then(() => this._serializeAndSet(collection, entities));
  }

  _deleteFromPersistance(collection) {
    this._store.removeItem(collection);
    return Promise.resolve();
  }

  // this is now used in the ReactNative shim as a protected method
  _buildMasterCollectionName() {
    return `${Client.sharedInstance().appKey}.${browserStorageCollectionsMaster}`;
  }

  // private methods

  _ensureCollectionExists(collection) {
    const masterCollectionName = this._buildMasterCollectionName();
    return this._readFromPersistance(masterCollectionName)
      .then((allCollections) => {
        allCollections = allCollections || [];
        const exists = allCollections.find(c => c === collection);
        if (exists) {
          return Promise.resolve();
        }
        allCollections.push(collection);
        return this._serializeAndSet(masterCollectionName, allCollections);
      });
  }

  _serializeAndSet(collection, entities) {
    return this._serialize(entities)
      .then(serialized => this._store.setItem(collection, serialized));
  }

  _serialize(obj) {
    try {
      return Promise.resolve(JSON.stringify(obj));
    } catch (err) {
      return Promise.reject(err);
    }
  }

  _deserialize(serializedObj) {
    try {
      const deserialized = JSON.parse(serializedObj);
      return Promise.resolve(deserialized);
    } catch (err) {
      return Promise.reject(err);
    }
  }
}