WIP - add extractor, generate snippet_data

This commit is contained in:
Stefan Fejes
2019-08-20 15:52:05 +02:00
parent 88084d3d30
commit cc8f1d8a7a
37396 changed files with 4588842 additions and 133 deletions

325
node_modules/workbox-core/_private/DBWrapper.mjs generated vendored Normal file
View File

@ -0,0 +1,325 @@
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import '../_version.mjs';
/**
* 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(this:DBWrapper, Event)} [callbacks.onupgradeneeded]
* @param {function(this:DBWrapper, Event)} [callbacks.onversionchange]
* Defaults to DBWrapper.prototype._onversionchange when not specified.
*/
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;
}
/**
* 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 = (evt) => reject(openRequest.error);
openRequest.onupgradeneeded = (evt) => {
if (openRequestTimedOut) {
openRequest.transaction.abort();
evt.target.result.close();
} else if (this._onupgradeneeded) {
this._onupgradeneeded(evt);
}
};
openRequest.onsuccess = (evt) => {
const db = evt.target.result;
if (openRequestTimedOut) {
db.close();
} else {
db.onversionchange = this._onversionchange;
resolve(db);
}
};
});
return this;
}
/**
* Delegates to the native `get()` method for the object store.
*
* @param {string} storeName The name of the object store to put the value.
* @param {...*} args The values passed to the delegated method.
* @return {*} The key of the entry.
*
* @private
*/
async get(storeName, ...args) {
return await this._call('get', storeName, 'readonly', ...args);
}
/**
* Delegates to the native `add()` method for the object store.
*
* @param {string} storeName The name of the object store to put the value.
* @param {...*} args The values passed to the delegated method.
* @return {*} The key of the entry.
*
* @private
*/
async add(storeName, ...args) {
return await this._call('add', storeName, 'readwrite', ...args);
}
/**
* Delegates to the native `put()` method for the object store.
*
* @param {string} storeName The name of the object store to put the value.
* @param {...*} args The values passed to the delegated method.
* @return {*} The key of the entry.
*
* @private
*/
async put(storeName, ...args) {
return await this._call('put', storeName, 'readwrite', ...args);
}
/**
* Delegates to the native `delete()` method for the object store.
*
* @param {string} storeName
* @param {...*} args The values passed to the delegated method.
*
* @private
*/
async delete(storeName, ...args) {
await this._call('delete', storeName, 'readwrite', ...args);
}
/**
* Deletes the underlying database, ensuring that any open connections are
* closed first.
*
* @private
*/
async deleteDatabase() {
this.close();
this._db = null;
await new Promise((resolve, reject) => {
const request = indexedDB.deleteDatabase(this._name);
request.onerror = (evt) => reject(evt.target.error);
request.onblocked = () => reject(new Error('Deletion was blocked.'));
request.onsuccess = () => resolve();
});
}
/**
* Delegates to the native `getAll()` or polyfills it via the `find()`
* method in older browsers.
*
* @param {string} storeName
* @param {*} query
* @param {number} count
* @return {Array}
*
* @private
*/
async getAll(storeName, query, count) {
if ('getAll' in IDBObjectStore.prototype) {
return await this._call('getAll', storeName, 'readonly', query, count);
} else {
return await this.getAllMatching(storeName, {query, count});
}
}
/**
* 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 {IDBCursorDirection} [opts.direction]
* @param {*} [opts.query]
* @param {string} [opts.index] The index to use (if specified).
* @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, opts = {}) {
return await this.transaction([storeName], 'readonly', (stores, done) => {
const store = stores[storeName];
const target = opts.index ? store.index(opts.index) : store;
const results = [];
// Passing `undefined` arguments to Edge's `openCursor(...)` causes
// 'DOMException: DataError'
// Details in issue: https://github.com/GoogleChrome/workbox/issues/1509
const query = opts.query || null;
const direction = opts.direction || 'next';
target.openCursor(query, direction).onsuccess = (evt) => {
const cursor = evt.target.result;
if (cursor) {
const {primaryKey, key, value} = cursor;
results.push(opts.includeKeys ? {primaryKey, key, value} : value);
if (opts.count && results.length >= opts.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 three arguments:
* 1. An object mapping object store names to IDBObjectStore values.
* 2. A `done` function, that's used to resolve the promise when
* when the transaction is done.
* 3. An `abort` function that can be called to abort the transaction
* at any time.
*
* @param {Array<string>} storeNames An array of object store names
* involved in the transaction.
* @param {string} type Can be `readonly` or `readwrite`.
* @param {function(Object, function(), function(*)):?IDBRequest} callback
* @return {*} The result of the transaction ran by the callback.
*
* @private
*/
async transaction(storeNames, type, callback) {
await this.open();
const result = await new Promise((resolve, reject) => {
const txn = this._db.transaction(storeNames, type);
const done = (value) => resolve(value);
const abort = () => {
reject(new Error('The transaction was manually aborted'));
txn.abort();
};
txn.onerror = (evt) => reject(evt.target.error);
txn.onabort = (evt) => reject(evt.target.error);
txn.oncomplete = () => resolve();
const stores = {};
for (const storeName of storeNames) {
stores[storeName] = txn.objectStore(storeName);
}
callback(stores, done, abort);
});
return result;
}
/**
* 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) {
await this.open();
const callback = (stores, done) => {
stores[storeName][method](...args).onsuccess = (evt) => {
done(evt.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.
*
* @param {Event} evt
*
* @private
*/
_onversionchange(evt) {
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();
}
}
// Exposed to let users modify the default timeout on a per-instance
// or global basis.
DBWrapper.prototype.OPEN_TIMEOUT = 2000;
export {DBWrapper};

