@serwist/sw 9.0.0-preview.17 → 9.0.0-preview.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Serwist.d.ts → abstractions/Serwist.d.ts} +6 -15
- package/dist/abstractions/Serwist.d.ts.map +1 -0
- package/dist/abstractions/disableDevLogs.d.ts.map +1 -0
- package/dist/{fallbacks.d.ts → abstractions/fallbacks.d.ts} +2 -2
- package/dist/abstractions/fallbacks.d.ts.map +1 -0
- package/dist/{handlePrecaching.d.ts → abstractions/handlePrecaching.d.ts} +1 -1
- package/dist/abstractions/handlePrecaching.d.ts.map +1 -0
- package/dist/abstractions/installSerwist.d.ts.map +1 -0
- package/dist/abstractions/registerRuntimeCaching.d.ts.map +1 -0
- package/dist/{types.d.ts → abstractions/types.d.ts} +1 -1
- package/dist/abstractions/types.d.ts.map +1 -0
- package/dist/chunks/NavigationRoute.js +54 -0
- package/dist/chunks/NetworkOnly.js +193 -0
- package/dist/chunks/PrecacheFallbackPlugin.js +573 -0
- package/dist/chunks/Strategy.js +410 -0
- package/dist/chunks/getOrCreatePrecacheController.js +429 -0
- package/dist/chunks/precacheAndRoute.js +112 -0
- package/dist/chunks/registerRoute.js +408 -0
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -9
- package/dist/index.plugins.d.ts +40 -11
- package/dist/index.plugins.d.ts.map +1 -1
- package/dist/index.plugins.js +671 -5
- package/dist/index.precaching.d.ts +24 -0
- package/dist/index.precaching.d.ts.map +1 -0
- package/dist/index.precaching.js +24 -0
- package/dist/index.routing.d.ts +13 -0
- package/dist/index.routing.d.ts.map +1 -0
- package/dist/index.routing.js +21 -0
- package/dist/index.strategies.d.ts +19 -2
- package/dist/index.strategies.d.ts.map +1 -1
- package/dist/index.strategies.js +146 -1
- package/dist/plugins/backgroundSync/BackgroundSyncPlugin.d.ts +23 -0
- package/dist/plugins/backgroundSync/BackgroundSyncPlugin.d.ts.map +1 -0
- package/dist/plugins/backgroundSync/Queue.d.ts +166 -0
- package/dist/plugins/backgroundSync/Queue.d.ts.map +1 -0
- package/dist/plugins/backgroundSync/QueueDb.d.ts +90 -0
- package/dist/plugins/backgroundSync/QueueDb.d.ts.map +1 -0
- package/dist/plugins/backgroundSync/QueueStore.d.ts +75 -0
- package/dist/plugins/backgroundSync/QueueStore.d.ts.map +1 -0
- package/dist/plugins/backgroundSync/StorableRequest.d.ts +51 -0
- package/dist/plugins/backgroundSync/StorableRequest.d.ts.map +1 -0
- package/dist/plugins/broadcastUpdate/BroadcastCacheUpdate.d.ts +45 -0
- package/dist/plugins/broadcastUpdate/BroadcastCacheUpdate.d.ts.map +1 -0
- package/dist/plugins/broadcastUpdate/BroadcastUpdatePlugin.d.ts +27 -0
- package/dist/plugins/broadcastUpdate/BroadcastUpdatePlugin.d.ts.map +1 -0
- package/dist/plugins/broadcastUpdate/constants.d.ts +5 -0
- package/dist/plugins/broadcastUpdate/constants.d.ts.map +1 -0
- package/dist/plugins/broadcastUpdate/responsesAreSame.d.ts +11 -0
- package/dist/plugins/broadcastUpdate/responsesAreSame.d.ts.map +1 -0
- package/dist/plugins/broadcastUpdate/types.d.ts +34 -0
- package/dist/plugins/broadcastUpdate/types.d.ts.map +1 -0
- package/dist/plugins/cacheableResponse/CacheableResponse.d.ts +40 -0
- package/dist/plugins/cacheableResponse/CacheableResponse.d.ts.map +1 -0
- package/dist/plugins/cacheableResponse/CacheableResponsePlugin.d.ts +27 -0
- package/dist/plugins/cacheableResponse/CacheableResponsePlugin.d.ts.map +1 -0
- package/dist/plugins/expiration/CacheExpiration.d.ts +66 -0
- package/dist/plugins/expiration/CacheExpiration.d.ts.map +1 -0
- package/dist/plugins/expiration/ExpirationPlugin.d.ts +116 -0
- package/dist/plugins/expiration/ExpirationPlugin.d.ts.map +1 -0
- package/dist/plugins/expiration/models/CacheTimestampsModel.d.ts +73 -0
- package/dist/plugins/expiration/models/CacheTimestampsModel.d.ts.map +1 -0
- package/dist/plugins/googleAnalytics/constants.d.ts +10 -0
- package/dist/plugins/googleAnalytics/constants.d.ts.map +1 -0
- package/dist/plugins/googleAnalytics/initialize.d.ts +26 -0
- package/dist/plugins/googleAnalytics/initialize.d.ts.map +1 -0
- package/dist/plugins/precaching/PrecacheFallbackPlugin.d.ts +54 -0
- package/dist/plugins/precaching/PrecacheFallbackPlugin.d.ts.map +1 -0
- package/dist/plugins/rangeRequests/RangeRequestsPlugin.d.ts +19 -0
- package/dist/plugins/rangeRequests/RangeRequestsPlugin.d.ts.map +1 -0
- package/dist/plugins/rangeRequests/createPartialResponse.d.ts +18 -0
- package/dist/plugins/rangeRequests/createPartialResponse.d.ts.map +1 -0
- package/dist/plugins/rangeRequests/utils/calculateEffectiveBoundaries.d.ts +14 -0
- package/dist/plugins/rangeRequests/utils/calculateEffectiveBoundaries.d.ts.map +1 -0
- package/dist/plugins/rangeRequests/utils/parseRangeHeader.d.ts +12 -0
- package/dist/plugins/rangeRequests/utils/parseRangeHeader.d.ts.map +1 -0
- package/dist/precaching/PrecacheController.d.ts +145 -0
- package/dist/precaching/PrecacheController.d.ts.map +1 -0
- package/dist/precaching/PrecacheRoute.d.ts +20 -0
- package/dist/precaching/PrecacheRoute.d.ts.map +1 -0
- package/dist/precaching/PrecacheStrategy.d.ts +68 -0
- package/dist/precaching/PrecacheStrategy.d.ts.map +1 -0
- package/dist/precaching/addPlugins.d.ts +8 -0
- package/dist/precaching/addPlugins.d.ts.map +1 -0
- package/dist/precaching/addRoute.d.ts +15 -0
- package/dist/precaching/addRoute.d.ts.map +1 -0
- package/dist/precaching/cleanupOutdatedCaches.d.ts +6 -0
- package/dist/precaching/cleanupOutdatedCaches.d.ts.map +1 -0
- package/dist/precaching/createHandlerBoundToURL.d.ts +17 -0
- package/dist/precaching/createHandlerBoundToURL.d.ts.map +1 -0
- package/dist/precaching/getCacheKeyForURL.d.ts +20 -0
- package/dist/precaching/getCacheKeyForURL.d.ts.map +1 -0
- package/dist/precaching/matchPrecache.d.ts +14 -0
- package/dist/precaching/matchPrecache.d.ts.map +1 -0
- package/dist/precaching/precache.d.ts +19 -0
- package/dist/precaching/precache.d.ts.map +1 -0
- package/dist/precaching/precacheAndRoute.d.ts +14 -0
- package/dist/precaching/precacheAndRoute.d.ts.map +1 -0
- package/dist/precaching/types.d.ts +37 -0
- package/dist/precaching/types.d.ts.map +1 -0
- package/dist/precaching/utils/PrecacheCacheKeyPlugin.d.ts +17 -0
- package/dist/precaching/utils/PrecacheCacheKeyPlugin.d.ts.map +1 -0
- package/dist/precaching/utils/PrecacheInstallReportPlugin.d.ts +15 -0
- package/dist/precaching/utils/PrecacheInstallReportPlugin.d.ts.map +1 -0
- package/dist/precaching/utils/createCacheKey.d.ts +16 -0
- package/dist/precaching/utils/createCacheKey.d.ts.map +1 -0
- package/dist/precaching/utils/deleteOutdatedCaches.d.ts +18 -0
- package/dist/precaching/utils/deleteOutdatedCaches.d.ts.map +1 -0
- package/dist/precaching/utils/generateURLVariations.d.ts +12 -0
- package/dist/precaching/utils/generateURLVariations.d.ts.map +1 -0
- package/dist/precaching/utils/getCacheKeyForURL.d.ts +14 -0
- package/dist/precaching/utils/getCacheKeyForURL.d.ts.map +1 -0
- package/dist/precaching/utils/getOrCreatePrecacheController.d.ts +7 -0
- package/dist/precaching/utils/getOrCreatePrecacheController.d.ts.map +1 -0
- package/dist/precaching/utils/printCleanupDetails.d.ts +6 -0
- package/dist/precaching/utils/printCleanupDetails.d.ts.map +1 -0
- package/dist/precaching/utils/printInstallDetails.d.ts +7 -0
- package/dist/precaching/utils/printInstallDetails.d.ts.map +1 -0
- package/dist/precaching/utils/removeIgnoredSearchParams.d.ts +12 -0
- package/dist/precaching/utils/removeIgnoredSearchParams.d.ts.map +1 -0
- package/dist/routing/NavigationRoute.d.ts +57 -0
- package/dist/routing/NavigationRoute.d.ts.map +1 -0
- package/dist/routing/RegExpRoute.d.ts +24 -0
- package/dist/routing/RegExpRoute.d.ts.map +1 -0
- package/dist/routing/Route.d.ts +33 -0
- package/dist/routing/Route.d.ts.map +1 -0
- package/dist/routing/Router.d.ts +124 -0
- package/dist/routing/Router.d.ts.map +1 -0
- package/dist/routing/registerRoute.d.ts +15 -0
- package/dist/routing/registerRoute.d.ts.map +1 -0
- package/dist/routing/setCatchHandler.d.ts +9 -0
- package/dist/routing/setCatchHandler.d.ts.map +1 -0
- package/dist/routing/setDefaultHandler.d.ts +12 -0
- package/dist/routing/setDefaultHandler.d.ts.map +1 -0
- package/dist/routing/unregisterRoute.d.ts +8 -0
- package/dist/routing/unregisterRoute.d.ts.map +1 -0
- package/dist/routing/utils/constants.d.ts +15 -0
- package/dist/routing/utils/constants.d.ts.map +1 -0
- package/dist/routing/utils/getOrCreateDefaultRouter.d.ts +10 -0
- package/dist/routing/utils/getOrCreateDefaultRouter.d.ts.map +1 -0
- package/dist/routing/utils/normalizeHandler.d.ts +10 -0
- package/dist/routing/utils/normalizeHandler.d.ts.map +1 -0
- package/dist/routing/utils/parseRoute.d.ts +5 -0
- package/dist/routing/utils/parseRoute.d.ts.map +1 -0
- package/dist/strategies/CacheFirst.d.ts +23 -0
- package/dist/strategies/CacheFirst.d.ts.map +1 -0
- package/dist/strategies/CacheOnly.d.ts +20 -0
- package/dist/strategies/CacheOnly.d.ts.map +1 -0
- package/dist/strategies/NetworkFirst.d.ts +61 -0
- package/dist/strategies/NetworkFirst.d.ts.map +1 -0
- package/dist/strategies/NetworkOnly.d.ts +32 -0
- package/dist/strategies/NetworkOnly.d.ts.map +1 -0
- package/dist/strategies/StaleWhileRevalidate.d.ts +35 -0
- package/dist/strategies/StaleWhileRevalidate.d.ts.map +1 -0
- package/dist/strategies/Strategy.d.ts +83 -0
- package/dist/strategies/Strategy.d.ts.map +1 -0
- package/dist/strategies/StrategyHandler.d.ts +189 -0
- package/dist/strategies/StrategyHandler.d.ts.map +1 -0
- package/dist/strategies/plugins/cacheOkAndOpaquePlugin.d.ts +3 -0
- package/dist/strategies/plugins/cacheOkAndOpaquePlugin.d.ts.map +1 -0
- package/dist/strategies/utils/messages.d.ts +5 -0
- package/dist/strategies/utils/messages.d.ts.map +1 -0
- package/package.json +20 -14
- package/src/{Serwist.ts → abstractions/Serwist.ts} +16 -19
- package/src/{fallbacks.ts → abstractions/fallbacks.ts} +5 -5
- package/src/{handlePrecaching.ts → abstractions/handlePrecaching.ts} +6 -3
- package/src/{installSerwist.ts → abstractions/installSerwist.ts} +2 -2
- package/src/{registerRuntimeCaching.ts → abstractions/registerRuntimeCaching.ts} +1 -1
- package/src/{types.ts → abstractions/types.ts} +1 -1
- package/src/index.plugins.ts +65 -16
- package/src/index.precaching.ts +38 -0
- package/src/index.routing.ts +14 -0
- package/src/index.strategies.ts +22 -2
- package/src/index.ts +8 -8
- package/src/plugins/backgroundSync/BackgroundSyncPlugin.ts +39 -0
- package/src/plugins/backgroundSync/Queue.ts +438 -0
- package/src/plugins/backgroundSync/QueueDb.ts +176 -0
- package/src/plugins/backgroundSync/QueueStore.ts +161 -0
- package/src/plugins/backgroundSync/StorableRequest.ts +142 -0
- package/src/plugins/broadcastUpdate/BroadcastCacheUpdate.ts +159 -0
- package/src/plugins/broadcastUpdate/BroadcastUpdatePlugin.ts +43 -0
- package/src/plugins/broadcastUpdate/constants.ts +12 -0
- package/src/plugins/broadcastUpdate/responsesAreSame.ts +48 -0
- package/src/plugins/broadcastUpdate/types.ts +37 -0
- package/src/plugins/cacheableResponse/CacheableResponse.ts +141 -0
- package/src/plugins/cacheableResponse/CacheableResponsePlugin.ts +46 -0
- package/src/plugins/expiration/CacheExpiration.ts +192 -0
- package/src/plugins/expiration/ExpirationPlugin.ts +297 -0
- package/src/plugins/expiration/models/CacheTimestampsModel.ts +184 -0
- package/src/plugins/googleAnalytics/constants.ts +22 -0
- package/src/plugins/googleAnalytics/initialize.ts +200 -0
- package/src/plugins/precaching/PrecacheFallbackPlugin.ts +86 -0
- package/src/plugins/rangeRequests/RangeRequestsPlugin.ts +39 -0
- package/src/plugins/rangeRequests/createPartialResponse.ts +92 -0
- package/src/plugins/rangeRequests/utils/calculateEffectiveBoundaries.ts +58 -0
- package/src/plugins/rangeRequests/utils/parseRangeHeader.ts +54 -0
- package/src/precaching/PrecacheController.ts +332 -0
- package/src/precaching/PrecacheRoute.ts +50 -0
- package/src/precaching/PrecacheStrategy.ts +238 -0
- package/src/precaching/addPlugins.ts +21 -0
- package/src/precaching/addRoute.ts +30 -0
- package/src/precaching/cleanupOutdatedCaches.ts +33 -0
- package/src/precaching/createHandlerBoundToURL.ts +30 -0
- package/src/precaching/getCacheKeyForURL.ts +33 -0
- package/src/precaching/matchPrecache.ts +26 -0
- package/src/precaching/precache.ts +31 -0
- package/src/precaching/precacheAndRoute.ts +27 -0
- package/src/precaching/types.ts +46 -0
- package/src/precaching/utils/PrecacheCacheKeyPlugin.ts +36 -0
- package/src/precaching/utils/PrecacheInstallReportPlugin.ts +49 -0
- package/src/precaching/utils/createCacheKey.ts +68 -0
- package/src/precaching/utils/deleteOutdatedCaches.ts +40 -0
- package/src/precaching/utils/generateURLVariations.ts +55 -0
- package/src/precaching/utils/getCacheKeyForURL.ts +36 -0
- package/src/precaching/utils/getOrCreatePrecacheController.ts +22 -0
- package/src/precaching/utils/printCleanupDetails.ts +38 -0
- package/src/precaching/utils/printInstallDetails.ts +53 -0
- package/src/precaching/utils/removeIgnoredSearchParams.ts +29 -0
- package/src/routing/NavigationRoute.ts +119 -0
- package/src/routing/RegExpRoute.ts +74 -0
- package/src/routing/Route.ts +68 -0
- package/src/routing/Router.ts +432 -0
- package/src/routing/registerRoute.ts +33 -0
- package/src/routing/setCatchHandler.ts +22 -0
- package/src/routing/setDefaultHandler.ts +25 -0
- package/src/routing/unregisterRoute.ts +12 -0
- package/src/routing/utils/constants.ts +24 -0
- package/src/routing/utils/getOrCreateDefaultRouter.ts +29 -0
- package/src/routing/utils/normalizeHandler.ts +40 -0
- package/src/routing/utils/parseRoute.ts +67 -0
- package/src/strategies/CacheFirst.ts +87 -0
- package/src/strategies/CacheOnly.ts +58 -0
- package/src/strategies/NetworkFirst.ts +228 -0
- package/src/strategies/NetworkOnly.ts +96 -0
- package/src/strategies/StaleWhileRevalidate.ts +109 -0
- package/src/strategies/Strategy.ts +202 -0
- package/src/strategies/StrategyHandler.ts +557 -0
- package/src/strategies/plugins/cacheOkAndOpaquePlugin.ts +26 -0
- package/src/strategies/utils/messages.ts +20 -0
- package/dist/Serwist.d.ts.map +0 -1
- package/dist/disableDevLogs.d.ts.map +0 -1
- package/dist/fallbacks.d.ts.map +0 -1
- package/dist/handlePrecaching.d.ts.map +0 -1
- package/dist/installSerwist.d.ts.map +0 -1
- package/dist/registerRuntimeCaching.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- /package/dist/{disableDevLogs.d.ts → abstractions/disableDevLogs.d.ts} +0 -0
- /package/dist/{installSerwist.d.ts → abstractions/installSerwist.d.ts} +0 -0
- /package/dist/{registerRuntimeCaching.d.ts → abstractions/registerRuntimeCaching.d.ts} +0 -0
- /package/src/{disableDevLogs.ts → abstractions/disableDevLogs.ts} +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020 Google LLC
|
|
3
|
+
|
|
4
|
+
Use of this source code is governed by an MIT-style
|
|
5
|
+
license that can be found in the LICENSE file or at
|
|
6
|
+
https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { HandlerDidErrorCallbackParam, SerwistPlugin } from "@serwist/core";
|
|
10
|
+
|
|
11
|
+
import type { PrecacheController } from "../../precaching/PrecacheController.js";
|
|
12
|
+
import { getOrCreatePrecacheController } from "../../precaching/utils/getOrCreatePrecacheController.js";
|
|
13
|
+
|
|
14
|
+
export interface PrecacheFallbackEntry {
|
|
15
|
+
/**
|
|
16
|
+
* A function that checks whether the fallback entry can be used
|
|
17
|
+
* for a request.
|
|
18
|
+
*/
|
|
19
|
+
matcher: (param: HandlerDidErrorCallbackParam) => boolean;
|
|
20
|
+
/**
|
|
21
|
+
* A precached URL to be used as a fallback.
|
|
22
|
+
*/
|
|
23
|
+
url: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface PrecacheFallbackPluginOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Precached URLs to be used as the fallback
|
|
29
|
+
* if the associated strategy can't generate a response.
|
|
30
|
+
*/
|
|
31
|
+
fallbackUrls: (string | PrecacheFallbackEntry)[];
|
|
32
|
+
/**
|
|
33
|
+
* An optional `PrecacheController` instance. If not provided, the default
|
|
34
|
+
* `PrecacheController` will be used.
|
|
35
|
+
*/
|
|
36
|
+
precacheController?: PrecacheController;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* `PrecacheFallbackPlugin` allows you to specify offline fallbacks
|
|
41
|
+
* to be used when a given strategy is unable to generate a response.
|
|
42
|
+
*
|
|
43
|
+
* It does this by intercepting the `handlerDidError` plugin callback
|
|
44
|
+
* and returning a precached response, taking the expected revision parameter
|
|
45
|
+
* into account automatically.
|
|
46
|
+
*
|
|
47
|
+
* Unless you explicitly pass in a `PrecacheController` instance to the
|
|
48
|
+
* constructor, the default instance will be used. Generally speaking, most
|
|
49
|
+
* developers will end up using the default.
|
|
50
|
+
*/
|
|
51
|
+
export class PrecacheFallbackPlugin implements SerwistPlugin {
|
|
52
|
+
private readonly _fallbackUrls: (string | PrecacheFallbackEntry)[];
|
|
53
|
+
private readonly _precacheController: PrecacheController;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Constructs a new `PrecacheFallbackPlugin` with the associated `fallbackUrls`.
|
|
57
|
+
*
|
|
58
|
+
* @param config
|
|
59
|
+
*/
|
|
60
|
+
constructor({ fallbackUrls, precacheController }: PrecacheFallbackPluginOptions) {
|
|
61
|
+
this._fallbackUrls = fallbackUrls;
|
|
62
|
+
this._precacheController = precacheController || getOrCreatePrecacheController();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @returns The precache response for one of the fallback URLs, or `undefined` if
|
|
67
|
+
* nothing satisfies the conditions.
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
async handlerDidError(param: HandlerDidErrorCallbackParam) {
|
|
71
|
+
for (const fallback of this._fallbackUrls) {
|
|
72
|
+
if (typeof fallback === "string") {
|
|
73
|
+
const fallbackResponse = await this._precacheController.matchPrecache(fallback);
|
|
74
|
+
if (fallbackResponse !== undefined) {
|
|
75
|
+
return fallbackResponse;
|
|
76
|
+
}
|
|
77
|
+
} else if (fallback.matcher(param)) {
|
|
78
|
+
const fallbackResponse = await this._precacheController.matchPrecache(fallback.url);
|
|
79
|
+
if (fallbackResponse !== undefined) {
|
|
80
|
+
return fallbackResponse;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2018 Google LLC
|
|
3
|
+
|
|
4
|
+
Use of this source code is governed by an MIT-style
|
|
5
|
+
license that can be found in the LICENSE file or at
|
|
6
|
+
https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { SerwistPlugin } from "@serwist/core";
|
|
10
|
+
|
|
11
|
+
import { createPartialResponse } from "./createPartialResponse.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The range request plugin makes it easy for a request with a 'Range' header to
|
|
15
|
+
* be fulfilled by a cached response.
|
|
16
|
+
*
|
|
17
|
+
* It does this by intercepting the `cachedResponseWillBeUsed` plugin callback
|
|
18
|
+
* and returning the appropriate subset of the cached response body.
|
|
19
|
+
*/
|
|
20
|
+
export class RangeRequestsPlugin implements SerwistPlugin {
|
|
21
|
+
/**
|
|
22
|
+
* @param options
|
|
23
|
+
* @returns If request contains a 'Range' header, then a
|
|
24
|
+
* new response with status 206 whose body is a subset of `cachedResponse` is
|
|
25
|
+
* returned. Otherwise, `cachedResponse` is returned as-is.
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
cachedResponseWillBeUsed: SerwistPlugin["cachedResponseWillBeUsed"] = async ({ request, cachedResponse }) => {
|
|
29
|
+
// Only return a sliced response if there's something valid in the cache,
|
|
30
|
+
// and there's a Range: header in the request.
|
|
31
|
+
if (cachedResponse && request.headers.has("range")) {
|
|
32
|
+
return await createPartialResponse(request, cachedResponse);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// If there was no Range: header, or if cachedResponse wasn't valid, just
|
|
36
|
+
// pass it through as-is.
|
|
37
|
+
return cachedResponse;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2018 Google LLC
|
|
3
|
+
|
|
4
|
+
Use of this source code is governed by an MIT-style
|
|
5
|
+
license that can be found in the LICENSE file or at
|
|
6
|
+
https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { assert, SerwistError, logger } from "@serwist/core/internal";
|
|
10
|
+
|
|
11
|
+
import { calculateEffectiveBoundaries } from "./utils/calculateEffectiveBoundaries.js";
|
|
12
|
+
import { parseRangeHeader } from "./utils/parseRangeHeader.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Given a `Request` and `Response` objects as input, this will return a
|
|
16
|
+
* promise for a new `Response`.
|
|
17
|
+
*
|
|
18
|
+
* If the original `Response` already contains partial content (i.e. it has
|
|
19
|
+
* a status of 206), then this assumes it already fulfills the `Range:`
|
|
20
|
+
* requirements, and will return it as-is.
|
|
21
|
+
*
|
|
22
|
+
* @param request A request, which should contain a Range:
|
|
23
|
+
* header.
|
|
24
|
+
* @param originalResponse A response.
|
|
25
|
+
* @returns Either a `206 Partial Content` response, with
|
|
26
|
+
* the response body set to the slice of content specified by the request's
|
|
27
|
+
* `Range:` header, or a `416 Range Not Satisfiable` response if the
|
|
28
|
+
* conditions of the `Range:` header can't be met.
|
|
29
|
+
*/
|
|
30
|
+
export const createPartialResponse = async (request: Request, originalResponse: Response): Promise<Response> => {
|
|
31
|
+
try {
|
|
32
|
+
if (process.env.NODE_ENV !== "production") {
|
|
33
|
+
assert!.isInstance(request, Request, {
|
|
34
|
+
moduleName: "@serwist/range-requests",
|
|
35
|
+
funcName: "createPartialResponse",
|
|
36
|
+
paramName: "request",
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
assert!.isInstance(originalResponse, Response, {
|
|
40
|
+
moduleName: "@serwist/range-requests",
|
|
41
|
+
funcName: "createPartialResponse",
|
|
42
|
+
paramName: "originalResponse",
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (originalResponse.status === 206) {
|
|
47
|
+
// If we already have a 206, then just pass it through as-is;
|
|
48
|
+
// see https://github.com/GoogleChrome/workbox/issues/1720
|
|
49
|
+
return originalResponse;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const rangeHeader = request.headers.get("range");
|
|
53
|
+
if (!rangeHeader) {
|
|
54
|
+
throw new SerwistError("no-range-header");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const boundaries = parseRangeHeader(rangeHeader);
|
|
58
|
+
const originalBlob = await originalResponse.blob();
|
|
59
|
+
|
|
60
|
+
const effectiveBoundaries = calculateEffectiveBoundaries(originalBlob, boundaries.start, boundaries.end);
|
|
61
|
+
|
|
62
|
+
const slicedBlob = originalBlob.slice(effectiveBoundaries.start, effectiveBoundaries.end);
|
|
63
|
+
const slicedBlobSize = slicedBlob.size;
|
|
64
|
+
|
|
65
|
+
const slicedResponse = new Response(slicedBlob, {
|
|
66
|
+
// Status code 206 is for a Partial Content response.
|
|
67
|
+
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206
|
|
68
|
+
status: 206,
|
|
69
|
+
statusText: "Partial Content",
|
|
70
|
+
headers: originalResponse.headers,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
slicedResponse.headers.set("Content-Length", String(slicedBlobSize));
|
|
74
|
+
slicedResponse.headers.set("Content-Range", `bytes ${effectiveBoundaries.start}-${effectiveBoundaries.end - 1}/` + `${originalBlob.size}`);
|
|
75
|
+
|
|
76
|
+
return slicedResponse;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
if (process.env.NODE_ENV !== "production") {
|
|
79
|
+
logger.warn("Unable to construct a partial response; returning a " + "416 Range Not Satisfiable response instead.");
|
|
80
|
+
logger.groupCollapsed("View details here.");
|
|
81
|
+
logger.log(error);
|
|
82
|
+
logger.log(request);
|
|
83
|
+
logger.log(originalResponse);
|
|
84
|
+
logger.groupEnd();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return new Response("", {
|
|
88
|
+
status: 416,
|
|
89
|
+
statusText: "Range Not Satisfiable",
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2018 Google LLC
|
|
3
|
+
|
|
4
|
+
Use of this source code is governed by an MIT-style
|
|
5
|
+
license that can be found in the LICENSE file or at
|
|
6
|
+
https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { assert, SerwistError } from "@serwist/core/internal";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param blob A source blob.
|
|
13
|
+
* @param start The offset to use as the start of the
|
|
14
|
+
* slice.
|
|
15
|
+
* @param end The offset to use as the end of the slice.
|
|
16
|
+
* @returns An object with `start` and `end` properties, reflecting
|
|
17
|
+
* the effective boundaries to use given the size of the blob.
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
export const calculateEffectiveBoundaries = (blob: Blob, start?: number, end?: number): { start: number; end: number } => {
|
|
21
|
+
if (process.env.NODE_ENV !== "production") {
|
|
22
|
+
assert!.isInstance(blob, Blob, {
|
|
23
|
+
moduleName: "@serwist/range-requests",
|
|
24
|
+
funcName: "calculateEffectiveBoundaries",
|
|
25
|
+
paramName: "blob",
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const blobSize = blob.size;
|
|
30
|
+
|
|
31
|
+
if ((end && end > blobSize) || (start && start < 0)) {
|
|
32
|
+
throw new SerwistError("range-not-satisfiable", {
|
|
33
|
+
size: blobSize,
|
|
34
|
+
end,
|
|
35
|
+
start,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let effectiveStart: number;
|
|
40
|
+
let effectiveEnd: number;
|
|
41
|
+
|
|
42
|
+
if (start !== undefined && end !== undefined) {
|
|
43
|
+
effectiveStart = start;
|
|
44
|
+
// Range values are inclusive, so add 1 to the value.
|
|
45
|
+
effectiveEnd = end + 1;
|
|
46
|
+
} else if (start !== undefined && end === undefined) {
|
|
47
|
+
effectiveStart = start;
|
|
48
|
+
effectiveEnd = blobSize;
|
|
49
|
+
} else if (end !== undefined && start === undefined) {
|
|
50
|
+
effectiveStart = blobSize - end;
|
|
51
|
+
effectiveEnd = blobSize;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
start: effectiveStart!,
|
|
56
|
+
end: effectiveEnd!,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2018 Google LLC
|
|
3
|
+
|
|
4
|
+
Use of this source code is governed by an MIT-style
|
|
5
|
+
license that can be found in the LICENSE file or at
|
|
6
|
+
https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { assert, SerwistError } from "@serwist/core/internal";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param rangeHeader A Range: header value.
|
|
13
|
+
* @returns An object with `start` and `end` properties, reflecting
|
|
14
|
+
* the parsed value of the Range: header. If either the `start` or `end` are
|
|
15
|
+
* omitted, then `null` will be returned.
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
export const parseRangeHeader = (
|
|
19
|
+
rangeHeader: string,
|
|
20
|
+
): {
|
|
21
|
+
start?: number;
|
|
22
|
+
end?: number;
|
|
23
|
+
} => {
|
|
24
|
+
if (process.env.NODE_ENV !== "production") {
|
|
25
|
+
assert!.isType(rangeHeader, "string", {
|
|
26
|
+
moduleName: "@serwist/range-requests",
|
|
27
|
+
funcName: "parseRangeHeader",
|
|
28
|
+
paramName: "rangeHeader",
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const normalizedRangeHeader = rangeHeader.trim().toLowerCase();
|
|
33
|
+
if (!normalizedRangeHeader.startsWith("bytes=")) {
|
|
34
|
+
throw new SerwistError("unit-must-be-bytes", { normalizedRangeHeader });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Specifying multiple ranges separate by commas is valid syntax, but this
|
|
38
|
+
// library only attempts to handle a single, contiguous sequence of bytes.
|
|
39
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range#Syntax
|
|
40
|
+
if (normalizedRangeHeader.includes(",")) {
|
|
41
|
+
throw new SerwistError("single-range-only", { normalizedRangeHeader });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const rangeParts = /(\d*)-(\d*)/.exec(normalizedRangeHeader);
|
|
45
|
+
// We need either at least one of the start or end values.
|
|
46
|
+
if (!rangeParts || !(rangeParts[1] || rangeParts[2])) {
|
|
47
|
+
throw new SerwistError("invalid-range-values", { normalizedRangeHeader });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
start: rangeParts[1] === "" ? undefined : Number(rangeParts[1]),
|
|
52
|
+
end: rangeParts[2] === "" ? undefined : Number(rangeParts[2]),
|
|
53
|
+
};
|
|
54
|
+
};
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2019 Google LLC
|
|
3
|
+
|
|
4
|
+
Use of this source code is governed by an MIT-style
|
|
5
|
+
license that can be found in the LICENSE file or at
|
|
6
|
+
https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { RouteHandlerCallback, SerwistPlugin } from "@serwist/core";
|
|
10
|
+
import { assert, SerwistError, logger, privateCacheNames, waitUntil } from "@serwist/core/internal";
|
|
11
|
+
import { parallel } from "@serwist/utils";
|
|
12
|
+
import type { Strategy } from "../strategies/Strategy.js";
|
|
13
|
+
import { PrecacheStrategy } from "./PrecacheStrategy.js";
|
|
14
|
+
import type { CleanupResult, InstallResult, PrecacheEntry } from "./types.js";
|
|
15
|
+
import { PrecacheCacheKeyPlugin } from "./utils/PrecacheCacheKeyPlugin.js";
|
|
16
|
+
import { PrecacheInstallReportPlugin } from "./utils/PrecacheInstallReportPlugin.js";
|
|
17
|
+
import { createCacheKey } from "./utils/createCacheKey.js";
|
|
18
|
+
import { printCleanupDetails } from "./utils/printCleanupDetails.js";
|
|
19
|
+
import { printInstallDetails } from "./utils/printInstallDetails.js";
|
|
20
|
+
|
|
21
|
+
// Give TypeScript the correct global.
|
|
22
|
+
declare const self: ServiceWorkerGlobalScope;
|
|
23
|
+
|
|
24
|
+
interface PrecacheControllerOptions {
|
|
25
|
+
/**
|
|
26
|
+
* The cache to use for precaching.
|
|
27
|
+
*/
|
|
28
|
+
cacheName?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Plugins to use when precaching as well as responding to fetch
|
|
31
|
+
* events for precached assets.
|
|
32
|
+
*/
|
|
33
|
+
plugins?: SerwistPlugin[];
|
|
34
|
+
/**
|
|
35
|
+
* Whether to attempt to get the response from the network if there's
|
|
36
|
+
* a precache miss.
|
|
37
|
+
*/
|
|
38
|
+
fallbackToNetwork?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* A number of how many precache requests should be made concurrently.
|
|
41
|
+
*
|
|
42
|
+
* @default 1
|
|
43
|
+
*/
|
|
44
|
+
concurrentPrecaching?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Performs efficient precaching of assets.
|
|
49
|
+
*/
|
|
50
|
+
export class PrecacheController {
|
|
51
|
+
private _installAndActiveListenersAdded?: boolean;
|
|
52
|
+
private _concurrentPrecaching: number;
|
|
53
|
+
private readonly _strategy: Strategy;
|
|
54
|
+
private readonly _urlsToCacheKeys: Map<string, string> = new Map();
|
|
55
|
+
private readonly _urlsToCacheModes: Map<string, "reload" | "default" | "no-store" | "no-cache" | "force-cache" | "only-if-cached"> = new Map();
|
|
56
|
+
private readonly _cacheKeysToIntegrities: Map<string, string> = new Map();
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Create a new PrecacheController.
|
|
60
|
+
*
|
|
61
|
+
* @param options
|
|
62
|
+
*/
|
|
63
|
+
constructor({ cacheName, plugins = [], fallbackToNetwork = true, concurrentPrecaching = 1 }: PrecacheControllerOptions = {}) {
|
|
64
|
+
this._concurrentPrecaching = concurrentPrecaching;
|
|
65
|
+
this._strategy = new PrecacheStrategy({
|
|
66
|
+
cacheName: privateCacheNames.getPrecacheName(cacheName),
|
|
67
|
+
plugins: [...plugins, new PrecacheCacheKeyPlugin({ precacheController: this })],
|
|
68
|
+
fallbackToNetwork,
|
|
69
|
+
});
|
|
70
|
+
// Bind the install and activate methods to the instance.
|
|
71
|
+
this.install = this.install.bind(this);
|
|
72
|
+
this.activate = this.activate.bind(this);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The strategy created by this controller and
|
|
77
|
+
* used to cache assets and respond to fetch events.
|
|
78
|
+
*/
|
|
79
|
+
get strategy(): Strategy {
|
|
80
|
+
return this._strategy;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Adds items to the precache list, removing any duplicates and
|
|
85
|
+
* stores the files in the precache cache when the service
|
|
86
|
+
* worker installs.
|
|
87
|
+
*
|
|
88
|
+
* This method can be called multiple times.
|
|
89
|
+
*
|
|
90
|
+
* @param entries Array of entries to precache.
|
|
91
|
+
*/
|
|
92
|
+
precache(entries: (PrecacheEntry | string)[]): void {
|
|
93
|
+
this.addToCacheList(entries);
|
|
94
|
+
|
|
95
|
+
if (!this._installAndActiveListenersAdded) {
|
|
96
|
+
self.addEventListener("install", this.install);
|
|
97
|
+
self.addEventListener("activate", this.activate);
|
|
98
|
+
this._installAndActiveListenersAdded = true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* This method will add items to the precache list, removing duplicates
|
|
104
|
+
* and ensuring the information is valid.
|
|
105
|
+
*
|
|
106
|
+
* @param entries Array of entries to precache.
|
|
107
|
+
*/
|
|
108
|
+
addToCacheList(entries: (PrecacheEntry | string)[]): void {
|
|
109
|
+
if (process.env.NODE_ENV !== "production") {
|
|
110
|
+
assert!.isArray(entries, {
|
|
111
|
+
moduleName: "@serwist/precaching",
|
|
112
|
+
className: "PrecacheController",
|
|
113
|
+
funcName: "addToCacheList",
|
|
114
|
+
paramName: "entries",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const urlsToWarnAbout: string[] = [];
|
|
119
|
+
for (const entry of entries) {
|
|
120
|
+
// See https://github.com/GoogleChrome/workbox/issues/2259
|
|
121
|
+
if (typeof entry === "string") {
|
|
122
|
+
urlsToWarnAbout.push(entry);
|
|
123
|
+
} else if (entry && !entry.integrity && entry.revision === undefined) {
|
|
124
|
+
urlsToWarnAbout.push(entry.url);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const { cacheKey, url } = createCacheKey(entry);
|
|
128
|
+
const cacheMode = typeof entry !== "string" && entry.revision ? "reload" : "default";
|
|
129
|
+
|
|
130
|
+
if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) {
|
|
131
|
+
throw new SerwistError("add-to-cache-list-conflicting-entries", {
|
|
132
|
+
firstEntry: this._urlsToCacheKeys.get(url),
|
|
133
|
+
secondEntry: cacheKey,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (typeof entry !== "string" && entry.integrity) {
|
|
138
|
+
if (this._cacheKeysToIntegrities.has(cacheKey) && this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity) {
|
|
139
|
+
throw new SerwistError("add-to-cache-list-conflicting-integrities", {
|
|
140
|
+
url,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
this._cacheKeysToIntegrities.set(cacheKey, entry.integrity);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
this._urlsToCacheKeys.set(url, cacheKey);
|
|
147
|
+
this._urlsToCacheModes.set(url, cacheMode);
|
|
148
|
+
|
|
149
|
+
if (urlsToWarnAbout.length > 0) {
|
|
150
|
+
const warningMessage = `Serwist is precaching URLs without revision info: ${urlsToWarnAbout.join(
|
|
151
|
+
", ",
|
|
152
|
+
)}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;
|
|
153
|
+
if (process.env.NODE_ENV === "production") {
|
|
154
|
+
// Use console directly to display this warning without bloating
|
|
155
|
+
// bundle sizes by pulling in all of the logger codebase in prod.
|
|
156
|
+
console.warn(warningMessage);
|
|
157
|
+
} else {
|
|
158
|
+
logger.warn(warningMessage);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Precaches new and updated assets. Call this method from the service worker
|
|
166
|
+
* install event.
|
|
167
|
+
*
|
|
168
|
+
* Note: this method calls `event.waitUntil()` for you, so you do not need
|
|
169
|
+
* to call it yourself in your event handlers.
|
|
170
|
+
*
|
|
171
|
+
* @param event
|
|
172
|
+
* @returns
|
|
173
|
+
*/
|
|
174
|
+
install(event: ExtendableEvent): Promise<InstallResult> {
|
|
175
|
+
return waitUntil<InstallResult>(event, async () => {
|
|
176
|
+
const installReportPlugin = new PrecacheInstallReportPlugin();
|
|
177
|
+
this.strategy.plugins.push(installReportPlugin);
|
|
178
|
+
|
|
179
|
+
await parallel(this._concurrentPrecaching, Array.from(this._urlsToCacheKeys.entries()), async ([url, cacheKey]): Promise<void> => {
|
|
180
|
+
const integrity = this._cacheKeysToIntegrities.get(cacheKey);
|
|
181
|
+
const cacheMode = this._urlsToCacheModes.get(url);
|
|
182
|
+
|
|
183
|
+
const request = new Request(url, {
|
|
184
|
+
integrity,
|
|
185
|
+
cache: cacheMode,
|
|
186
|
+
credentials: "same-origin",
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
await Promise.all(
|
|
190
|
+
this.strategy.handleAll({
|
|
191
|
+
event,
|
|
192
|
+
request,
|
|
193
|
+
url: new URL(request.url),
|
|
194
|
+
params: { cacheKey },
|
|
195
|
+
}),
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const { updatedURLs, notUpdatedURLs } = installReportPlugin;
|
|
200
|
+
|
|
201
|
+
if (process.env.NODE_ENV !== "production") {
|
|
202
|
+
printInstallDetails(updatedURLs, notUpdatedURLs);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return { updatedURLs, notUpdatedURLs };
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Deletes assets that are no longer present in the current precache manifest.
|
|
211
|
+
* Call this method from the service worker activate event.
|
|
212
|
+
*
|
|
213
|
+
* Note: this method calls `event.waitUntil()` for you, so you do not need
|
|
214
|
+
* to call it yourself in your event handlers.
|
|
215
|
+
*
|
|
216
|
+
* @param event
|
|
217
|
+
* @returns
|
|
218
|
+
*/
|
|
219
|
+
activate(event: ExtendableEvent): Promise<CleanupResult> {
|
|
220
|
+
return waitUntil<CleanupResult>(event, async () => {
|
|
221
|
+
const cache = await self.caches.open(this.strategy.cacheName);
|
|
222
|
+
const currentlyCachedRequests = await cache.keys();
|
|
223
|
+
const expectedCacheKeys = new Set(this._urlsToCacheKeys.values());
|
|
224
|
+
|
|
225
|
+
const deletedCacheRequests: string[] = [];
|
|
226
|
+
|
|
227
|
+
for (const request of currentlyCachedRequests) {
|
|
228
|
+
if (!expectedCacheKeys.has(request.url)) {
|
|
229
|
+
await cache.delete(request);
|
|
230
|
+
deletedCacheRequests.push(request.url);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (process.env.NODE_ENV !== "production") {
|
|
235
|
+
printCleanupDetails(deletedCacheRequests);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return { deletedCacheRequests };
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Returns a mapping of a precached URL to the corresponding cache key, taking
|
|
244
|
+
* into account the revision information for the URL.
|
|
245
|
+
*
|
|
246
|
+
* @returns A URL to cache key mapping.
|
|
247
|
+
*/
|
|
248
|
+
getURLsToCacheKeys(): Map<string, string> {
|
|
249
|
+
return this._urlsToCacheKeys;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Returns a list of all the URLs that have been precached by the current
|
|
254
|
+
* service worker.
|
|
255
|
+
*
|
|
256
|
+
* @returns The precached URLs.
|
|
257
|
+
*/
|
|
258
|
+
getCachedURLs(): string[] {
|
|
259
|
+
return [...this._urlsToCacheKeys.keys()];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Returns the cache key used for storing a given URL. If that URL is
|
|
264
|
+
* unversioned, like `/index.html', then the cache key will be the original
|
|
265
|
+
* URL with a search parameter appended to it.
|
|
266
|
+
*
|
|
267
|
+
* @param url A URL whose cache key you want to look up.
|
|
268
|
+
* @returns The versioned URL that corresponds to a cache key
|
|
269
|
+
* for the original URL, or undefined if that URL isn't precached.
|
|
270
|
+
*/
|
|
271
|
+
getCacheKeyForURL(url: string): string | undefined {
|
|
272
|
+
const urlObject = new URL(url, location.href);
|
|
273
|
+
return this._urlsToCacheKeys.get(urlObject.href);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* @param url A cache key whose SRI you want to look up.
|
|
278
|
+
* @returns The subresource integrity associated with the cache key,
|
|
279
|
+
* or undefined if it's not set.
|
|
280
|
+
*/
|
|
281
|
+
getIntegrityForCacheKey(cacheKey: string): string | undefined {
|
|
282
|
+
return this._cacheKeysToIntegrities.get(cacheKey);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* This acts as a drop-in replacement for
|
|
287
|
+
* [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
|
|
288
|
+
* with the following differences:
|
|
289
|
+
*
|
|
290
|
+
* - It knows what the name of the precache is, and only checks in that cache.
|
|
291
|
+
* - It allows you to pass in an "original" URL without versioning parameters,
|
|
292
|
+
* and it will automatically look up the correct cache key for the currently
|
|
293
|
+
* active revision of that URL.
|
|
294
|
+
*
|
|
295
|
+
* E.g., `matchPrecache('index.html')` will find the correct precached
|
|
296
|
+
* response for the currently active service worker, even if the actual cache
|
|
297
|
+
* key is `'/index.html?__WB_REVISION__=1234abcd'`.
|
|
298
|
+
*
|
|
299
|
+
* @param request The key (without revisioning parameters)
|
|
300
|
+
* to look up in the precache.
|
|
301
|
+
* @returns
|
|
302
|
+
*/
|
|
303
|
+
async matchPrecache(request: string | Request): Promise<Response | undefined> {
|
|
304
|
+
const url = request instanceof Request ? request.url : request;
|
|
305
|
+
const cacheKey = this.getCacheKeyForURL(url);
|
|
306
|
+
if (cacheKey) {
|
|
307
|
+
const cache = await self.caches.open(this.strategy.cacheName);
|
|
308
|
+
return cache.match(cacheKey);
|
|
309
|
+
}
|
|
310
|
+
return undefined;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Returns a function that looks up `url` in the precache (taking into
|
|
315
|
+
* account revision information), and returns the corresponding `Response`.
|
|
316
|
+
*
|
|
317
|
+
* @param url The precached URL which will be used to lookup the response.
|
|
318
|
+
* @return
|
|
319
|
+
*/
|
|
320
|
+
createHandlerBoundToURL(url: string): RouteHandlerCallback {
|
|
321
|
+
const cacheKey = this.getCacheKeyForURL(url);
|
|
322
|
+
if (!cacheKey) {
|
|
323
|
+
throw new SerwistError("non-precached-url", { url });
|
|
324
|
+
}
|
|
325
|
+
return (options) => {
|
|
326
|
+
options.request = new Request(url);
|
|
327
|
+
options.params = { cacheKey, ...options.params };
|
|
328
|
+
|
|
329
|
+
return this.strategy.handle(options);
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
}
|