From 6ec00afac5afc892dca5a184b66467d9408f14a5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 21 Nov 2022 22:00:30 +0000 Subject: chore: autopublish 2022-11-21T22:00:30Z --- public/workbox-v4.3.1/workbox-core.dev.js | 1712 +++++++++++++++++++++++++++++ 1 file changed, 1712 insertions(+) create mode 100644 public/workbox-v4.3.1/workbox-core.dev.js (limited to 'public/workbox-v4.3.1/workbox-core.dev.js') diff --git a/public/workbox-v4.3.1/workbox-core.dev.js b/public/workbox-v4.3.1/workbox-core.dev.js new file mode 100644 index 0000000..18b8b85 --- /dev/null +++ b/public/workbox-v4.3.1/workbox-core.dev.js @@ -0,0 +1,1712 @@ +this.workbox = this.workbox || {}; +this.workbox.core = (function (exports) { + 'use strict'; + + try { + self['workbox:core:4.3.1'] && _(); + } catch (e) {} // eslint-disable-line + + /* + 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 logger = (() => { + let inGroup = false; + const methodToColorMap = { + debug: `#7f8c8d`, + // Gray + log: `#2ecc71`, + // Green + warn: `#f39c12`, + // Yellow + error: `#c0392b`, + // Red + groupCollapsed: `#3498db`, + // Blue + groupEnd: null // No colored prefix on groupEnd + + }; + + const print = function (method, args) { + if (method === 'groupCollapsed') { + // Safari doesn't print all console.groupCollapsed() arguments: + // https://bugs.webkit.org/show_bug.cgi?id=182754 + if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) { + console[method](...args); + return; + } + } + + const styles = [`background: ${methodToColorMap[method]}`, `border-radius: 0.5em`, `color: white`, `font-weight: bold`, `padding: 2px 0.5em`]; // When in a group, the workbox prefix is not displayed. + + const logPrefix = inGroup ? [] : ['%cworkbox', styles.join(';')]; + console[method](...logPrefix, ...args); + + if (method === 'groupCollapsed') { + inGroup = true; + } + + if (method === 'groupEnd') { + inGroup = false; + } + }; + + const api = {}; + + for (const method of Object.keys(methodToColorMap)) { + api[method] = (...args) => { + print(method, args); + }; + } + + return api; + })(); + + /* + 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. + */ + const messages = { + 'invalid-value': ({ + paramName, + validValueDescription, + value + }) => { + if (!paramName || !validValueDescription) { + throw new Error(`Unexpected input to 'invalid-value' error.`); + } + + return `The '${paramName}' parameter was given a value with an ` + `unexpected value. ${validValueDescription} Received a value of ` + `${JSON.stringify(value)}.`; + }, + 'not-in-sw': ({ + moduleName + }) => { + if (!moduleName) { + throw new Error(`Unexpected input to 'not-in-sw' error.`); + } + + return `The '${moduleName}' must be used in a service worker.`; + }, + 'not-an-array': ({ + moduleName, + className, + funcName, + paramName + }) => { + if (!moduleName || !className || !funcName || !paramName) { + throw new Error(`Unexpected input to 'not-an-array' error.`); + } + + return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className}.${funcName}()' must be an array.`; + }, + 'incorrect-type': ({ + expectedType, + paramName, + moduleName, + className, + funcName + }) => { + if (!expectedType || !paramName || !moduleName || !funcName) { + throw new Error(`Unexpected input to 'incorrect-type' error.`); + } + + return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className ? className + '.' : ''}` + `${funcName}()' must be of type ${expectedType}.`; + }, + 'incorrect-class': ({ + expectedClass, + paramName, + moduleName, + className, + funcName, + isReturnValueProblem + }) => { + if (!expectedClass || !moduleName || !funcName) { + throw new Error(`Unexpected input to 'incorrect-class' error.`); + } + + if (isReturnValueProblem) { + return `The return value from ` + `'${moduleName}.${className ? className + '.' : ''}${funcName}()' ` + `must be an instance of class ${expectedClass.name}.`; + } + + return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className ? className + '.' : ''}${funcName}()' ` + `must be an instance of class ${expectedClass.name}.`; + }, + 'missing-a-method': ({ + expectedMethod, + paramName, + moduleName, + className, + funcName + }) => { + if (!expectedMethod || !paramName || !moduleName || !className || !funcName) { + throw new Error(`Unexpected input to 'missing-a-method' error.`); + } + + return `${moduleName}.${className}.${funcName}() expected the ` + `'${paramName}' parameter to expose a '${expectedMethod}' method.`; + }, + 'add-to-cache-list-unexpected-type': ({ + entry + }) => { + return `An unexpected entry was passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' The entry ` + `'${JSON.stringify(entry)}' isn't supported. You must supply an array of ` + `strings with one or more characters, objects with a url property or ` + `Request objects.`; + }, + 'add-to-cache-list-conflicting-entries': ({ + firstEntry, + secondEntry + }) => { + if (!firstEntry || !secondEntry) { + throw new Error(`Unexpected input to ` + `'add-to-cache-list-duplicate-entries' error.`); + } + + return `Two of the entries passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` + `${firstEntry._entryId} but different revision details. Workbox is ` + `is unable to cache and version the asset correctly. Please remove one ` + `of the entries.`; + }, + 'plugin-error-request-will-fetch': ({ + thrownError + }) => { + if (!thrownError) { + throw new Error(`Unexpected input to ` + `'plugin-error-request-will-fetch', error.`); + } + + return `An error was thrown by a plugins 'requestWillFetch()' method. ` + `The thrown error message was: '${thrownError.message}'.`; + }, + 'invalid-cache-name': ({ + cacheNameId, + value + }) => { + if (!cacheNameId) { + throw new Error(`Expected a 'cacheNameId' for error 'invalid-cache-name'`); + } + + return `You must provide a name containing at least one character for ` + `setCacheDeatils({${cacheNameId}: '...'}). Received a value of ` + `'${JSON.stringify(value)}'`; + }, + 'unregister-route-but-not-found-with-method': ({ + method + }) => { + if (!method) { + throw new Error(`Unexpected input to ` + `'unregister-route-but-not-found-with-method' error.`); + } + + return `The route you're trying to unregister was not previously ` + `registered for the method type '${method}'.`; + }, + 'unregister-route-route-not-registered': () => { + return `The route you're trying to unregister was not previously ` + `registered.`; + }, + 'queue-replay-failed': ({ + name + }) => { + return `Replaying the background sync queue '${name}' failed.`; + }, + 'duplicate-queue-name': ({ + name + }) => { + return `The Queue name '${name}' is already being used. ` + `All instances of backgroundSync.Queue must be given unique names.`; + }, + 'expired-test-without-max-age': ({ + methodName, + paramName + }) => { + return `The '${methodName}()' method can only be used when the ` + `'${paramName}' is used in the constructor.`; + }, + 'unsupported-route-type': ({ + moduleName, + className, + funcName, + paramName + }) => { + return `The supplied '${paramName}' parameter was an unsupported type. ` + `Please check the docs for ${moduleName}.${className}.${funcName} for ` + `valid input types.`; + }, + 'not-array-of-class': ({ + value, + expectedClass, + moduleName, + className, + funcName, + paramName + }) => { + return `The supplied '${paramName}' parameter must be an array of ` + `'${expectedClass}' objects. Received '${JSON.stringify(value)},'. ` + `Please check the call to ${moduleName}.${className}.${funcName}() ` + `to fix the issue.`; + }, + 'max-entries-or-age-required': ({ + moduleName, + className, + funcName + }) => { + return `You must define either config.maxEntries or config.maxAgeSeconds` + `in ${moduleName}.${className}.${funcName}`; + }, + 'statuses-or-headers-required': ({ + moduleName, + className, + funcName + }) => { + return `You must define either config.statuses or config.headers` + `in ${moduleName}.${className}.${funcName}`; + }, + 'invalid-string': ({ + moduleName, + className, + funcName, + paramName + }) => { + if (!paramName || !moduleName || !funcName) { + throw new Error(`Unexpected input to 'invalid-string' error.`); + } + + return `When using strings, the '${paramName}' parameter must start with ` + `'http' (for cross-origin matches) or '/' (for same-origin matches). ` + `Please see the docs for ${moduleName}.${funcName}() for ` + `more info.`; + }, + 'channel-name-required': () => { + return `You must provide a channelName to construct a ` + `BroadcastCacheUpdate instance.`; + }, + 'invalid-responses-are-same-args': () => { + return `The arguments passed into responsesAreSame() appear to be ` + `invalid. Please ensure valid Responses are used.`; + }, + 'expire-custom-caches-only': () => { + return `You must provide a 'cacheName' property when using the ` + `expiration plugin with a runtime caching strategy.`; + }, + 'unit-must-be-bytes': ({ + normalizedRangeHeader + }) => { + if (!normalizedRangeHeader) { + throw new Error(`Unexpected input to 'unit-must-be-bytes' error.`); + } + + return `The 'unit' portion of the Range header must be set to 'bytes'. ` + `The Range header provided was "${normalizedRangeHeader}"`; + }, + 'single-range-only': ({ + normalizedRangeHeader + }) => { + if (!normalizedRangeHeader) { + throw new Error(`Unexpected input to 'single-range-only' error.`); + } + + return `Multiple ranges are not supported. Please use a single start ` + `value, and optional end value. The Range header provided was ` + `"${normalizedRangeHeader}"`; + }, + 'invalid-range-values': ({ + normalizedRangeHeader + }) => { + if (!normalizedRangeHeader) { + throw new Error(`Unexpected input to 'invalid-range-values' error.`); + } + + return `The Range header is missing both start and end values. At least ` + `one of those values is needed. The Range header provided was ` + `"${normalizedRangeHeader}"`; + }, + 'no-range-header': () => { + return `No Range header was found in the Request provided.`; + }, + 'range-not-satisfiable': ({ + size, + start, + end + }) => { + return `The start (${start}) and end (${end}) values in the Range are ` + `not satisfiable by the cached response, which is ${size} bytes.`; + }, + 'attempt-to-cache-non-get-request': ({ + url, + method + }) => { + return `Unable to cache '${url}' because it is a '${method}' request and ` + `only 'GET' requests can be cached.`; + }, + 'cache-put-with-no-response': ({ + url + }) => { + return `There was an attempt to cache '${url}' but the response was not ` + `defined.`; + }, + 'no-response': ({ + url, + error + }) => { + let message = `The strategy could not generate a response for '${url}'.`; + + if (error) { + message += ` The underlying error is ${error}.`; + } + + return message; + }, + 'bad-precaching-response': ({ + url, + status + }) => { + return `The precaching request for '${url}' failed with an HTTP ` + `status of ${status}.`; + } + }; + + /* + 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. + */ + + const generatorFunction = (code, ...args) => { + const message = messages[code]; + + if (!message) { + throw new Error(`Unable to find message for code '${code}'.`); + } + + return message(...args); + }; + + const messageGenerator = generatorFunction; + + /* + 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. + */ + /** + * Workbox errors should be thrown with this class. + * This allows use to ensure the type easily in tests, + * helps developers identify errors from workbox + * easily and allows use to optimise error + * messages correctly. + * + * @private + */ + + class WorkboxError extends Error { + /** + * + * @param {string} errorCode The error code that + * identifies this particular error. + * @param {Object=} details Any relevant arguments + * that will help developers identify issues should + * be added as a key on the context object. + */ + constructor(errorCode, details) { + let message = messageGenerator(errorCode, details); + super(message); + this.name = errorCode; + this.details = details; + } + + } + + /* + 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. + */ + /* + * This method returns true if the current context is a service worker. + */ + + const isSWEnv = moduleName => { + if (!('ServiceWorkerGlobalScope' in self)) { + throw new WorkboxError('not-in-sw', { + moduleName + }); + } + }; + /* + * This method throws if the supplied value is not an array. + * The destructed values are required to produce a meaningful error for users. + * The destructed and restructured object is so it's clear what is + * needed. + */ + + + const isArray = (value, { + moduleName, + className, + funcName, + paramName + }) => { + if (!Array.isArray(value)) { + throw new WorkboxError('not-an-array', { + moduleName, + className, + funcName, + paramName + }); + } + }; + + const hasMethod = (object, expectedMethod, { + moduleName, + className, + funcName, + paramName + }) => { + const type = typeof object[expectedMethod]; + + if (type !== 'function') { + throw new WorkboxError('missing-a-method', { + paramName, + expectedMethod, + moduleName, + className, + funcName + }); + } + }; + + const isType = (object, expectedType, { + moduleName, + className, + funcName, + paramName + }) => { + if (typeof object !== expectedType) { + throw new WorkboxError('incorrect-type', { + paramName, + expectedType, + moduleName, + className, + funcName + }); + } + }; + + const isInstance = (object, expectedClass, { + moduleName, + className, + funcName, + paramName, + isReturnValueProblem + }) => { + if (!(object instanceof expectedClass)) { + throw new WorkboxError('incorrect-class', { + paramName, + expectedClass, + moduleName, + className, + funcName, + isReturnValueProblem + }); + } + }; + + const isOneOf = (value, validValues, { + paramName + }) => { + if (!validValues.includes(value)) { + throw new WorkboxError('invalid-value', { + paramName, + value, + validValueDescription: `Valid values are ${JSON.stringify(validValues)}.` + }); + } + }; + + const isArrayOfClass = (value, expectedClass, { + moduleName, + className, + funcName, + paramName + }) => { + const error = new WorkboxError('not-array-of-class', { + value, + expectedClass, + moduleName, + className, + funcName, + paramName + }); + + if (!Array.isArray(value)) { + throw error; + } + + for (let item of value) { + if (!(item instanceof expectedClass)) { + throw error; + } + } + }; + + const finalAssertExports = { + hasMethod, + isArray, + isInstance, + isOneOf, + isSWEnv, + isType, + isArrayOfClass + }; + + /* + 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. + */ + + const quotaErrorCallbacks = new Set(); + + /* + 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 function to the set of quotaErrorCallbacks that will be executed if + * there's a quota error. + * + * @param {Function} callback + * @memberof workbox.core + */ + + function registerQuotaErrorCallback(callback) { + { + finalAssertExports.isType(callback, 'function', { + moduleName: 'workbox-core', + funcName: 'register', + paramName: 'callback' + }); + } + + quotaErrorCallbacks.add(callback); + + { + logger.log('Registered a callback to respond to quota errors.', callback); + } + } + + /* + 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. + */ + const _cacheNameDetails = { + googleAnalytics: 'googleAnalytics', + precache: 'precache-v2', + prefix: 'workbox', + runtime: 'runtime', + suffix: self.registration.scope + }; + + const _createCacheName = cacheName => { + return [_cacheNameDetails.prefix, cacheName, _cacheNameDetails.suffix].filter(value => value.length > 0).join('-'); + }; + + const cacheNames = { + updateDetails: details => { + Object.keys(_cacheNameDetails).forEach(key => { + if (typeof details[key] !== 'undefined') { + _cacheNameDetails[key] = details[key]; + } + }); + }, + getGoogleAnalyticsName: userCacheName => { + return userCacheName || _createCacheName(_cacheNameDetails.googleAnalytics); + }, + getPrecacheName: userCacheName => { + return userCacheName || _createCacheName(_cacheNameDetails.precache); + }, + getPrefix: () => { + return _cacheNameDetails.prefix; + }, + getRuntimeName: userCacheName => { + return userCacheName || _createCacheName(_cacheNameDetails.runtime); + }, + getSuffix: () => { + return _cacheNameDetails.suffix; + } + }; + + /* + 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. + */ + + const getFriendlyURL = url => { + const urlObj = new URL(url, location); + + if (urlObj.origin === location.origin) { + return urlObj.pathname; + } + + return urlObj.href; + }; + + /* + 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. + */ + /** + * Runs all of the callback functions, one at a time sequentially, in the order + * in which they were registered. + * + * @memberof workbox.core + * @private + */ + + async function executeQuotaErrorCallbacks() { + { + logger.log(`About to run ${quotaErrorCallbacks.size} ` + `callbacks to clean up caches.`); + } + + for (const callback of quotaErrorCallbacks) { + await callback(); + + { + logger.log(callback, 'is complete.'); + } + } + + { + logger.log('Finished running callbacks.'); + } + } + + /* + 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. + */ + const pluginEvents = { + CACHE_DID_UPDATE: 'cacheDidUpdate', + CACHE_KEY_WILL_BE_USED: 'cacheKeyWillBeUsed', + CACHE_WILL_UPDATE: 'cacheWillUpdate', + CACHED_RESPONSE_WILL_BE_USED: 'cachedResponseWillBeUsed', + FETCH_DID_FAIL: 'fetchDidFail', + FETCH_DID_SUCCEED: 'fetchDidSucceed', + REQUEST_WILL_FETCH: 'requestWillFetch' + }; + + /* + 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. + */ + const pluginUtils = { + filter: (plugins, callbackName) => { + return plugins.filter(plugin => callbackName in plugin); + } + }; + + /* + 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. + */ + /** + * Wrapper around cache.put(). + * + * Will call `cacheDidUpdate` on plugins if the cache was updated, using + * `matchOptions` when determining what the old entry is. + * + * @param {Object} options + * @param {string} options.cacheName + * @param {Request} options.request + * @param {Response} options.response + * @param {Event} [options.event] + * @param {Array} [options.plugins=[]] + * @param {Object} [options.matchOptions] + * + * @private + * @memberof module:workbox-core + */ + + const putWrapper = async ({ + cacheName, + request, + response, + event, + plugins = [], + matchOptions + } = {}) => { + { + if (request.method && request.method !== 'GET') { + throw new WorkboxError('attempt-to-cache-non-get-request', { + url: getFriendlyURL(request.url), + method: request.method + }); + } + } + + const effectiveRequest = await _getEffectiveRequest({ + plugins, + request, + mode: 'write' + }); + + if (!response) { + { + logger.error(`Cannot cache non-existent response for ` + `'${getFriendlyURL(effectiveRequest.url)}'.`); + } + + throw new WorkboxError('cache-put-with-no-response', { + url: getFriendlyURL(effectiveRequest.url) + }); + } + + let responseToCache = await _isResponseSafeToCache({ + event, + plugins, + response, + request: effectiveRequest + }); + + if (!responseToCache) { + { + logger.debug(`Response '${getFriendlyURL(effectiveRequest.url)}' will ` + `not be cached.`, responseToCache); + } + + return; + } + + const cache = await caches.open(cacheName); + const updatePlugins = pluginUtils.filter(plugins, pluginEvents.CACHE_DID_UPDATE); + let oldResponse = updatePlugins.length > 0 ? await matchWrapper({ + cacheName, + matchOptions, + request: effectiveRequest + }) : null; + + { + logger.debug(`Updating the '${cacheName}' cache with a new Response for ` + `${getFriendlyURL(effectiveRequest.url)}.`); + } + + try { + await cache.put(effectiveRequest, responseToCache); + } catch (error) { + // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError + if (error.name === 'QuotaExceededError') { + await executeQuotaErrorCallbacks(); + } + + throw error; + } + + for (let plugin of updatePlugins) { + await plugin[pluginEvents.CACHE_DID_UPDATE].call(plugin, { + cacheName, + event, + oldResponse, + newResponse: responseToCache, + request: effectiveRequest + }); + } + }; + /** + * This is a wrapper around cache.match(). + * + * @param {Object} options + * @param {string} options.cacheName Name of the cache to match against. + * @param {Request} options.request The Request that will be used to look up + * cache entries. + * @param {Event} [options.event] The event that propted the action. + * @param {Object} [options.matchOptions] Options passed to cache.match(). + * @param {Array} [options.plugins=[]] Array of plugins. + * @return {Response} A cached response if available. + * + * @private + * @memberof module:workbox-core + */ + + + const matchWrapper = async ({ + cacheName, + request, + event, + matchOptions, + plugins = [] + }) => { + const cache = await caches.open(cacheName); + const effectiveRequest = await _getEffectiveRequest({ + plugins, + request, + mode: 'read' + }); + let cachedResponse = await cache.match(effectiveRequest, matchOptions); + + { + if (cachedResponse) { + logger.debug(`Found a cached response in '${cacheName}'.`); + } else { + logger.debug(`No cached response found in '${cacheName}'.`); + } + } + + for (const plugin of plugins) { + if (pluginEvents.CACHED_RESPONSE_WILL_BE_USED in plugin) { + cachedResponse = await plugin[pluginEvents.CACHED_RESPONSE_WILL_BE_USED].call(plugin, { + cacheName, + event, + matchOptions, + cachedResponse, + request: effectiveRequest + }); + + { + if (cachedResponse) { + finalAssertExports.isInstance(cachedResponse, Response, { + moduleName: 'Plugin', + funcName: pluginEvents.CACHED_RESPONSE_WILL_BE_USED, + isReturnValueProblem: true + }); + } + } + } + } + + return cachedResponse; + }; + /** + * This method will call cacheWillUpdate on the available plugins (or use + * status === 200) to determine if the Response is safe and valid to cache. + * + * @param {Object} options + * @param {Request} options.request + * @param {Response} options.response + * @param {Event} [options.event] + * @param {Array} [options.plugins=[]] + * @return {Promise} + * + * @private + * @memberof module:workbox-core + */ + + + const _isResponseSafeToCache = async ({ + request, + response, + event, + plugins + }) => { + let responseToCache = response; + let pluginsUsed = false; + + for (let plugin of plugins) { + if (pluginEvents.CACHE_WILL_UPDATE in plugin) { + pluginsUsed = true; + responseToCache = await plugin[pluginEvents.CACHE_WILL_UPDATE].call(plugin, { + request, + response: responseToCache, + event + }); + + { + if (responseToCache) { + finalAssertExports.isInstance(responseToCache, Response, { + moduleName: 'Plugin', + funcName: pluginEvents.CACHE_WILL_UPDATE, + isReturnValueProblem: true + }); + } + } + + if (!responseToCache) { + break; + } + } + } + + if (!pluginsUsed) { + { + if (!responseToCache.status === 200) { + if (responseToCache.status === 0) { + logger.warn(`The response for '${request.url}' is an opaque ` + `response. The caching strategy that you're using will not ` + `cache opaque responses by default.`); + } else { + logger.debug(`The response for '${request.url}' returned ` + `a status code of '${response.status}' and won't be cached as a ` + `result.`); + } + } + } + + responseToCache = responseToCache.status === 200 ? responseToCache : null; + } + + return responseToCache ? responseToCache : null; + }; + /** + * 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 {Object} options + * @param {Request} options.request + * @param {string} options.mode + * @param {Array} [options.plugins=[]] + * @return {Promise} + * + * @private + * @memberof module:workbox-core + */ + + + const _getEffectiveRequest = async ({ + request, + mode, + plugins + }) => { + const cacheKeyWillBeUsedPlugins = pluginUtils.filter(plugins, pluginEvents.CACHE_KEY_WILL_BE_USED); + let effectiveRequest = request; + + for (const plugin of cacheKeyWillBeUsedPlugins) { + effectiveRequest = await plugin[pluginEvents.CACHE_KEY_WILL_BE_USED].call(plugin, { + mode, + request: effectiveRequest + }); + + if (typeof effectiveRequest === 'string') { + effectiveRequest = new Request(effectiveRequest); + } + + { + finalAssertExports.isInstance(effectiveRequest, Request, { + moduleName: 'Plugin', + funcName: pluginEvents.CACHE_KEY_WILL_BE_USED, + isReturnValueProblem: true + }); + } + } + + return effectiveRequest; + }; + + const cacheWrapper = { + put: putWrapper, + match: matchWrapper + }; + + /* + 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. + */ + /** + * A class that wraps common IndexedDB functionality in a promise-based API. + * It exposes all the underlying power and functionality of IndexedDB, but + * wraps the most commonly used features in a way that's much simpler to use. + * + * @private + */ + + class DBWrapper { + /** + * @param {string} name + * @param {number} version + * @param {Object=} [callback] + * @param {!Function} [callbacks.onupgradeneeded] + * @param {!Function} [callbacks.onversionchange] Defaults to + * DBWrapper.prototype._onversionchange when not specified. + * @private + */ + constructor(name, version, { + onupgradeneeded, + onversionchange = this._onversionchange + } = {}) { + this._name = name; + this._version = version; + this._onupgradeneeded = onupgradeneeded; + this._onversionchange = onversionchange; // If this is null, it means the database isn't open. + + this._db = null; + } + /** + * Returns the IDBDatabase instance (not normally needed). + * + * @private + */ + + + get db() { + return this._db; + } + /** + * Opens a connected to an IDBDatabase, invokes any onupgradedneeded + * callback, and added an onversionchange callback to the database. + * + * @return {IDBDatabase} + * @private + */ + + + async open() { + if (this._db) return; + this._db = await new Promise((resolve, reject) => { + // This flag is flipped to true if the timeout callback runs prior + // to the request failing or succeeding. Note: we use a timeout instead + // of an onblocked handler since there are cases where onblocked will + // never never run. A timeout better handles all possible scenarios: + // https://github.com/w3c/IndexedDB/issues/223 + let openRequestTimedOut = false; + setTimeout(() => { + openRequestTimedOut = true; + reject(new Error('The open request was blocked and timed out')); + }, this.OPEN_TIMEOUT); + const openRequest = indexedDB.open(this._name, this._version); + + openRequest.onerror = () => reject(openRequest.error); + + openRequest.onupgradeneeded = evt => { + if (openRequestTimedOut) { + openRequest.transaction.abort(); + evt.target.result.close(); + } else if (this._onupgradeneeded) { + this._onupgradeneeded(evt); + } + }; + + openRequest.onsuccess = ({ + target + }) => { + const db = target.result; + + if (openRequestTimedOut) { + db.close(); + } else { + db.onversionchange = this._onversionchange.bind(this); + resolve(db); + } + }; + }); + return this; + } + /** + * Polyfills the native `getKey()` method. Note, this is overridden at + * runtime if the browser supports the native method. + * + * @param {string} storeName + * @param {*} query + * @return {Array} + * @private + */ + + + async getKey(storeName, query) { + return (await this.getAllKeys(storeName, query, 1))[0]; + } + /** + * Polyfills the native `getAll()` method. Note, this is overridden at + * runtime if the browser supports the native method. + * + * @param {string} storeName + * @param {*} query + * @param {number} count + * @return {Array} + * @private + */ + + + async getAll(storeName, query, count) { + return await this.getAllMatching(storeName, { + query, + count + }); + } + /** + * Polyfills the native `getAllKeys()` method. Note, this is overridden at + * runtime if the browser supports the native method. + * + * @param {string} storeName + * @param {*} query + * @param {number} count + * @return {Array} + * @private + */ + + + async getAllKeys(storeName, query, count) { + return (await this.getAllMatching(storeName, { + query, + count, + includeKeys: true + })).map(({ + key + }) => key); + } + /** + * Supports flexible lookup in an object store by specifying an index, + * query, direction, and count. This method returns an array of objects + * with the signature . + * + * @param {string} storeName + * @param {Object} [opts] + * @param {string} [opts.index] The index to use (if specified). + * @param {*} [opts.query] + * @param {IDBCursorDirection} [opts.direction] + * @param {number} [opts.count] The max number of results to return. + * @param {boolean} [opts.includeKeys] When true, the structure of the + * returned objects is changed from an array of values to an array of + * objects in the form {key, primaryKey, value}. + * @return {Array} + * @private + */ + + + async getAllMatching(storeName, { + index, + query = null, + // IE errors if query === `undefined`. + direction = 'next', + count, + includeKeys + } = {}) { + return await this.transaction([storeName], 'readonly', (txn, done) => { + const store = txn.objectStore(storeName); + const target = index ? store.index(index) : store; + const results = []; + + target.openCursor(query, direction).onsuccess = ({ + target + }) => { + const cursor = target.result; + + if (cursor) { + const { + primaryKey, + key, + value + } = cursor; + results.push(includeKeys ? { + primaryKey, + key, + value + } : value); + + if (count && results.length >= count) { + done(results); + } else { + cursor.continue(); + } + } else { + done(results); + } + }; + }); + } + /** + * Accepts a list of stores, a transaction type, and a callback and + * performs a transaction. A promise is returned that resolves to whatever + * value the callback chooses. The callback holds all the transaction logic + * and is invoked with two arguments: + * 1. The IDBTransaction object + * 2. A `done` function, that's used to resolve the promise when + * when the transaction is done, if passed a value, the promise is + * resolved to that value. + * + * @param {Array} storeNames An array of object store names + * involved in the transaction. + * @param {string} type Can be `readonly` or `readwrite`. + * @param {!Function} callback + * @return {*} The result of the transaction ran by the callback. + * @private + */ + + + async transaction(storeNames, type, callback) { + await this.open(); + return await new Promise((resolve, reject) => { + const txn = this._db.transaction(storeNames, type); + + txn.onabort = ({ + target + }) => reject(target.error); + + txn.oncomplete = () => resolve(); + + callback(txn, value => resolve(value)); + }); + } + /** + * Delegates async to a native IDBObjectStore method. + * + * @param {string} method The method name. + * @param {string} storeName The object store name. + * @param {string} type Can be `readonly` or `readwrite`. + * @param {...*} args The list of args to pass to the native method. + * @return {*} The result of the transaction. + * @private + */ + + + async _call(method, storeName, type, ...args) { + const callback = (txn, done) => { + txn.objectStore(storeName)[method](...args).onsuccess = ({ + target + }) => { + done(target.result); + }; + }; + + return await this.transaction([storeName], type, callback); + } + /** + * The default onversionchange handler, which closes the database so other + * connections can open without being blocked. + * + * @private + */ + + + _onversionchange() { + this.close(); + } + /** + * Closes the connection opened by `DBWrapper.open()`. Generally this method + * doesn't need to be called since: + * 1. It's usually better to keep a connection open since opening + * a new connection is somewhat slow. + * 2. Connections are automatically closed when the reference is + * garbage collected. + * The primary use case for needing to close a connection is when another + * reference (typically in another tab) needs to upgrade it and would be + * blocked by the current, open connection. + * + * @private + */ + + + close() { + if (this._db) { + this._db.close(); + + this._db = null; + } + } + + } // Exposed to let users modify the default timeout on a per-instance + // or global basis. + + DBWrapper.prototype.OPEN_TIMEOUT = 2000; // Wrap native IDBObjectStore methods according to their mode. + + const methodsToWrap = { + 'readonly': ['get', 'count', 'getKey', 'getAll', 'getAllKeys'], + 'readwrite': ['add', 'put', 'clear', 'delete'] + }; + + for (const [mode, methods] of Object.entries(methodsToWrap)) { + for (const method of methods) { + if (method in IDBObjectStore.prototype) { + // Don't use arrow functions here since we're outside of the class. + DBWrapper.prototype[method] = async function (storeName, ...args) { + return await this._call(method, storeName, mode, ...args); + }; + } + } + } + + /* + 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. + */ + /** + * The Deferred class composes Promises in a way that allows for them to be + * resolved or rejected from outside the constructor. In most cases promises + * should be used directly, but Deferreds can be necessary when the logic to + * resolve a promise must be separate. + * + * @private + */ + + class Deferred { + /** + * Creates a promise and exposes its resolve and reject functions as methods. + */ + constructor() { + this.promise = new Promise((resolve, reject) => { + this.resolve = resolve; + this.reject = reject; + }); + } + + } + + /* + 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. + */ + /** + * Deletes the database. + * Note: this is exported separately from the DBWrapper module because most + * usages of IndexedDB in workbox dont need deleting, and this way it can be + * reused in tests to delete databases without creating DBWrapper instances. + * + * @param {string} name The database name. + * @private + */ + + const deleteDatabase = async name => { + await new Promise((resolve, reject) => { + const request = indexedDB.deleteDatabase(name); + + request.onerror = ({ + target + }) => { + reject(target.error); + }; + + request.onblocked = () => { + reject(new Error('Delete blocked')); + }; + + request.onsuccess = () => { + resolve(); + }; + }); + }; + + /* + 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. + */ + /** + * Wrapper around the fetch API. + * + * Will call requestWillFetch on available plugins. + * + * @param {Object} options + * @param {Request|string} options.request + * @param {Object} [options.fetchOptions] + * @param {Event} [options.event] + * @param {Array} [options.plugins=[]] + * @return {Promise} + * + * @private + * @memberof module:workbox-core + */ + + const wrappedFetch = async ({ + request, + fetchOptions, + event, + plugins = [] + }) => { + // We *should* be able to call `await event.preloadResponse` even if it's + // undefined, but for some reason, doing so leads to errors in our Node unit + // tests. To work around that, explicitly check preloadResponse's value first. + if (event && event.preloadResponse) { + const possiblePreloadResponse = await event.preloadResponse; + + if (possiblePreloadResponse) { + { + logger.log(`Using a preloaded navigation response for ` + `'${getFriendlyURL(request.url)}'`); + } + + return possiblePreloadResponse; + } + } + + if (typeof request === 'string') { + request = new Request(request); + } + + { + finalAssertExports.isInstance(request, Request, { + paramName: request, + expectedClass: 'Request', + moduleName: 'workbox-core', + className: 'fetchWrapper', + funcName: 'wrappedFetch' + }); + } + + const failedFetchPlugins = pluginUtils.filter(plugins, pluginEvents.FETCH_DID_FAIL); // 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 = failedFetchPlugins.length > 0 ? request.clone() : null; + + try { + for (let plugin of plugins) { + if (pluginEvents.REQUEST_WILL_FETCH in plugin) { + request = await plugin[pluginEvents.REQUEST_WILL_FETCH].call(plugin, { + request: request.clone(), + event + }); + + { + if (request) { + finalAssertExports.isInstance(request, Request, { + moduleName: 'Plugin', + funcName: pluginEvents.CACHED_RESPONSE_WILL_BE_USED, + isReturnValueProblem: true + }); + } + } + } + } + } 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) to be different + // to the Request we make. Pass both to `fetchDidFail` to aid debugging. + + + let pluginFilteredRequest = request.clone(); + + try { + let fetchResponse; // See https://github.com/GoogleChrome/workbox/issues/1796 + + if (request.mode === 'navigate') { + fetchResponse = await fetch(request); + } else { + fetchResponse = await fetch(request, fetchOptions); + } + + { + logger.debug(`Network request for ` + `'${getFriendlyURL(request.url)}' returned a response with ` + `status '${fetchResponse.status}'.`); + } + + for (const plugin of plugins) { + if (pluginEvents.FETCH_DID_SUCCEED in plugin) { + fetchResponse = await plugin[pluginEvents.FETCH_DID_SUCCEED].call(plugin, { + event, + request: pluginFilteredRequest, + response: fetchResponse + }); + + { + if (fetchResponse) { + finalAssertExports.isInstance(fetchResponse, Response, { + moduleName: 'Plugin', + funcName: pluginEvents.FETCH_DID_SUCCEED, + isReturnValueProblem: true + }); + } + } + } + } + + return fetchResponse; + } catch (error) { + { + logger.error(`Network request for ` + `'${getFriendlyURL(request.url)}' threw an error.`, error); + } + + for (const plugin of failedFetchPlugins) { + await plugin[pluginEvents.FETCH_DID_FAIL].call(plugin, { + error, + event, + originalRequest: originalRequest.clone(), + request: pluginFilteredRequest.clone() + }); + } + + throw error; + } + }; + + const fetchWrapper = { + fetch: wrappedFetch + }; + + /* + 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. + */ + + var _private = /*#__PURE__*/Object.freeze({ + assert: finalAssertExports, + cacheNames: cacheNames, + cacheWrapper: cacheWrapper, + DBWrapper: DBWrapper, + Deferred: Deferred, + deleteDatabase: deleteDatabase, + executeQuotaErrorCallbacks: executeQuotaErrorCallbacks, + fetchWrapper: fetchWrapper, + getFriendlyURL: getFriendlyURL, + logger: logger, + WorkboxError: WorkboxError + }); + + /* + 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. + */ + /** + * Claim any currently available clients once the service worker + * becomes active. This is normally used in conjunction with `skipWaiting()`. + * + * @alias workbox.core.clientsClaim + */ + + const clientsClaim = () => { + addEventListener('activate', () => clients.claim()); + }; + + /* + 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. + */ + /** + * Get the current cache names and prefix/suffix used by Workbox. + * + * `cacheNames.precache` is used for precached assets, + * `cacheNames.googleAnalytics` is used by `workbox-google-analytics` to + * store `analytics.js`, and `cacheNames.runtime` is used for everything else. + * + * `cacheNames.prefix` can be used to retrieve just the current prefix value. + * `cacheNames.suffix` can be used to retrieve just the current suffix value. + * + * @return {Object} An object with `precache`, `runtime`, `prefix`, and + * `googleAnalytics` properties. + * + * @alias workbox.core.cacheNames + */ + + const cacheNames$1 = { + get googleAnalytics() { + return cacheNames.getGoogleAnalyticsName(); + }, + + get precache() { + return cacheNames.getPrecacheName(); + }, + + get prefix() { + return cacheNames.getPrefix(); + }, + + get runtime() { + return cacheNames.getRuntimeName(); + }, + + get suffix() { + return cacheNames.getSuffix(); + } + + }; + + /* + 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. + */ + /** + * Modifies the default cache names used by the Workbox packages. + * Cache names are generated as `--`. + * + * @param {Object} details + * @param {Object} [details.prefix] The string to add to the beginning of + * the precache and runtime cache names. + * @param {Object} [details.suffix] The string to add to the end of + * the precache and runtime cache names. + * @param {Object} [details.precache] The cache name to use for precache + * caching. + * @param {Object} [details.runtime] The cache name to use for runtime caching. + * @param {Object} [details.googleAnalytics] The cache name to use for + * `workbox-google-analytics` caching. + * + * @alias workbox.core.setCacheNameDetails + */ + + const setCacheNameDetails = details => { + { + Object.keys(details).forEach(key => { + finalAssertExports.isType(details[key], 'string', { + moduleName: 'workbox-core', + funcName: 'setCacheNameDetails', + paramName: `details.${key}` + }); + }); + + if ('precache' in details && details.precache.length === 0) { + throw new WorkboxError('invalid-cache-name', { + cacheNameId: 'precache', + value: details.precache + }); + } + + if ('runtime' in details && details.runtime.length === 0) { + throw new WorkboxError('invalid-cache-name', { + cacheNameId: 'runtime', + value: details.runtime + }); + } + + if ('googleAnalytics' in details && details.googleAnalytics.length === 0) { + throw new WorkboxError('invalid-cache-name', { + cacheNameId: 'googleAnalytics', + value: details.googleAnalytics + }); + } + } + + cacheNames.updateDetails(details); + }; + + /* + 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. + */ + /** + * Force a service worker to become active, instead of waiting. This is + * normally used in conjunction with `clientsClaim()`. + * + * @alias workbox.core.skipWaiting + */ + + const skipWaiting = () => { + // We need to explicitly call `self.skipWaiting()` here because we're + // shadowing `skipWaiting` with this local function. + addEventListener('install', () => self.skipWaiting()); + }; + + /* + 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. + */ + + try { + self.workbox.v = self.workbox.v || {}; + } catch (errer) {} // NOOP + + exports._private = _private; + exports.clientsClaim = clientsClaim; + exports.cacheNames = cacheNames$1; + exports.registerQuotaErrorCallback = registerQuotaErrorCallback; + exports.setCacheNameDetails = setCacheNameDetails; + exports.skipWaiting = skipWaiting; + + return exports; + +}({})); +//# sourceMappingURL=workbox-core.dev.js.map -- cgit