Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

workbox-precaching

Package Overview
Dependencies
Maintainers
4
Versions
96
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

workbox-precaching - npm Package Compare versions

Comparing version 5.1.3 to 6.0.0-alpha.0

PrecacheFallbackPlugin.d.ts

6

_types.d.ts

@@ -14,2 +14,8 @@ import './_version.js';

}
export interface FetchListenerOptions {
directoryIndex?: string;
ignoreURLParametersMatching?: RegExp[];
cleanURLs?: boolean;
urlManipulation?: urlManipulation;
}
export declare type urlManipulation = ({ url }: {

@@ -16,0 +22,0 @@ url: URL;

6

addPlugins.d.ts
import { WorkboxPlugin } from 'workbox-core/types.js';
import './_version.js';
/**
* Adds plugins to precaching.
* Adds plugins to the precaching strategy.
*
* @param {Array<Object>} newPlugins
* @param {Array<Object>} plugins
*
* @memberof module:workbox-precaching
*/
declare function addPlugins(newPlugins: WorkboxPlugin[]): void;
declare function addPlugins(plugins: WorkboxPlugin[]): void;
export { addPlugins };

@@ -8,14 +8,15 @@ /*

*/
import { precachePlugins } from './utils/precachePlugins.js';
import { getOrCreatePrecacheController } from './utils/getOrCreatePrecacheController.js';
import './_version.js';
/**
* Adds plugins to precaching.
* Adds plugins to the precaching strategy.
*
* @param {Array<Object>} newPlugins
* @param {Array<Object>} plugins
*
* @memberof module:workbox-precaching
*/
function addPlugins(newPlugins) {
precachePlugins.add(newPlugins);
function addPlugins(plugins) {
const precacheController = getOrCreatePrecacheController();
return precacheController.addPlugins(plugins);
}
export { addPlugins };

@@ -1,2 +0,2 @@

import { FetchListenerOptions } from './utils/addFetchListener.js';
import { FetchListenerOptions } from './_types.js';
import './_version.js';

@@ -17,3 +17,3 @@ /**

* appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An
* array of regex's to remove search params when looking for a cache match.

@@ -20,0 +20,0 @@ * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will

@@ -7,5 +7,4 @@ /*

*/
import { addFetchListener } from './utils/addFetchListener.js';
import { getOrCreatePrecacheController } from './utils/getOrCreatePrecacheController.js';
import './_version.js';
let listenerAdded = false;
/**

@@ -25,3 +24,3 @@ * Add a `fetch` listener to the service worker that will

* appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An
* array of regex's to remove search params when looking for a cache match.

@@ -37,7 +36,5 @@ * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will

function addRoute(options) {
if (!listenerAdded) {
addFetchListener(options);
listenerAdded = true;
}
const precacheController = getOrCreatePrecacheController();
return precacheController.addRoute(options);
}
export { addRoute };
this.workbox = this.workbox || {};
this.workbox.precaching = (function (exports, cacheNames_js, getFriendlyURL_js, logger_js, assert_js, cacheWrapper_js, fetchWrapper_js, WorkboxError_js, copyResponse_js) {
this.workbox.precaching = (function (exports, assert_js, cacheNames_js, getFriendlyURL_js, logger_js, WorkboxError_js, Route_js, Router_js, copyResponse_js, Strategy_js) {
'use strict';

@@ -10,48 +10,2 @@

/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const plugins = [];
const precachePlugins = {
/*
* @return {Array}
* @private
*/
get() {
return plugins;
},
/*
* @param {Array} newPlugins
* @private
*/
add(newPlugins) {
plugins.push(...newPlugins);
}
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Adds plugins to precaching.
*
* @param {Array<Object>} newPlugins
*
* @memberof module:workbox-precaching
*/
function addPlugins(newPlugins) {
precachePlugins.add(newPlugins);
}
/*
Copyright 2018 Google LLC

@@ -125,2 +79,118 @@

/*
Copyright 2020 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const copyRedirectedCacheableResponsesPlugin = {
async cacheWillUpdate({
response
}) {
return response.redirected ? await copyResponse_js.copyResponse(response) : response;
}
};
class PrecacheStrategy extends Strategy_js.Strategy {
constructor(options) {
super(options); // Redirected responses cannot be used to satisfy a navigation request, so
// any redirected response must be "copied" rather than cloned, so the new
// response doesn't contain the `redirected` flag. See:
// https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1
this.plugins.push(copyRedirectedCacheableResponsesPlugin);
}
_handle(request, handler) {
// If this is an `install` event then populate the cache. If this is a
// `fetch` event (or any other event) then respond with the cached response.
if (handler.event && handler.event.type === 'install') {
return this._handleInstall(request, handler);
}
return this._handleFetch(request, handler);
}
async _handleFetch(request, handler) {
let response = await handler.cacheMatch(request);
if (!response) {
// Fall back to the network if we don't have a cached response
// (perhaps due to manual cache cleanup).
if (handler.params && handler.params.fallbackToNetwork === false) {
// This shouldn't normally happen, but there are edge cases:
// https://github.com/GoogleChrome/workbox/issues/1441
throw new WorkboxError_js.WorkboxError('missing-precache-entry', {
cacheName: this.cacheName,
url: request.url
});
} else {
{
logger_js.logger.warn(`The precached response for ` + `${getFriendlyURL_js.getFriendlyURL(request.url)} in ${this.cacheName} was not ` + `found. Falling back to the network instead.`);
}
response = await handler.fetch(request);
}
}
{
// Workbox is going to handle the route.
// print the routing details to the console.
logger_js.logger.groupCollapsed(`Precaching is responding to: ` + getFriendlyURL_js.getFriendlyURL(request.url));
logger_js.logger.log(`Serving the precached url: ` + handler.params.cacheKey);
logger_js.logger.groupCollapsed(`View request details here.`);
logger_js.logger.log(request);
logger_js.logger.groupEnd();
logger_js.logger.groupCollapsed(`View response details here.`);
logger_js.logger.log(response);
logger_js.logger.groupEnd();
logger_js.logger.groupEnd();
}
return response;
}
async _handleInstall(request, handler) {
const response = await handler.fetchAndCachePut(request); // Any time there's no response, consider it a precaching error.
let responseSafeToPrecache = Boolean(response); // Also consider it an error if the user didn't pass their own
// cacheWillUpdate plugin, and the response is a 400+ (note: this means
// that by default opaque responses can be precached).
if (response && response.status >= 400 && !this._usesCustomCacheableResponseLogic()) {
responseSafeToPrecache = false;
}
if (!responseSafeToPrecache) {
// Throwing here will lead to the `install` handler failing, which
// we want to do if *any* of the responses aren't safe to cache.
throw new WorkboxError_js.WorkboxError('bad-precaching-response', {
url: request.url,
status: response.status
});
}
return response;
}
/**
* Returns true if any users plugins were added containing their own
* `cacheWillUpdate` callback.
*
* This method indicates whether the default cacheable response logic (i.e.
* <400, including opaque responses) should be used. If a custom plugin
* with a `cacheWillUpdate` callback is passed, then the strategy should
* defer to that plugin's logic.
*
* @private
*/
_usesCustomCacheableResponseLogic() {
return this.plugins.some(plugin => plugin.cacheWillUpdate && plugin !== copyRedirectedCacheableResponsesPlugin);
}
}
/*
Copyright 2018 Google LLC

@@ -224,2 +294,34 @@

/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Removes any URL search parameters that should be ignored.
*
* @param {URL} urlObject The original URL.
* @param {Array<RegExp>} ignoreURLParametersMatching RegExps to test against
* each search parameter name. Matches mean that the search parameter should be
* ignored.
* @return {URL} The URL with any ignored search parameters removed.
*
* @private
* @memberof module:workbox-precaching
*/
function removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching = []) {
// Convert the iterable into an array at the start of the loop to make sure
// deletion doesn't mess up iteration.
for (const paramName of [...urlObject.searchParams.keys()]) {
if (ignoreURLParametersMatching.some(regExp => regExp.test(paramName))) {
urlObject.searchParams.delete(paramName);
}
}
return urlObject;
}
/*
Copyright 2019 Google LLC

@@ -232,2 +334,55 @@

/**
* Generator function that yields possible variations on the original URL to
* check, one at a time.
*
* @param {string} url
* @param {Object} options
*
* @private
* @memberof module:workbox-precaching
*/
function* generateURLVariations(url, {
ignoreURLParametersMatching = [/^utm_/, /^fbclid$/],
directoryIndex = 'index.html',
cleanURLs = true,
urlManipulation
} = {}) {
const urlObject = new URL(url, location.href);
urlObject.hash = '';
yield urlObject.href;
const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching);
yield urlWithoutIgnoredParams.href;
if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith('/')) {
const directoryURL = new URL(urlWithoutIgnoredParams.href);
directoryURL.pathname += directoryIndex;
yield directoryURL.href;
}
if (cleanURLs) {
const cleanURL = new URL(urlWithoutIgnoredParams.href);
cleanURL.pathname += '.html';
yield cleanURL.href;
}
if (urlManipulation) {
const additionalURLs = urlManipulation({
url: urlObject
});
for (const urlToAttempt of additionalURLs) {
yield urlToAttempt.href;
}
}
}
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Performs efficient precaching of assets.

@@ -246,2 +401,4 @@ *

