UNPKG

session-storage-sync

Version:

sync session storage across multiple browser tabs from same origin

117 lines (116 loc) 4.82 kB
import { v4 as uuid } from 'uuid'; import { SESSION_STORAGE_ID, WINDOW_STORAGE_EVENT, GET_SESSION_STORAGE_KEY, SET_SESSION_STORAGE_KEY, DELETE_SESSION_STORAGE_KEY, ADD_TO_SESSION_STORAGE_KEY, CLEAR_SESSION_STORAGE_KEY } from './constants'; import { LocalStorage } from './local-storage'; import { SessionStorage } from './session-storage'; export class Storage { _local; _session; _ignored; _sessionId; _isInitialized = false; constructor(ignoredKeys) { this._sessionId = uuid(); this._ignored = [].concat(ignoredKeys); this._ignored.push(SESSION_STORAGE_ID); this._local = new LocalStorage(window.localStorage); this._session = new SessionStorage(window.sessionStorage); this._session.addEventListener('set', this.onSetItem.bind(this)); this._session.addEventListener('delete', this.onDeleteItem.bind(this)); this._session.addEventListener('clear', this.onClearItems.bind(this)); this.listenForStorageEvents(); } get local() { return this._local; } get session() { return this._session; } listenForStorageEvents() { window.addEventListener(WINDOW_STORAGE_EVENT, (event) => { if (event == null) { event = window.event; } if (event == null) return; let eventData = null; try { eventData = JSON.parse(event.newValue); } catch (ex) { //do nothing } //ensure our current tab did not send this event if (eventData != null && eventData[SESSION_STORAGE_ID] === this._sessionId) return; if (eventData != null) delete eventData[SESSION_STORAGE_ID]; if (event.key === GET_SESSION_STORAGE_KEY && event.newValue != null) { try { if (this.session.length > 0) { let data = JSON.parse(JSON.stringify(window.sessionStorage)); //remove any ignored items this._ignored.forEach((i) => { delete data[i]; }); data[SESSION_STORAGE_ID] = this._sessionId; this.local.set(SET_SESSION_STORAGE_KEY, data); this.local.remove(SET_SESSION_STORAGE_KEY); } } catch { this.local.remove(SET_SESSION_STORAGE_KEY); } } else if (event.key === SET_SESSION_STORAGE_KEY && event.newValue != null) { try { if (this._isInitialized === true) return; this._isInitialized = true; if (eventData != null) { for (let p in eventData) { window.sessionStorage.setItem(p, eventData[p]); } } } catch { //do nothing here } } else if (event.key === ADD_TO_SESSION_STORAGE_KEY && event.newValue != null) { try { window.sessionStorage.setItem(eventData.key, eventData.value); } catch { //do nothing here } } else if (event.key === DELETE_SESSION_STORAGE_KEY && event.newValue != null) { window.sessionStorage.removeItem(eventData.key); } else if (event.key === CLEAR_SESSION_STORAGE_KEY && event.newValue != null) { window.sessionStorage.clear(); } }, { capture: true, passive: true }); // check if this is a new window.. if the session storage has nothing we will trigger // an event to request session storage from other tab if (this.session.length <= 0) { this.local.set(GET_SESSION_STORAGE_KEY, { [SESSION_STORAGE_ID]: this._sessionId }); this.local.remove(GET_SESSION_STORAGE_KEY); } } onSetItem(key, value) { this.local.set(ADD_TO_SESSION_STORAGE_KEY, { key: key, value: value, [SESSION_STORAGE_ID]: this._sessionId }); this.local.remove(ADD_TO_SESSION_STORAGE_KEY); } onDeleteItem(key) { this.local.set(DELETE_SESSION_STORAGE_KEY, { key: key, [SESSION_STORAGE_ID]: this._sessionId }); this.local.remove(DELETE_SESSION_STORAGE_KEY); } onClearItems() { this.local.set(CLEAR_SESSION_STORAGE_KEY, { [SESSION_STORAGE_ID]: this._sessionId }); this.local.remove(CLEAR_SESSION_STORAGE_KEY); } }