Skip to content

Latest commit

 

History

History
410 lines (294 loc) · 14.6 KB

README.md

File metadata and controls

410 lines (294 loc) · 14.6 KB

Proxy Storage

This library is intended to use as a proxy that implements a basic Web Storage interface, which is very useful to deal with the lack of compatibility between document.cookie and localStorage / sessionStorage api.

It also provides a fallback that stores the data in memory when all of above mechanisms are not available, for example in some browsers when you are in private navigation. The behavior of the memoryStorage is similar to sessionStorage.

The exposed Web Storage interface allow us saving data as JSON, with the advantage that you can store Object and Array<Any> values, which is not possible when you are using native localStorage, sessionStorage and cookie storages.

Another plus in proxy-storage is that you can register interceptors for each of the exposed Web Storage methods: setItem, getItem, removeItem, clear

Getting started

To include this library into your package manager with npm or yarn

# with npm
$ npm install proxy-storage --save

# with yarn
$ yarn add proxy-storage

Including the library

proxy-storage can be included directly from a CDN in your page:

<!-- last version: 1.0.0 -->
<script src="https://cdn.rawgit.com/jherax/proxy-storage/1.0.0/dist/proxy-storage.min.js"></script>

In the above case, the library is included into the namespace proxyStorage as a global object.

// get the default storage mechanism
var storage = proxyStorage.default;

// or get the constructor
var cookieStore = new proxyStorage.WebStorage('cookieStorage');

As proxy-storage is built as an UMD (Universal Module Definition), it can be included from a module loader as AMD, CommonJS, or ES2015 Export.

CommonJS

// gets the default storage mechanism
var storage = require('proxy-storage').default;

// or get the constructor
var WebStorage = require('proxy-storage').WebStorage;
var cookieStore = new WebStorage('cookieStorage');

ES2015 Export

// gets the default storage mechanism
import storage from 'proxy-storage';

// or get some API members
import storage, { WebStorage, configStorage } from 'proxy-storage';

AMD

requirejs.config({
  paths: {
    'proxy-storage': '<PATH>/proxy-storage.min'
  }
});
define(['proxy-storage'], function(proxyStorage) {
  // localStorage usually is the default storage
  var storage = proxyStorage.default;
  // creates a new storage mechanism
  var sessionStore = new proxyStorage.WebStorage('sessionStorage');
});

API

The exposed Web Storage interface allow us saving data as JSON, with the advantage that you can store Object and Array<Any> values, which is not possible when you are using native localStorage, sessionStorage and cookie storages.

This library has been written as an ES2015 module and the exported API contains the following members:

storage (or default)

@type Object. This is the default module and is an instance of WebStorage. It saves and retrieves the data internally as JSON, which allows not only store Primitive values but also Object values. It inherits the following methods in the WebStorage prototype:

  • setItem(key, value [,options]): stores a value given a key name.
    options is an optional parameter and only works with cookieStorage. See here for more details.
  • getItem(key): retrieves a value by its key name.
  • removeItem(key): deletes a key from the storage.
  • clear(): removes all keys from the storage.
  • length: Gets the number of data items stored in the storage object.

By default this object is a proxy for the first storage mechanism available, usually localStorage. The availability is determined in the following order:

  1. localStorage: proxy for localStorage object.
  2. sessionStorage: proxy for sessionStorage object.
  3. cookieStorage: proxy for document.cookie object and implements the Web Storage interface.
  4. memoryStorage: internal storage mechanism that can be used as a fallback when none of the above mechanisms are available. The behavior of memoryStorage is similar to sessionStorage

Note: you can override the default storage mechanism by setting the new storage type with configStorage.set()

Example

import storage from 'proxy-storage';
// 'storage' is the default module

// use the default storage mechanism, usually localStorage
storage.setItem('qwerty', [{ some: 'object', garbage: true }]);
let data = storage.getItem('qwerty');
// [{ some: 'object', garbage: true }]

storage.setItem('o-really', { status: 'saved' });
storage.setItem('persisted', true);

storage.removeItem('qwerty');
data = storage.getItem('qwerty');
// null

//removes all data in the current storage
storage.clear();
data = storage.getItem('o-really');
// null

setItem for cookieStorage

When you are working with an instance of WebStorage and set its mechanism to "cookieStorage", the API method .setItem() has a special behavior, allowing you to set an expiration date and also specifying a path where the cookie will be valid.

setItem(key, value, options) receives the optional parameter options which is an object where you can specify the following properties:

  • path {string}: the relative path where the cookie will be valid. Its default value is "/"
  • expires {Date, object}: the expiration date of the cookie. Also you can provide an object to describe the expiration date:
    • date    {Date}: if provided, the timestamps will affect this date, otherwise a new current date will be used.
    • hours  {number}: hours to add / subtract
    • days    {number}: days to add / subtract
    • months {number}: months to add / subtract
    • years   {number}: years to add / subtract

Example

import { WebStorage } from 'proxy-storage';

const cookieStore = new WebStorage('cookieStorage');
const data = {
  start: new Date().toISOString(),
  sessionId: 'J34H5J34609-DSFG7BND98W3',
  platform: 'Linux x86_64',
};
const options = {
  path: '/profile',
  expires: { hours: 6 }
};

cookieStore.setItem('activity', data, options);
cookieStore.setItem('valid', true, {expires: new Date('2017/01/02')});

Getting all items stored

As this library implements the Web Storage interface, you can access to all data items in the same way as localStorage or sessionStorage, thus you can loop over the keys in the storage mechanism you are using (localStorage, sessionStorage, cookieStorage, memoryStorage)

const cookieStore = new WebStorage('cookieStorage');

cookieStore.setItem('test1', 1);
cookieStore.setItem('test2', 2);

