pinia-cache
Version:
Cache dispatched actions in memory and prevent repeated requests and heavy actions.
153 lines (149 loc) • 4.93 kB
JavaScript
(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