UNPKG

@cnamts/vue-dot

Version:

Implementation of our Design System for the French Health Insurance

199 lines (149 loc) 4.03 kB
/* eslint-disable @typescript-eslint/no-explicit-any */ /** @see https://developer.mozilla.org/en-US/docs/Web/API/Storage for native specifications */ interface ControlItem { version?: number; expiresAt?: number; } /** @see https://gist.github.com/paulirish/5558557 */ function isStorageAvailable(): boolean { try { const item = 'test'; localStorage.setItem(item, item); localStorage.removeItem(item); return true; } catch (e) { return false; } } export class LocalStorageUtility { readonly localStorageSupported: boolean; /** Integer number */ readonly version?: number; /** Passive expiration time in ms */ readonly expiration?: number; readonly prefix: string; private CONTROL_ITEM_KEY = 'vd-storage-control'; constructor( version?: number, expiration?: number, prefix = 'vd-' ) { this.localStorageSupported = isStorageAvailable(); this.prefix = prefix; if (version && Number.isInteger(version)) { this.version = version; } else { this.version = undefined; } this.expiration = expiration; const isOldVersion = this.checkIfOldVersion(); const expired = this.checkIfExpired(); if (isOldVersion || expired) { this.clear(); this.setControlItem(); } } get length(): number { return this.getAll().length; } key(n: number): string { return this.getAllKeys()[n]; } getItem<T = any>(key: string): T | null { const controlItem = this.getControlItem(); if (!this.localStorageSupported && !controlItem) { return null; } const hasExpired = this.checkIfExpired(); if (hasExpired) { this.clear(); return null; } this.setControlItem(); return this.get(this.prefix + key); } setItem<T>(key: string, value: T): void { if (this.localStorageSupported) { this.set(this.prefix + key, value); this.setControlItem(); } } removeItem(key: string): void { this.filterStorage((storageKey) => { if (storageKey === this.prefix + key) { delete localStorage[storageKey]; } }); } clear(): void { this.filterStorage((storageKey) => { delete localStorage[storageKey]; }); } getAll(): any[] { const items = [] as any[]; this.filterStorage((storageKey) => { items.push(this.get(storageKey)); }); return items; } private getAllKeys(): string[] { const keys = [] as string[]; this.filterStorage((storageKey) => { keys.push(storageKey); }); return keys; } private filterStorage(callback: (storageKey: string) => void): void { if (!this.localStorageSupported) { return; } for (const storageKey in localStorage) { if (storageKey.startsWith(this.prefix) && storageKey !== this.CONTROL_ITEM_KEY) { callback(storageKey); } } } /** Wrapper for localStorage.getItem that parses the result */ private get(key: string): any | null { return JSON.parse(localStorage.getItem(key) || JSON.stringify(null)); } /** Wrapper for localStorage.setItem that stringify the value */ private set(key: string, value: any): void { localStorage.setItem(key, JSON.stringify(value)); } private checkIfExpired(): boolean { const controlItem = this.getControlItem(); if (!controlItem) { return true; } let timeExpired = false; let versionExpired = false; if (controlItem.expiresAt) { timeExpired = controlItem.expiresAt < new Date().getTime(); } if (controlItem.version && this.version) { versionExpired = controlItem.version < this.version; } return timeExpired || versionExpired; } private getControlItem(): ControlItem | null { if (this.localStorageSupported) { return this.get(this.CONTROL_ITEM_KEY); } return null; } private setControlItem(): void { const expiresAt = this.expiration ? new Date().getTime() + this.expiration / 1 : undefined; const controlItemObj: ControlItem = { version: this.version, expiresAt }; if (this.localStorageSupported) { this.set(this.CONTROL_ITEM_KEY, controlItemObj); } } private checkIfOldVersion(): boolean { return this.getControlItem() === null; } }