WIP - add extractor, generate snippet_data
This commit is contained in:
325
node_modules/workbox-core/_private/DBWrapper.mjs
generated
vendored
Normal file
325
node_modules/workbox-core/_private/DBWrapper.mjs
generated
vendored
Normal 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
48
node_modules/workbox-core/_private/WorkboxError.mjs
generated
vendored
Normal 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
109
node_modules/workbox-core/_private/assert.mjs
generated
vendored
Normal 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
52
node_modules/workbox-core/_private/cacheNames.mjs
generated
vendored
Normal 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
236
node_modules/workbox-core/_private/cacheWrapper.mjs
generated
vendored
Normal 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};
|
||||
88
node_modules/workbox-core/_private/checkSWFileCacheHeaders.mjs
generated
vendored
Normal file
88
node_modules/workbox-core/_private/checkSWFileCacheHeaders.mjs
generated
vendored
Normal 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
143
node_modules/workbox-core/_private/fetchWrapper.mjs
generated
vendored
Normal 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
27
node_modules/workbox-core/_private/getFriendlyURL.mjs
generated
vendored
Normal 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
95
node_modules/workbox-core/_private/logger.mjs
generated
vendored
Normal 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
73
node_modules/workbox-core/_private/quota.mjs
generated
vendored
Normal 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,
|
||||
};
|
||||
Reference in New Issue
Block a user