| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- import { api } from "src/boot/axios";
- const createDbConnection = (dbName = "apiCache", version = 1) => {
- let db = null;
- const ready = new Promise((resolve, reject) => {
- const request = indexedDB.open(dbName, version);
- request.onerror = () => reject(request.error);
- request.onsuccess = () => {
- db = request.result;
- resolve(db);
- };
- request.onupgradeneeded = (event) => {
- const db = event.target.result;
- if (!db.objectStoreNames.contains("apiCache")) {
- db.createObjectStore("apiCache", { keyPath: "key" });
- }
- };
- });
- return {
- getDb: () => ready,
- };
- };
- const { getDb } = createDbConnection();
- const getFromCache = async (key) => {
- const db = await getDb();
- return new Promise((resolve) => {
- const transaction = db.transaction(["apiCache"], "readonly");
- const store = transaction.objectStore("apiCache");
- const request = store.get(key);
- request.onsuccess = () => {
- const entry = request.result;
- if (entry?.timestamp + entry?.ttl > Date.now()) {
- resolve(entry.data);
- } else {
- resolve(null);
- }
- };
- });
- };
- const setInCache = async (key, data, ttl) => {
- const db = await getDb();
- const entry = {
- key,
- data,
- timestamp: Date.now(),
- ttl: ttl * 1000,
- };
- return new Promise((resolve) => {
- const transaction = db.transaction(["apiCache"], "readwrite");
- const store = transaction.objectStore("apiCache");
- store.put(entry);
- transaction.oncomplete = () => resolve();
- });
- };
- const clearCache = async (cacheKey) => {
- const db = await getDb();
- const transaction = db.transaction(["apiCache"], "readwrite");
- const store = transaction.objectStore("apiCache");
- return new Promise((resolve) => {
- if (!cacheKey) {
- store.clear();
- transaction.oncomplete = () => resolve();
- return;
- }
- const request = store.getAllKeys();
- request.onsuccess = () => {
- const deletePromises = request.result
- .filter((key) => key.includes(cacheKey))
- .map(
- (key) =>
- new Promise((resolve) => {
- const deleteRequest = store.delete(key);
- deleteRequest.onsuccess = () => resolve();
- }),
- );
- Promise.all(deletePromises).then(() => resolve());
- };
- });
- };
- export const createCachedApi = (namespace, ttl = 3600) => {
- const getCacheKey = (path) => `${namespace}:${path}`;
- const getResourcePaths = (path) => {
- const segments = path.split("/").filter(Boolean);
- const paths = [];
- for (let i = 0; i <= segments.length; i++) {
- const currentPath = "/" + segments.slice(0, i).join("/");
- paths.push(currentPath);
- }
- return paths;
- };
- const invalidateAll = async (path) => {
- const paths = getResourcePaths(path);
- await Promise.all(paths.map((path) => clearCache(getCacheKey(path))));
- };
- const get = async (path, options = {}) => {
- const key = getCacheKey(path);
- const cached = await getFromCache(key);
- if (cached) return cached;
- const { data } = await api.get(path);
- await setInCache(key, { data }, options.ttl ?? ttl);
- return { data };
- };
- const post = async (path, payload) => {
- const { data } = await api.post(path, payload);
- await invalidateAll(path);
- return { data };
- };
- const put = async (path, payload) => {
- const { data } = await api.put(path, payload);
- await invalidateAll(path);
- return { data };
- };
- const del = async (path) => {
- const { data } = await api.delete(path);
- await invalidateAll(path);
- return { data };
- };
- return { get, post, put, del, invalidateAll };
- };
|