UNPKG

pinia-cache

Version:

Cache dispatched actions in memory and prevent repeated requests and heavy actions.

153 lines (149 loc) 4.93 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue-demi'), require('pinia')) : typeof define === 'function' && define.amd ? define(['exports', 'vue-demi', 'pinia'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.PiniaCachePlugin = {}, global.VueDemi)); })(this, (function (exports, vueDemi) { 'use strict'; function isObject(value) { return !!value && typeof value === "object"; } function isPromise(value) { return !!value && value instanceof Promise; } function toString(value) { return isObject(value) ? JSON.stringify(value) : String(value); } function generateKey(action, payload) { try { return `${action}:${toString(payload)}`; } catch (_) { return null; } } const hasTimeout = (value) => { return isObject(value) && typeof value.timeout === "number"; }; const isExpired = (expiresIn) => { return expiresIn && Date.now() > expiresIn; }; class Cache { constructor(store, options) { this._state = /* @__PURE__ */ new Map(); this._store = store; this._options = options; } /** * Resolve timeout from parameters and plugin options. */ resolveTimeout(dispatchOptions = {}) { if (hasTimeout(dispatchOptions)) { return dispatchOptions.timeout; } else if (hasTimeout(this._options)) { return this._options.timeout; } return 0; } /** * Dispatch an action and set it on cache. * @param {String} action * @param {?any} payload * @param {?any} options * @returns {Promise<any>} */ dispatch(action, payload, options) { const entry = this._store[action]; if (!entry) { throw new Error(`[pinia-cache] unknown action: ${action}`); } const key = generateKey(action, payload); if (key === null) { return entry.call(this._store, payload); } const { value: cachedValue, expiresIn } = this._state.get(key) || {}; if (!!cachedValue && !isExpired(expiresIn)) { return cachedValue; } let result = entry.call(this._store, payload); if (!isPromise(result)) { result = Promise.resolve(result); } const timeout = this.resolveTimeout(options); const record = { expiresIn: timeout ? Date.now() + timeout : void 0, value: new Promise((resolve, reject) => { result.then( (res) => resolve(res), (error) => { this._state.delete(key); reject(error); } ); }) }; this._state.set(key, record); return record.value; } /** * Check if an action dispatch is on cache. * @param {String} action * @param {?any} payload * * @returns {boolean} */ has(action, payload) { const key = generateKey(action, payload); if (key === null) { return false; } const record = this._state.get(key); return isObject(record) && !isExpired(record.expiresIn); } /** * Clear cache. Returns `true` if cache was cleared and `false` otherwise. * If using the type parameter, only actions with the specified type are * deleted from cache and the number of deleted keys is returned. */ clear(action) { if (action) { return Array.from(this._state.keys()).filter((key) => key.split(":")[0] === action).reduce((done, key) => this._state.delete(key) || done, false); } this._state.clear(); return true; } /** * Delete an action dispatch from cache. Returns `true` if it was deleted * and `false` otherwise. */ delete(action, payload) { const key = generateKey(action, payload); if (key === null) { return false; } return this._state.delete(key); } state() { return this._state; } } function mapCacheActions(useStore, keysOrMapper) { return Array.isArray(keysOrMapper) ? keysOrMapper.reduce((reduced, key) => { reduced[key] = function(...args) { return useStore(this.$pinia).cache.dispatch(key, ...args); }; return reduced; }, {}) : Object.keys(keysOrMapper).reduce((reduced, key) => { reduced[key] = function(...args) { const action = keysOrMapper[key]; const cache = useStore(this.$pinia).cache; return cache.dispatch(action, ...args); }; return reduced; }, {}); } function piniaCachePlugin(context) { var _a; const cacheOptions = (_a = context.options.cache) != null ? _a : {}; context.store.cache = vueDemi.markRaw(new Cache(context.store, cacheOptions)); } exports.mapCacheActions = mapCacheActions; exports.piniaCachePlugin = piniaCachePlugin; })); //# sourceMappingURL=pinia-cache.umd.js.map