// loop over the storage object
Object.keys(cookieStore).forEach((key) => {
  console.log(key, cookieStore[key]);
});
// or...
for (let key in cookieStore) {
  console.log(key, cookieStore[key]);
}

WebStorage

@type Class. This constructor implements the Web Storage interface and handles an adapter that allows to store values Object and Array<Any>. It also lets you register interceptors for the methods setItem, getItem, removeItem and clear.

You can create multiple instances of WebStorage to handle different storage mechanisms. It is very useful when you need to store data in more than one storage mechanism at the same time, for example in cookies but also in sessionStorage

Example

import storage, { WebStorage } from 'proxy-storage';

// use the default storage mechanism, usually localStorage
storage.setItem('tv-show', { name: 'Regular Show' });

// saves also in sessionStorage
const sessionStore = new WebStorage('sessionStorage');
sessionStore.setItem('character', { name: 'Mordecai' });

// saves also in cookies
const options = { expires: {days:1} };
const cookieStore = new WebStorage('cookieStorage');
cookieStore.setItem('character', { name: 'Rigby' }, options);

Clearing all data

import { WebStorage } from 'proxy-storage';

function clearDataFromStorage() {
  new WebStorage('localStorage').clear();
  new WebStorage('sessionStorage').clear();
  new WebStorage('cookieStorage').clear();
}

Static Methods

WebStorage provides the static method interceptors which allows us to register callbacks that runs when an API method is invoked. It is very useful when you need to perform some additional actions when accessing the WebStorage methods.

  • WebStorage.interceptors(command, action): adds an interceptor to a WebStorage method.
    • command {string}. The name of the API method to intercept. It can be setItem, getItem, removeItem, clear
    • action {function}. Callback executed when the API method is called.

Example

import storage, { WebStorage, isAvaliable } from 'proxy-storage';

// detect if we are in a private navigation session
// and we have no access to default storage mechanisms
if (!isAvaliable.localStorage && !isAvaliable.cookieStorage) {
  WebStorage.interceptors('setItem', (key, value) => console.log(`setItem: ${key}: ${value}`));
  WebStorage.interceptors('getItem', (key) => console.log(`getItem: ${key}`));
  WebStorage.interceptors('removeItem', (key) => console.log(`removeItem: ${key}`));
}

// memoryStorage is the fallback mechanism in 'storage'
storage.setItem('proxy-storage-test', {data: 'it works!'});
storage.getItem('proxy-storage-test');

configStorage

@type Object. Gets and sets the storage mechanism to use by default. It contains the following methods:

  • get(): returns a string with the name of the current storage mechanism.
  • set(storageType): sets the current storage mechanism. storageType must be one of the following strings: "localStorage", "sessionStorage", "cookieStorage", or "memoryStorage"

Example

import storage, { configStorage } from 'proxy-storage';

// gets the default storage mechanism
let storageName = configStorage.get();
console.log('Default:', storageName);

storage.setItem('defaultStorage', storageName);

// sets the new default storage mechanism
configStorage.set('sessionStorage');
storageName = configStorage.get();
console.log('Current:', storageName);

storage.setItem('currentStorage', storageName);

isAvaliable

@type Object. Determines which storage mechanisms are available. It contains the following flags:

  • localStorage: is set to true if the local storage is available.
  • sessionStorage: is set to true if the session storage is available.
  • cookieStorage: is set to true if the cookie storage is available.
  • memoryStorage: always is set to true

Example

import storage, * as proxyStorage from 'proxy-storage';
// * imports the entire module's members into proxyStorage.

console.info('Available storage mechanisms');
console.log(proxyStorage.isAvaliable);

function init() {
  // memoryStorage is always available
  proxyStorage.configStorage.set('memoryStorage');

  if (isSafariInPrivateMode(proxyStorage.isAvaliable)) {
    // do something additional...
  }

  storage.setItem('hidden-data', {
    mechanism: 'memoryStorage',
    availability: 'Browser-tab, you can refresh your window'
  });

  let data = storage.getItem('hidden-data');
  console.log('in memoryStorage', data);
}

function isSafariInPrivateMode(flags) {
  return !flags.localStorage && !flags.sessionStorage && !flags.cookieStorage;
}

Running the project

If you want to fork or build your own, you must run this project.

Requirements

  1. Git (git-linux or git-windows).
  2. Node.js (latest stable version v6+).
  3. Node Package Manager (npm v3+), the one that comes with your node.js version.
    It is preferable to install Node Version Manager - nvm, it contains both node.js and npm.
  4. Yarn installed as a global package.

NOTE: Consider to install Node Version Manager (NVM) to upgrade easily the Node.js version.
Go to https://github.com/creationix/nvm and check the installation process for your OS.

Building the project

Clone the repository:

$ git https://github.com/jherax/proxy-storage.git

If you don't have installed yarn as a global package, run this command:

$ npm install -g yarn

Now yarn will install dependencies in package.json:

$ yarn

And finally execute the webpack task:

$ yarn run build

This command will lint the code with ESLint and after that it will transpile with Babel the ES2015 Module in src/ folder to an UMD ES5 Module in dist/ and finally it will generate the minified and source map files.

Versioning

This projects adopts the Semantic Versioning (SemVer) guidelines:

<MAJOR>.<MINOR>.<PATCH>

Given a version number MAJOR.MINOR.PATCH, increment the:

  1. MAJOR version when you make incompatible API changes
  2. MINOR version when you add functionality in a backwards-compatible manner
  3. PATCH version when you make backwards-compatible bug fixes.

Issues

To report an issue and keep traceability of bug-fixes, please report to:

Changelog

Details changes for each release are documented here.

License

This project has been released under the MIT license. This license applies ONLY to the source of this repository and does not extend to any other distribution, or any other 3rd party libraries used in a repository. See LICENSE file for more information.