workbox-strategies
Advanced tools
Comparing version 6.0.0-alpha.2 to 6.0.0-alpha.3
"use strict"; | ||
// @ts-ignore | ||
try { | ||
self['workbox:strategies:6.0.0-alpha.1'] && _(); | ||
self['workbox:strategies:6.0.0-alpha.2'] && _(); | ||
} | ||
catch (e) { } |
this.workbox = this.workbox || {}; | ||
this.workbox.strategies = (function (exports, assert_js, logger_js, WorkboxError_js, cacheNames_js, getFriendlyURL_js, Deferred_js, executeQuotaErrorCallbacks_js, timeout_js) { | ||
this.workbox.strategies = (function (exports, assert_js, logger_js, WorkboxError_js, cacheNames_js, getFriendlyURL_js, cacheMatchIgnoreParams_js, Deferred_js, executeQuotaErrorCallbacks_js, timeout_js) { | ||
'use strict'; | ||
@@ -24,3 +24,3 @@ | ||
try { | ||
self['workbox:strategies:6.0.0-alpha.1'] && _(); | ||
self['workbox:strategies:6.0.0-alpha.2'] && _(); | ||
} catch (e) {} | ||
@@ -61,2 +61,3 @@ | ||
constructor(strategy, options) { | ||
this._cacheKeys = {}; | ||
/** | ||
@@ -102,2 +103,3 @@ * The request the strategy is performing (passed to the strategy's | ||
*/ | ||
{ | ||
@@ -144,3 +146,80 @@ assert_js.assert.isInstance(options.event, ExtendableEvent, { | ||
fetch(input) { | ||
return this.waitUntil(this._fetch(input)); | ||
return this.waitUntil((async () => { | ||
const { | ||
event | ||
} = this; | ||
let request = toRequest(input); | ||
if (request.mode === 'navigate' && event instanceof FetchEvent && event.preloadResponse) { | ||
const possiblePreloadResponse = await event.preloadResponse; | ||
if (possiblePreloadResponse) { | ||
{ | ||
logger_js.logger.log(`Using a preloaded navigation response for ` + `'${getFriendlyURL_js.getFriendlyURL(request.url)}'`); | ||
} | ||
return possiblePreloadResponse; | ||
} | ||
} // If there is a fetchDidFail plugin, we need to save a clone of the | ||
// original request before it's either modified by a requestWillFetch | ||
// plugin or before the original request's body is consumed via fetch(). | ||
const originalRequest = this.hasCallback('fetchDidFail') ? request.clone() : null; | ||
try { | ||
for (const cb of this.iterateCallbacks('requestWillFetch')) { | ||
request = await cb({ | ||
request: request.clone(), | ||
event | ||
}); | ||
} | ||
} catch (err) { | ||
throw new WorkboxError_js.WorkboxError('plugin-error-request-will-fetch', { | ||
thrownError: err | ||
}); | ||
} // The request can be altered by plugins with `requestWillFetch` making | ||
// the original request (most likely from a `fetch` event) different | ||
// from the Request we make. Pass both to `fetchDidFail` to aid debugging. | ||
const pluginFilteredRequest = request.clone(); | ||
try { | ||
let fetchResponse; // See https://github.com/GoogleChrome/workbox/issues/1796 | ||
fetchResponse = await fetch(request, request.mode === 'navigate' ? undefined : this._strategy.fetchOptions); | ||
if ("dev" !== 'production') { | ||
logger_js.logger.debug(`Network request for ` + `'${getFriendlyURL_js.getFriendlyURL(request.url)}' returned a response with ` + `status '${fetchResponse.status}'.`); | ||
} | ||
for (const callback of this.iterateCallbacks('fetchDidSucceed')) { | ||
fetchResponse = await callback({ | ||
event, | ||
request: pluginFilteredRequest, | ||
response: fetchResponse | ||
}); | ||
} | ||
return fetchResponse; | ||
} catch (error) { | ||
{ | ||
logger_js.logger.error(`Network request for ` + `'${getFriendlyURL_js.getFriendlyURL(request.url)}' threw an error.`, error); | ||
} // `originalRequest` will only exist if a `fetchDidFail` callback | ||
// is being used (see above). | ||
if (originalRequest) { | ||
await this.runCallbacks('fetchDidFail', { | ||
error, | ||
event, | ||
originalRequest: originalRequest.clone(), | ||
request: pluginFilteredRequest.clone() | ||
}); | ||
} | ||
throw error; | ||
} | ||
})()); | ||
} | ||
@@ -180,3 +259,37 @@ /** | ||
cacheMatch(key) { | ||
return this.waitUntil(this._cacheMatch(key)); | ||
return this.waitUntil((async () => { | ||
const request = toRequest(key); | ||
let cachedResponse; | ||
const { | ||
cacheName, | ||
matchOptions | ||
} = this._strategy; | ||
const effectiveRequest = await this.getCacheKey(request, 'read'); | ||
const multiMatchOptions = _extends({}, matchOptions, { | ||
cacheName | ||
}); | ||
cachedResponse = await caches.match(effectiveRequest, multiMatchOptions); | ||
{ | ||
if (cachedResponse) { | ||
logger_js.logger.debug(`Found a cached response in '${cacheName}'.`); | ||
} else { | ||
logger_js.logger.debug(`No cached response found in '${cacheName}'.`); | ||
} | ||
} | ||
for (const callback of this.iterateCallbacks('cachedResponseWillBeUsed')) { | ||
cachedResponse = (await callback({ | ||
cacheName, | ||
matchOptions, | ||
cachedResponse, | ||
request: effectiveRequest, | ||
event: this.event | ||
})) || undefined; | ||
} | ||
return cachedResponse; | ||
})()); | ||
} | ||
@@ -199,18 +312,17 @@ /** | ||
async cachePut(key, response) { | ||
const request = toRequest(key); | ||
const request = toRequest(key); // Run in the next task to avoid blocking other cache reads. | ||
// https://github.com/w3c/ServiceWorker/issues/1397 | ||
await timeout_js.timeout(0); | ||
const effectiveRequest = await this.getCacheKey(request, 'write'); | ||
{ | ||
if (request.method && request.method !== 'GET') { | ||
if (effectiveRequest.method && effectiveRequest.method !== 'GET') { | ||
throw new WorkboxError_js.WorkboxError('attempt-to-cache-non-get-request', { | ||
url: getFriendlyURL_js.getFriendlyURL(request.url), | ||
method: request.method | ||
url: getFriendlyURL_js.getFriendlyURL(effectiveRequest.url), | ||
method: effectiveRequest.method | ||
}); | ||
} | ||
} // Run in the next task to avoid blocking other cache reads. | ||
// https://github.com/w3c/ServiceWorker/issues/1397 | ||
} | ||
await timeout_js.timeout(0); | ||
const effectiveRequest = await this._getEffectiveRequest(request, 'write'); | ||
if (!response) { | ||
@@ -237,6 +349,11 @@ { | ||
const { | ||
cacheName | ||
cacheName, | ||
matchOptions | ||
} = this._strategy; | ||
const cache = await self.caches.open(cacheName); | ||
const oldResponse = this.hasCallback('cacheDidUpdate') ? await this.cacheMatch(request) : null; | ||
const hasCacheUpdateCallback = this.hasCallback('cacheDidUpdate'); | ||
const oldResponse = hasCacheUpdateCallback ? await cacheMatchIgnoreParams_js.cacheMatchIgnoreParams( // TODO(philipwalton): the `__WB_REVISION__` param is a precaching | ||
// feature. Consider into ways to only add this behavior if using | ||
// precaching. | ||
cache, effectiveRequest.clone(), ['__WB_REVISION__'], matchOptions) : null; | ||
@@ -248,3 +365,3 @@ { | ||
try { | ||
await cache.put(effectiveRequest, responseToCache); | ||
await cache.put(effectiveRequest, hasCacheUpdateCallback ? responseToCache.clone() : responseToCache); | ||
} catch (error) { | ||
@@ -259,11 +376,44 @@ // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError | ||
await this.runCallbacks('cacheDidUpdate', { | ||
cacheName, | ||
oldResponse, | ||
newResponse: responseToCache, | ||
request: effectiveRequest, | ||
event: this.event | ||
}); | ||
for (const callback of this.iterateCallbacks('cacheDidUpdate')) { | ||
await callback({ | ||
cacheName, | ||
oldResponse, | ||
newResponse: responseToCache.clone(), | ||
request: effectiveRequest, | ||
event: this.event | ||
}); | ||
} | ||
} | ||
/** | ||
* Checks the list of plugins for the `cacheKeyWillBeUsed` callback, and | ||
* executes any of those callbacks found in sequence. The final `Request` | ||
* object returned by the last plugin is treated as the cache key for cache | ||
* reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have | ||
* been registered, the passed request is returned unmodified | ||
* | ||
* @param {Request} request | ||
* @param {string} mode | ||
* @return {Promise<Request>} | ||
*/ | ||
async getCacheKey(request, mode) { | ||
if (!this._cacheKeys[mode]) { | ||
let effectiveRequest = request; | ||
for (const callback of this.iterateCallbacks('cacheKeyWillBeUsed')) { | ||
effectiveRequest = toRequest(await callback({ | ||
mode, | ||
request: effectiveRequest, | ||
event: this.event, | ||
params: this.params | ||
})); | ||
} | ||
this._cacheKeys[mode] = effectiveRequest; | ||
} | ||
return this._cacheKeys[mode]; | ||
} | ||
/** | ||
* Returns true if the strategy has at least one plugin with the given | ||
@@ -340,82 +490,2 @@ * callback. | ||
} | ||
} // An async function version of `fetch()`, making it easier for that | ||
// function to add a promise to `waitUntil()`. | ||
async _fetch(input) { | ||
const { | ||
event | ||
} = this; | ||
let request = toRequest(input); | ||
if (request.mode === 'navigate' && event instanceof FetchEvent && event.preloadResponse) { | ||
const possiblePreloadResponse = await event.preloadResponse; | ||
if (possiblePreloadResponse) { | ||
{ | ||
logger_js.logger.log(`Using a preloaded navigation response for ` + `'${getFriendlyURL_js.getFriendlyURL(request.url)}'`); | ||
} | ||
return possiblePreloadResponse; | ||
} | ||
} // If there is a fetchDidFail plugin, we need to save a clone of the | ||
// original request before it's either modified by a requestWillFetch | ||
// plugin or before the original request's body is consumed via fetch(). | ||
const originalRequest = this.hasCallback('fetchDidFail') ? request.clone() : null; | ||
try { | ||
for (const cb of this.iterateCallbacks('requestWillFetch')) { | ||
request = await cb({ | ||
request: request.clone(), | ||
event | ||
}); | ||
} | ||
} catch (err) { | ||
throw new WorkboxError_js.WorkboxError('plugin-error-request-will-fetch', { | ||
thrownError: err | ||
}); | ||
} // The request can be altered by plugins with `requestWillFetch` making | ||
// the original request (most likely from a `fetch` event) different | ||
// from the Request we make. Pass both to `fetchDidFail` to aid debugging. | ||
const pluginFilteredRequest = request.clone(); | ||
try { | ||
let fetchResponse; // See https://github.com/GoogleChrome/workbox/issues/1796 | ||
fetchResponse = await fetch(request, request.mode === 'navigate' ? undefined : this._strategy.fetchOptions); | ||
if ("dev" !== 'production') { | ||
logger_js.logger.debug(`Network request for ` + `'${getFriendlyURL_js.getFriendlyURL(request.url)}' returned a response with ` + `status '${fetchResponse.status}'.`); | ||
} | ||
for (const callback of this.iterateCallbacks('fetchDidSucceed')) { | ||
fetchResponse = await callback({ | ||
event, | ||
request: pluginFilteredRequest, | ||
response: fetchResponse | ||
}); | ||
} | ||
return fetchResponse; | ||
} catch (error) { | ||
{ | ||
logger_js.logger.error(`Network request for ` + `'${getFriendlyURL_js.getFriendlyURL(request.url)}' threw an error.`, error); | ||
} // `originalRequest` will only exist if there's a `fetchDidFail` callback. | ||
if (originalRequest) { | ||
await this.runCallbacks('fetchDidFail', { | ||
error, | ||
event, | ||
originalRequest: originalRequest.clone(), | ||
request: pluginFilteredRequest.clone() | ||
}); | ||
} | ||
throw error; | ||
} | ||
} | ||
@@ -469,67 +539,4 @@ /** | ||
this._handlerDeferred.resolve(); | ||
} // An async function version of `cacheMatch()`, making it easier for that | ||
// function to add a promise to `waitUntil()`. | ||
async _cacheMatch(key) { | ||
const request = toRequest(key); | ||
let cachedResponse; | ||
const { | ||
cacheName, | ||
matchOptions | ||
} = this._strategy; | ||
const effectiveRequest = await this._getEffectiveRequest(request, 'read'); | ||
cachedResponse = await caches.match(effectiveRequest, _extends({}, matchOptions, { | ||
cacheName | ||
})); | ||
{ | ||
if (cachedResponse) { | ||
logger_js.logger.debug(`Found a cached response in '${cacheName}'.`); | ||
} else { | ||
logger_js.logger.debug(`No cached response found in '${cacheName}'.`); | ||
} | ||
} | ||
for (const callback of this.iterateCallbacks('cachedResponseWillBeUsed')) { | ||
cachedResponse = (await callback({ | ||
cacheName, | ||
matchOptions, | ||
cachedResponse, | ||
request: effectiveRequest, | ||
event: this.event | ||
})) || undefined; | ||
} | ||
return cachedResponse; | ||
} | ||
/** | ||
* Checks the list of plugins for the cacheKeyWillBeUsed callback, and | ||
* executes any of those callbacks found in sequence. The final `Request` | ||
* object returned by the last plugin is treated as the cache key for cache | ||
* reads and/or writes. | ||
* | ||
* @param {Request} request | ||
* @param {string} mode | ||
* @return {Promise<Request>} | ||
* | ||
* @private | ||
*/ | ||
async _getEffectiveRequest(request, mode) { | ||
let effectiveRequest = request; | ||
for (const callback of this.iterateCallbacks('cacheKeyWillBeUsed')) { | ||
effectiveRequest = toRequest(await callback({ | ||
mode, | ||
request: effectiveRequest, | ||
event: this.event, | ||
params: this.params | ||
})); | ||
} | ||
return effectiveRequest; | ||
} | ||
/** | ||
* This method will call cacheWillUpdate on the available plugins (or use | ||
@@ -608,12 +615,12 @@ * status === 200) to determine if the Response is safe and valid to cache. | ||
* | ||
* @param {Object} options | ||
* @param {string} options.cacheName Cache name to store and retrieve | ||
* @param {Object} [options] | ||
* @param {string} [options.cacheName] Cache name to store and retrieve | ||
* requests. Defaults to the cache names provided by | ||
* [workbox-core]{@link module:workbox-core.cacheNames}. | ||
* @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* @param {Array<Object>} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* to use in conjunction with this caching strategy. | ||
* @param {Object} options.fetchOptions Values passed along to the | ||
* @param {Object} [options.fetchOptions] Values passed along to the | ||
* [`init`]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters} | ||
* of all fetch() requests made by this strategy. | ||
* @param {Object} options.matchOptions The | ||
* @param {Object} [options.matchOptions] The | ||
* [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} | ||
@@ -628,3 +635,3 @@ * for any `cache.match()` or `cache.put()` calls made by this strategy. | ||
* | ||
* @instance | ||
* @type {string} | ||
*/ | ||
@@ -637,3 +644,3 @@ this.cacheName = cacheNames_js.cacheNames.getRuntimeName(options.cacheName); | ||
* | ||
* @instance | ||
* @type {Array<Object>} | ||
*/ | ||
@@ -647,3 +654,3 @@ | ||
* | ||
* @instance | ||
* @type {Object} | ||
*/ | ||
@@ -657,3 +664,3 @@ | ||
* | ||
* @instance | ||
* @type {Object} | ||
*/ | ||
@@ -876,3 +883,3 @@ | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -895,3 +902,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'CacheFirst', | ||
className: this.constructor.name, | ||
funcName: 'makeRequest', | ||
@@ -930,3 +937,3 @@ paramName: 'request' | ||
{ | ||
logger_js.logger.groupCollapsed(messages.strategyStart('CacheFirst', request)); | ||
logger_js.logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
@@ -970,3 +977,3 @@ for (const log of logs) { | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -987,3 +994,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'CacheOnly', | ||
className: this.constructor.name, | ||
funcName: 'makeRequest', | ||
@@ -997,6 +1004,6 @@ paramName: 'request' | ||
{ | ||
logger_js.logger.groupCollapsed(messages.strategyStart('CacheOnly', request)); | ||
logger_js.logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
if (response) { | ||
logger_js.logger.log(`Found a cached response in the '${this.cacheName}'` + ` cache.`); | ||
logger_js.logger.log(`Found a cached response in the '${this.cacheName}' ` + `cache.`); | ||
messages.printFinalResponse(response); | ||
@@ -1070,3 +1077,3 @@ } else { | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -1077,13 +1084,13 @@ */ | ||
/** | ||
* @param {Object} options | ||
* @param {string} options.cacheName Cache name to store and retrieve | ||
* @param {Object} [options] | ||
* @param {string} [options.cacheName Cache name to store and retrieve | ||
* requests. Defaults to cache names provided by | ||
* [workbox-core]{@link module:workbox-core.cacheNames}. | ||
* @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* @param {Array<Object>} [options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* to use in conjunction with this caching strategy. | ||
* @param {Object} options.fetchOptions Values passed along to the | ||
* @param {Object} [options.fetchOptions Values passed along to the | ||
* [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) | ||
* of all fetch() requests made by this strategy. | ||
* @param {Object} options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) | ||
* @param {number} options.networkTimeoutSeconds If set, any network requests | ||
* @param {Object} [options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) | ||
* @param {number} [options.networkTimeoutSeconds] If set, any network requests | ||
* that fail to respond within the timeout will fallback to the cache. | ||
@@ -1109,3 +1116,3 @@ * | ||
moduleName: 'workbox-strategies', | ||
className: 'NetworkFirst', | ||
className: this.constructor.name, | ||
funcName: 'constructor', | ||
@@ -1132,3 +1139,3 @@ paramName: 'networkTimeoutSeconds' | ||
moduleName: 'workbox-strategies', | ||
className: 'NetworkFirst', | ||
className: this.constructor.name, | ||
funcName: 'handle', | ||
@@ -1181,3 +1188,3 @@ paramName: 'makeRequest' | ||
{ | ||
logger_js.logger.groupCollapsed(messages.strategyStart('NetworkFirst', request)); | ||
logger_js.logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
@@ -1306,3 +1313,3 @@ for (const log of logs) { | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -1323,3 +1330,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'NetworkOnly', | ||
className: this.constructor.name, | ||
funcName: 'handle', | ||
@@ -1340,3 +1347,3 @@ paramName: 'request' | ||
{ | ||
logger_js.logger.groupCollapsed(messages.strategyStart('NetworkOnly', request)); | ||
logger_js.logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
@@ -1390,3 +1397,3 @@ if (response) { | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -1431,3 +1438,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'StaleWhileRevalidate', | ||
className: this.constructor.name, | ||
funcName: 'handle', | ||
@@ -1463,3 +1470,3 @@ paramName: 'request' | ||
{ | ||
logger_js.logger.groupCollapsed(messages.strategyStart('StaleWhileRevalidate', request)); | ||
logger_js.logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
@@ -1496,3 +1503,3 @@ for (const log of logs) { | ||
}({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private)); | ||
}({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private)); | ||
//# sourceMappingURL=workbox-strategies.dev.js.map |
@@ -1,2 +0,2 @@ | ||
this.workbox=this.workbox||{},this.workbox.strategies=function(t,e,s,r,a,i,n,o){"use strict";function c(){return(c=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var r in s)Object.prototype.hasOwnProperty.call(s,r)&&(t[r]=s[r])}return t}).apply(this,arguments)}try{self["workbox:strategies:6.0.0-alpha.1"]&&_()}catch(t){}function h(t){return"string"==typeof t?new Request(t):t}class l{constructor(t,e){Object.assign(this,e),this.event=e.event,this.t=t,this.s=new i.Deferred,this.i=[],this.o=[...t.plugins],this.h=new Map;for(const t of this.o)this.h.set(t,{});this.event.waitUntil(this.s.promise)}fetch(t){return this.waitUntil(this.l(t))}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}cacheMatch(t){return this.waitUntil(this.u(t))}async cachePut(t,e){const r=h(t);await o.timeout(0);const i=await this.p(r,"write");if(!e)throw new s.WorkboxError("cache-put-with-no-response",{url:a.getFriendlyURL(i.url)});const c=await this.v(e);if(!c)return;const{cacheName:l}=this.t,u=await self.caches.open(l),w=this.hasCallback("cacheDidUpdate")?await this.cacheMatch(r):null;try{await u.put(i,c)}catch(t){throw"QuotaExceededError"===t.name&&await n.executeQuotaErrorCallbacks(),t}await this.runCallbacks("cacheDidUpdate",{cacheName:l,oldResponse:w,newResponse:c,request:i,event:this.event})}hasCallback(t){for(const e of this.t.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.t.plugins)if("function"==typeof e[t]){const s=this.h.get(e),r=r=>{const a=c({},r,{state:s});return e[t](a)};yield r}}async l(t){const{event:e}=this;let r=h(t);if("navigate"===r.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const a=this.hasCallback("fetchDidFail")?r.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))r=await t({request:r.clone(),event:e})}catch(t){throw new s.WorkboxError("plugin-error-request-will-fetch",{thrownError:t})}const i=r.clone();try{let t;t=await fetch(r,"navigate"===r.mode?void 0:this.t.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:i,response:t});return t}catch(t){throw a&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:a.clone(),request:i.clone()}),t}}waitUntil(t){return this.i.push(t),t}async doneWaiting(){let t;for(;t=this.i.shift();)await t}destroy(){this.s.resolve()}async u(t){const e=h(t);let s;const{cacheName:r,matchOptions:a}=this.t,i=await this.p(e,"read");s=await caches.match(i,c({},a,{cacheName:r}));for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:r,matchOptions:a,cachedResponse:s,request:i,event:this.event})||void 0;return s}async p(t,e){let s=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))s=h(await t({mode:e,request:s,event:this.event,params:this.params}));return s}async v(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class u{constructor(t={}){this.cacheName=r.cacheNames.getRuntimeName(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,r="params"in t?t.params:void 0,a=new l(this,{event:e,request:s,params:r}),i=this.m(a,s,e);return[i,this.q(i,a,s,e)]}async m(t,e,r){await t.runCallbacks("handlerWillStart",{event:r,request:e});let a=void 0;try{if(a=await this.g(e,t),!a||"error"===a.type)throw new s.WorkboxError("no-response",{url:e.url})}catch(s){for(const i of t.iterateCallbacks("handlerDidError"))if(a=await i({error:s,event:r,request:e}),a)break;if(!a)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))a=await s({event:r,request:e,response:a});return a}async q(t,e,s,r){let a,i;try{a=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:r,request:s,response:a}),await e.doneWaiting()}catch(t){i=t}if(await e.runCallbacks("handlerDidComplete",{event:r,request:s,response:a,error:i}),e.destroy(),i)throw i}}const w={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null};return t.CacheFirst=class extends u{async g(t,e){let r,a=await e.cacheMatch(t);if(!a)try{a=await e.fetchAndCachePut(t)}catch(t){r=t}if(!a)throw new s.WorkboxError("no-response",{url:t.url,error:r});return a}},t.CacheOnly=class extends u{async g(t,e){const r=await e.cacheMatch(t);if(!r)throw new s.WorkboxError("no-response",{url:t.url});return r}},t.NetworkFirst=class extends u{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(w),this._=t.networkTimeoutSeconds||0}async g(t,e){const r=[],a=[];let i;if(this._){const{id:s,promise:n}=this.k({request:t,logs:r,handler:e});i=s,a.push(n)}const n=this.R({timeoutId:i,request:t,logs:r,handler:e});a.push(n);for(const t of a)e.waitUntil(t);let o=await Promise.race(a);if(o||(o=await n),!o)throw new s.WorkboxError("no-response",{url:t.url});return o}k({request:t,logs:e,handler:s}){let r;return{promise:new Promise(e=>{r=setTimeout(async()=>{e(await s.cacheMatch(t))},1e3*this._)}),id:r}}async R({timeoutId:t,request:e,logs:s,handler:r}){let a,i;try{i=await r.fetchAndCachePut(e)}catch(t){a=t}return t&&clearTimeout(t),!a&&i||(i=await r.cacheMatch(e)),i}},t.NetworkOnly=class extends u{async g(t,e){let r,a;try{a=await e.fetch(t)}catch(t){r=t}if(!a)throw new s.WorkboxError("no-response",{url:t.url,error:r});return a}},t.StaleWhileRevalidate=class extends u{constructor(t){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(w)}async g(t,e){const r=e.fetchAndCachePut(t).catch(()=>{});let a,i=await e.cacheMatch(t);if(i);else try{i=await r}catch(t){a=t}if(!i)throw new s.WorkboxError("no-response",{url:t.url,error:a});return i}},t.Strategy=u,t.StrategyHandler=l,t}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private); | ||
this.workbox=this.workbox||{},this.workbox.strategies=function(t,e,s,r,a,i,n,o,c){"use strict";function h(){return(h=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var r in s)Object.prototype.hasOwnProperty.call(s,r)&&(t[r]=s[r])}return t}).apply(this,arguments)}try{self["workbox:strategies:6.0.0-alpha.2"]&&_()}catch(t){}function l(t){return"string"==typeof t?new Request(t):t}class u{constructor(t,e){this.t={},Object.assign(this,e),this.event=e.event,this.i=t,this.o=new n.Deferred,this.h=[],this.l=[...t.plugins],this.u=new Map;for(const t of this.l)this.u.set(t,{});this.event.waitUntil(this.o.promise)}fetch(t){return this.waitUntil((async()=>{const{event:e}=this;let r=l(t);if("navigate"===r.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const a=this.hasCallback("fetchDidFail")?r.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))r=await t({request:r.clone(),event:e})}catch(t){throw new s.WorkboxError("plugin-error-request-will-fetch",{thrownError:t})}const i=r.clone();try{let t;t=await fetch(r,"navigate"===r.mode?void 0:this.i.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:i,response:t});return t}catch(t){throw a&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:a.clone(),request:i.clone()}),t}})())}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}cacheMatch(t){return this.waitUntil((async()=>{const e=l(t);let s;const{cacheName:r,matchOptions:a}=this.i,i=await this.getCacheKey(e,"read"),n=h({},a,{cacheName:r});s=await caches.match(i,n);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:r,matchOptions:a,cachedResponse:s,request:i,event:this.event})||void 0;return s})())}async cachePut(t,e){const r=l(t);await c.timeout(0);const n=await this.getCacheKey(r,"write");if(!e)throw new s.WorkboxError("cache-put-with-no-response",{url:a.getFriendlyURL(n.url)});const h=await this.p(e);if(!h)return;const{cacheName:u,matchOptions:w}=this.i,f=await self.caches.open(u),d=this.hasCallback("cacheDidUpdate"),p=d?await i.cacheMatchIgnoreParams(f,n.clone(),["__WB_REVISION__"],w):null;try{await f.put(n,d?h.clone():h)}catch(t){throw"QuotaExceededError"===t.name&&await o.executeQuotaErrorCallbacks(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:u,oldResponse:p,newResponse:h.clone(),request:n,event:this.event})}async getCacheKey(t,e){if(!this.t[e]){let s=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))s=l(await t({mode:e,request:s,event:this.event,params:this.params}));this.t[e]=s}return this.t[e]}hasCallback(t){for(const e of this.i.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.i.plugins)if("function"==typeof e[t]){const s=this.u.get(e),r=r=>{const a=h({},r,{state:s});return e[t](a)};yield r}}waitUntil(t){return this.h.push(t),t}async doneWaiting(){let t;for(;t=this.h.shift();)await t}destroy(){this.o.resolve()}async p(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class w{constructor(t={}){this.cacheName=r.cacheNames.getRuntimeName(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,r="params"in t?t.params:void 0,a=new u(this,{event:e,request:s,params:r}),i=this.v(a,s,e);return[i,this.m(i,a,s,e)]}async v(t,e,r){await t.runCallbacks("handlerWillStart",{event:r,request:e});let a=void 0;try{if(a=await this.q(e,t),!a||"error"===a.type)throw new s.WorkboxError("no-response",{url:e.url})}catch(s){for(const i of t.iterateCallbacks("handlerDidError"))if(a=await i({error:s,event:r,request:e}),a)break;if(!a)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))a=await s({event:r,request:e,response:a});return a}async m(t,e,s,r){let a,i;try{a=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:r,request:s,response:a}),await e.doneWaiting()}catch(t){i=t}if(await e.runCallbacks("handlerDidComplete",{event:r,request:s,response:a,error:i}),e.destroy(),i)throw i}}const f={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null};return t.CacheFirst=class extends w{async q(t,e){let r,a=await e.cacheMatch(t);if(!a)try{a=await e.fetchAndCachePut(t)}catch(t){r=t}if(!a)throw new s.WorkboxError("no-response",{url:t.url,error:r});return a}},t.CacheOnly=class extends w{async q(t,e){const r=await e.cacheMatch(t);if(!r)throw new s.WorkboxError("no-response",{url:t.url});return r}},t.NetworkFirst=class extends w{constructor(t={}){super(t),this.plugins.some((t=>"cacheWillUpdate"in t))||this.plugins.unshift(f),this._=t.networkTimeoutSeconds||0}async q(t,e){const r=[],a=[];let i;if(this._){const{id:s,promise:n}=this.g({request:t,logs:r,handler:e});i=s,a.push(n)}const n=this.k({timeoutId:i,request:t,logs:r,handler:e});a.push(n);for(const t of a)e.waitUntil(t);let o=await Promise.race(a);if(o||(o=await n),!o)throw new s.WorkboxError("no-response",{url:t.url});return o}g({request:t,logs:e,handler:s}){let r;return{promise:new Promise((e=>{r=setTimeout((async()=>{e(await s.cacheMatch(t))}),1e3*this._)})),id:r}}async k({timeoutId:t,request:e,logs:s,handler:r}){let a,i;try{i=await r.fetchAndCachePut(e)}catch(t){a=t}return t&&clearTimeout(t),!a&&i||(i=await r.cacheMatch(e)),i}},t.NetworkOnly=class extends w{async q(t,e){let r,a;try{a=await e.fetch(t)}catch(t){r=t}if(!a)throw new s.WorkboxError("no-response",{url:t.url,error:r});return a}},t.StaleWhileRevalidate=class extends w{constructor(t){super(t),this.plugins.some((t=>"cacheWillUpdate"in t))||this.plugins.unshift(f)}async q(t,e){const r=e.fetchAndCachePut(t).catch((()=>{}));let a,i=await e.cacheMatch(t);if(i);else try{i=await r}catch(t){a=t}if(!i)throw new s.WorkboxError("no-response",{url:t.url,error:a});return i}},t.Strategy=w,t.StrategyHandler=u,t}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private); | ||
//# sourceMappingURL=workbox-strategies.prod.js.map |
@@ -15,3 +15,3 @@ import { Strategy } from './Strategy.js'; | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -18,0 +18,0 @@ */ |
@@ -25,3 +25,3 @@ /* | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -42,3 +42,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'CacheFirst', | ||
className: this.constructor.name, | ||
funcName: 'makeRequest', | ||
@@ -76,3 +76,3 @@ paramName: 'request', | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.groupCollapsed(messages.strategyStart('CacheFirst', request)); | ||
logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
for (const log of logs) { | ||
@@ -79,0 +79,0 @@ logger.log(log); |
@@ -14,3 +14,3 @@ import { Strategy } from './Strategy.js'; | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -17,0 +17,0 @@ */ |
@@ -24,3 +24,3 @@ /* | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -40,3 +40,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'CacheOnly', | ||
className: this.constructor.name, | ||
funcName: 'makeRequest', | ||
@@ -48,6 +48,6 @@ paramName: 'request', | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.groupCollapsed(messages.strategyStart('CacheOnly', request)); | ||
logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
if (response) { | ||
logger.log(`Found a cached response in the '${this.cacheName}'` + | ||
` cache.`); | ||
logger.log(`Found a cached response in the '${this.cacheName}' ` + | ||
`cache.`); | ||
messages.printFinalResponse(response); | ||
@@ -54,0 +54,0 @@ } |
import { Strategy, StrategyOptions } from './Strategy.js'; | ||
import { StrategyHandler } from './StrategyHandler.js'; | ||
import './_version.js'; | ||
interface NetworkFirstOptions extends StrategyOptions { | ||
export interface NetworkFirstOptions extends StrategyOptions { | ||
networkTimeoutSeconds?: number; | ||
@@ -20,3 +20,3 @@ } | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -27,13 +27,13 @@ */ | ||
/** | ||
* @param {Object} options | ||
* @param {string} options.cacheName Cache name to store and retrieve | ||
* @param {Object} [options] | ||
* @param {string} [options.cacheName Cache name to store and retrieve | ||
* requests. Defaults to cache names provided by | ||
* [workbox-core]{@link module:workbox-core.cacheNames}. | ||
* @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* @param {Array<Object>} [options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* to use in conjunction with this caching strategy. | ||
* @param {Object} options.fetchOptions Values passed along to the | ||
* @param {Object} [options.fetchOptions Values passed along to the | ||
* [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) | ||
* of all fetch() requests made by this strategy. | ||
* @param {Object} options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) | ||
* @param {number} options.networkTimeoutSeconds If set, any network requests | ||
* @param {Object} [options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) | ||
* @param {number} [options.networkTimeoutSeconds] If set, any network requests | ||
* that fail to respond within the timeout will fallback to the cache. | ||
@@ -40,0 +40,0 @@ * |
@@ -28,3 +28,3 @@ /* | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -34,13 +34,13 @@ */ | ||
/** | ||
* @param {Object} options | ||
* @param {string} options.cacheName Cache name to store and retrieve | ||
* @param {Object} [options] | ||
* @param {string} [options.cacheName Cache name to store and retrieve | ||
* requests. Defaults to cache names provided by | ||
* [workbox-core]{@link module:workbox-core.cacheNames}. | ||
* @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* @param {Array<Object>} [options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* to use in conjunction with this caching strategy. | ||
* @param {Object} options.fetchOptions Values passed along to the | ||
* @param {Object} [options.fetchOptions Values passed along to the | ||
* [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) | ||
* of all fetch() requests made by this strategy. | ||
* @param {Object} options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) | ||
* @param {number} options.networkTimeoutSeconds If set, any network requests | ||
* @param {Object} [options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) | ||
* @param {number} [options.networkTimeoutSeconds] If set, any network requests | ||
* that fail to respond within the timeout will fallback to the cache. | ||
@@ -64,3 +64,3 @@ * | ||
moduleName: 'workbox-strategies', | ||
className: 'NetworkFirst', | ||
className: this.constructor.name, | ||
funcName: 'constructor', | ||
@@ -84,3 +84,3 @@ paramName: 'networkTimeoutSeconds', | ||
moduleName: 'workbox-strategies', | ||
className: 'NetworkFirst', | ||
className: this.constructor.name, | ||
funcName: 'handle', | ||
@@ -113,3 +113,3 @@ paramName: 'makeRequest', | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.groupCollapsed(messages.strategyStart('NetworkFirst', request)); | ||
logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
for (const log of logs) { | ||
@@ -116,0 +116,0 @@ logger.log(log); |
@@ -14,3 +14,3 @@ import { Strategy } from './Strategy.js'; | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -17,0 +17,0 @@ */ |
@@ -24,3 +24,3 @@ /* | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -40,3 +40,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'NetworkOnly', | ||
className: this.constructor.name, | ||
funcName: 'handle', | ||
@@ -55,3 +55,3 @@ paramName: 'request', | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.groupCollapsed(messages.strategyStart('NetworkOnly', request)); | ||
logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
if (response) { | ||
@@ -58,0 +58,0 @@ logger.log(`Got response from network.`); |
{ | ||
"name": "workbox-strategies", | ||
"version": "6.0.0-alpha.2", | ||
"version": "6.0.0-alpha.3", | ||
"license": "MIT", | ||
@@ -26,5 +26,5 @@ "author": "Google's Web DevRel Team", | ||
"dependencies": { | ||
"workbox-core": "^6.0.0-alpha.2" | ||
"workbox-core": "^6.0.0-alpha.3" | ||
}, | ||
"gitHead": "45f41a2d2f9870c49837923bb5c5854917da3a08" | ||
"gitHead": "00ba07467b253751e874f53f424f2adb1c06e176" | ||
} |
// @ts-ignore | ||
try{self['workbox:strategies:6.0.0-alpha.1']&&_()}catch(e){} | ||
try{self['workbox:strategies:6.0.0-alpha.2']&&_()}catch(e){} |
@@ -30,3 +30,3 @@ /* | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -48,3 +48,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'CacheFirst', | ||
className: this.constructor.name, | ||
funcName: 'makeRequest', | ||
@@ -86,3 +86,3 @@ paramName: 'request', | ||
logger.groupCollapsed( | ||
messages.strategyStart('CacheFirst', request)); | ||
messages.strategyStart(this.constructor.name, request)); | ||
for (const log of logs) { | ||
@@ -89,0 +89,0 @@ logger.log(log); |
@@ -29,3 +29,3 @@ /* | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -45,3 +45,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'CacheOnly', | ||
className: this.constructor.name, | ||
funcName: 'makeRequest', | ||
@@ -56,6 +56,6 @@ paramName: 'request', | ||
logger.groupCollapsed( | ||
messages.strategyStart('CacheOnly', request)); | ||
messages.strategyStart(this.constructor.name, request)); | ||
if (response) { | ||
logger.log(`Found a cached response in the '${this.cacheName}'` + | ||
` cache.`); | ||
logger.log(`Found a cached response in the '${this.cacheName}' ` + | ||
`cache.`); | ||
messages.printFinalResponse(response); | ||
@@ -62,0 +62,0 @@ } else { |
@@ -20,3 +20,3 @@ /* | ||
interface NetworkFirstOptions extends StrategyOptions { | ||
export interface NetworkFirstOptions extends StrategyOptions { | ||
networkTimeoutSeconds?: number; | ||
@@ -38,3 +38,3 @@ } | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -46,13 +46,13 @@ */ | ||
/** | ||
* @param {Object} options | ||
* @param {string} options.cacheName Cache name to store and retrieve | ||
* @param {Object} [options] | ||
* @param {string} [options.cacheName Cache name to store and retrieve | ||
* requests. Defaults to cache names provided by | ||
* [workbox-core]{@link module:workbox-core.cacheNames}. | ||
* @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* @param {Array<Object>} [options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* to use in conjunction with this caching strategy. | ||
* @param {Object} options.fetchOptions Values passed along to the | ||
* @param {Object} [options.fetchOptions Values passed along to the | ||
* [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) | ||
* of all fetch() requests made by this strategy. | ||
* @param {Object} options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) | ||
* @param {number} options.networkTimeoutSeconds If set, any network requests | ||
* @param {Object} [options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) | ||
* @param {number} [options.networkTimeoutSeconds] If set, any network requests | ||
* that fail to respond within the timeout will fallback to the cache. | ||
@@ -78,3 +78,3 @@ * | ||
moduleName: 'workbox-strategies', | ||
className: 'NetworkFirst', | ||
className: this.constructor.name, | ||
funcName: 'constructor', | ||
@@ -100,3 +100,3 @@ paramName: 'networkTimeoutSeconds', | ||
moduleName: 'workbox-strategies', | ||
className: 'NetworkFirst', | ||
className: this.constructor.name, | ||
funcName: 'handle', | ||
@@ -137,3 +137,3 @@ paramName: 'makeRequest', | ||
logger.groupCollapsed( | ||
messages.strategyStart('NetworkFirst', request)); | ||
messages.strategyStart(this.constructor.name, request)); | ||
for (const log of logs) { | ||
@@ -140,0 +140,0 @@ logger.log(log); |
@@ -29,3 +29,3 @@ /* | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -45,3 +45,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'NetworkOnly', | ||
className: this.constructor.name, | ||
funcName: 'handle', | ||
@@ -62,3 +62,3 @@ paramName: 'request', | ||
logger.groupCollapsed( | ||
messages.strategyStart('NetworkOnly', request)); | ||
messages.strategyStart(this.constructor.name, request)); | ||
if (response) { | ||
@@ -65,0 +65,0 @@ logger.log(`Got response from network.`); |
@@ -38,3 +38,3 @@ /* | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -78,3 +78,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'StaleWhileRevalidate', | ||
className: this.constructor.name, | ||
funcName: 'handle', | ||
@@ -116,3 +116,3 @@ paramName: 'request', | ||
logger.groupCollapsed( | ||
messages.strategyStart('StaleWhileRevalidate', request)); | ||
messages.strategyStart(this.constructor.name, request)); | ||
for (const log of logs) { | ||
@@ -119,0 +119,0 @@ logger.log(log); |
@@ -51,12 +51,12 @@ /* | ||
* | ||
* @param {Object} options | ||
* @param {string} options.cacheName Cache name to store and retrieve | ||
* @param {Object} [options] | ||
* @param {string} [options.cacheName] Cache name to store and retrieve | ||
* requests. Defaults to the cache names provided by | ||
* [workbox-core]{@link module:workbox-core.cacheNames}. | ||
* @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* @param {Array<Object>} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* to use in conjunction with this caching strategy. | ||
* @param {Object} options.fetchOptions Values passed along to the | ||
* @param {Object} [options.fetchOptions] Values passed along to the | ||
* [`init`]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters} | ||
* of all fetch() requests made by this strategy. | ||
* @param {Object} options.matchOptions The | ||
* @param {Object} [options.matchOptions] The | ||
* [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} | ||
@@ -71,3 +71,3 @@ * for any `cache.match()` or `cache.put()` calls made by this strategy. | ||
* | ||
* @instance | ||
* @type {string} | ||
*/ | ||
@@ -80,3 +80,3 @@ this.cacheName = cacheNames.getRuntimeName(options.cacheName); | ||
* | ||
* @instance | ||
* @type {Array<Object>} | ||
*/ | ||
@@ -89,3 +89,3 @@ this.plugins = options.plugins || []; | ||
* | ||
* @instance | ||
* @type {Object} | ||
*/ | ||
@@ -98,3 +98,3 @@ this.fetchOptions = options.fetchOptions; | ||
* | ||
* @instance | ||
* @type {Object} | ||
*/ | ||
@@ -196,3 +196,3 @@ this.matchOptions = options.matchOptions; | ||
} | ||
if (!response) { | ||
@@ -199,0 +199,0 @@ throw error; |
@@ -10,2 +10,3 @@ /* | ||
import {assert} from 'workbox-core/_private/assert.js'; | ||
import {cacheMatchIgnoreParams} from 'workbox-core/_private/cacheMatchIgnoreParams.js'; | ||
import {Deferred} from 'workbox-core/_private/Deferred.js'; | ||
@@ -27,2 +28,3 @@ import {executeQuotaErrorCallbacks} from 'workbox-core/_private/executeQuotaErrorCallbacks.js'; | ||
function toRequest(input: RequestInfo) { | ||
@@ -47,2 +49,4 @@ return (typeof input === 'string') ? new Request(input) : input; | ||
private _cacheKeys: {read?: Request; write?: Request} = {}; | ||
private readonly _strategy: Strategy; | ||
@@ -150,3 +154,80 @@ private readonly _extendLifetimePromises: Promise<any>[]; | ||
fetch(input: RequestInfo): Promise<Response> { | ||
return this.waitUntil(this._fetch(input)); | ||
return this.waitUntil((async () => { | ||
const {event} = this; | ||
let request: Request = toRequest(input); | ||
if (request.mode === 'navigate' && | ||
event instanceof FetchEvent && | ||
event.preloadResponse) { | ||
const possiblePreloadResponse = await event.preloadResponse; | ||
if (possiblePreloadResponse) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.log(`Using a preloaded navigation response for ` + | ||
`'${getFriendlyURL(request.url)}'`); | ||
} | ||
return possiblePreloadResponse; | ||
} | ||
} | ||
// If there is a fetchDidFail plugin, we need to save a clone of the | ||
// original request before it's either modified by a requestWillFetch | ||
// plugin or before the original request's body is consumed via fetch(). | ||
const originalRequest = this.hasCallback('fetchDidFail') ? | ||
request.clone() : null; | ||
try { | ||
for (const cb of this.iterateCallbacks('requestWillFetch')) { | ||
request = await cb({request: request.clone(), event}); | ||
} | ||
} catch (err) { | ||
throw new WorkboxError('plugin-error-request-will-fetch', { | ||
thrownError: err, | ||
}); | ||
} | ||
// The request can be altered by plugins with `requestWillFetch` making | ||
// the original request (most likely from a `fetch` event) different | ||
// from the Request we make. Pass both to `fetchDidFail` to aid debugging. | ||
const pluginFilteredRequest: Request = request.clone(); | ||
try { | ||
let fetchResponse: Response; | ||
// See https://github.com/GoogleChrome/workbox/issues/1796 | ||
fetchResponse = await fetch(request, request.mode === 'navigate' ? | ||
undefined : this._strategy.fetchOptions); | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.debug(`Network request for ` + | ||
`'${getFriendlyURL(request.url)}' returned a response with ` + | ||
`status '${fetchResponse.status}'.`); | ||
} | ||
for (const callback of this.iterateCallbacks('fetchDidSucceed')) { | ||
fetchResponse = await callback({ | ||
event, | ||
request: pluginFilteredRequest, | ||
response: fetchResponse, | ||
}); | ||
} | ||
return fetchResponse; | ||
} catch (error) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.error(`Network request for `+ | ||
`'${getFriendlyURL(request.url)}' threw an error.`, error); | ||
} | ||
// `originalRequest` will only exist if a `fetchDidFail` callback | ||
// is being used (see above). | ||
if (originalRequest) { | ||
await this.runCallbacks('fetchDidFail', { | ||
error, | ||
event, | ||
originalRequest: originalRequest.clone(), | ||
request: pluginFilteredRequest.clone(), | ||
}); | ||
} | ||
throw error; | ||
} | ||
})()); | ||
} | ||
@@ -186,3 +267,31 @@ | ||
cacheMatch(key: RequestInfo): Promise<Response | undefined> { | ||
return this.waitUntil(this._cacheMatch(key)); | ||
return this.waitUntil((async () => { | ||
const request: Request = toRequest(key); | ||
let cachedResponse: Response | undefined; | ||
const {cacheName, matchOptions} = this._strategy; | ||
const effectiveRequest = await this.getCacheKey(request, 'read'); | ||
const multiMatchOptions = {...matchOptions, ...{cacheName}}; | ||
cachedResponse = await caches.match(effectiveRequest, multiMatchOptions); | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (cachedResponse) { | ||
logger.debug(`Found a cached response in '${cacheName}'.`); | ||
} else { | ||
logger.debug(`No cached response found in '${cacheName}'.`); | ||
} | ||
} | ||
for (const callback of this.iterateCallbacks('cachedResponseWillBeUsed')) { | ||
cachedResponse = (await callback({ | ||
cacheName, | ||
matchOptions, | ||
cachedResponse, | ||
request: effectiveRequest, | ||
event: this.event, | ||
})) || undefined; | ||
} | ||
return cachedResponse; | ||
})()); | ||
} | ||
@@ -206,7 +315,13 @@ | ||
// Run in the next task to avoid blocking other cache reads. | ||
// https://github.com/w3c/ServiceWorker/issues/1397 | ||
await timeout(0); | ||
const effectiveRequest = await this.getCacheKey(request, 'write'); | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (request.method && request.method !== 'GET') { | ||
if (effectiveRequest.method && effectiveRequest.method !== 'GET') { | ||
throw new WorkboxError('attempt-to-cache-non-get-request', { | ||
url: getFriendlyURL(request.url), | ||
method: request.method, | ||
url: getFriendlyURL(effectiveRequest.url), | ||
method: effectiveRequest.method, | ||
}); | ||
@@ -216,8 +331,2 @@ } | ||
// Run in the next task to avoid blocking other cache reads. | ||
// https://github.com/w3c/ServiceWorker/issues/1397 | ||
await timeout(0); | ||
const effectiveRequest = await this._getEffectiveRequest(request, 'write'); | ||
if (!response) { | ||
@@ -244,7 +353,12 @@ if (process.env.NODE_ENV !== 'production') { | ||
const {cacheName} = this._strategy; | ||
const {cacheName, matchOptions} = this._strategy; | ||
const cache = await self.caches.open(cacheName); | ||
const oldResponse = this.hasCallback('cacheDidUpdate') ? | ||
await this.cacheMatch(request) : null; | ||
const hasCacheUpdateCallback = this.hasCallback('cacheDidUpdate'); | ||
const oldResponse = hasCacheUpdateCallback ? await cacheMatchIgnoreParams( | ||
// TODO(philipwalton): the `__WB_REVISION__` param is a precaching | ||
// feature. Consider into ways to only add this behavior if using | ||
// precaching. | ||
cache, effectiveRequest.clone(), ['__WB_REVISION__'], matchOptions) : | ||
null; | ||
@@ -257,3 +371,4 @@ if (process.env.NODE_ENV !== 'production') { | ||
try { | ||
await cache.put(effectiveRequest, responseToCache); | ||
await cache.put(effectiveRequest, hasCacheUpdateCallback ? | ||
responseToCache.clone() : responseToCache); | ||
} catch (error) { | ||
@@ -267,12 +382,43 @@ // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError | ||
await this.runCallbacks('cacheDidUpdate', { | ||
cacheName, | ||
oldResponse, | ||
newResponse: responseToCache, | ||
request: effectiveRequest, | ||
event: this.event, | ||
}); | ||
for (const callback of this.iterateCallbacks('cacheDidUpdate')) { | ||
await callback({ | ||
cacheName, | ||
oldResponse, | ||
newResponse: responseToCache.clone(), | ||
request: effectiveRequest, | ||
event: this.event, | ||
}); | ||
} | ||
} | ||
/** | ||
* Checks the list of plugins for the `cacheKeyWillBeUsed` callback, and | ||
* executes any of those callbacks found in sequence. The final `Request` | ||
* object returned by the last plugin is treated as the cache key for cache | ||
* reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have | ||
* been registered, the passed request is returned unmodified | ||
* | ||
* @param {Request} request | ||
* @param {string} mode | ||
* @return {Promise<Request>} | ||
*/ | ||
async getCacheKey(request: Request, mode: 'read' | 'write'): Promise<Request> { | ||
if (!this._cacheKeys[mode]) { | ||
let effectiveRequest = request; | ||
for (const callback of this.iterateCallbacks('cacheKeyWillBeUsed')) { | ||
effectiveRequest = toRequest(await callback({ | ||
mode, | ||
request: effectiveRequest, | ||
event: this.event, | ||
params: this.params, | ||
})); | ||
} | ||
this._cacheKeys[mode] = effectiveRequest; | ||
} | ||
return this._cacheKeys[mode]!; | ||
} | ||
/** | ||
* Returns true if the strategy has at least one plugin with the given | ||
@@ -347,83 +493,2 @@ * callback. | ||
// An async function version of `fetch()`, making it easier for that | ||
// function to add a promise to `waitUntil()`. | ||
async _fetch(input: RequestInfo): Promise<Response> { | ||
const {event} = this; | ||
let request: Request = toRequest(input); | ||
if (request.mode === 'navigate' && | ||
event instanceof FetchEvent && | ||
event.preloadResponse) { | ||
const possiblePreloadResponse = await event.preloadResponse; | ||
if (possiblePreloadResponse) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.log(`Using a preloaded navigation response for ` + | ||
`'${getFriendlyURL(request.url)}'`); | ||
} | ||
return possiblePreloadResponse; | ||
} | ||
} | ||
// If there is a fetchDidFail plugin, we need to save a clone of the | ||
// original request before it's either modified by a requestWillFetch | ||
// plugin or before the original request's body is consumed via fetch(). | ||
const originalRequest = this.hasCallback('fetchDidFail') ? | ||
request.clone() : null; | ||
try { | ||
for (const cb of this.iterateCallbacks('requestWillFetch')) { | ||
request = await cb({request: request.clone(), event}); | ||
} | ||
} catch (err) { | ||
throw new WorkboxError('plugin-error-request-will-fetch', { | ||
thrownError: err, | ||
}); | ||
} | ||
// The request can be altered by plugins with `requestWillFetch` making | ||
// the original request (most likely from a `fetch` event) different | ||
// from the Request we make. Pass both to `fetchDidFail` to aid debugging. | ||
const pluginFilteredRequest: Request = request.clone(); | ||
try { | ||
let fetchResponse: Response; | ||
// See https://github.com/GoogleChrome/workbox/issues/1796 | ||
fetchResponse = await fetch(request, request.mode === 'navigate' ? | ||
undefined : this._strategy.fetchOptions); | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.debug(`Network request for ` + | ||
`'${getFriendlyURL(request.url)}' returned a response with ` + | ||
`status '${fetchResponse.status}'.`); | ||
} | ||
for (const callback of this.iterateCallbacks('fetchDidSucceed')) { | ||
fetchResponse = await callback({ | ||
event, | ||
request: pluginFilteredRequest, | ||
response: fetchResponse, | ||
}); | ||
} | ||
return fetchResponse; | ||
} catch (error) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.error(`Network request for `+ | ||
`'${getFriendlyURL(request.url)}' threw an error.`, error); | ||
} | ||
// `originalRequest` will only exist if there's a `fetchDidFail` callback. | ||
if (originalRequest) { | ||
await this.runCallbacks('fetchDidFail', { | ||
error, | ||
event, | ||
originalRequest: originalRequest.clone(), | ||
request: pluginFilteredRequest.clone(), | ||
}); | ||
} | ||
throw error; | ||
} | ||
} | ||
/** | ||
@@ -472,61 +537,3 @@ * Adds a promise to the | ||
// An async function version of `cacheMatch()`, making it easier for that | ||
// function to add a promise to `waitUntil()`. | ||
async _cacheMatch(key: RequestInfo): Promise<Response | undefined> { | ||
const request: Request = toRequest(key); | ||
let cachedResponse: Response | undefined; | ||
const {cacheName, matchOptions} = this._strategy; | ||
const effectiveRequest = await this._getEffectiveRequest(request, 'read'); | ||
cachedResponse = await caches.match( | ||
effectiveRequest, {...matchOptions, ...{cacheName}}); | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (cachedResponse) { | ||
logger.debug(`Found a cached response in '${cacheName}'.`); | ||
} else { | ||
logger.debug(`No cached response found in '${cacheName}'.`); | ||
} | ||
} | ||
for (const callback of this.iterateCallbacks('cachedResponseWillBeUsed')) { | ||
cachedResponse = (await callback({ | ||
cacheName, | ||
matchOptions, | ||
cachedResponse, | ||
request: effectiveRequest, | ||
event: this.event, | ||
})) || undefined; | ||
} | ||
return cachedResponse; | ||
} | ||
/** | ||
* Checks the list of plugins for the cacheKeyWillBeUsed callback, and | ||
* executes any of those callbacks found in sequence. The final `Request` | ||
* object returned by the last plugin is treated as the cache key for cache | ||
* reads and/or writes. | ||
* | ||
* @param {Request} request | ||
* @param {string} mode | ||
* @return {Promise<Request>} | ||
* | ||
* @private | ||
*/ | ||
async _getEffectiveRequest(request: Request, mode: string): Promise<Request> { | ||
let effectiveRequest = request; | ||
for (const callback of this.iterateCallbacks('cacheKeyWillBeUsed')) { | ||
effectiveRequest = toRequest(await callback({ | ||
mode, | ||
request: effectiveRequest, | ||
event: this.event, | ||
params: this.params, | ||
})); | ||
} | ||
return effectiveRequest; | ||
} | ||
/** | ||
* This method will call cacheWillUpdate on the available plugins (or use | ||
@@ -533,0 +540,0 @@ * status === 200) to determine if the Response is safe and valid to cache. |
@@ -22,3 +22,3 @@ import { Strategy, StrategyOptions } from './Strategy.js'; | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -25,0 +25,0 @@ */ |
@@ -33,3 +33,3 @@ /* | ||
* | ||
* @extends module:workbox-core.Strategy | ||
* @extends module:workbox-strategies.Strategy | ||
* @memberof module:workbox-strategies | ||
@@ -70,3 +70,3 @@ */ | ||
moduleName: 'workbox-strategies', | ||
className: 'StaleWhileRevalidate', | ||
className: this.constructor.name, | ||
funcName: 'handle', | ||
@@ -105,3 +105,3 @@ paramName: 'request', | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.groupCollapsed(messages.strategyStart('StaleWhileRevalidate', request)); | ||
logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); | ||
for (const log of logs) { | ||
@@ -108,0 +108,0 @@ logger.log(log); |
@@ -29,12 +29,12 @@ import { HandlerCallbackOptions, RouteHandlerObject, WorkboxPlugin } from 'workbox-core/types.js'; | ||
* | ||
* @param {Object} options | ||
* @param {string} options.cacheName Cache name to store and retrieve | ||
* @param {Object} [options] | ||
* @param {string} [options.cacheName] Cache name to store and retrieve | ||
* requests. Defaults to the cache names provided by | ||
* [workbox-core]{@link module:workbox-core.cacheNames}. | ||
* @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* @param {Array<Object>} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* to use in conjunction with this caching strategy. | ||
* @param {Object} options.fetchOptions Values passed along to the | ||
* @param {Object} [options.fetchOptions] Values passed along to the | ||
* [`init`]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters} | ||
* of all fetch() requests made by this strategy. | ||
* @param {Object} options.matchOptions The | ||
* @param {Object} [options.matchOptions] The | ||
* [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} | ||
@@ -41,0 +41,0 @@ * for any `cache.match()` or `cache.put()` calls made by this strategy. |
@@ -28,12 +28,12 @@ /* | ||
* | ||
* @param {Object} options | ||
* @param {string} options.cacheName Cache name to store and retrieve | ||
* @param {Object} [options] | ||
* @param {string} [options.cacheName] Cache name to store and retrieve | ||
* requests. Defaults to the cache names provided by | ||
* [workbox-core]{@link module:workbox-core.cacheNames}. | ||
* @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* @param {Array<Object>} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} | ||
* to use in conjunction with this caching strategy. | ||
* @param {Object} options.fetchOptions Values passed along to the | ||
* @param {Object} [options.fetchOptions] Values passed along to the | ||
* [`init`]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters} | ||
* of all fetch() requests made by this strategy. | ||
* @param {Object} options.matchOptions The | ||
* @param {Object} [options.matchOptions] The | ||
* [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} | ||
@@ -48,3 +48,3 @@ * for any `cache.match()` or `cache.put()` calls made by this strategy. | ||
* | ||
* @instance | ||
* @type {string} | ||
*/ | ||
@@ -57,3 +57,3 @@ this.cacheName = cacheNames.getRuntimeName(options.cacheName); | ||
* | ||
* @instance | ||
* @type {Array<Object>} | ||
*/ | ||
@@ -66,3 +66,3 @@ this.plugins = options.plugins || []; | ||
* | ||
* @instance | ||
* @type {Object} | ||
*/ | ||
@@ -75,3 +75,3 @@ this.fetchOptions = options.fetchOptions; | ||
* | ||
* @instance | ||
* @type {Object} | ||
*/ | ||
@@ -78,0 +78,0 @@ this.matchOptions = options.matchOptions; |
@@ -18,2 +18,3 @@ import { HandlerCallbackOptions, WorkboxPlugin, WorkboxPluginCallbackParam } from 'workbox-core/types.js'; | ||
params?: any; | ||
private _cacheKeys; | ||
private readonly _strategy; | ||
@@ -95,2 +96,14 @@ private readonly _extendLifetimePromises; | ||
/** | ||
* Checks the list of plugins for the `cacheKeyWillBeUsed` callback, and | ||
* executes any of those callbacks found in sequence. The final `Request` | ||
* object returned by the last plugin is treated as the cache key for cache | ||
* reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have | ||
* been registered, the passed request is returned unmodified | ||
* | ||
* @param {Request} request | ||
* @param {string} mode | ||
* @return {Promise<Request>} | ||
*/ | ||
getCacheKey(request: Request, mode: 'read' | 'write'): Promise<Request>; | ||
/** | ||
* Returns true if the strategy has at least one plugin with the given | ||
@@ -130,3 +143,2 @@ * callback. | ||
iterateCallbacks<C extends keyof WorkboxPlugin>(name: C): Generator<NonNullable<WorkboxPlugin[C]>>; | ||
_fetch(input: RequestInfo): Promise<Response>; | ||
/** | ||
@@ -162,17 +174,3 @@ * Adds a promise to the | ||
destroy(): void; | ||
_cacheMatch(key: RequestInfo): Promise<Response | undefined>; | ||
/** | ||
* Checks the list of plugins for the cacheKeyWillBeUsed callback, and | ||
* executes any of those callbacks found in sequence. The final `Request` | ||
* object returned by the last plugin is treated as the cache key for cache | ||
* reads and/or writes. | ||
* | ||
* @param {Request} request | ||
* @param {string} mode | ||
* @return {Promise<Request>} | ||
* | ||
* @private | ||
*/ | ||
_getEffectiveRequest(request: Request, mode: string): Promise<Request>; | ||
/** | ||
* This method will call cacheWillUpdate on the available plugins (or use | ||
@@ -179,0 +177,0 @@ * status === 200) to determine if the Response is safe and valid to cache. |
@@ -9,2 +9,3 @@ /* | ||
import { assert } from 'workbox-core/_private/assert.js'; | ||
import { cacheMatchIgnoreParams } from 'workbox-core/_private/cacheMatchIgnoreParams.js'; | ||
import { Deferred } from 'workbox-core/_private/Deferred.js'; | ||
@@ -48,2 +49,3 @@ import { executeQuotaErrorCallbacks } from 'workbox-core/_private/executeQuotaErrorCallbacks.js'; | ||
constructor(strategy, options) { | ||
this._cacheKeys = {}; | ||
/** | ||
@@ -122,3 +124,73 @@ * The request the strategy is performing (passed to the strategy's | ||
fetch(input) { | ||
return this.waitUntil(this._fetch(input)); | ||
return this.waitUntil((async () => { | ||
const { event } = this; | ||
let request = toRequest(input); | ||
if (request.mode === 'navigate' && | ||
event instanceof FetchEvent && | ||
event.preloadResponse) { | ||
const possiblePreloadResponse = await event.preloadResponse; | ||
if (possiblePreloadResponse) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.log(`Using a preloaded navigation response for ` + | ||
`'${getFriendlyURL(request.url)}'`); | ||
} | ||
return possiblePreloadResponse; | ||
} | ||
} | ||
// If there is a fetchDidFail plugin, we need to save a clone of the | ||
// original request before it's either modified by a requestWillFetch | ||
// plugin or before the original request's body is consumed via fetch(). | ||
const originalRequest = this.hasCallback('fetchDidFail') ? | ||
request.clone() : null; | ||
try { | ||
for (const cb of this.iterateCallbacks('requestWillFetch')) { | ||
request = await cb({ request: request.clone(), event }); | ||
} | ||
} | ||
catch (err) { | ||
throw new WorkboxError('plugin-error-request-will-fetch', { | ||
thrownError: err, | ||
}); | ||
} | ||
// The request can be altered by plugins with `requestWillFetch` making | ||
// the original request (most likely from a `fetch` event) different | ||
// from the Request we make. Pass both to `fetchDidFail` to aid debugging. | ||
const pluginFilteredRequest = request.clone(); | ||
try { | ||
let fetchResponse; | ||
// See https://github.com/GoogleChrome/workbox/issues/1796 | ||
fetchResponse = await fetch(request, request.mode === 'navigate' ? | ||
undefined : this._strategy.fetchOptions); | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.debug(`Network request for ` + | ||
`'${getFriendlyURL(request.url)}' returned a response with ` + | ||
`status '${fetchResponse.status}'.`); | ||
} | ||
for (const callback of this.iterateCallbacks('fetchDidSucceed')) { | ||
fetchResponse = await callback({ | ||
event, | ||
request: pluginFilteredRequest, | ||
response: fetchResponse, | ||
}); | ||
} | ||
return fetchResponse; | ||
} | ||
catch (error) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.error(`Network request for ` + | ||
`'${getFriendlyURL(request.url)}' threw an error.`, error); | ||
} | ||
// `originalRequest` will only exist if a `fetchDidFail` callback | ||
// is being used (see above). | ||
if (originalRequest) { | ||
await this.runCallbacks('fetchDidFail', { | ||
error, | ||
event, | ||
originalRequest: originalRequest.clone(), | ||
request: pluginFilteredRequest.clone(), | ||
}); | ||
} | ||
throw error; | ||
} | ||
})()); | ||
} | ||
@@ -154,3 +226,28 @@ /** | ||
cacheMatch(key) { | ||
return this.waitUntil(this._cacheMatch(key)); | ||
return this.waitUntil((async () => { | ||
const request = toRequest(key); | ||
let cachedResponse; | ||
const { cacheName, matchOptions } = this._strategy; | ||
const effectiveRequest = await this.getCacheKey(request, 'read'); | ||
const multiMatchOptions = { ...matchOptions, ...{ cacheName } }; | ||
cachedResponse = await caches.match(effectiveRequest, multiMatchOptions); | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (cachedResponse) { | ||
logger.debug(`Found a cached response in '${cacheName}'.`); | ||
} | ||
else { | ||
logger.debug(`No cached response found in '${cacheName}'.`); | ||
} | ||
} | ||
for (const callback of this.iterateCallbacks('cachedResponseWillBeUsed')) { | ||
cachedResponse = (await callback({ | ||
cacheName, | ||
matchOptions, | ||
cachedResponse, | ||
request: effectiveRequest, | ||
event: this.event, | ||
})) || undefined; | ||
} | ||
return cachedResponse; | ||
})()); | ||
} | ||
@@ -172,14 +269,14 @@ /** | ||
const request = toRequest(key); | ||
// Run in the next task to avoid blocking other cache reads. | ||
// https://github.com/w3c/ServiceWorker/issues/1397 | ||
await timeout(0); | ||
const effectiveRequest = await this.getCacheKey(request, 'write'); | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (request.method && request.method !== 'GET') { | ||
if (effectiveRequest.method && effectiveRequest.method !== 'GET') { | ||
throw new WorkboxError('attempt-to-cache-non-get-request', { | ||
url: getFriendlyURL(request.url), | ||
method: request.method, | ||
url: getFriendlyURL(effectiveRequest.url), | ||
method: effectiveRequest.method, | ||
}); | ||
} | ||
} | ||
// Run in the next task to avoid blocking other cache reads. | ||
// https://github.com/w3c/ServiceWorker/issues/1397 | ||
await timeout(0); | ||
const effectiveRequest = await this._getEffectiveRequest(request, 'write'); | ||
if (!response) { | ||
@@ -202,6 +299,11 @@ if (process.env.NODE_ENV !== 'production') { | ||
} | ||
const { cacheName } = this._strategy; | ||
const { cacheName, matchOptions } = this._strategy; | ||
const cache = await self.caches.open(cacheName); | ||
const oldResponse = this.hasCallback('cacheDidUpdate') ? | ||
await this.cacheMatch(request) : null; | ||
const hasCacheUpdateCallback = this.hasCallback('cacheDidUpdate'); | ||
const oldResponse = hasCacheUpdateCallback ? await cacheMatchIgnoreParams( | ||
// TODO(philipwalton): the `__WB_REVISION__` param is a precaching | ||
// feature. Consider into ways to only add this behavior if using | ||
// precaching. | ||
cache, effectiveRequest.clone(), ['__WB_REVISION__'], matchOptions) : | ||
null; | ||
if (process.env.NODE_ENV !== 'production') { | ||
@@ -212,3 +314,4 @@ logger.debug(`Updating the '${cacheName}' cache with a new Response ` + | ||
try { | ||
await cache.put(effectiveRequest, responseToCache); | ||
await cache.put(effectiveRequest, hasCacheUpdateCallback ? | ||
responseToCache.clone() : responseToCache); | ||
} | ||
@@ -222,11 +325,39 @@ catch (error) { | ||
} | ||
await this.runCallbacks('cacheDidUpdate', { | ||
cacheName, | ||
oldResponse, | ||
newResponse: responseToCache, | ||
request: effectiveRequest, | ||
event: this.event, | ||
}); | ||
for (const callback of this.iterateCallbacks('cacheDidUpdate')) { | ||
await callback({ | ||
cacheName, | ||
oldResponse, | ||
newResponse: responseToCache.clone(), | ||
request: effectiveRequest, | ||
event: this.event, | ||
}); | ||
} | ||
} | ||
/** | ||
* Checks the list of plugins for the `cacheKeyWillBeUsed` callback, and | ||
* executes any of those callbacks found in sequence. The final `Request` | ||
* object returned by the last plugin is treated as the cache key for cache | ||
* reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have | ||
* been registered, the passed request is returned unmodified | ||
* | ||
* @param {Request} request | ||
* @param {string} mode | ||
* @return {Promise<Request>} | ||
*/ | ||
async getCacheKey(request, mode) { | ||
if (!this._cacheKeys[mode]) { | ||
let effectiveRequest = request; | ||
for (const callback of this.iterateCallbacks('cacheKeyWillBeUsed')) { | ||
effectiveRequest = toRequest(await callback({ | ||
mode, | ||
request: effectiveRequest, | ||
event: this.event, | ||
params: this.params, | ||
})); | ||
} | ||
this._cacheKeys[mode] = effectiveRequest; | ||
} | ||
return this._cacheKeys[mode]; | ||
} | ||
/** | ||
* Returns true if the strategy has at least one plugin with the given | ||
@@ -292,74 +423,2 @@ * callback. | ||
} | ||
// An async function version of `fetch()`, making it easier for that | ||
// function to add a promise to `waitUntil()`. | ||
async _fetch(input) { | ||
const { event } = this; | ||
let request = toRequest(input); | ||
if (request.mode === 'navigate' && | ||
event instanceof FetchEvent && | ||
event.preloadResponse) { | ||
const possiblePreloadResponse = await event.preloadResponse; | ||
if (possiblePreloadResponse) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.log(`Using a preloaded navigation response for ` + | ||
`'${getFriendlyURL(request.url)}'`); | ||
} | ||
return possiblePreloadResponse; | ||
} | ||
} | ||
// If there is a fetchDidFail plugin, we need to save a clone of the | ||
// original request before it's either modified by a requestWillFetch | ||
// plugin or before the original request's body is consumed via fetch(). | ||
const originalRequest = this.hasCallback('fetchDidFail') ? | ||
request.clone() : null; | ||
try { | ||
for (const cb of this.iterateCallbacks('requestWillFetch')) { | ||
request = await cb({ request: request.clone(), event }); | ||
} | ||
} | ||
catch (err) { | ||
throw new WorkboxError('plugin-error-request-will-fetch', { | ||
thrownError: err, | ||
}); | ||
} | ||
// The request can be altered by plugins with `requestWillFetch` making | ||
// the original request (most likely from a `fetch` event) different | ||
// from the Request we make. Pass both to `fetchDidFail` to aid debugging. | ||
const pluginFilteredRequest = request.clone(); | ||
try { | ||
let fetchResponse; | ||
// See https://github.com/GoogleChrome/workbox/issues/1796 | ||
fetchResponse = await fetch(request, request.mode === 'navigate' ? | ||
undefined : this._strategy.fetchOptions); | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.debug(`Network request for ` + | ||
`'${getFriendlyURL(request.url)}' returned a response with ` + | ||
`status '${fetchResponse.status}'.`); | ||
} | ||
for (const callback of this.iterateCallbacks('fetchDidSucceed')) { | ||
fetchResponse = await callback({ | ||
event, | ||
request: pluginFilteredRequest, | ||
response: fetchResponse, | ||
}); | ||
} | ||
return fetchResponse; | ||
} | ||
catch (error) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
logger.error(`Network request for ` + | ||
`'${getFriendlyURL(request.url)}' threw an error.`, error); | ||
} | ||
// `originalRequest` will only exist if there's a `fetchDidFail` callback. | ||
if (originalRequest) { | ||
await this.runCallbacks('fetchDidFail', { | ||
error, | ||
event, | ||
originalRequest: originalRequest.clone(), | ||
request: pluginFilteredRequest.clone(), | ||
}); | ||
} | ||
throw error; | ||
} | ||
} | ||
/** | ||
@@ -405,54 +464,3 @@ * Adds a promise to the | ||
} | ||
// An async function version of `cacheMatch()`, making it easier for that | ||
// function to add a promise to `waitUntil()`. | ||
async _cacheMatch(key) { | ||
const request = toRequest(key); | ||
let cachedResponse; | ||
const { cacheName, matchOptions } = this._strategy; | ||
const effectiveRequest = await this._getEffectiveRequest(request, 'read'); | ||
cachedResponse = await caches.match(effectiveRequest, { ...matchOptions, ...{ cacheName } }); | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (cachedResponse) { | ||
logger.debug(`Found a cached response in '${cacheName}'.`); | ||
} | ||
else { | ||
logger.debug(`No cached response found in '${cacheName}'.`); | ||
} | ||
} | ||
for (const callback of this.iterateCallbacks('cachedResponseWillBeUsed')) { | ||
cachedResponse = (await callback({ | ||
cacheName, | ||
matchOptions, | ||
cachedResponse, | ||
request: effectiveRequest, | ||
event: this.event, | ||
})) || undefined; | ||
} | ||
return cachedResponse; | ||
} | ||
/** | ||
* Checks the list of plugins for the cacheKeyWillBeUsed callback, and | ||
* executes any of those callbacks found in sequence. The final `Request` | ||
* object returned by the last plugin is treated as the cache key for cache | ||
* reads and/or writes. | ||
* | ||
* @param {Request} request | ||
* @param {string} mode | ||
* @return {Promise<Request>} | ||
* | ||
* @private | ||
*/ | ||
async _getEffectiveRequest(request, mode) { | ||
let effectiveRequest = request; | ||
for (const callback of this.iterateCallbacks('cacheKeyWillBeUsed')) { | ||
effectiveRequest = toRequest(await callback({ | ||
mode, | ||
request: effectiveRequest, | ||
event: this.event, | ||
params: this.params, | ||
})); | ||
} | ||
return effectiveRequest; | ||
} | ||
/** | ||
* This method will call cacheWillUpdate on the available plugins (or use | ||
@@ -459,0 +467,0 @@ * status === 200) to determine if the Response is safe and valid to cache. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 2 instances in 1 package
4510
401556
Updatedworkbox-core@^6.0.0-alpha.3