import { Injectable } from "@angular/core"; export interface IFunc { (prev?: T): T; } interface Option { stroage?: "local" | "session"; defaultValue?: T | IFunc; serializer?: (v: T) => string; deserializer?: (v: string) => T; } export const isFunction = (value: unknown): value is Function => typeof value === "function"; @Injectable() export class StorageService { constructor() {} private parseOption(option?: Option) { const storage = option?.stroage === "session" ? sessionStorage : localStorage; const serializer = option?.serializer ? option?.serializer : JSON.stringify; const deserializer = option?.deserializer ? option?.deserializer : JSON.parse; let defaultValue = option?.defaultValue; if (isFunction(option?.defaultValue)) { defaultValue = option?.defaultValue(); } return { storage, serializer, deserializer, defaultValue, }; } get(key: string, option?: Option) { const { storage, deserializer, defaultValue } = this.parseOption(option); try { const val = storage.getItem(key); if (val) { return deserializer(val); } } catch (error) { console.error(error); } return defaultValue; } set(key: string, value: T | IFunc, option?: Option) { const { storage, serializer, defaultValue } = this.parseOption(option); const val = (isFunction(value) ? value() : value) ?? defaultValue; if (typeof val === "undefined") { storage.removeItem(key); } else { try { storage.setItem(key, serializer(val)); } catch (error) { console.error(error); } } } remove(key: string, option?: Pick) { const { storage } = this.parseOption(option); storage.removeItem(key); } clear(option?: Pick) { const { storage } = this.parseOption(option); storage.clear(); } keys(option?: Pick) { const { storage } = this.parseOption(option); return Object.keys(storage); } }