constructor(cacheName) {
this._installed = false;
this._plugins = [];
this._cacheName = cacheNames_js.cacheNames.getPrecacheName(cacheName);

@@ -251,10 +408,112 @@ this._urlsToCacheKeys = new Map();

this._cacheKeysToIntegrities = new Map();
this._cacheKeyPlugin = {
cacheKeyWillBeUsed: async ({
request,
params
}) => {
const cacheKey = params && params.cacheKey || this.getCacheKeyForURL(request.url);
return cacheKey || request;
}
};
}
/**
* Adds plugins to the precaching strategy.
*
* @param {Array<Object>} plugins
*/
addPlugins(plugins) {
this._plugins.push(...plugins);
}
/**
* Creates a Workbox `Route` to handle requests for precached assets (based
* on the passed configuration options).
*
* @param {Object} [options]
* @param {string} [options.directoryIndex=index.html] The `directoryIndex`
* will check cache entries for a URLs ending with '/' to see if there is a
* hit when appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An
* array of regex's to remove search params when looking for a cache match.
* @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
* check the cache for the URL with a `.html` added to the end of the end.
* @param {module:workbox-precaching~urlManipulation} [options.urlManipulation]
* This is a function that should take a URL and return an array of
* alternative URLs that should be checked for precache matches.
*/
addRoute(options) {
if (!this._router) {
const matchCallback = this.createMatchCallback(options);
const handlerCallback = this.createHandler(true);
const route = new Route_js.Route(matchCallback, handlerCallback);
const router = new Router_js.Router();
router.registerRoute(route);
router.addFetchListener();
router.addCacheListener();
this._router = router;
}
}
/**
* Adds items to the precache list, removing any duplicates and
* stores the files in the
* ["precache cache"]{@link module:workbox-core.cacheNames} when the service
* worker installs.
*
* This method can be called multiple times.
*
* Please note: This method **will not** serve any of the cached files for you.
* It only precaches files. To respond to a network request you call
* [addRoute()]{@link module:workbox-precaching.PreacheController#addRoute}.
*
* If you have a single array of files to precache, you can just call
* [precacheAndRoute()]{@link module:workbox-precaching.precacheAndRoute}.
*
* @param {Array<Object|string>} [entries=[]] Array of entries to precache.
*/
precache(entries) {
this.addToCacheList(entries);
if (!this._installed) {
self.addEventListener('install', event => {
event.waitUntil(this.install({
event
}));
});
self.addEventListener('activate', event => {
event.waitUntil(this.activate());
});
this._installed = true;
}
}
/**
* This method will add entries to the precache list and add a route to
* respond to fetch events.
*
* This is a convenience method that will call
* [precache()]{@link module:workbox-precaching.PrecacheController#precache}
* and
* [addRoute()]{@link module:workbox-precaching.PrecacheController#addRoute}
* in a single call.
*
* @param {Array<Object|string>} entries Array of entries to precache.
* @param {Object} [options] See
* [addRoute() options]{@link module:workbox-precaching.PrecacheController#addRoute}.
*/
precacheAndRoute(entries, options) {
this.precache(entries);
this.addRoute(options);
}
/**
* This method will add items to the precache list, removing duplicates
* and ensuring the information is valid.
*
* @param {
* Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>
* } entries Array of entries to precache.
* @param {Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>} entries
* Array of entries to precache.
*/

@@ -324,3 +583,3 @@

* @param {Object} options
* @param {Event} [options.event] The install event (if needed).
* @param {Event} options.event The install event.
* @param {Array<Object>} [options.plugins] Plugins to be used for fetching

@@ -335,3 +594,3 @@ * and caching during install.

plugins
} = {}) {
}) {
{

@@ -348,2 +607,6 @@ if (plugins) {

if (plugins) {
this.addPlugins(plugins);
}
const toBePrecached = [];

@@ -364,8 +627,10 @@ const alreadyPrecached = [];

}
}
} // Cache entries one at a time.
// See https://github.com/GoogleChrome/workbox/issues/2528
const precacheRequests = toBePrecached.map(({
for (const {
cacheKey,
url
}) => {
} of toBePrecached) {
const integrity = this._cacheKeysToIntegrities.get(cacheKey);

@@ -375,3 +640,3 @@

return this._addURLToCache({
await this._addURLToCache({
cacheKey,

@@ -381,7 +646,6 @@ cacheMode,

integrity,
plugins,
url
});
});
await Promise.all(precacheRequests);
}
const updatedURLs = toBePrecached.map(item => item.url);

@@ -440,6 +704,4 @@

* @param {string} options.url The URL to fetch and cache.
* @param {Event} options.event The install event.
* @param {string} [options.cacheMode] The cache mode for the network request.
* @param {Event} [options.event] The install event (if passed).
* @param {Array<Object>} [options.plugins] An array of plugins to apply to
* fetch and caching.
* @param {string} [options.integrity] The value to use for the `integrity`

@@ -455,3 +717,2 @@ * field when making the request.

event,
plugins,
integrity

@@ -464,56 +725,9 @@ }) {

});
let response = await fetchWrapper_js.fetchWrapper.fetch({
event,
plugins,
request
}); // Allow developers to override the default logic about what is and isn't
// valid by passing in a plugin implementing cacheWillUpdate(), e.g.
// a `CacheableResponsePlugin` instance.
let cacheWillUpdatePlugin;
for (const plugin of plugins || []) {
if ('cacheWillUpdate' in plugin) {
cacheWillUpdatePlugin = plugin;
}
}
const isValidResponse = cacheWillUpdatePlugin ? // Use a callback if provided. It returns a truthy value if valid.
// NOTE: invoke the method on the plugin instance so the `this` context
// is correct.
await cacheWillUpdatePlugin.cacheWillUpdate({
event,
await Promise.all(this._getStrategy().handleAll({
params: {
cacheKey
},
request,
response
}) : // Otherwise, default to considering any response status under 400 valid.
// This includes, by default, considering opaque responses valid.
response.status < 400; // Consider this a failure, leading to the `install` handler failing, if
// we get back an invalid response.
if (!isValidResponse) {
throw new WorkboxError_js.WorkboxError('bad-precaching-response', {
url,
status: response.status
});
} // Redirected responses cannot be used to satisfy a navigation request, so
// any redirected response must be "copied" rather than cloned, so the new
// response doesn't contain the `redirected` flag. See:
// https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1
if (response.redirected) {
response = await copyResponse_js.copyResponse(response);
}
await cacheWrapper_js.cacheWrapper.put({
event,
plugins,
response,
// `request` already uses `url`. We may be able to reuse it.
request: cacheKey === url ? request : new Request(cacheKey),
cacheName: this._cacheName,
matchOptions: {
ignoreSearch: true
}
});
event
}));
}

@@ -558,3 +772,4 @@ /**

/**
* This acts as a drop-in replacement for [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
* This acts as a drop-in replacement for
* [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
* with the following differences:

@@ -589,2 +804,40 @@ *

/**
* Creates a [`matchCallback`]{@link module:workbox-precaching~matchCallback}
* based on the passed configuration options) that with will identify
* requests in the precache and return a respective `params` object
* containing the `cacheKey` of the precached asset.
*
* This `cacheKey` can be used by a
* [`handlerCallback`]{@link module:workbox-precaching~handlerCallback}
* to get the precached asset from the cache.
*
* @param {Object} [options] See
* [addRoute() options]{@link module:workbox-precaching.PrecacheController#addRoute}.
*/
createMatchCallback(options) {
return ({
request
}) => {
const urlsToCacheKeys = this.getURLsToCacheKeys();
for (const possibleURL of generateURLVariations(request.url, options)) {
const cacheKey = urlsToCacheKeys.get(possibleURL);
if (cacheKey) {
return {
cacheKey
};
}
}
{
logger_js.logger.debug(`Precaching did not find a match for ` + getFriendlyURL_js.getFriendlyURL(request.url));
}
return;
};
}
/**
* Returns a function that can be used within a

@@ -605,29 +858,12 @@ * {@link module:workbox-routing.Route} that will find a response for the

createHandler(fallbackToNetwork = true) {
return async ({
request
}) => {
try {
const response = await this.matchPrecache(request);
return options => {
const request = options.request instanceof Request ? options.request : new Request(options.request);
options.params = options.params || {};
options.params.fallbackToNetwork = fallbackToNetwork;
if (response) {
return response;
} // This shouldn't normally happen, but there are edge cases:
// https://github.com/GoogleChrome/workbox/issues/1441
if (!options.params.cacheKey) {
options.params.cacheKey = this.getCacheKeyForURL(request.url);
}
throw new WorkboxError_js.WorkboxError('missing-precache-entry', {
cacheName: this._cacheName,
url: request instanceof Request ? request.url : request
});
} catch (error) {
if (fallbackToNetwork) {
{
logger_js.logger.debug(`Unable to respond with precached response. ` + `Falling back to network.`, error);
}
return fetch(request);
}
throw error;
}
return this._getStrategy().handle(options);
};

@@ -662,7 +898,23 @@ }

const request = new Request(url);
return () => handler({
return options => handler(Object.assign(options, {
request
});
}));
}
_getStrategy() {
// NOTE: this needs to be done lazily to match v5 behavior, since the
// `addPlugins()` method can be called at any time.
if (!this._strategy) {
this._strategy = new PrecacheStrategy({
cacheName: this._cacheName,
matchOptions: {
ignoreSearch: true
},
plugins: [this._cacheKeyPlugin, ...this._plugins]
});
}
return this._strategy;
}
}

@@ -692,34 +944,2 @@

/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Removes any URL search parameters that should be ignored.
*
* @param {URL} urlObject The original URL.
* @param {Array<RegExp>} ignoreURLParametersMatching RegExps to test against
* each search parameter name. Matches mean that the search parameter should be
* ignored.
* @return {URL} The URL with any ignored search parameters removed.
*
* @private
* @memberof module:workbox-precaching
*/
function removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching = []) {
// Convert the iterable into an array at the start of the loop to make sure
// deletion doesn't mess up iteration.
for (const paramName of [...urlObject.searchParams.keys()]) {
if (ignoreURLParametersMatching.some(regExp => regExp.test(paramName))) {
urlObject.searchParams.delete(paramName);
}
}
return urlObject;
}
/*
Copyright 2019 Google LLC

@@ -732,45 +952,12 @@

/**
* Generator function that yields possible variations on the original URL to
* check, one at a time.
* Adds plugins to the precaching strategy.
*
* @param {string} url
* @param {Object} options
* @param {Array<Object>} plugins
*
* @private
* @memberof module:workbox-precaching
*/
function* generateURLVariations(url, {
ignoreURLParametersMatching,
directoryIndex,
cleanURLs,
urlManipulation
} = {}) {
const urlObject = new URL(url, location.href);
urlObject.hash = '';
yield urlObject.href;
const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching);
yield urlWithoutIgnoredParams.href;
if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith('/')) {
const directoryURL = new URL(urlWithoutIgnoredParams.href);
directoryURL.pathname += directoryIndex;
yield directoryURL.href;
}
if (cleanURLs) {
const cleanURL = new URL(urlWithoutIgnoredParams.href);
cleanURL.pathname += '.html';
yield cleanURL.href;
}
if (urlManipulation) {
const additionalURLs = urlManipulation({
url: urlObject
});
for (const urlToAttempt of additionalURLs) {
yield urlToAttempt.href;
}
}
function addPlugins(plugins) {
const precacheController = getOrCreatePrecacheController();
return precacheController.addPlugins(plugins);
}

