UNPKG

@epilogo/stringifyr

Version:
69 lines (56 loc) 1.57 kB
import { IStorage } from "./IStorage"; import { AsyncReturnType } from "./Types"; type TPersistLayerParams = { storage?: IStorage; noCache?: boolean; } function wrapValue(val: any) { if (val) { return JSON.stringify(val); } return '__null'; } function unwrapValue(val: any) { if (val === '__null') { return null; } try { return JSON.parse(val); } catch (e) { return null; } } export class PersistLayer { private readonly storage?: IStorage; private readonly noCache: boolean; private inMemory?: Record<string, string> = {}; constructor(params: TPersistLayerParams) { this.storage = params.storage; this.noCache = params.noCache ?? false; this.sync = this.sync.bind(this); this.wrap = this.wrap.bind(this); } sync<T>(cacheKey: string): T { const inMemory = this.inMemory[cacheKey]; if (!this.noCache && inMemory) { return unwrapValue(inMemory); } const inStorage = this.storage?.getItem(cacheKey) if (!this.noCache && inStorage) { this.inMemory[cacheKey] = inStorage; return unwrapValue(inStorage); } return null; } async wrap<T extends (...any: any) => Promise<any>>(cacheKey: string, call: T): Promise<AsyncReturnType<T>> { const value = this.sync<AsyncReturnType<T>>(cacheKey); if (value) { return value; } const fetched = await call(); const valueToSave = wrapValue(fetched); this.inMemory[cacheKey] = valueToSave; this.storage?.setItem(cacheKey, valueToSave); return unwrapValue(valueToSave); } }