UNPKG

@tdb/util

Version:
120 lines (108 loc) 2.69 kB
import { R } from '../../libs'; import { ILocalStorageOptions, ILocalStorageValue, StorageValueType, LocalStorageProp, } from './types'; import { init as initStore } from './store.web'; import { subject$ } from './events.rx'; const store = initStore(); function asTypeName(value: any): StorageValueType { if (value === null) { return 'null'; } if (R.is(Boolean, value)) { return 'bool'; } if (R.is(String, value)) { return 'string'; } if (R.is(Number, value)) { return 'number'; } if (R.is(Boolean, value)) { return 'bool'; } if (R.is(Date, value)) { return 'date'; } return 'object'; } function toValue(key: string, json?: string | null): any { try { return parse(json); } catch (error) { throw new Error( `Failed to read '${key}' from storage. The value '${json}' cannot be parsed.`, ); } } export function parse(json?: string | null) { if (!json) { return json; } // Convert the JSON string to an object. const item = JSON.parse(json) as ILocalStorageValue; // Perform type conversions. switch (item.type) { case 'null': case 'bool': case 'string': return item.value; case 'number': return parseFloat(item.value); case 'date': return new Date(item.value); case 'object': return item.value; default: // Ignore. } } /** * Asynchronous read/write interface to the store. * * READ: Pass nothing (undefined) to read the value for the `key` parameter. * WRITE: Pass a `value` to write. * CLEAR: Pass null to `value` to clear. */ export function prop<T>( key: string, defaultOptions: ILocalStorageOptions = {}, ): LocalStorageProp<T> { async function func<T>(value?: T | null, options: ILocalStorageOptions = {}) { const args = { ...defaultOptions, ...options }; let result: any = value; const fireEvent = () => { subject$.next({ key, value, type: asTypeName(value), }); }; if (value === null) { // CLEAR. await store.removeItem(key); fireEvent(); } else if (value !== undefined) { // WRITE. const storageValue: ILocalStorageValue = { value, type: asTypeName(value), }; await store.setItem(key, JSON.stringify(storageValue)); fireEvent(); } else { // READ. const json = await store.getItem(key); result = json ? toValue(key, json) : undefined; } // Finish up. return result === undefined ? args.default : (result as T); } // Finish up. const result = func as LocalStorageProp<T>; result.key = key; result.isProp = true; return result; }