48
node_modules/workbox-core/_private/WorkboxError.mjs generated vendored Normal file
View File

@ -0,0 +1,48 @@
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import messageGenerator from '../models/messages/messageGenerator.mjs';
import '../_version.mjs';
/**
* 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;
}
}
export {WorkboxError};

109
node_modules/workbox-core/_private/assert.mjs generated vendored Normal file
View File

@ -0,0 +1,109 @@
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {WorkboxError} from '../_private/WorkboxError.mjs';
import '../_version.mjs';
/*
* 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 = process.env.NODE_ENV === 'production' ? null : {
hasMethod,
isArray,
isInstance,
isOneOf,
isSwEnv,
isType,
isArrayOfClass,
};
export {finalAssertExports as assert};

52
node_modules/workbox-core/_private/cacheNames.mjs generated vendored Normal file
View File

@ -0,0 +1,52 @@
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import '../_version.mjs';
const _cacheNameDetails = {
prefix: 'workbox',
suffix: self.registration.scope,
googleAnalytics: 'googleAnalytics',
precache: 'precache',
runtime: 'runtime',
};
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);
},
getRuntimeName: (userCacheName) => {
return userCacheName || _createCacheName(_cacheNameDetails.runtime);
},
};
export {cacheNames};

236
node_modules/workbox-core/_private/cacheWrapper.mjs generated vendored Normal file
View File

@ -0,0 +1,236 @@
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import pluginEvents from '../models/pluginEvents.mjs';
import pluginUtils from '../utils/pluginUtils.mjs';
import {WorkboxError} from './WorkboxError.mjs';
import {assert} from './assert.mjs';
import {executeQuotaErrorCallbacks} from './quota.mjs';
import {getFriendlyURL} from './getFriendlyURL.mjs';
import {logger} from './logger.mjs';
import '../_version.mjs';
/**
* Wrapper around cache.put().
*
* Will call `cacheDidUpdate` on plugins if the cache was updated.
*
* @param {Object} options
* @param {string} options.cacheName
* @param {Request} options.request
* @param {Response} options.response
* @param {Event} [options.event]
* @param {Array<Object>} [options.plugins=[]]
*
* @private
* @memberof module:workbox-core
*/
const putWrapper = async ({
cacheName,
request,
response,
event,
plugins = [],
} = {}) => {
if (!response) {
if (process.env.NODE_ENV !== 'production') {
logger.error(`Cannot cache non-existent response for ` +
`'${getFriendlyURL(request.url)}'.`);
}
throw new WorkboxError('cache-put-with-no-response', {
url: getFriendlyURL(request.url),
});
}
let responseToCache =
await _isResponseSafeToCache({request, response, event, plugins});
if (!responseToCache) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Response '${getFriendlyURL(request.url)}' will not be ` +
`cached.`, responseToCache);
}
return;
}
if (process.env.NODE_ENV !== 'production') {
if (responseToCache.method && responseToCache.method !== 'GET') {
throw new WorkboxError('attempt-to-cache-non-get-request', {
url: getFriendlyURL(request.url),
method: responseToCache.method,
});
}
}
const cache = await caches.open(cacheName);
const updatePlugins = pluginUtils.filter(
plugins, pluginEvents.CACHE_DID_UPDATE);
let oldResponse = updatePlugins.length > 0 ?
await matchWrapper({cacheName, request}) : null;
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Updating the '${cacheName}' cache with a new Response for ` +
`${getFriendlyURL(request.url)}.`);
}
try {
await cache.put(request, 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,
request,
event,
oldResponse,
newResponse: responseToCache,
});
}
};
/**
* 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<Object>} [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);
let cachedResponse = await cache.match(request, matchOptions);
if (process.env.NODE_ENV !== 'production') {
if (cachedResponse) {
logger.debug(`Found a cached response in '${cacheName}'.`);
} else {
logger.debug(`No cached response found in '${cacheName}'.`);
}
}
for (let plugin of plugins) {
if (pluginEvents.CACHED_RESPONSE_WILL_BE_USED in plugin) {
cachedResponse = await plugin[pluginEvents.CACHED_RESPONSE_WILL_BE_USED]
.call(plugin, {
cacheName,
request,
event,
matchOptions,
cachedResponse,
});
if (process.env.NODE_ENV !== 'production') {
if (cachedResponse) {
assert.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
* response.ok) 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<Object>} [options.plugins=[]]
* @return {Promise<Response>}
*
* @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 (process.env.NODE_ENV !== 'production') {
if (responseToCache) {
assert.isInstance(responseToCache, Response, {
moduleName: 'Plugin',
funcName: pluginEvents.CACHE_WILL_UPDATE,
isReturnValueProblem: true,
});
}
}
if (!responseToCache) {
break;
}
}
}
if (!pluginsUsed) {
if (process.env.NODE_ENV !== 'production') {
if (!responseToCache.ok) {
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.ok ? responseToCache : null;
}
return responseToCache ? responseToCache : null;
};
const cacheWrapper = {
put: putWrapper,
match: matchWrapper,
};
export {cacheWrapper};

View File

@ -0,0 +1,88 @@
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {logger} from './logger.mjs';
import '../_version.mjs';
/**
* Logs a warning to the user recommending changing
* to max-age=0 or no-cache.
*
* @param {string} cacheControlHeader
*
* @private
*/
function showWarning(cacheControlHeader) {
const docsUrl = 'https://developers.google.com/web/tools/workbox/guides/service-worker-checklist#cache-control_of_your_service_worker_file';
logger.warn(`You are setting a 'cache-control' header of ` +
`'${cacheControlHeader}' on your service worker file. This should be ` +
`set to 'max-age=0' or 'no-cache' to ensure the latest service worker ` +
`is served to your users. Learn more here: ${docsUrl}`
);
}
/**
* Checks for cache-control header on SW file and
* warns the developer if it exists with a value
* other than max-age=0 or no-cache.
*
* @return {Promise}
* @private
*/
function checkSWFileCacheHeaders() {
// This is wrapped as an iife to allow async/await while making
// rollup exclude it in builds.
return (async () => {
try {
const swFile = self.location.href;
const response = await fetch(swFile);
if (!response.ok) {
// Response failed so nothing we can check;
return;
}
if (!response.headers.has('cache-control')) {
// No cache control header.
return;
}
const cacheControlHeader = response.headers.get('cache-control');
const maxAgeResult = /max-age\s*=\s*(\d*)/g.exec(cacheControlHeader);
if (maxAgeResult) {
if (parseInt(maxAgeResult[1], 10) === 0) {
return;
}
}
if (cacheControlHeader.indexOf('no-cache') !== -1) {
return;
}
if (cacheControlHeader.indexOf('no-store') !== -1) {
return;
}
showWarning(cacheControlHeader);
} catch (err) {
// NOOP
}
})();
}
const finalCheckSWFileCacheHeaders =
process.env.NODE_ENV === 'production' ? null : checkSWFileCacheHeaders;
export {finalCheckSWFileCacheHeaders as checkSWFileCacheHeaders};