@@ -780,3 +967,2 @@

Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style

@@ -787,130 +973,2 @@ license that can be found in the LICENSE file or at

/**
* This function will take the request URL and manipulate it based on the
* configuration options.
*
* @param {string} url
* @param {Object} options
* @return {string} Returns the URL in the cache that matches the request,
* if possible.
*
* @private
*/
const getCacheKeyForURL = (url, options) => {
const precacheController = getOrCreatePrecacheController();
const urlsToCacheKeys = precacheController.getURLsToCacheKeys();
for (const possibleURL of generateURLVariations(url, options)) {
const possibleCacheKey = urlsToCacheKeys.get(possibleURL);
if (possibleCacheKey) {
return possibleCacheKey;
}
}
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Adds a `fetch` listener to the service worker that will
* respond to
* [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests}
* with precached assets.
*
* Requests for assets that aren't precached, the `FetchEvent` will not be
* responded to, allowing the event to fall through to other `fetch` event
* listeners.
*
* NOTE: when called more than once this method will replace the previously set
* configuration options. Calling it more than once is not recommended outside
* of tests.
*
* @private
* @param {Object} [options]
* @param {string} [options.directoryIndex=index.html] The `directoryIndex` will
* check cache entries for a URLs ending with '/' to see if there is a hit when
* appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
* array of regex's to remove search params when looking for a cache match.
* @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
* check the cache for the URL with a `.html` added to the end of the end.
* @param {workbox.precaching~urlManipulation} [options.urlManipulation]
* This is a function that should take a URL and return an array of
* alternative URLs that should be checked for precache matches.
*/
const addFetchListener = ({
ignoreURLParametersMatching = [/^utm_/],
directoryIndex = 'index.html',
cleanURLs = true,
urlManipulation
} = {}) => {
const cacheName = cacheNames_js.cacheNames.getPrecacheName(); // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
self.addEventListener('fetch', event => {
const precachedURL = getCacheKeyForURL(event.request.url, {
cleanURLs,
directoryIndex,
ignoreURLParametersMatching,
urlManipulation
});
if (!precachedURL) {
{
logger_js.logger.debug(`Precaching did not find a match for ` + getFriendlyURL_js.getFriendlyURL(event.request.url));
}
return;
}
let responsePromise = self.caches.open(cacheName).then(cache => {
return cache.match(precachedURL);
}).then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
} // Fall back to the network if we don't have a cached response
// (perhaps due to manual cache cleanup).
{
logger_js.logger.warn(`The precached response for ` + `${getFriendlyURL_js.getFriendlyURL(precachedURL)} in ${cacheName} was not found. ` + `Falling back to the network instead.`);
}
return fetch(precachedURL);
});
{
responsePromise = responsePromise.then(response => {
// Workbox is going to handle the route.
// print the routing details to the console.
logger_js.logger.groupCollapsed(`Precaching is responding to: ` + getFriendlyURL_js.getFriendlyURL(event.request.url));
logger_js.logger.log(`Serving the precached url: ${precachedURL}`);
logger_js.logger.groupCollapsed(`View request details here.`);
logger_js.logger.log(event.request);
logger_js.logger.groupEnd();
logger_js.logger.groupCollapsed(`View response details here.`);
logger_js.logger.log(response);
logger_js.logger.groupEnd();
logger_js.logger.groupEnd();
return response;
});
}
event.respondWith(responsePromise);
});
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
let listenerAdded = false;
/**
* Add a `fetch` listener to the service worker that will

@@ -929,3 +987,3 @@ * respond to

* appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An
* array of regex's to remove search params when looking for a cache match.

@@ -942,6 +1000,4 @@ * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will

function addRoute(options) {
if (!listenerAdded) {
addFetchListener(options);
listenerAdded = true;
}
const precacheController = getOrCreatePrecacheController();
return precacheController.addRoute(options);
}

@@ -1098,3 +1154,3 @@

function getCacheKeyForURL$1(url) {
function getCacheKeyForURL(url) {
const precacheController = getOrCreatePrecacheController();

@@ -1139,23 +1195,2 @@ return precacheController.getCacheKeyForURL(url);

*/
const installListener = event => {
const precacheController = getOrCreatePrecacheController();
const plugins = precachePlugins.get();
event.waitUntil(precacheController.install({
event,
plugins
}).catch(error => {
{
logger_js.logger.error(`Service worker installation failed. It will ` + `be retried automatically during the next navigation.`);
} // Re-throw the error to ensure installation fails.
throw error;
}));
};
const activateListener = event => {
const precacheController = getOrCreatePrecacheController();
event.waitUntil(precacheController.activate());
};
/**

@@ -1181,15 +1216,5 @@ * Adds items to the precache list, removing any duplicates and

function precache(entries) {
const precacheController = getOrCreatePrecacheController();
precacheController.addToCacheList(entries);
if (entries.length > 0) {
// NOTE: these listeners will only be added once (even if the `precache()`
// method is called multiple times) because event listeners are implemented
// as a set, where each listener must be unique.
// See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
self.addEventListener('install', installListener);
self.addEventListener('activate', activateListener);
}
precacheController.precache(entries);
}

@@ -1220,7 +1245,58 @@

function precacheAndRoute(entries, options) {
precache(entries);
addRoute(options);
const precacheController = getOrCreatePrecacheController();
precacheController.precacheAndRoute(entries, options);
}
/*
Copyright 2020 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* `PrecacheFallbackPlugin` allows you to specify an "offline fallback"
* response to be used when a given strategy is unable to generate a response.
*
* It does this by intercepting the `handlerDidError` plugin callback
* and returning a precached response, taking the expected revision parameter
* into account automatically.
*
* Unless you explicitly pass in a `PrecacheController` instance to the
* constructor, the default instance will be used. Generally speaking, most
* developers will end up using the default.
*
* @memberof module:workbox-precaching
*/
class PrecacheFallbackPlugin {
/**
* Constructs a new PrecacheFallbackPlugin with the associated fallbackURL.
*
* @param {Object} config
* @param {string} config.fallbackURL A precached URL to use as the fallback
* if the associated strategy can't generate a response.
* @param {PrecacheController} [config.precacheController] An optional
* PrecacheController instance. If not provided, the default
* PrecacheController will be used.
*/
constructor({
fallbackURL,
precacheController
}) {
/**
* @return {Promise<Response>} The precache response for the fallback URL.
*
* @private
*/
this.handlerDidError = () => this._precacheController.matchPrecache(this._fallbackURL);
this._fallbackURL = fallbackURL;
this._precacheController = precacheController || getOrCreatePrecacheController();
}
}
exports.PrecacheController = PrecacheController;
exports.PrecacheFallbackPlugin = PrecacheFallbackPlugin;
exports.addPlugins = addPlugins;

@@ -1231,3 +1307,3 @@ exports.addRoute = addRoute;

exports.createHandlerBoundToURL = createHandlerBoundToURL;
exports.getCacheKeyForURL = getCacheKeyForURL$1;
exports.getCacheKeyForURL = getCacheKeyForURL;
exports.matchPrecache = matchPrecache;

@@ -1239,3 +1315,3 @@ exports.precache = precache;

}({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core));
}({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.routing, workbox.routing, workbox.core, workbox.strategies));
//# sourceMappingURL=workbox-precaching.dev.js.map

@@ -1,2 +0,2 @@

