import dayjs, { Dayjs } from "dayjs"; import { defineStore } from "pinia"; /** * Type for cache storage */ interface CachedData { /** The in-flight or resolved data, shared by concurrent callers */ data: Promise; /** Expiration date of the cached data */ expiration: Dayjs; } export const useCacheStore = defineStore('cache', () => { const cachedData: Record> = {}; async function getData(key: string, callback: () => Promise): Promise { let cache = cachedData[key] as CachedData|undefined; if (isDataEmptyOrExpired(cache)) { // Store the promise immediately so concurrent callers share this fetch const data = callback(); const expiration = dayjs().add(30, 'minutes'); cache = { data, expiration }; cachedData[key] = cache; // Don't keep a failed fetch cached: let the next call retry data.catch(() => invalidate(key)); } return cache.data; } function invalidate(key: string): void { delete cachedData[key]; } function isDataEmptyOrExpired(data: CachedData|undefined): boolean { if (!data) { return true; } else { return dayjs().isAfter(data.expiration); } } return { getData, invalidate }; });