143
node_modules/workbox-core/_private/fetchWrapper.mjs generated vendored Normal file
View File

@ -0,0 +1,143 @@
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {WorkboxError} from './WorkboxError.mjs';
import {logger} from './logger.mjs';
import {assert} from './assert.mjs';
import {getFriendlyURL} from '../_private/getFriendlyURL.mjs';
import pluginEvents from '../models/pluginEvents.mjs';
import pluginUtils from '../utils/pluginUtils.mjs';
import '../_version.mjs';
/**
* 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<Object>} [options.plugins=[]]
* @return {Promise<Response>}
*
* @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) {
if (process.env.NODE_ENV !== 'production') {
logger.log(`Using a preloaded navigation response for ` +
`'${getFriendlyURL(request.url)}'`);
}
return possiblePreloadResponse;
}
}
if (typeof request === 'string') {
request = new Request(request);
}
if (process.env.NODE_ENV !== 'production') {
assert.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 (process.env.NODE_ENV !== 'production') {
if (request) {
assert.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.
const pluginFilteredRequest = request.clone();
try {
const fetchResponse = await fetch(request, fetchOptions);
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Network request for `+
`'${getFriendlyURL(request.url)}' returned a response with ` +
`status '${fetchResponse.status}'.`);
}
return fetchResponse;
} catch (error) {
if (process.env.NODE_ENV !== 'production') {
logger.error(`Network request for `+
`'${getFriendlyURL(request.url)}' threw an error.`, error);
}
for (let 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,
};
export {fetchWrapper};

27
node_modules/workbox-core/_private/getFriendlyURL.mjs generated vendored Normal file
View File

@ -0,0 +1,27 @@
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import '../_version.mjs';
const getFriendlyURL = (url) => {
const urlObj = new URL(url, location);
if (urlObj.origin === location.origin) {
return urlObj.pathname;
}
return urlObj.href;
};
export {getFriendlyURL};

95
node_modules/workbox-core/_private/logger.mjs generated vendored Normal file
View File

@ -0,0 +1,95 @@
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import LOG_LEVELS from '../models/LogLevels.mjs';
import '../_version.mjs';
// Safari doesn't print all console.groupCollapsed() arguments.
// Related bug: https://bugs.webkit.org/show_bug.cgi?id=182754
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
const GREY = `#7f8c8d`;
const GREEN = `#2ecc71`;
const YELLOW = `#f39c12`;
const RED = `#c0392b`;
const BLUE = `#3498db`;
const getDefaultLogLevel = () => (process.env.NODE_ENV === 'production') ?
LOG_LEVELS.warn : LOG_LEVELS.log;
let logLevel = getDefaultLogLevel();
const shouldPrint = (minLevel) => (logLevel <= minLevel);
const setLoggerLevel = (newLogLevel) => logLevel = newLogLevel;
const getLoggerLevel = () => logLevel;
// We always want groups to be logged unless logLevel is silent.
const groupLevel = LOG_LEVELS.error;
const _print = function(keyName, logArgs, levelColor) {
const logLevel = keyName.indexOf('group') === 0 ?
groupLevel : LOG_LEVELS[keyName];
if (!shouldPrint(logLevel)) {
return;
}
if (!levelColor || (keyName === 'groupCollapsed' && isSafari)) {
console[keyName](...logArgs);
return;
}
const logPrefix = [
'%cworkbox',
`background: ${levelColor}; color: white; padding: 2px 0.5em; ` +
`border-radius: 0.5em;`,
];
console[keyName](...logPrefix, ...logArgs);
};
const groupEnd = () => {
if (shouldPrint(groupLevel)) {
console.groupEnd();
}
};
const defaultExport = {
groupEnd,
unprefixed: {
groupEnd,
},
};
const setupLogs = (keyName, color) => {
defaultExport[keyName] =
(...args) => _print(keyName, args, color);
defaultExport.unprefixed[keyName] =
(...args) => _print(keyName, args);
};
const levelToColor = {
debug: GREY,
log: GREEN,
warn: YELLOW,
error: RED,
groupCollapsed: BLUE,
};
Object.keys(levelToColor).forEach(
(keyName) => setupLogs(keyName, levelToColor[keyName])
);
export {getDefaultLogLevel};
export {setLoggerLevel};
export {getLoggerLevel};
export {defaultExport as logger};

73
node_modules/workbox-core/_private/quota.mjs generated vendored Normal file
View File

@ -0,0 +1,73 @@
/*
Copyright 2018 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {logger} from './logger.mjs';
import {assert} from './assert.mjs';
import '../_version.mjs';
const callbacks = new Set();
/**
* Adds a function to the set of callbacks that will be executed when there's
* a quota error.
*
* @param {Function} callback
* @memberof workbox.core
*/
function registerQuotaErrorCallback(callback) {
if (process.env.NODE_ENV !== 'production') {
assert.isType(callback, 'function', {
moduleName: 'workbox-core',
funcName: 'register',
paramName: 'callback',
});
}
callbacks.add(callback);
if (process.env.NODE_ENV !== 'production') {
logger.log('Registered a callback to respond to quota errors.', callback);
}
}
/**
* 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() {
if (process.env.NODE_ENV !== 'production') {
logger.log(`About to run ${callbacks.size} callbacks to clean up caches.`);
}
for (const callback of callbacks) {
await callback();
if (process.env.NODE_ENV !== 'production') {
logger.log(callback, 'is complete.');
}
}
if (process.env.NODE_ENV !== 'production') {
logger.log('Finished running callbacks.');
}
}
export {
executeQuotaErrorCallbacks,
registerQuotaErrorCallback,
};