@epilogo/stringifyr
Version:
Stringifyr JS bundle
69 lines (56 loc) • 1.57 kB
text/typescript
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);
}
}