blob: d0a03072a07cbf1824ebd671f93deca1d34e362c [file] [log] [blame]
{"version":3,"file":"workbox-expiration.dev.js","sources":["../_version.mjs","../models/CacheTimestampsModel.mjs","../CacheExpiration.mjs","../Plugin.mjs","../index.mjs"],"sourcesContent":["try{self['workbox:expiration:4.3.1']&&_()}catch(e){}// eslint-disable-line","/*\n Copyright 2018 Google LLC\n\n Use of this source code is governed by an MIT-style\n license that can be found in the LICENSE file or at\n https://opensource.org/licenses/MIT.\n*/\n\nimport {DBWrapper} from 'workbox-core/_private/DBWrapper.mjs';\nimport {deleteDatabase} from 'workbox-core/_private/deleteDatabase.mjs';\nimport '../_version.mjs';\n\n\nconst DB_NAME = 'workbox-expiration';\nconst OBJECT_STORE_NAME = 'cache-entries';\n\nconst normalizeURL = (unNormalizedUrl) => {\n const url = new URL(unNormalizedUrl, location);\n url.hash = '';\n\n return url.href;\n};\n\n\n/**\n * Returns the timestamp model.\n *\n * @private\n */\nclass CacheTimestampsModel {\n /**\n *\n * @param {string} cacheName\n *\n * @private\n */\n constructor(cacheName) {\n this._cacheName = cacheName;\n\n this._db = new DBWrapper(DB_NAME, 1, {\n onupgradeneeded: (event) => this._handleUpgrade(event),\n });\n }\n\n /**\n * Should perform an upgrade of indexedDB.\n *\n * @param {Event} event\n *\n * @private\n */\n _handleUpgrade(event) {\n const db = event.target.result;\n\n // TODO(philipwalton): EdgeHTML doesn't support arrays as a keyPath, so we\n // have to use the `id` keyPath here and create our own values (a\n // concatenation of `url + cacheName`) instead of simply using\n // `keyPath: ['url', 'cacheName']`, which is supported in other browsers.\n const objStore = db.createObjectStore(OBJECT_STORE_NAME, {keyPath: 'id'});\n\n // TODO(philipwalton): once we don't have to support EdgeHTML, we can\n // create a single index with the keyPath `['cacheName', 'timestamp']`\n // instead of doing both these indexes.\n objStore.createIndex('cacheName', 'cacheName', {unique: false});\n objStore.createIndex('timestamp', 'timestamp', {unique: false});\n\n // Previous versions of `workbox-expiration` used `this._cacheName`\n // as the IDBDatabase name.\n deleteDatabase(this._cacheName);\n }\n\n /**\n * @param {string} url\n * @param {number} timestamp\n *\n * @private\n */\n async setTimestamp(url, timestamp) {\n url = normalizeURL(url);\n\n await this._db.put(OBJECT_STORE_NAME, {\n url,\n timestamp,\n cacheName: this._cacheName,\n // Creating an ID from the URL and cache name won't be necessary once\n // Edge switches to Chromium and all browsers we support work with\n // array keyPaths.\n id: this._getId(url),\n });\n }\n\n /**\n * Returns the timestamp stored for a given URL.\n *\n * @param {string} url\n * @return {number}\n *\n * @private\n */\n async getTimestamp(url) {\n const entry = await this._db.get(OBJECT_STORE_NAME, this._getId(url));\n return entry.timestamp;\n }\n\n /**\n * Iterates through all the entries in the object store (from newest to\n * oldest) and removes entries once either `maxCount` is reached or the\n * entry's timestamp is less than `minTimestamp`.\n *\n * @param {number} minTimestamp\n * @param {number} maxCount\n *\n * @private\n */\n async expireEntries(minTimestamp, maxCount) {\n const entriesToDelete = await this._db.transaction(\n OBJECT_STORE_NAME, 'readwrite', (txn, done) => {\n const store = txn.objectStore(OBJECT_STORE_NAME);\n const entriesToDelete = [];\n let entriesNotDeletedCount = 0;\n\n store.index('timestamp')\n .openCursor(null, 'prev')\n .onsuccess = ({target}) => {\n const cursor = target.result;\n if (cursor) {\n const result = cursor.value;\n // TODO(philipwalton): once we can use a multi-key index, we\n // won't have to check `cacheName` here.\n if (result.cacheName === this._cacheName) {\n // Delete an entry if it's older than the max age or\n // if we already have the max number allowed.\n if ((minTimestamp && result.timestamp < minTimestamp) ||\n (maxCount && entriesNotDeletedCount >= maxCount)) {\n // TODO(philipwalton): we should be able to delete the\n // entry right here, but doing so causes an iteration\n // bug in Safari stable (fixed in TP). Instead we can\n // store the keys of the entries to delete, and then\n // delete the separate transactions.\n // https://github.com/GoogleChrome/workbox/issues/1978\n // cursor.delete();\n\n // We only need to return the URL, not the whole entry.\n entriesToDelete.push(cursor.value);\n } else {\n entriesNotDeletedCount++;\n }\n }\n cursor.continue();\n } else {\n done(entriesToDelete);\n }\n };\n });\n\n // TODO(philipwalton): once the Safari bug in the following issue is fixed,\n // we should be able to remove this loop and do the entry deletion in the\n // cursor loop above:\n // https://github.com/GoogleChrome/workbox/issues/1978\n const urlsDeleted = [];\n for (const entry of entriesToDelete) {\n await this._db.delete(OBJECT_STORE_NAME, entry.id);\n urlsDeleted.push(entry.url);\n }\n\n return urlsDeleted;\n }\n\n /**\n * Takes a URL and returns an ID that will be unique in the object store.\n *\n * @param {string} url\n * @return {string}\n *\n * @private\n */\n _getId(url) {\n // Creating an ID from the URL and cache name won't be necessary once\n // Edge switches to Chromium and all browsers we support work with\n // array keyPaths.\n return this._cacheName + '|' + normalizeURL(url);\n }\n}\n\nexport {CacheTimestampsModel};\n","/*\n Copyright 2018 Google LLC\n\n Use of this source code is governed by an MIT-style\n license that can be found in the LICENSE file or at\n https://opensource.org/licenses/MIT.\n*/\n\nimport {CacheTimestampsModel} from './models/CacheTimestampsModel.mjs';\nimport {WorkboxError} from 'workbox-core/_private/WorkboxError.mjs';\nimport {assert} from 'workbox-core/_private/assert.mjs';\nimport {logger} from 'workbox-core/_private/logger.mjs';\n\nimport './_version.mjs';\n\n/**\n * The `CacheExpiration` class allows you define an expiration and / or\n * limit on the number of responses stored in a\n * [`Cache`](https://developer.mozilla.org/en-US/docs/Web/API/Cache).\n *\n * @memberof workbox.expiration\n */\nclass CacheExpiration {\n /**\n * To construct a new CacheExpiration instance you must provide at least\n * one of the `config` properties.\n *\n * @param {string} cacheName Name of the cache to apply restrictions to.\n * @param {Object} config\n * @param {number} [config.maxEntries] The maximum number of entries to cache.\n * Entries used the least will be removed as the maximum is reached.\n * @param {number} [config.maxAgeSeconds] The maximum age of an entry before\n * it's treated as stale and removed.\n */\n constructor(cacheName, config = {}) {\n if (process.env.NODE_ENV !== 'production') {\n assert.isType(cacheName, 'string', {\n moduleName: 'workbox-expiration',\n className: 'CacheExpiration',\n funcName: 'constructor',\n paramName: 'cacheName',\n });\n\n if (!(config.maxEntries || config.maxAgeSeconds)) {\n throw new WorkboxError('max-entries-or-age-required', {\n moduleName: 'workbox-expiration',\n className: 'CacheExpiration',\n funcName: 'constructor',\n });\n }\n\n if (config.maxEntries) {\n assert.isType(config.maxEntries, 'number', {\n moduleName: 'workbox-expiration',\n className: 'CacheExpiration',\n funcName: 'constructor',\n paramName: 'config.maxEntries',\n });\n\n // TODO: Assert is positive\n }\n\n if (config.maxAgeSeconds) {\n assert.isType(config.maxAgeSeconds, 'number', {\n moduleName: 'workbox-expiration',\n className: 'CacheExpiration',\n funcName: 'constructor',\n paramName: 'config.maxAgeSeconds',\n });\n\n // TODO: Assert is positive\n }\n }\n\n this._isRunning = false;\n this._rerunRequested = false;\n this._maxEntries = config.maxEntries;\n this._maxAgeSeconds = config.maxAgeSeconds;\n this._cacheName = cacheName;\n this._timestampModel = new CacheTimestampsModel(cacheName);\n }\n\n /**\n * Expires entries for the given cache and given criteria.\n */\n async expireEntries() {\n if (this._isRunning) {\n this._rerunRequested = true;\n return;\n }\n this._isRunning = true;\n\n const minTimestamp = this._maxAgeSeconds ?\n Date.now() - (this._maxAgeSeconds * 1000) : undefined;\n\n const urlsExpired = await this._timestampModel.expireEntries(\n minTimestamp, this._maxEntries);\n\n // Delete URLs from the cache\n const cache = await caches.open(this._cacheName);\n for (const url of urlsExpired) {\n await cache.delete(url);\n }\n\n if (process.env.NODE_ENV !== 'production') {\n if (urlsExpired.length > 0) {\n logger.groupCollapsed(\n `Expired ${urlsExpired.length} ` +\n `${urlsExpired.length === 1 ? 'entry' : 'entries'} and removed ` +\n `${urlsExpired.length === 1 ? 'it' : 'them'} from the ` +\n `'${this._cacheName}' cache.`);\n logger.log(`Expired the following ${urlsExpired.length === 1 ?\n 'URL' : 'URLs'}:`);\n urlsExpired.forEach((url) => logger.log(` ${url}`));\n logger.groupEnd();\n } else {\n logger.debug(`Cache expiration ran and found no entries to remove.`);\n }\n }\n\n this._isRunning = false;\n if (this._rerunRequested) {\n this._rerunRequested = false;\n this.expireEntries();\n }\n }\n\n /**\n * Update the timestamp for the given URL. This ensures the when\n * removing entries based on maximum entries, most recently used\n * is accurate or when expiring, the timestamp is up-to-date.\n *\n * @param {string} url\n */\n async updateTimestamp(url) {\n if (process.env.NODE_ENV !== 'production') {\n assert.isType(url, 'string', {\n moduleName: 'workbox-expiration',\n className: 'CacheExpiration',\n funcName: 'updateTimestamp',\n paramName: 'url',\n });\n }\n\n await this._timestampModel.setTimestamp(url, Date.now());\n }\n\n /**\n * Can be used to check if a URL has expired or not before it's used.\n *\n * This requires a look up from IndexedDB, so can be slow.\n *\n * Note: This method will not remove the cached entry, call\n * `expireEntries()` to remove indexedDB and Cache entries.\n *\n * @param {string} url\n * @return {boolean}\n */\n async isURLExpired(url) {\n if (process.env.NODE_ENV !== 'production') {\n if (!this._maxAgeSeconds) {\n throw new WorkboxError(`expired-test-without-max-age`, {\n methodName: 'isURLExpired',\n paramName: 'maxAgeSeconds',\n });\n }\n }\n\n const timestamp = await this._timestampModel.getTimestamp(url);\n const expireOlderThan = Date.now() - (this._maxAgeSeconds * 1000);\n return (timestamp < expireOlderThan);\n }\n\n /**\n * Removes the IndexedDB object store used to keep track of cache expiration\n * metadata.\n */\n async delete() {\n // Make sure we don't attempt another rerun if we're called in the middle of\n // a cache expiration.\n this._rerunRequested = false;\n await this._timestampModel.expireEntries(Infinity); // Expires all.\n }\n}\n\nexport {CacheExpiration};\n","/*\n Copyright 2018 Google LLC\n\n Use of this source code is governed by an MIT-style\n license that can be found in the LICENSE file or at\n https://opensource.org/licenses/MIT.\n*/\n\nimport {assert} from 'workbox-core/_private/assert.mjs';\nimport {cacheNames} from 'workbox-core/_private/cacheNames.mjs';\nimport {getFriendlyURL} from 'workbox-core/_private/getFriendlyURL.mjs';\nimport {logger} from 'workbox-core/_private/logger.mjs';\nimport {WorkboxError} from 'workbox-core/_private/WorkboxError.mjs';\nimport {registerQuotaErrorCallback}\n from 'workbox-core/registerQuotaErrorCallback.mjs';\n\nimport {CacheExpiration} from './CacheExpiration.mjs';\nimport './_version.mjs';\n\n/**\n * This plugin can be used in the Workbox APIs to regularly enforce a\n * limit on the age and / or the number of cached requests.\n *\n * Whenever a cached request is used or updated, this plugin will look\n * at the used Cache and remove any old or extra requests.\n *\n * When using `maxAgeSeconds`, requests may be used *once* after expiring\n * because the expiration clean up will not have occurred until *after* the\n * cached request has been used. If the request has a \"Date\" header, then\n * a light weight expiration check is performed and the request will not be\n * used immediately.\n *\n * When using `maxEntries`, the entry least-recently requested will be removed from the cache first.\n *\n * @memberof workbox.expiration\n */\nclass Plugin {\n /**\n * @param {Object} config\n * @param {number} [config.maxEntries] The maximum number of entries to cache.\n * Entries used the least will be removed as the maximum is reached.\n * @param {number} [config.maxAgeSeconds] The maximum age of an entry before\n * it's treated as stale and removed.\n * @param {boolean} [config.purgeOnQuotaError] Whether to opt this cache in to\n * automatic deletion if the available storage quota has been exceeded.\n */\n constructor(config = {}) {\n if (process.env.NODE_ENV !== 'production') {\n if (!(config.maxEntries || config.maxAgeSeconds)) {\n throw new WorkboxError('max-entries-or-age-required', {\n moduleName: 'workbox-expiration',\n className: 'Plugin',\n funcName: 'constructor',\n });\n }\n\n if (config.maxEntries) {\n assert.isType(config.maxEntries, 'number', {\n moduleName: 'workbox-expiration',\n className: 'Plugin',\n funcName: 'constructor',\n paramName: 'config.maxEntries',\n });\n }\n\n if (config.maxAgeSeconds) {\n assert.isType(config.maxAgeSeconds, 'number', {\n moduleName: 'workbox-expiration',\n className: 'Plugin',\n funcName: 'constructor',\n paramName: 'config.maxAgeSeconds',\n });\n }\n }\n\n this._config = config;\n this._maxAgeSeconds = config.maxAgeSeconds;\n this._cacheExpirations = new Map();\n\n if (config.purgeOnQuotaError) {\n registerQuotaErrorCallback(() => this.deleteCacheAndMetadata());\n }\n }\n\n /**\n * A simple helper method to return a CacheExpiration instance for a given\n * cache name.\n *\n * @param {string} cacheName\n * @return {CacheExpiration}\n *\n * @private\n */\n _getCacheExpiration(cacheName) {\n if (cacheName === cacheNames.getRuntimeName()) {\n throw new WorkboxError('expire-custom-caches-only');\n }\n\n let cacheExpiration = this._cacheExpirations.get(cacheName);\n if (!cacheExpiration) {\n cacheExpiration = new CacheExpiration(cacheName, this._config);\n this._cacheExpirations.set(cacheName, cacheExpiration);\n }\n return cacheExpiration;\n }\n\n /**\n * A \"lifecycle\" callback that will be triggered automatically by the\n * `workbox.strategies` handlers when a `Response` is about to be returned\n * from a [Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache) to\n * the handler. It allows the `Response` to be inspected for freshness and\n * prevents it from being used if the `Response`'s `Date` header value is\n * older than the configured `maxAgeSeconds`.\n *\n * @param {Object} options\n * @param {string} options.cacheName Name of the cache the response is in.\n * @param {Response} options.cachedResponse The `Response` object that's been\n * read from a cache and whose freshness should be checked.\n * @return {Response} Either the `cachedResponse`, if it's\n * fresh, or `null` if the `Response` is older than `maxAgeSeconds`.\n *\n * @private\n */\n cachedResponseWillBeUsed({event, request, cacheName, cachedResponse}) {\n if (!cachedResponse) {\n return null;\n }\n\n let isFresh = this._isResponseDateFresh(cachedResponse);\n\n // Expire entries to ensure that even if the expiration date has\n // expired, it'll only be used once.\n const cacheExpiration = this._getCacheExpiration(cacheName);\n cacheExpiration.expireEntries();\n\n // Update the metadata for the request URL to the current timestamp,\n // but don't `await` it as we don't want to block the response.\n const updateTimestampDone = cacheExpiration.updateTimestamp(request.url);\n if (event) {\n try {\n event.waitUntil(updateTimestampDone);\n } catch (error) {\n if (process.env.NODE_ENV !== 'production') {\n logger.warn(`Unable to ensure service worker stays alive when ` +\n `updating cache entry for '${getFriendlyURL(event.request.url)}'.`);\n }\n }\n }\n\n return isFresh ? cachedResponse : null;\n }\n\n /**\n * @param {Response} cachedResponse\n * @return {boolean}\n *\n * @private\n */\n _isResponseDateFresh(cachedResponse) {\n if (!this._maxAgeSeconds) {\n // We aren't expiring by age, so return true, it's fresh\n return true;\n }\n\n // Check if the 'date' header will suffice a quick expiration check.\n // See https://github.com/GoogleChromeLabs/sw-toolbox/issues/164 for\n // discussion.\n const dateHeaderTimestamp = this._getDateHeaderTimestamp(cachedResponse);\n if (dateHeaderTimestamp === null) {\n // Unable to parse date, so assume it's fresh.\n return true;\n }\n\n // If we have a valid headerTime, then our response is fresh iff the\n // headerTime plus maxAgeSeconds is greater than the current time.\n const now = Date.now();\n return dateHeaderTimestamp >= now - (this._maxAgeSeconds * 1000);\n }\n\n /**\n * This method will extract the data header and parse it into a useful\n * value.\n *\n * @param {Response} cachedResponse\n * @return {number}\n *\n * @private\n */\n _getDateHeaderTimestamp(cachedResponse) {\n if (!cachedResponse.headers.has('date')) {\n return null;\n }\n\n const dateHeader = cachedResponse.headers.get('date');\n const parsedDate = new Date(dateHeader);\n const headerTime = parsedDate.getTime();\n\n // If the Date header was invalid for some reason, parsedDate.getTime()\n // will return NaN.\n if (isNaN(headerTime)) {\n return null;\n }\n\n return headerTime;\n }\n\n /**\n * A \"lifecycle\" callback that will be triggered automatically by the\n * `workbox.strategies` handlers when an entry is added to a cache.\n *\n * @param {Object} options\n * @param {string} options.cacheName Name of the cache that was updated.\n * @param {string} options.request The Request for the cached entry.\n *\n * @private\n */\n async cacheDidUpdate({cacheName, request}) {\n if (process.env.NODE_ENV !== 'production') {\n assert.isType(cacheName, 'string', {\n moduleName: 'workbox-expiration',\n className: 'Plugin',\n funcName: 'cacheDidUpdate',\n paramName: 'cacheName',\n });\n assert.isInstance(request, Request, {\n moduleName: 'workbox-expiration',\n className: 'Plugin',\n funcName: 'cacheDidUpdate',\n paramName: 'request',\n });\n }\n\n const cacheExpiration = this._getCacheExpiration(cacheName);\n await cacheExpiration.updateTimestamp(request.url);\n await cacheExpiration.expireEntries();\n }\n\n\n /**\n * This is a helper method that performs two operations:\n *\n * - Deletes *all* the underlying Cache instances associated with this plugin\n * instance, by calling caches.delete() on your behalf.\n * - Deletes the metadata from IndexedDB used to keep track of expiration\n * details for each Cache instance.\n *\n * When using cache expiration, calling this method is preferable to calling\n * `caches.delete()` directly, since this will ensure that the IndexedDB\n * metadata is also cleanly removed and open IndexedDB instances are deleted.\n *\n * Note that if you're *not* using cache expiration for a given cache, calling\n * `caches.delete()` and passing in the cache's name should be sufficient.\n * There is no Workbox-specific method needed for cleanup in that case.\n */\n async deleteCacheAndMetadata() {\n // Do this one at a time instead of all at once via `Promise.all()` to\n // reduce the chance of inconsistency if a promise rejects.\n for (const [cacheName, cacheExpiration] of this._cacheExpirations) {\n await caches.delete(cacheName);\n await cacheExpiration.delete();\n }\n\n // Reset this._cacheExpirations to its initial state.\n this._cacheExpirations = new Map();\n }\n}\n\nexport {Plugin};\n","/*\n Copyright 2018 Google LLC\n\n Use of this source code is governed by an MIT-style\n license that can be found in the LICENSE file or at\n https://opensource.org/licenses/MIT.\n*/\n\nimport {CacheExpiration} from './CacheExpiration.mjs';\nimport {Plugin} from './Plugin.mjs';\nimport './_version.mjs';\n\n\n/**\n * @namespace workbox.expiration\n */\n\nexport {\n CacheExpiration,\n Plugin,\n};\n"],"names":["self","_","e","DB_NAME","OBJECT_STORE_NAME","normalizeURL","unNormalizedUrl","url","URL","location","hash","href","CacheTimestampsModel","constructor","cacheName","_cacheName","_db","DBWrapper","onupgradeneeded","event","_handleUpgrade","db","target","result","objStore","createObjectStore","keyPath","createIndex","unique","deleteDatabase","setTimestamp","timestamp","put","id","_getId","getTimestamp","entry","get","expireEntries","minTimestamp","maxCount","entriesToDelete","transaction","txn","done","store","objectStore","entriesNotDeletedCount","index","openCursor","onsuccess","cursor","value","push","continue","urlsDeleted","delete","CacheExpiration","config","assert","isType","moduleName","className","funcName","paramName","maxEntries","maxAgeSeconds","WorkboxError","_isRunning","_rerunRequested","_maxEntries","_maxAgeSeconds","_timestampModel","Date","now","undefined","urlsExpired","cache","caches","open","length","logger","groupCollapsed","log","forEach","groupEnd","debug","updateTimestamp","isURLExpired","methodName","expireOlderThan","Infinity","Plugin","_config","_cacheExpirations","Map","purgeOnQuotaError","registerQuotaErrorCallback","deleteCacheAndMetadata","_getCacheExpiration","cacheNames","getRuntimeName","cacheExpiration","set","cachedResponseWillBeUsed","request","cachedResponse","isFresh","_isResponseDateFresh","updateTimestampDone","waitUntil","error","warn","getFriendlyURL","dateHeaderTimestamp","_getDateHeaderTimestamp","headers","has","dateHeader","parsedDate","headerTime","getTime","isNaN","cacheDidUpdate","isInstance","Request"],"mappings":"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"}