this.workbox=this.workbox||{},this.workbox.precaching=function(t,e,n,i,s,c){"use strict";try{self["workbox:precaching:5.1.3"]&&_()}catch(t){}const r=[],o={get:()=>r,add(t){r.push(...t)}};function a(t){if(!t)throw new s.WorkboxError("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location.href);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new s.WorkboxError("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location.href);return{cacheKey:t.href,url:t.href}}const i=new URL(n,location.href),c=new URL(n,location.href);return i.searchParams.set("__WB_REVISION__",e),{cacheKey:i.href,url:c.href}}class h{constructor(t){this.t=e.cacheNames.getPrecacheName(t),this.i=new Map,this.s=new Map,this.o=new Map}addToCacheList(t){const e=[];for(const n of t){"string"==typeof n?e.push(n):n&&void 0===n.revision&&e.push(n.url);const{cacheKey:t,url:i}=a(n),c="string"!=typeof n&&n.revision?"reload":"default";if(this.i.has(i)&&this.i.get(i)!==t)throw new s.WorkboxError("add-to-cache-list-conflicting-entries",{firstEntry:this.i.get(i),secondEntry:t});if("string"!=typeof n&&n.integrity){if(this.o.has(t)&&this.o.get(t)!==n.integrity)throw new s.WorkboxError("add-to-cache-list-conflicting-integrities",{url:i});this.o.set(t,n.integrity)}if(this.i.set(i,t),this.s.set(i,c),e.length>0){const t="Workbox is precaching URLs without revision "+`info: ${e.join(", ")}\nThis is generally NOT safe. `+"Learn more at https://bit.ly/wb-precache";console.warn(t)}}}async install({event:t,plugins:e}={}){const n=[],i=[],s=await self.caches.open(this.t),c=await s.keys(),r=new Set(c.map(t=>t.url));for(const[t,e]of this.i)r.has(e)?i.push(t):n.push({cacheKey:e,url:t});const o=n.map(({cacheKey:n,url:i})=>{const s=this.o.get(n),c=this.s.get(i);return this.h({cacheKey:n,cacheMode:c,event:t,integrity:s,plugins:e,url:i})});return await Promise.all(o),{updatedURLs:n.map(t=>t.url),notUpdatedURLs:i}}async activate(){const t=await self.caches.open(this.t),e=await t.keys(),n=new Set(this.i.values()),i=[];for(const s of e)n.has(s.url)||(await t.delete(s),i.push(s.url));return{deletedURLs:i}}async h({cacheKey:t,url:e,cacheMode:r,event:o,plugins:a,integrity:h}){const u=new Request(e,{integrity:h,cache:r,credentials:"same-origin"});let l,f=await i.fetchWrapper.fetch({event:o,plugins:a,request:u});for(const t of a||[])"cacheWillUpdate"in t&&(l=t);if(!(l?await l.cacheWillUpdate({event:o,request:u,response:f}):f.status<400))throw new s.WorkboxError("bad-precaching-response",{url:e,status:f.status});f.redirected&&(f=await c.copyResponse(f)),await n.cacheWrapper.put({event:o,plugins:a,response:f,request:t===e?u:new Request(t),cacheName:this.t,matchOptions:{ignoreSearch:!0}})}getURLsToCacheKeys(){return this.i}getCachedURLs(){return[...this.i.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.i.get(e.href)}async matchPrecache(t){const e=t instanceof Request?t.url:t,n=this.getCacheKeyForURL(e);if(n){return(await self.caches.open(this.t)).match(n)}}createHandler(t=!0){return async({request:e})=>{try{const t=await this.matchPrecache(e);if(t)return t;throw new s.WorkboxError("missing-precache-entry",{cacheName:this.t,url:e instanceof Request?e.url:e})}catch(n){if(t)return fetch(e);throw n}}}createHandlerBoundToURL(t,e=!0){if(!this.getCacheKeyForURL(t))throw new s.WorkboxError("non-precached-url",{url:t});const n=this.createHandler(e),i=new Request(t);return()=>n({request:i})}}let u;const l=()=>(u||(u=new h),u);const f=(t,e)=>{const n=l().getURLsToCacheKeys();for(const i of function*(t,{ignoreURLParametersMatching:e,directoryIndex:n,cleanURLs:i,urlManipulation:s}={}){const c=new URL(t,location.href);c.hash="",yield c.href;const r=function(t,e=[]){for(const n of[...t.searchParams.keys()])e.some(t=>t.test(n))&&t.searchParams.delete(n);return t}(c,e);if(yield r.href,n&&r.pathname.endsWith("/")){const t=new URL(r.href);t.pathname+=n,yield t.href}if(i){const t=new URL(r.href);t.pathname+=".html",yield t.href}if(s){const t=s({url:c});for(const e of t)yield e.href}}(t,e)){const t=n.get(i);if(t)return t}};let w=!1;function d(t){w||((({ignoreURLParametersMatching:t=[/^utm_/],directoryIndex:n="index.html",cleanURLs:i=!0,urlManipulation:s}={})=>{const c=e.cacheNames.getPrecacheName();self.addEventListener("fetch",e=>{const r=f(e.request.url,{cleanURLs:i,directoryIndex:n,ignoreURLParametersMatching:t,urlManipulation:s});if(!r)return;let o=self.caches.open(c).then(t=>t.match(r)).then(t=>t||fetch(r));e.respondWith(o)})})(t),w=!0)}const y=t=>{const e=l(),n=o.get();t.waitUntil(e.install({event:t,plugins:n}).catch(t=>{throw t}))},p=t=>{const e=l();t.waitUntil(e.activate())};function g(t){l().addToCacheList(t),t.length>0&&(self.addEventListener("install",y),self.addEventListener("activate",p))}return t.PrecacheController=h,t.addPlugins=function(t){o.add(t)},t.addRoute=d,t.cleanupOutdatedCaches=function(){self.addEventListener("activate",t=>{const n=e.cacheNames.getPrecacheName();t.waitUntil((async(t,e="-precache-")=>{const n=(await self.caches.keys()).filter(n=>n.includes(e)&&n.includes(self.registration.scope)&&n!==t);return await Promise.all(n.map(t=>self.caches.delete(t))),n})(n).then(t=>{}))})},t.createHandler=function(t=!0){return l().createHandler(t)},t.createHandlerBoundToURL=function(t){return l().createHandlerBoundToURL(t)},t.getCacheKeyForURL=function(t){return l().getCacheKeyForURL(t)},t.matchPrecache=function(t){return l().matchPrecache(t)},t.precache=g,t.precacheAndRoute=function(t,e){g(t),d(e)},t}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core);
this.workbox=this.workbox||{},this.workbox.precaching=function(t,e,n,s,i,c,r){"use strict";try{self["workbox:precaching:5.1.3"]&&_()}catch(t){}function o(t){if(!t)throw new n.WorkboxError("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location.href);return{cacheKey:e.href,url:e.href}}const{revision:e,url:s}=t;if(!s)throw new n.WorkboxError("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(s,location.href);return{cacheKey:t.href,url:t.href}}const i=new URL(s,location.href),c=new URL(s,location.href);return i.searchParams.set("__WB_REVISION__",e),{cacheKey:i.href,url:c.href}}const a={cacheWillUpdate:async({response:t})=>t.redirected?await c.copyResponse(t):t};class h extends r.Strategy{constructor(t){super(t),this.plugins.push(a)}t(t,e){return e.event&&"install"===e.event.type?this.s(t,e):this.i(t,e)}async i(t,e){let s=await e.cacheMatch(t);if(!s){if(e.params&&!1===e.params.fallbackToNetwork)throw new n.WorkboxError("missing-precache-entry",{cacheName:this.cacheName,url:t.url});s=await e.fetch(t)}return s}async s(t,e){const s=await e.fetchAndCachePut(t);let i=Boolean(s);if(s&&s.status>=400&&!this.o()&&(i=!1),!i)throw new n.WorkboxError("bad-precaching-response",{url:t.url,status:s.status});return s}o(){return this.plugins.some(t=>t.cacheWillUpdate&&t!==a)}}class l{constructor(t){this.h=!1,this.l=[],this.u=e.cacheNames.getPrecacheName(t),this.p=new Map,this.R=new Map,this.g=new Map,this.L={cacheKeyWillBeUsed:async({request:t,params:e})=>e&&e.cacheKey||this.getCacheKeyForURL(t.url)||t}}addPlugins(t){this.l.push(...t)}addRoute(t){if(!this.U){const e=this.createMatchCallback(t),n=this.createHandler(!0),c=new s.Route(e,n),r=new i.Router;r.registerRoute(c),r.addFetchListener(),r.addCacheListener(),this.U=r}}precache(t){this.addToCacheList(t),this.h||(self.addEventListener("install",t=>{t.waitUntil(this.install({event:t}))}),self.addEventListener("activate",t=>{t.waitUntil(this.activate())}),this.h=!0)}precacheAndRoute(t,e){this.precache(t),this.addRoute(e)}addToCacheList(t){const e=[];for(const s of t){"string"==typeof s?e.push(s):s&&void 0===s.revision&&e.push(s.url);const{cacheKey:t,url:i}=o(s),c="string"!=typeof s&&s.revision?"reload":"default";if(this.p.has(i)&&this.p.get(i)!==t)throw new n.WorkboxError("add-to-cache-list-conflicting-entries",{firstEntry:this.p.get(i),secondEntry:t});if("string"!=typeof s&&s.integrity){if(this.g.has(t)&&this.g.get(t)!==s.integrity)throw new n.WorkboxError("add-to-cache-list-conflicting-integrities",{url:i});this.g.set(t,s.integrity)}if(this.p.set(i,t),this.R.set(i,c),e.length>0){const t=`Workbox is precaching URLs without revision info: ${e.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(t)}}}async install({event:t,plugins:e}){e&&this.addPlugins(e);const n=[],s=[],i=await self.caches.open(this.u),c=await i.keys(),r=new Set(c.map(t=>t.url));for(const[t,e]of this.p)r.has(e)?s.push(t):n.push({cacheKey:e,url:t});for(const{cacheKey:e,url:s}of n){const n=this.g.get(e),i=this.R.get(s);await this.m({cacheKey:e,cacheMode:i,event:t,integrity:n,url:s})}return{updatedURLs:n.map(t=>t.url),notUpdatedURLs:s}}async activate(){const t=await self.caches.open(this.u),e=await t.keys(),n=new Set(this.p.values()),s=[];for(const i of e)n.has(i.url)||(await t.delete(i),s.push(i.url));return{deletedURLs:s}}async m({cacheKey:t,url:e,cacheMode:n,event:s,integrity:i}){const c=new Request(e,{integrity:i,cache:n,credentials:"same-origin"});await Promise.all(this.K().handleAll({params:{cacheKey:t},request:c,event:s}))}getURLsToCacheKeys(){return this.p}getCachedURLs(){return[...this.p.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.p.get(e.href)}async matchPrecache(t){const e=t instanceof Request?t.url:t,n=this.getCacheKeyForURL(e);if(n){return(await self.caches.open(this.u)).match(n)}}createMatchCallback(t){return({request:e})=>{const n=this.getURLsToCacheKeys();for(const s of function*(t,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:n="index.html",cleanURLs:s=!0,urlManipulation:i}={}){const c=new URL(t,location.href);c.hash="",yield c.href;const r=function(t,e=[]){for(const n of[...t.searchParams.keys()])e.some(t=>t.test(n))&&t.searchParams.delete(n);return t}(c,e);if(yield r.href,n&&r.pathname.endsWith("/")){const t=new URL(r.href);t.pathname+=n,yield t.href}if(s){const t=new URL(r.href);t.pathname+=".html",yield t.href}if(i){const t=i({url:c});for(const e of t)yield e.href}}(e.url,t)){const t=n.get(s);if(t)return{cacheKey:t}}}}createHandler(t=!0){return e=>{const n=e.request instanceof Request?e.request:new Request(e.request);return e.params=e.params||{},e.params.fallbackToNetwork=t,e.params.cacheKey||(e.params.cacheKey=this.getCacheKeyForURL(n.url)),this.K().handle(e)}}createHandlerBoundToURL(t,e=!0){if(!this.getCacheKeyForURL(t))throw new n.WorkboxError("non-precached-url",{url:t});const s=this.createHandler(e),i=new Request(t);return t=>s(Object.assign(t,{request:i}))}K(){return this._||(this._=new h({cacheName:this.u,matchOptions:{ignoreSearch:!0},plugins:[this.L,...this.l]})),this._}}let u;const f=()=>(u||(u=new l),u);return t.PrecacheController=l,t.PrecacheFallbackPlugin=class{constructor({fallbackURL:t,precacheController:e}){this.handlerDidError=()=>this.v.matchPrecache(this.k),this.k=t,this.v=e||f()}},t.addPlugins=function(t){return f().addPlugins(t)},t.addRoute=function(t){return f().addRoute(t)},t.cleanupOutdatedCaches=function(){self.addEventListener("activate",t=>{const n=e.cacheNames.getPrecacheName();t.waitUntil((async(t,e="-precache-")=>{const n=(await self.caches.keys()).filter(n=>n.includes(e)&&n.includes(self.registration.scope)&&n!==t);return await Promise.all(n.map(t=>self.caches.delete(t))),n})(n).then(t=>{}))})},t.createHandler=function(t=!0){return f().createHandler(t)},t.createHandlerBoundToURL=function(t){return f().createHandlerBoundToURL(t)},t.getCacheKeyForURL=function(t){return f().getCacheKeyForURL(t)},t.matchPrecache=function(t){return f().matchPrecache(t)},t.precache=function(t){f().precache(t)},t.precacheAndRoute=function(t,e){f().precacheAndRoute(t,e)},t}({},workbox.core._private,workbox.core._private,workbox.routing,workbox.routing,workbox.core,workbox.strategies);
//# sourceMappingURL=workbox-precaching.prod.js.map

@@ -11,2 +11,3 @@ import { addPlugins } from './addPlugins.js';

import { PrecacheController } from './PrecacheController.js';
import { PrecacheFallbackPlugin } from './PrecacheFallbackPlugin.js';
import './_version.js';

@@ -25,2 +26,2 @@ /**

*/
export { addPlugins, addRoute, cleanupOutdatedCaches, createHandler, createHandlerBoundToURL, getCacheKeyForURL, matchPrecache, precache, precacheAndRoute, PrecacheController, };
export { addPlugins, addRoute, cleanupOutdatedCaches, createHandler, createHandlerBoundToURL, getCacheKeyForURL, matchPrecache, precache, precacheAndRoute, PrecacheController, PrecacheFallbackPlugin, };

@@ -18,2 +18,3 @@ /*

import { PrecacheController } from './PrecacheController.js';
import { PrecacheFallbackPlugin } from './PrecacheFallbackPlugin.js';
import './_version.js';

@@ -32,2 +33,2 @@ /**

*/
export { addPlugins, addRoute, cleanupOutdatedCaches, createHandler, createHandlerBoundToURL, getCacheKeyForURL, matchPrecache, precache, precacheAndRoute, PrecacheController, };
export { addPlugins, addRoute, cleanupOutdatedCaches, createHandler, createHandlerBoundToURL, getCacheKeyForURL, matchPrecache, precache, precacheAndRoute, PrecacheController, PrecacheFallbackPlugin, };
{
"name": "workbox-precaching",
"version": "5.1.3",
"version": "6.0.0-alpha.0",
"license": "MIT",

@@ -16,10 +16,5 @@ "author": "Google's Web DevRel Team",

],
"scripts": {
"build": "gulp build-packages --package workbox-precaching",
"version": "npm run build",
"prepare": "npm run build"
},
"workbox": {
"browserNamespace": "workbox.precaching",
"packageType": "browser"
"packageType": "sw"
},

@@ -30,5 +25,7 @@ "main": "index.js",

"dependencies": {
"workbox-core": "^5.1.3"
"workbox-core": "^6.0.0-alpha.0",
"workbox-routing": "^6.0.0-alpha.0",
"workbox-strategies": "^6.0.0-alpha.0"
},
"gitHead": "fe4399505e02c3af6515fc8ffae8c58791f43f3c"
"gitHead": "3dfe1f4c5ed450bc4b7420321f1a113ff4382d1b"
}
import { PrecacheEntry } from './_types.js';
import './_version.js';
declare global {
interface WorkerGlobalScope {
__WB_MANIFEST: Array<PrecacheEntry | string>;
}
}
/**

@@ -9,0 +4,0 @@ * Adds items to the precache list, removing any duplicates and

@@ -8,23 +8,4 @@ /*

*/
import { logger } from 'workbox-core/_private/logger.js';
import { getOrCreatePrecacheController } from './utils/getOrCreatePrecacheController.js';
import { precachePlugins } from './utils/precachePlugins.js';
import './_version.js';
const installListener = (event) => {
const precacheController = getOrCreatePrecacheController();
const plugins = precachePlugins.get();
event.waitUntil(precacheController.install({ event, plugins })
.catch((error) => {
if (process.env.NODE_ENV !== 'production') {
logger.error(`Service worker installation failed. It will ` +
`be retried automatically during the next navigation.`);
}
// Re-throw the error to ensure installation fails.
throw error;
}));
};
const activateListener = (event) => {
const precacheController = getOrCreatePrecacheController();
event.waitUntil(precacheController.activate());
};
/**

@@ -51,12 +32,4 @@ * Adds items to the precache list, removing any duplicates and

const precacheController = getOrCreatePrecacheController();
precacheController.addToCacheList(entries);
if (entries.length > 0) {
// NOTE: these listeners will only be added once (even if the `precache()`
// method is called multiple times) because event listeners are implemented
// as a set, where each listener must be unique.
// See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
self.addEventListener('install', installListener);
self.addEventListener('activate', activateListener);
}
precacheController.precache(entries);
}
export { precache };

@@ -1,9 +0,3 @@

import { FetchListenerOptions } from './utils/addFetchListener.js';
import { PrecacheEntry } from './_types.js';
import { FetchListenerOptions, PrecacheEntry } from './_types.js';
import './_version.js';
declare global {
interface WorkerGlobalScope {
__WB_MANIFEST: Array<PrecacheEntry | string>;
}
}
/**

@@ -10,0 +4,0 @@ * This method will add entries to the precache list and add a route to

@@ -8,4 +8,3 @@ /*

*/
import { addRoute } from './addRoute.js';
import { precache } from './precache.js';
import { getOrCreatePrecacheController } from './utils/getOrCreatePrecacheController.js';
import './_version.js';

@@ -27,5 +26,5 @@ /**

function precacheAndRoute(entries, options) {
precache(entries);
addRoute(options);
const precacheController = getOrCreatePrecacheController();
precacheController.precacheAndRoute(entries, options);
}
export { precacheAndRoute };

@@ -1,5 +0,10 @@

import { RouteHandlerCallback } from 'workbox-core/types.js';
import { WorkboxPlugin } from 'workbox-core/types.js';
import { PrecacheEntry } from './_types.js';
import { RouteMatchCallbackOptions, RouteHandlerCallback, WorkboxPlugin } from 'workbox-core/types.js';
import { Strategy } from 'workbox-strategies/Strategy.js';
import { PrecacheEntry, FetchListenerOptions } from './_types.js';
import './_version.js';
declare global {
interface WorkerGlobalScope {
__WB_MANIFEST: Array<PrecacheEntry | string>;
}
}
/**

@@ -15,2 +20,7 @@ * Performs efficient precaching of assets.

private readonly _cacheKeysToIntegrities;
private _router?;
private _strategy?;
private _installed?;
private readonly _cacheKeyPlugin;
private readonly _plugins;
/**

@@ -24,8 +34,63 @@ * Create a new PrecacheController.

/**
* Adds plugins to the precaching strategy.
*
* @param {Array<Object>} plugins
*/
addPlugins(plugins: WorkboxPlugin[]): void;
/**
* Creates a Workbox `Route` to handle requests for precached assets (based
* on the passed configuration options).
*
* @param {Object} [options]
* @param {string} [options.directoryIndex=index.html] The `directoryIndex`
* will check cache entries for a URLs ending with '/' to see if there is a
* hit when appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An
* array of regex's to remove search params when looking for a cache match.
* @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
* check the cache for the URL with a `.html` added to the end of the end.
* @param {module:workbox-precaching~urlManipulation} [options.urlManipulation]
* This is a function that should take a URL and return an array of
* alternative URLs that should be checked for precache matches.
*/
addRoute(options?: FetchListenerOptions): void;
/**
* Adds items to the precache list, removing any duplicates and
* stores the files in the
* ["precache cache"]{@link module:workbox-core.cacheNames} when the service
* worker installs.
*
* This method can be called multiple times.
*
* Please note: This method **will not** serve any of the cached files for you.
* It only precaches files. To respond to a network request you call
* [addRoute()]{@link module:workbox-precaching.PreacheController#addRoute}.
*
* If you have a single array of files to precache, you can just call
* [precacheAndRoute()]{@link module:workbox-precaching.precacheAndRoute}.
*
* @param {Array<Object|string>} [entries=[]] Array of entries to precache.
*/
precache(entries: Array<PrecacheEntry | string>): void;
/**
* This method will add entries to the precache list and add a route to
* respond to fetch events.
*
* This is a convenience method that will call
* [precache()]{@link module:workbox-precaching.PrecacheController#precache}
* and
* [addRoute()]{@link module:workbox-precaching.PrecacheController#addRoute}
* in a single call.
*
* @param {Array<Object|string>} entries Array of entries to precache.
* @param {Object} [options] See
* [addRoute() options]{@link module:workbox-precaching.PrecacheController#addRoute}.
*/
precacheAndRoute(entries: Array<PrecacheEntry | string>, options?: FetchListenerOptions): void;
/**
* This method will add items to the precache list, removing duplicates
* and ensuring the information is valid.
*
* @param {
* Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>
* } entries Array of entries to precache.
* @param {Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>} entries
* Array of entries to precache.
*/

@@ -38,3 +103,3 @@ addToCacheList(entries: Array<PrecacheEntry | string>): void;

* @param {Object} options
* @param {Event} [options.event] The install event (if needed).
* @param {Event} options.event The install event.
* @param {Array<Object>} [options.plugins] Plugins to be used for fetching

@@ -44,4 +109,4 @@ * and caching during install.

*/
install({ event, plugins }?: {
event?: ExtendableEvent;
install({ event, plugins }: {
event: ExtendableEvent;
plugins?: WorkboxPlugin[];

@@ -74,15 +139,12 @@ }): Promise<{

* @param {string} options.url The URL to fetch and cache.
* @param {Event} options.event The install event.
* @param {string} [options.cacheMode] The cache mode for the network request.
* @param {Event} [options.event] The install event (if passed).
* @param {Array<Object>} [options.plugins] An array of plugins to apply to
* fetch and caching.
* @param {string} [options.integrity] The value to use for the `integrity`
* field when making the request.
*/
_addURLToCache({ cacheKey, url, cacheMode, event, plugins, integrity }: {
_addURLToCache({ cacheKey, url, cacheMode, event, integrity }: {
cacheKey: string;
url: string;
cacheMode: "reload" | "default" | "no-store" | "no-cache" | "force-cache" | "only-if-cached" | undefined;
event?: ExtendableEvent;
plugins?: WorkboxPlugin[];
event: ExtendableEvent;
integrity?: string;

@@ -115,3 +177,4 @@ }): Promise<void>;

/**
* This acts as a drop-in replacement for [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
* This acts as a drop-in replacement for
* [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
* with the following differences:

@@ -134,2 +197,18 @@ *

/**
* Creates a [`matchCallback`]{@link module:workbox-precaching~matchCallback}
* based on the passed configuration options) that with will identify
* requests in the precache and return a respective `params` object
* containing the `cacheKey` of the precached asset.
*
* This `cacheKey` can be used by a
* [`handlerCallback`]{@link module:workbox-precaching~handlerCallback}
* to get the precached asset from the cache.
*
* @param {Object} [options] See
* [addRoute() options]{@link module:workbox-precaching.PrecacheController#addRoute}.
*/
createMatchCallback(options?: FetchListenerOptions): ({ request }: RouteMatchCallbackOptions) => {
cacheKey: string;
} | undefined;
/**
* Returns a function that can be used within a

@@ -163,3 +242,4 @@ * {@link module:workbox-routing.Route} that will find a response for the

createHandlerBoundToURL(url: string, fallbackToNetwork?: boolean): RouteHandlerCallback;
_getStrategy(): Strategy;
}
export { PrecacheController };

@@ -10,10 +10,12 @@ /*

import { cacheNames } from 'workbox-core/_private/cacheNames.js';
import { cacheWrapper } from 'workbox-core/_private/cacheWrapper.js';
import { fetchWrapper } from 'workbox-core/_private/fetchWrapper.js';
import { getFriendlyURL } from 'workbox-core/_private/getFriendlyURL.js';
import { logger } from 'workbox-core/_private/logger.js';
import { WorkboxError } from 'workbox-core/_private/WorkboxError.js';
import { copyResponse } from 'workbox-core/copyResponse.js';
import { Route } from 'workbox-routing/Route.js';
import { Router } from 'workbox-routing/Router.js';
import { createCacheKey } from './utils/createCacheKey.js';
import { PrecacheStrategy } from './utils/PrecacheStrategy.js';
import { printCleanupDetails } from './utils/printCleanupDetails.js';
import { printInstallDetails } from './utils/printInstallDetails.js';
import { generateURLVariations } from './utils/generateURLVariations.js';
import './_version.js';

@@ -33,2 +35,4 @@ /**

constructor(cacheName) {
this._installed = false;
this._plugins = [];
this._cacheName = cacheNames.getPrecacheName(cacheName);

@@ -38,10 +42,99 @@ this._urlsToCacheKeys = new Map();

this._cacheKeysToIntegrities = new Map();
this._cacheKeyPlugin = {
cacheKeyWillBeUsed: async ({ request, params }) => {
const cacheKey = params && params.cacheKey ||
this.getCacheKeyForURL(request.url);
return cacheKey || request;
},
};
}
/**
* Adds plugins to the precaching strategy.
*
* @param {Array<Object>} plugins
*/
addPlugins(plugins) {
this._plugins.push(...plugins);
}
/**
* Creates a Workbox `Route` to handle requests for precached assets (based
* on the passed configuration options).
*
* @param {Object} [options]
* @param {string} [options.directoryIndex=index.html] The `directoryIndex`
* will check cache entries for a URLs ending with '/' to see if there is a
* hit when appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An
* array of regex's to remove search params when looking for a cache match.
* @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
* check the cache for the URL with a `.html` added to the end of the end.
* @param {module:workbox-precaching~urlManipulation} [options.urlManipulation]
* This is a function that should take a URL and return an array of
* alternative URLs that should be checked for precache matches.
*/
addRoute(options) {
if (!this._router) {
const matchCallback = this.createMatchCallback(options);
const handlerCallback = this.createHandler(true);
const route = new Route(matchCallback, handlerCallback);
const router = new Router();
router.registerRoute(route);
router.addFetchListener();
router.addCacheListener();
this._router = router;
}
}
/**
* Adds items to the precache list, removing any duplicates and
* stores the files in the
* ["precache cache"]{@link module:workbox-core.cacheNames} when the service
* worker installs.
*
* This method can be called multiple times.
*
* Please note: This method **will not** serve any of the cached files for you.
* It only precaches files. To respond to a network request you call
* [addRoute()]{@link module:workbox-precaching.PreacheController#addRoute}.
*
* If you have a single array of files to precache, you can just call
* [precacheAndRoute()]{@link module:workbox-precaching.precacheAndRoute}.
*
* @param {Array<Object|string>} [entries=[]] Array of entries to precache.
*/
precache(entries) {
this.addToCacheList(entries);
if (!this._installed) {
self.addEventListener('install', (event) => {
event.waitUntil(this.install({ event }));
});
self.addEventListener('activate', (event) => {
event.waitUntil(this.activate());
});
this._installed = true;
}
}
/**
* This method will add entries to the precache list and add a route to
* respond to fetch events.
*
* This is a convenience method that will call
* [precache()]{@link module:workbox-precaching.PrecacheController#precache}
* and
* [addRoute()]{@link module:workbox-precaching.PrecacheController#addRoute}
* in a single call.
*
* @param {Array<Object|string>} entries Array of entries to precache.
* @param {Object} [options] See
* [addRoute() options]{@link module:workbox-precaching.PrecacheController#addRoute}.
*/
precacheAndRoute(entries, options) {
this.precache(entries);
this.addRoute(options);
}
/**
* This method will add items to the precache list, removing duplicates
* and ensuring the information is valid.
*
* @param {
* Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>
* } entries Array of entries to precache.
* @param {Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>} entries
* Array of entries to precache.
*/

@@ -107,3 +200,3 @@ addToCacheList(entries) {

* @param {Object} options
* @param {Event} [options.event] The install event (if needed).
* @param {Event} options.event The install event.
* @param {Array<Object>} [options.plugins] Plugins to be used for fetching

@@ -113,3 +206,3 @@ * and caching during install.

*/
async install({ event, plugins } = {}) {
async install({ event, plugins }) {
if (process.env.NODE_ENV !== 'production') {

@@ -125,2 +218,5 @@ if (plugins) {

}
if (plugins) {
this.addPlugins(plugins);
}
const toBePrecached = [];

@@ -139,6 +235,8 @@ const alreadyPrecached = [];

}
const precacheRequests = toBePrecached.map(({ cacheKey, url }) => {
// Cache entries one at a time.
// See https://github.com/GoogleChrome/workbox/issues/2528
for (const { cacheKey, url } of toBePrecached) {
const integrity = this._cacheKeysToIntegrities.get(cacheKey);
const cacheMode = this._urlsToCacheModes.get(url);
return this._addURLToCache({
await this._addURLToCache({
cacheKey,

@@ -148,7 +246,5 @@ cacheMode,

integrity,
plugins,
url,
});
});
await Promise.all(precacheRequests);
}
const updatedURLs = toBePrecached.map((item) => item.url);

@@ -198,10 +294,8 @@ if (process.env.NODE_ENV !== 'production') {

* @param {string} options.url The URL to fetch and cache.
* @param {Event} options.event The install event.
* @param {string} [options.cacheMode] The cache mode for the network request.
* @param {Event} [options.event] The install event (if passed).
* @param {Array<Object>} [options.plugins] An array of plugins to apply to
* fetch and caching.
* @param {string} [options.integrity] The value to use for the `integrity`
* field when making the request.
*/
async _addURLToCache({ cacheKey, url, cacheMode, event, plugins, integrity }) {
async _addURLToCache({ cacheKey, url, cacheMode, event, integrity }) {
const request = new Request(url, {

@@ -212,50 +306,7 @@ integrity,

});
let response = await fetchWrapper.fetch({
event,
plugins,
await Promise.all(this._getStrategy().handleAll({
params: { cacheKey },
request,
});
// Allow developers to override the default logic about what is and isn't
// valid by passing in a plugin implementing cacheWillUpdate(), e.g.
// a `CacheableResponsePlugin` instance.
let cacheWillUpdatePlugin;
for (const plugin of (plugins || [])) {
if ('cacheWillUpdate' in plugin) {
cacheWillUpdatePlugin = plugin;
}
}
const isValidResponse = cacheWillUpdatePlugin ?
// Use a callback if provided. It returns a truthy value if valid.
// NOTE: invoke the method on the plugin instance so the `this` context
// is correct.
await cacheWillUpdatePlugin.cacheWillUpdate({ event, request, response }) :
// Otherwise, default to considering any response status under 400 valid.
// This includes, by default, considering opaque responses valid.
response.status < 400;
// Consider this a failure, leading to the `install` handler failing, if
// we get back an invalid response.
if (!isValidResponse) {
throw new WorkboxError('bad-precaching-response', {
url,
status: response.status,
});
}
// Redirected responses cannot be used to satisfy a navigation request, so
// any redirected response must be "copied" rather than cloned, so the new
// response doesn't contain the `redirected` flag. See:
// https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1
if (response.redirected) {
response = await copyResponse(response);
}
await cacheWrapper.put({
event,
plugins,
response,
// `request` already uses `url`. We may be able to reuse it.
request: cacheKey === url ? request : new Request(cacheKey),
cacheName: this._cacheName,
matchOptions: {
ignoreSearch: true,
},
});
}));
}

@@ -294,3 +345,4 @@ /**

/**
* This acts as a drop-in replacement for [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
* This acts as a drop-in replacement for
* [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
* with the following differences:

@@ -321,2 +373,31 @@ *

/**
* Creates a [`matchCallback`]{@link module:workbox-precaching~matchCallback}
* based on the passed configuration options) that with will identify
* requests in the precache and return a respective `params` object
* containing the `cacheKey` of the precached asset.
*
* This `cacheKey` can be used by a
* [`handlerCallback`]{@link module:workbox-precaching~handlerCallback}
* to get the precached asset from the cache.
*
* @param {Object} [options] See
* [addRoute() options]{@link module:workbox-precaching.PrecacheController#addRoute}.
*/
createMatchCallback(options) {
return ({ request }) => {
const urlsToCacheKeys = this.getURLsToCacheKeys();
for (const possibleURL of generateURLVariations(request.url, options)) {
const cacheKey = urlsToCacheKeys.get(possibleURL);
if (cacheKey) {
return { cacheKey };
}
}
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Precaching did not find a match for ` +
getFriendlyURL(request.url));
}
return;
};
}
/**
* Returns a function that can be used within a

@@ -335,25 +416,11 @@ * {@link module:workbox-routing.Route} that will find a response for the

createHandler(fallbackToNetwork = true) {
return async ({ request }) => {
try {
const response = await this.matchPrecache(request);
if (response) {
return response;
}
// This shouldn't normally happen, but there are edge cases:
// https://github.com/GoogleChrome/workbox/issues/1441
throw new WorkboxError('missing-precache-entry', {
cacheName: this._cacheName,
url: request instanceof Request ? request.url : request,
});
return (options) => {
const request = options.request instanceof Request ?
options.request : new Request(options.request);
options.params = options.params || {};
options.params.fallbackToNetwork = fallbackToNetwork;
if (!options.params.cacheKey) {
options.params.cacheKey = this.getCacheKeyForURL(request.url);
}
catch (error) {
if (fallbackToNetwork) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Unable to respond with precached response. ` +
`Falling back to network.`, error);
}
return fetch(request);
}
throw error;
}
return this._getStrategy().handle(options);
};

@@ -382,5 +449,22 @@ }

const request = new Request(url);
return () => handler({ request });
return (options) => handler(Object.assign(options, { request }));
}
_getStrategy() {
// NOTE: this needs to be done lazily to match v5 behavior, since the
// `addPlugins()` method can be called at any time.
if (!this._strategy) {
this._strategy = new PrecacheStrategy({
cacheName: this._cacheName,
matchOptions: {
ignoreSearch: true,
},
plugins: [
this._cacheKeyPlugin,
...this._plugins,
],
});
}
return this._strategy;
}
}
export { PrecacheController };

@@ -26,2 +26,9 @@ /*

export interface FetchListenerOptions {
directoryIndex?: string;
ignoreURLParametersMatching?: RegExp[];
cleanURLs?: boolean;
urlManipulation?: urlManipulation;
}
export type urlManipulation = ({url}: {url: URL}) => URL[];

@@ -28,0 +35,0 @@

@@ -10,3 +10,3 @@ /*

import {WorkboxPlugin} from 'workbox-core/types.js';
import {precachePlugins} from './utils/precachePlugins.js';
import {getOrCreatePrecacheController} from './utils/getOrCreatePrecacheController.js';
import './_version.js';

@@ -16,12 +16,13 @@

/**
* Adds plugins to precaching.
* Adds plugins to the precaching strategy.
*
* @param {Array<Object>} newPlugins
* @param {Array<Object>} plugins
*
* @memberof module:workbox-precaching
*/
function addPlugins(newPlugins: WorkboxPlugin[]) {
precachePlugins.add(newPlugins);
function addPlugins(plugins: WorkboxPlugin[]) {
const precacheController = getOrCreatePrecacheController();
return precacheController.addPlugins(plugins);
}
export {addPlugins};

@@ -9,8 +9,7 @@

import {addFetchListener, FetchListenerOptions} from './utils/addFetchListener.js';
import {getOrCreatePrecacheController} from './utils/getOrCreatePrecacheController.js';
import {FetchListenerOptions} from './_types.js';
import './_version.js';
let listenerAdded = false;
/**

@@ -30,3 +29,3 @@ * Add a `fetch` listener to the service worker that will

* appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An
* array of regex's to remove search params when looking for a cache match.

@@ -42,8 +41,6 @@ * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will

function addRoute(options?: FetchListenerOptions) {
if (!listenerAdded) {
addFetchListener(options);
listenerAdded = true;
}
const precacheController = getOrCreatePrecacheController();
return precacheController.addRoute(options);
}
export {addRoute}

@@ -19,2 +19,3 @@ /*

import {PrecacheController} from './PrecacheController.js';
import {PrecacheFallbackPlugin} from './PrecacheFallbackPlugin.js';

@@ -47,2 +48,3 @@ import './_version.js';

PrecacheController,
PrecacheFallbackPlugin,
};

@@ -9,37 +9,7 @@ /*

import {logger} from 'workbox-core/_private/logger.js';
import {getOrCreatePrecacheController} from './utils/getOrCreatePrecacheController.js';
import {precachePlugins} from './utils/precachePlugins.js';
import {PrecacheEntry} from './_types.js';
import './_version.js';
declare global {
interface WorkerGlobalScope {
__WB_MANIFEST: Array<PrecacheEntry|string>;
}
}
const installListener = (event: ExtendableEvent) => {
const precacheController = getOrCreatePrecacheController();
const plugins = precachePlugins.get();
event.waitUntil(
precacheController.install({event, plugins})
.catch((error: Error) => {
if (process.env.NODE_ENV !== 'production') {
logger.error(`Service worker installation failed. It will ` +
`be retried automatically during the next navigation.`);
}
// Re-throw the error to ensure installation fails.
throw error;
})
);
};
const activateListener = (event: ExtendableEvent) => {
const precacheController = getOrCreatePrecacheController();
event.waitUntil(precacheController.activate());
};
/**

@@ -66,14 +36,5 @@ * Adds items to the precache list, removing any duplicates and

const precacheController = getOrCreatePrecacheController();
precacheController.addToCacheList(entries);
if (entries.length > 0) {
// NOTE: these listeners will only be added once (even if the `precache()`
// method is called multiple times) because event listeners are implemented
// as a set, where each listener must be unique.
// See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
self.addEventListener('install', installListener as EventListener);
self.addEventListener('activate', activateListener as EventListener);
}
precacheController.precache(entries);
}
export {precache}

@@ -9,13 +9,6 @@ /*

import {FetchListenerOptions} from './utils/addFetchListener.js';
import {addRoute} from './addRoute.js';
import {precache} from './precache.js';
import {PrecacheEntry} from './_types.js';
import {getOrCreatePrecacheController} from './utils/getOrCreatePrecacheController.js';
import {FetchListenerOptions, PrecacheEntry} from './_types.js';
import './_version.js';
declare global {
interface WorkerGlobalScope {
__WB_MANIFEST: Array<PrecacheEntry|string>;
}
}

@@ -37,6 +30,7 @@ /**

function precacheAndRoute(entries: Array<PrecacheEntry|string>, options?: FetchListenerOptions) {
precache(entries);
addRoute(options);
const precacheController = getOrCreatePrecacheController();
precacheController.precacheAndRoute(entries, options);
}
export {precacheAndRoute}

@@ -11,18 +11,29 @@ /*

import {cacheNames} from 'workbox-core/_private/cacheNames.js';
import {cacheWrapper} from 'workbox-core/_private/cacheWrapper.js';
import {fetchWrapper} from 'workbox-core/_private/fetchWrapper.js';
import {getFriendlyURL} from 'workbox-core/_private/getFriendlyURL.js';
import {logger} from 'workbox-core/_private/logger.js';
import {WorkboxError} from 'workbox-core/_private/WorkboxError.js';
import {copyResponse} from 'workbox-core/copyResponse.js';
import {RouteHandlerCallback, RouteHandlerCallbackOptions}
from 'workbox-core/types.js';
import {WorkboxPlugin} from 'workbox-core/types.js';
import {RouteMatchCallbackOptions, RouteHandlerCallback, RouteHandlerCallbackOptions, WorkboxPlugin} from 'workbox-core/types.js';
import {PrecacheEntry} from './_types.js';
import {Route} from 'workbox-routing/Route.js';
import {Router} from 'workbox-routing/Router.js';
import {Strategy} from 'workbox-strategies/Strategy.js';
import {createCacheKey} from './utils/createCacheKey.js';
import {PrecacheStrategy} from './utils/PrecacheStrategy.js';
import {printCleanupDetails} from './utils/printCleanupDetails.js';
import {printInstallDetails} from './utils/printInstallDetails.js';
import {generateURLVariations} from './utils/generateURLVariations.js';
import {PrecacheEntry, FetchListenerOptions} from './_types.js';
import './_version.js';
// Give TypeScript the correct global.
declare let self: ServiceWorkerGlobalScope;
declare global {
interface WorkerGlobalScope {
__WB_MANIFEST: Array<PrecacheEntry|string>;
}
}
/**

@@ -39,2 +50,8 @@ * Performs efficient precaching of assets.

private _router?: Router;
private _strategy?: Strategy;
private _installed?: boolean = false;
private readonly _cacheKeyPlugin: WorkboxPlugin;
private readonly _plugins: WorkboxPlugin[] = [];
/**

@@ -51,11 +68,109 @@ * Create a new PrecacheController.

this._cacheKeysToIntegrities = new Map();
this._cacheKeyPlugin = {
cacheKeyWillBeUsed: async ({request, params}: {request: Request; params?: any}) => {
const cacheKey = params && params.cacheKey ||
this.getCacheKeyForURL(request.url);
return cacheKey || request;
},
};
}
/**
* Adds plugins to the precaching strategy.
*
* @param {Array<Object>} plugins
*/
addPlugins(plugins: WorkboxPlugin[]) {
this._plugins.push(...plugins);
}
/**
* Creates a Workbox `Route` to handle requests for precached assets (based
* on the passed configuration options).
*
* @param {Object} [options]
* @param {string} [options.directoryIndex=index.html] The `directoryIndex`
* will check cache entries for a URLs ending with '/' to see if there is a
* hit when appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An
* array of regex's to remove search params when looking for a cache match.
* @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
* check the cache for the URL with a `.html` added to the end of the end.
* @param {module:workbox-precaching~urlManipulation} [options.urlManipulation]
* This is a function that should take a URL and return an array of
* alternative URLs that should be checked for precache matches.
*/
addRoute(options?: FetchListenerOptions) {
if (!this._router) {
const matchCallback = this.createMatchCallback(options);
const handlerCallback = this.createHandler(true);
const route = new Route(matchCallback, handlerCallback);
const router = new Router();
router.registerRoute(route);
router.addFetchListener();
router.addCacheListener();
this._router = router;
}
}
/**
* Adds items to the precache list, removing any duplicates and
* stores the files in the
* ["precache cache"]{@link module:workbox-core.cacheNames} when the service
* worker installs.
*
* This method can be called multiple times.
*
* Please note: This method **will not** serve any of the cached files for you.
* It only precaches files. To respond to a network request you call
* [addRoute()]{@link module:workbox-precaching.PreacheController#addRoute}.
*
* If you have a single array of files to precache, you can just call
* [precacheAndRoute()]{@link module:workbox-precaching.precacheAndRoute}.
*
* @param {Array<Object|string>} [entries=[]] Array of entries to precache.
*/
precache(entries: Array<PrecacheEntry|string>) {
this.addToCacheList(entries);
if (!this._installed) {
self.addEventListener('install', (event) => {
event.waitUntil(this.install({event}));
});
self.addEventListener('activate', (event) => {
event.waitUntil(this.activate());
});
this._installed = true;
}
}
/**
* This method will add entries to the precache list and add a route to
* respond to fetch events.
*
* This is a convenience method that will call
* [precache()]{@link module:workbox-precaching.PrecacheController#precache}
* and
* [addRoute()]{@link module:workbox-precaching.PrecacheController#addRoute}
* in a single call.
*
* @param {Array<Object|string>} entries Array of entries to precache.
* @param {Object} [options] See
* [addRoute() options]{@link module:workbox-precaching.PrecacheController#addRoute}.
*/
precacheAndRoute(entries: Array<PrecacheEntry|string>, options?: FetchListenerOptions) {
this.precache(entries);
this.addRoute(options);
}
/**
* This method will add items to the precache list, removing duplicates
* and ensuring the information is valid.
*
* @param {
* Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>
* } entries Array of entries to precache.
* @param {Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>} entries
* Array of entries to precache.
*/

@@ -126,3 +241,3 @@ addToCacheList(entries: Array<PrecacheEntry|string>) {

* @param {Object} options
* @param {Event} [options.event] The install event (if needed).
* @param {Event} options.event The install event.
* @param {Array<Object>} [options.plugins] Plugins to be used for fetching

@@ -133,5 +248,5 @@ * and caching during install.

async install({event, plugins}: {
event?: ExtendableEvent;
event: ExtendableEvent;
plugins?: WorkboxPlugin[];
} = {}) {
}) {
if (process.env.NODE_ENV !== 'production') {

@@ -148,2 +263,6 @@ if (plugins) {

if (plugins) {
this.addPlugins(plugins);
}
const toBePrecached: {cacheKey: string; url: string}[] = [];

@@ -165,6 +284,8 @@ const alreadyPrecached: string[] = [];

const precacheRequests = toBePrecached.map(({cacheKey, url}) => {
// Cache entries one at a time.
// See https://github.com/GoogleChrome/workbox/issues/2528
for (const {cacheKey, url} of toBePrecached) {
const integrity = this._cacheKeysToIntegrities.get(cacheKey);
const cacheMode = this._urlsToCacheModes.get(url);
return this._addURLToCache({
await this._addURLToCache({
cacheKey,

@@ -174,7 +295,5 @@ cacheMode,

integrity,
plugins,
url,
});
});
await Promise.all(precacheRequests);
}

@@ -232,15 +351,12 @@ const updatedURLs = toBePrecached.map((item) => item.url);

* @param {string} options.url The URL to fetch and cache.
* @param {Event} options.event The install event.
* @param {string} [options.cacheMode] The cache mode for the network request.
* @param {Event} [options.event] The install event (if passed).
* @param {Array<Object>} [options.plugins] An array of plugins to apply to
* fetch and caching.
* @param {string} [options.integrity] The value to use for the `integrity`
* field when making the request.
*/
async _addURLToCache({cacheKey, url, cacheMode, event, plugins, integrity}: {
async _addURLToCache({cacheKey, url, cacheMode, event, integrity}: {
cacheKey: string;
url: string;
cacheMode: "reload" | "default" | "no-store" | "no-cache" | "force-cache" | "only-if-cached" | undefined;
event?: ExtendableEvent;
plugins?: WorkboxPlugin[];
event: ExtendableEvent;
integrity?: string;

@@ -254,55 +370,7 @@ }) {

let response = await fetchWrapper.fetch({
event,
plugins,
await Promise.all(this._getStrategy().handleAll({
params: {cacheKey},
request,
});
// Allow developers to override the default logic about what is and isn't
// valid by passing in a plugin implementing cacheWillUpdate(), e.g.
// a `CacheableResponsePlugin` instance.
let cacheWillUpdatePlugin;
for (const plugin of (plugins || [])) {
if ('cacheWillUpdate' in plugin) {
cacheWillUpdatePlugin = plugin;
}
}
const isValidResponse = cacheWillUpdatePlugin ?
// Use a callback if provided. It returns a truthy value if valid.
// NOTE: invoke the method on the plugin instance so the `this` context
// is correct.
await cacheWillUpdatePlugin.cacheWillUpdate!({event, request, response}) :
// Otherwise, default to considering any response status under 400 valid.
// This includes, by default, considering opaque responses valid.
response.status < 400;
// Consider this a failure, leading to the `install` handler failing, if
// we get back an invalid response.
if (!isValidResponse) {
throw new WorkboxError('bad-precaching-response', {
url,
status: response.status,
});
}
// Redirected responses cannot be used to satisfy a navigation request, so
// any redirected response must be "copied" rather than cloned, so the new
// response doesn't contain the `redirected` flag. See:
// https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1
if (response.redirected) {
response = await copyResponse(response);
}
await cacheWrapper.put({
event,
plugins,
response,
// `request` already uses `url`. We may be able to reuse it.
request: cacheKey === url ? request : new Request(cacheKey),
cacheName: this._cacheName,
matchOptions: {
ignoreSearch: true,
},
});
}));
}

@@ -345,3 +413,4 @@

/**
* This acts as a drop-in replacement for [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
* This acts as a drop-in replacement for
* [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
* with the following differences:

@@ -373,2 +442,32 @@ *

/**
* Creates a [`matchCallback`]{@link module:workbox-precaching~matchCallback}
* based on the passed configuration options) that with will identify
* requests in the precache and return a respective `params` object
* containing the `cacheKey` of the precached asset.
*
* This `cacheKey` can be used by a
* [`handlerCallback`]{@link module:workbox-precaching~handlerCallback}
* to get the precached asset from the cache.
*
* @param {Object} [options] See
* [addRoute() options]{@link module:workbox-precaching.PrecacheController#addRoute}.
*/
createMatchCallback(options?: FetchListenerOptions) {
return ({request}: RouteMatchCallbackOptions) => {
const urlsToCacheKeys = this.getURLsToCacheKeys();
for (const possibleURL of generateURLVariations(request.url, options)) {
const cacheKey = urlsToCacheKeys.get(possibleURL);
if (cacheKey) {
return {cacheKey};
}
}
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Precaching did not find a match for ` +
getFriendlyURL(request.url));
}
return;
}
}
/**
* Returns a function that can be used within a

@@ -387,26 +486,14 @@ * {@link module:workbox-routing.Route} that will find a response for the

createHandler(fallbackToNetwork = true): RouteHandlerCallback {
return async ({request}: RouteHandlerCallbackOptions) => {
try {
const response = await this.matchPrecache(request);
if (response) {
return response;
}
return (options: RouteHandlerCallbackOptions) => {
const request = options.request instanceof Request ?
options.request : new Request(options.request);
// This shouldn't normally happen, but there are edge cases:
// https://github.com/GoogleChrome/workbox/issues/1441
throw new WorkboxError('missing-precache-entry', {
cacheName: this._cacheName,
url: request instanceof Request ? request.url : request,
});
} catch (error) {
if (fallbackToNetwork) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Unable to respond with precached response. ` +
`Falling back to network.`, error);
}
return fetch(request);
}
options.params = options.params || {};
throw error;
options.params.fallbackToNetwork = fallbackToNetwork;
if (!options.params.cacheKey) {
options.params.cacheKey = this.getCacheKeyForURL(request.url);
}
return this._getStrategy().handle(options);
};

@@ -437,6 +524,25 @@ }

const request = new Request(url);
return () => handler({request});
return (options) => handler(Object.assign(options, {request}));
}
_getStrategy(): Strategy {
// NOTE: this needs to be done lazily to match v5 behavior, since the
// `addPlugins()` method can be called at any time.
if (!this._strategy) {
this._strategy = new PrecacheStrategy({
cacheName: this._cacheName,
matchOptions: {
ignoreSearch: true,
},
plugins: [
this._cacheKeyPlugin,
...this._plugins,
],
});
}
return this._strategy;
}
}
export {PrecacheController};

@@ -9,4 +9,4 @@ /*

import {FetchListenerOptions} from './addFetchListener.js';
import {removeIgnoredSearchParams} from './removeIgnoredSearchParams.js';
import {FetchListenerOptions} from '../_types.js';
import '../_version.js';

@@ -26,5 +26,5 @@

export function* generateURLVariations(url: string, {
ignoreURLParametersMatching,
directoryIndex,
cleanURLs,
ignoreURLParametersMatching = [/^utm_/, /^fbclid$/],
directoryIndex = 'index.html',
cleanURLs = true,
urlManipulation,

@@ -31,0 +31,0 @@ }: FetchListenerOptions = {}) {

@@ -9,7 +9,8 @@ /*

import {FetchListenerOptions} from './addFetchListener.js';
import {getOrCreatePrecacheController} from './getOrCreatePrecacheController.js';
import {generateURLVariations} from './generateURLVariations.js';
import {FetchListenerOptions} from '../_types.js';
import '../_version.js';
/**

@@ -16,0 +17,0 @@ * This function will take the request URL and manipulate it based on the

@@ -12,4 +12,6 @@ {

"references": [
{ "path": "../workbox-core/" }
{ "path": "../workbox-core/" },
{ "path": "../workbox-routing/" },
{ "path": "../workbox-strategies/" }
]
}

@@ -1,2 +0,2 @@

import { FetchListenerOptions } from './addFetchListener.js';
import { FetchListenerOptions } from '../_types.js';
import '../_version.js';

@@ -3,0 +3,0 @@ /**

@@ -20,3 +20,3 @@ /*

*/
export function* generateURLVariations(url, { ignoreURLParametersMatching, directoryIndex, cleanURLs, urlManipulation, } = {}) {
export function* generateURLVariations(url, { ignoreURLParametersMatching = [/^utm_/, /^fbclid$/], directoryIndex = 'index.html', cleanURLs = true, urlManipulation, } = {}) {
const urlObject = new URL(url, location.href);

@@ -23,0 +23,0 @@ urlObject.hash = '';

@@ -1,2 +0,2 @@

import { FetchListenerOptions } from './addFetchListener.js';
import { FetchListenerOptions } from '../_types.js';
import '../_version.js';

@@ -3,0 +3,0 @@ /**

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc