UNPKG

@ima/core

Version:

IMA.js framework for isomorphic javascript application

147 lines (146 loc) 4.08 kB
import { Storage as ImaStorage } from './Storage'; import { GenericError } from '../error/GenericError'; import { Window } from '../window/Window'; /** * Implementation of the `link Storage` interface that relies on the * native `sessionStorage` DOM storage for storing its entries. */ export class SessionStorage extends ImaStorage { /** * The DOM storage providing the actual storage of the entries. */ _storage; static get $dependencies() { return [ Window ]; } /** * Initializes the session storage. */ constructor(window){ super(); this._storage = window.getWindow().sessionStorage; } /** * @inheritDoc */ init() { return this; } /** * @inheritDoc */ has(key) { return !!this._storage.getItem(key); } /** * @inheritDoc */ get(key) { try { return JSON.parse(this._storage.getItem(key))?.value; } catch (error) { throw new GenericError('ima.storage.SessionStorage.get: Failed to parse a session ' + `storage item value identified by the key ${key}: ` + error.message); } } /** * @inheritDoc */ set(key, value) { try { this._storage.setItem(key, JSON.stringify({ created: Date.now(), value })); } catch (error) { const storage = this._storage; const isItemTooBig = storage.length === 0 || storage.length === 1 && storage.key(0) === key; if (isItemTooBig) { throw error; } this._deleteOldestEntry(); this.set(key, value); } return this; } /** * @inheritDoc */ delete(key) { this._storage.removeItem(key); return this; } /** * @inheritDoc */ clear() { this._storage.clear(); return this; } /** * @inheritDoc */ keys() { return new StorageIterator(this._storage); } /** * @override */ size() { return this._storage.length; } /** * Deletes the oldest entry in this storage. */ _deleteOldestEntry() { let oldestEntry = { created: Date.now() + 1 }; for (const key of this.keys()){ const value = JSON.parse(this._storage.getItem(key)); if (value.created < oldestEntry.created) { oldestEntry = { key, created: value.created }; } } if (typeof oldestEntry.key === 'string') { this.delete(oldestEntry.key); } } } /** * Implementation of the iterator protocol and the iterable protocol for DOM * storage keys. * * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols */ class StorageIterator { /** * The DOM storage being iterated. */ _storage; /** * The current index of the DOM storage key this iterator will return * next. */ _currentKeyIndex = 0; /** * Initializes the DOM storage iterator. * * @param storage The DOM storage to iterate through. */ constructor(storage){ this._storage = storage; } /** * Iterates to the next item. This method implements the iterator protocol. * * @return The next value in * the sequence and whether the iterator is done iterating through * the values. */ next() { // We are sure there is always a value so it can be safely cast to string const key = this._storage.key(this._currentKeyIndex); return { done: this._currentKeyIndex++ === this._storage.length, value: key }; } /** * Returns the iterator for this object (this iterator). This method * implements the iterable protocol and provides compatibility with the * `for..of` loops. * * @return This iterator. */ [Symbol.iterator]() { return this; } } //# sourceMappingURL=SessionStorage.js.map