UNPKG

iconify-browser-cache

Version:

```html <script src="https://cdn.jsdelivr.net/npm/iconify-browser-cache@0.4.0/dist/iconify-browser-cache.umd.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/iconify-icon@3.0.0/dist/iconify-icon.min.js"></script> ```

105 lines (101 loc) 4.04 kB
const defaultConfig = { ttl: 6 * 30 * 24 * 60 * 60 * 1e3, // 6 months in milliseconds prefix: "iconify-browser-cache", storage: "localStorage" }; const json = (data, init) => { const jsonData = JSON.stringify(data); return new Response(jsonData, init); }; const localStore = { getItem: async (key) => { const value = window.localStorage.getItem(key); return value ? JSON.parse(value) : null; }, setItemRaw: async (key, value) => { window.localStorage.setItem(key, JSON.stringify(value)); }, remove: async (key) => { window.localStorage.removeItem(key); }, removeExpired: async (prefix) => { const now = Date.now(); const keys = Object.keys(window.localStorage); let collectionsForDelete = []; const metadataItems = keys.filter((key) => key.startsWith(prefix) && key.endsWith(".metadata")); metadataItems.map((key) => { const item = window.localStorage.getItem(key); if (item) { const metadata = JSON.parse(item); if (now >= metadata.expires) { window.localStorage.removeItem(key); const collectionKey = key.replace(/\.metadata$/, ""); collectionsForDelete.push(collectionKey); } } }); const collectionKeys = keys.filter((key) => collectionsForDelete.some((collection) => key.startsWith(collection))); collectionKeys.map((key) => window.localStorage.removeItem(key)); } }; const iconifyBrowserCache = (config, libType) => { if (typeof window === "undefined") return; window.IconifyBrowserCache = { fetch: window.fetch.bind(window), config: { ttl: config.ttl, prefix: config.prefix, storage: config.storage } }; window.fetch = async (url, init) => { const originalFetch = window.IconifyBrowserCache.fetch.bind(window.IconifyBrowserCache); if (url instanceof URL) url = url.toString(); else if (url instanceof Request) url = url.url; else url = String(url); if (!url.includes("https://api.iconify.design/")) { return originalFetch(url, init); } const now = Date.now(); const prefix = window.IconifyBrowserCache.config.prefix; const ttl = window.IconifyBrowserCache.config.ttl; const storage = (await import('../chunks/composables.mjs')).useStorage(window.IconifyBrowserCache.config); const collection = url.match(/\/([^\/?]+)\.json/)?.[1]; const icons = new URL(url).searchParams?.get("icons")?.split(","); const cachedIcons = {}; const collectionKey = `${prefix}:${collection}`; if (!collection || !icons?.length) { return originalFetch(url, init); } await storage.removeExpired(prefix); for (const icon of icons) { const key = `${collectionKey}:${icon}`; const body = await storage.getItem(key); if (body) cachedIcons[icon] = { body }; } const collectionData = await storage.getItem(`${collectionKey}.metadata`); const { width, height, expires } = collectionData ? collectionData : {}; if (Object.keys(cachedIcons).length === icons.length && expires && now < (expires || 0)) { return json({ icons: cachedIcons, prefix: collection, width, height }); } const response = await originalFetch(url, init); const data = await response.json(); for (const [icon, { body }] of Object.entries(data.icons)) { await Promise.all([ storage.setItemRaw(`${collectionKey}:${icon}`, body), storage.setItemRaw(`${collectionKey}.metadata`, { collection, width: data.width, height: data.height, expires: now + ttl }) ]); } return json(data); }; }; const { ttl, prefix, storage } = defaultConfig; const setupIconifyCache = (options) => { if (typeof window === "undefined") return; window.IconifyBrowserCache.config.ttl = options?.ttl || ttl; window.IconifyBrowserCache.config.prefix = options?.prefix || prefix; window.IconifyBrowserCache.config.storage = options?.storage || storage; }; iconifyBrowserCache({ ttl, prefix, storage }); export { localStore as l, setupIconifyCache as s };