import * as _ from './utils' export class Storage { clear(): void { _.internalsOf(this, 'Storage', 'clear').storage.clear() } getItem(key: string): string | null { return getStringOrNull( _.internalsOf(this, 'Storage', 'getItem').storage.get( String(key) ) ) } key(index: number): string | null { return getStringOrNull( [ ..._.internalsOf( this, 'Storage', 'key' ).storage.keys(), ][Number(index) || 0] ) } removeItem(key: string): void { _.internalsOf(this, 'Storage', 'getItem').storage.delete( String(key) ) } setItem(key: string, value: any): void { _.internalsOf(this, 'Storage', 'getItem').storage.set( String(key), String(value) ) } get length() { return _.internalsOf(this, 'Storage', 'size').storage.size } } const getStringOrNull = (value: string | void) => typeof value === 'string' ? value : null export const initStorage = (target: Target, exclude: Set) => { if (exclude.has('Storage') || exclude.has('localStorage')) return target.localStorage = Object.create(Storage.prototype) const storageInternals = new Map() _.INTERNALS.set(target.localStorage, { storage: storageInternals, } as StorageInternals) } interface StorageInternals { storage: Map } interface Target { localStorage: Storage }