UNPKG

wretch-middlewares

Version:

Middlewares for the wretch library

139 lines 5.48 kB
/* Defaults */ var defaultSkip = function (url, opts) { return (opts.skipCache || opts.method !== 'GET'); }; var defaultKey = function (url, opts) { return opts.method + '@' + url; }; var defaultClear = function (url, opts) { return false; }; var defaultInvalidate = function (url, opts) { return null; }; var defaultCondition = function (response) { return response.ok; }; /** * ## Throttling cache middleware * * #### A throttling cache which stores and serves server responses for a certain amount of time. * * **Options** * * - *throttle* `milliseconds` * * > the response will be stored for this amount of time before being deleted from the cache. * * - *skip* `(url, opts) => boolean` * * > If skip returns true, then the request is performed even if present in the cache. * * - *key* `(url, opts) => string` * * > Returns a key that is used to identify the request. * * - *clear* `(url, opts) => boolean` * * > Clears the cache if true. * * - *invalidate* `(url, opts) => string | RegExp | null` * * > Removes url(s) matching the string/RegExp from the cache. * * - *condition* `response => boolean` * * > If false then the response will not be added to the cache. * * - *flagResponseOnCacheHit* `string` * * > If set, a Response returned from the cache whill be flagged with a property name equal to this option. * */ export var throttlingCache = function (_a) { var _b = _a === void 0 ? {} : _a, _c = _b.throttle, throttle = _c === void 0 ? 1000 : _c, _d = _b.skip, skip = _d === void 0 ? defaultSkip : _d, _e = _b.key, key = _e === void 0 ? defaultKey : _e, _f = _b.clear, clear = _f === void 0 ? defaultClear : _f, _g = _b.invalidate, invalidate = _g === void 0 ? defaultInvalidate : _g, _h = _b.condition, condition = _h === void 0 ? defaultCondition : _h, _j = _b.flagResponseOnCacheHit, flagResponseOnCacheHit = _j === void 0 ? '__cached' : _j; var cache = new Map(); var inflight = new Map(); var throttling = new Set(); var throttleRequest = function (_key) { if (throttle && !throttling.has(_key)) { throttling.add(_key); setTimeout(function () { throttling.delete(_key); }, throttle); } }; var middleware = function (next) { return function (url, opts) { var _key = key(url, opts); var invalidatePatterns = invalidate(url, opts); if (invalidatePatterns) { if (!(invalidatePatterns instanceof Array)) { invalidatePatterns = [invalidatePatterns]; } invalidatePatterns.forEach(function (pattern) { if (typeof pattern === 'string') { cache.delete(pattern); } else if (pattern instanceof RegExp) { cache.forEach(function (_, key) { if (pattern.test(key)) { cache.delete(key); } }); } }); } if (clear(url, opts)) { cache.clear(); } if (skip(url, opts)) { return next(url, opts); } if (throttling.has(_key)) { // If the cache contains a previous response and we are throttling, serve it and bypass the chain. if (cache.has(_key)) { var cachedClone = cache.get(_key).clone(); if (flagResponseOnCacheHit) { // Flag the Response as cached Object.defineProperty(cachedClone, flagResponseOnCacheHit, { value: _key, enumerable: false }); } return Promise.resolve(cachedClone); // If the request in already in-flight, wait until it is resolved } else if (inflight.has(_key)) { return new Promise(function (resolve, reject) { inflight.get(_key).push([resolve, reject]); }); } } // Init. the pending promises Map if (!inflight.has(_key)) inflight.set(_key, []); // If we are not throttling, activate the throttle for X milliseconds throttleRequest(_key); // We call the next middleware in the chain. return next(url, opts) .then(function (response) { // Add a cloned response to the cache if (condition(response.clone())) { cache.set(_key, response.clone()); } // Resolve pending promises inflight.get(_key).forEach(function (_a) { var resolve = _a[0]; return resolve(response.clone()); }); // Remove the inflight pending promises inflight.delete(_key); // Return the original response return response; }) .catch(function (error) { // Reject pending promises on error inflight.get(_key).forEach(function (_a) { var resolve = _a[0], reject = _a[1]; return reject(error); }); inflight.delete(_key); throw error; }); }; }; // Programmatically cache a response middleware['cache'] = function (key, response) { throttleRequest(key); cache.set(key, response); }; return middleware; }; //# sourceMappingURL=index.js.map