serwist 9.0.0-preview.24
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/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/NavigationRoute.d.ts +57 -0
- package/dist/NavigationRoute.d.ts.map +1 -0
- package/dist/PrecacheRoute.d.ts +17 -0
- package/dist/PrecacheRoute.d.ts.map +1 -0
- package/dist/PrecacheStrategy.d.ts +66 -0
- package/dist/PrecacheStrategy.d.ts.map +1 -0
- package/dist/RegExpRoute.d.ts +24 -0
- package/dist/RegExpRoute.d.ts.map +1 -0
- package/dist/Route.d.ts +33 -0
- package/dist/Route.d.ts.map +1 -0
- package/dist/Serwist.d.ts +331 -0
- package/dist/Serwist.d.ts.map +1 -0
- package/dist/cacheNames.d.ts +20 -0
- package/dist/cacheNames.d.ts.map +1 -0
- package/dist/chunks/NetworkOnly.js +599 -0
- package/dist/chunks/PrecacheFallbackPlugin.js +634 -0
- package/dist/chunks/Serwist.js +1034 -0
- package/dist/chunks/registerQuotaErrorCallback.js +17 -0
- package/dist/chunks/resultingClientExists.js +32 -0
- package/dist/chunks/timeout.js +400 -0
- package/dist/chunks/waitUntil.js +24 -0
- package/dist/cleanupOutdatedCaches.d.ts +6 -0
- package/dist/cleanupOutdatedCaches.d.ts.map +1 -0
- package/dist/clientsClaim.d.ts +6 -0
- package/dist/clientsClaim.d.ts.map +1 -0
- package/dist/constants.d.ts +15 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/copyResponse.d.ts +20 -0
- package/dist/copyResponse.d.ts.map +1 -0
- package/dist/disableDevLogs.d.ts +7 -0
- package/dist/disableDevLogs.d.ts.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.internal.d.ts +16 -0
- package/dist/index.internal.d.ts.map +1 -0
- package/dist/index.internal.js +24 -0
- package/dist/index.js +27 -0
- package/dist/index.legacy.d.ts +32 -0
- package/dist/index.legacy.d.ts.map +1 -0
- package/dist/index.legacy.js +640 -0
- package/dist/index.plugins.d.ts +41 -0
- package/dist/index.plugins.d.ts.map +1 -0
- package/dist/index.plugins.js +669 -0
- package/dist/index.strategies.d.ts +22 -0
- package/dist/index.strategies.d.ts.map +1 -0
- package/dist/index.strategies.js +144 -0
- package/dist/legacy/PrecacheController.d.ts +146 -0
- package/dist/legacy/PrecacheController.d.ts.map +1 -0
- package/dist/legacy/PrecacheFallbackPlugin.d.ts +62 -0
- package/dist/legacy/PrecacheFallbackPlugin.d.ts.map +1 -0
- package/dist/legacy/PrecacheRoute.d.ts +19 -0
- package/dist/legacy/PrecacheRoute.d.ts.map +1 -0
- package/dist/legacy/Router.d.ts +151 -0
- package/dist/legacy/Router.d.ts.map +1 -0
- package/dist/legacy/addPlugins.d.ts +9 -0
- package/dist/legacy/addPlugins.d.ts.map +1 -0
- package/dist/legacy/addRoute.d.ts +16 -0
- package/dist/legacy/addRoute.d.ts.map +1 -0
- package/dist/legacy/createHandlerBoundToURL.d.ts +18 -0
- package/dist/legacy/createHandlerBoundToURL.d.ts.map +1 -0
- package/dist/legacy/fallbacks.d.ts +59 -0
- package/dist/legacy/fallbacks.d.ts.map +1 -0
- package/dist/legacy/getCacheKeyForURL.d.ts +20 -0
- package/dist/legacy/getCacheKeyForURL.d.ts.map +1 -0
- package/dist/legacy/handlePrecaching.d.ts +54 -0
- package/dist/legacy/handlePrecaching.d.ts.map +1 -0
- package/dist/legacy/installSerwist.d.ts +15 -0
- package/dist/legacy/installSerwist.d.ts.map +1 -0
- package/dist/legacy/matchPrecache.d.ts +15 -0
- package/dist/legacy/matchPrecache.d.ts.map +1 -0
- package/dist/legacy/precache.d.ts +20 -0
- package/dist/legacy/precache.d.ts.map +1 -0
- package/dist/legacy/precacheAndRoute.d.ts +15 -0
- package/dist/legacy/precacheAndRoute.d.ts.map +1 -0
- package/dist/legacy/registerRoute.d.ts +16 -0
- package/dist/legacy/registerRoute.d.ts.map +1 -0
- package/dist/legacy/registerRuntimeCaching.d.ts +11 -0
- package/dist/legacy/registerRuntimeCaching.d.ts.map +1 -0
- package/dist/legacy/setCatchHandler.d.ts +10 -0
- package/dist/legacy/setCatchHandler.d.ts.map +1 -0
- package/dist/legacy/setDefaultHandler.d.ts +13 -0
- package/dist/legacy/setDefaultHandler.d.ts.map +1 -0
- package/dist/legacy/singletonPrecacheController.d.ts +34 -0
- package/dist/legacy/singletonPrecacheController.d.ts.map +1 -0
- package/dist/legacy/singletonRouter.d.ts +41 -0
- package/dist/legacy/singletonRouter.d.ts.map +1 -0
- package/dist/legacy/unregisterRoute.d.ts +9 -0
- package/dist/legacy/unregisterRoute.d.ts.map +1 -0
- package/dist/legacy/utils/PrecacheCacheKeyPlugin.d.ts +16 -0
- package/dist/legacy/utils/PrecacheCacheKeyPlugin.d.ts.map +1 -0
- package/dist/legacy/utils/getCacheKeyForURL.d.ts +14 -0
- package/dist/legacy/utils/getCacheKeyForURL.d.ts.map +1 -0
- package/dist/models/messages/messageGenerator.d.ts +4 -0
- package/dist/models/messages/messageGenerator.d.ts.map +1 -0
- package/dist/models/messages/messages.d.ts +44 -0
- package/dist/models/messages/messages.d.ts.map +1 -0
- package/dist/models/pluginEvents.d.ts +10 -0
- package/dist/models/pluginEvents.d.ts.map +1 -0
- package/dist/models/quotaErrorCallbacks.d.ts +3 -0
- package/dist/models/quotaErrorCallbacks.d.ts.map +1 -0
- package/dist/navigationPreload.d.ts +24 -0
- package/dist/navigationPreload.d.ts.map +1 -0
- package/dist/parseRoute.d.ts +16 -0
- package/dist/parseRoute.d.ts.map +1 -0
- 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 +30 -0
- package/dist/plugins/googleAnalytics/initialize.d.ts.map +1 -0
- package/dist/plugins/precaching/PrecacheFallbackPlugin.d.ts +53 -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/registerQuotaErrorCallback.d.ts +8 -0
- package/dist/registerQuotaErrorCallback.d.ts.map +1 -0
- package/dist/setCacheNameDetails.d.ts +9 -0
- package/dist/setCacheNameDetails.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/dist/types.d.ts +317 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/Deferred.d.ts +19 -0
- package/dist/utils/Deferred.d.ts.map +1 -0
- package/dist/utils/PrecacheCacheKeyPlugin.d.ts +16 -0
- package/dist/utils/PrecacheCacheKeyPlugin.d.ts.map +1 -0
- package/dist/utils/PrecacheInstallReportPlugin.d.ts +14 -0
- package/dist/utils/PrecacheInstallReportPlugin.d.ts.map +1 -0
- package/dist/utils/SerwistError.d.ts +24 -0
- package/dist/utils/SerwistError.d.ts.map +1 -0
- package/dist/utils/assert.d.ts +11 -0
- package/dist/utils/assert.d.ts.map +1 -0
- package/dist/utils/cacheMatchIgnoreParams.d.ts +15 -0
- package/dist/utils/cacheMatchIgnoreParams.d.ts.map +1 -0
- package/dist/utils/cacheNames.d.ts +40 -0
- package/dist/utils/cacheNames.d.ts.map +1 -0
- package/dist/utils/canConstructReadableStream.d.ts +12 -0
- package/dist/utils/canConstructReadableStream.d.ts.map +1 -0
- package/dist/utils/canConstructResponseFromBodyStream.d.ts +11 -0
- package/dist/utils/canConstructResponseFromBodyStream.d.ts.map +1 -0
- package/dist/utils/createCacheKey.d.ts +16 -0
- package/dist/utils/createCacheKey.d.ts.map +1 -0
- package/dist/utils/deleteOutdatedCaches.d.ts +18 -0
- package/dist/utils/deleteOutdatedCaches.d.ts.map +1 -0
- package/dist/utils/dontWaitFor.d.ts +7 -0
- package/dist/utils/dontWaitFor.d.ts.map +1 -0
- package/dist/utils/executeQuotaErrorCallbacks.d.ts +8 -0
- package/dist/utils/executeQuotaErrorCallbacks.d.ts.map +1 -0
- package/dist/utils/generateURLVariations.d.ts +12 -0
- package/dist/utils/generateURLVariations.d.ts.map +1 -0
- package/dist/utils/getFriendlyURL.d.ts +3 -0
- package/dist/utils/getFriendlyURL.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +24 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/normalizeHandler.d.ts +10 -0
- package/dist/utils/normalizeHandler.d.ts.map +1 -0
- package/dist/utils/pluginUtils.d.ts +5 -0
- package/dist/utils/pluginUtils.d.ts.map +1 -0
- package/dist/utils/printCleanupDetails.d.ts +6 -0
- package/dist/utils/printCleanupDetails.d.ts.map +1 -0
- package/dist/utils/printInstallDetails.d.ts +7 -0
- package/dist/utils/printInstallDetails.d.ts.map +1 -0
- package/dist/utils/removeIgnoredSearchParams.d.ts +12 -0
- package/dist/utils/removeIgnoredSearchParams.d.ts.map +1 -0
- package/dist/utils/resultingClientExists.d.ts +12 -0
- package/dist/utils/resultingClientExists.d.ts.map +1 -0
- package/dist/utils/timeout.d.ts +10 -0
- package/dist/utils/timeout.d.ts.map +1 -0
- package/dist/utils/waitUntil.d.ts +11 -0
- package/dist/utils/waitUntil.d.ts.map +1 -0
- package/dist/utils/welcome.d.ts +2 -0
- package/dist/utils/welcome.d.ts.map +1 -0
- package/package.json +85 -0
- package/src/NavigationRoute.ts +119 -0
- package/src/PrecacheRoute.ts +46 -0
- package/src/PrecacheStrategy.ts +239 -0
- package/src/RegExpRoute.ts +74 -0
- package/src/Route.ts +67 -0
- package/src/Serwist.ts +920 -0
- package/src/cacheNames.ts +39 -0
- package/src/cleanupOutdatedCaches.ts +32 -0
- package/src/clientsClaim.ts +18 -0
- package/src/constants.ts +24 -0
- package/src/copyResponse.ts +60 -0
- package/src/disableDevLogs.ts +10 -0
- package/src/index.internal.ts +33 -0
- package/src/index.legacy.ts +66 -0
- package/src/index.plugins.ts +95 -0
- package/src/index.strategies.ts +26 -0
- package/src/index.ts +39 -0
- package/src/legacy/PrecacheController.ts +337 -0
- package/src/legacy/PrecacheFallbackPlugin.ts +93 -0
- package/src/legacy/PrecacheRoute.ts +48 -0
- package/src/legacy/Router.ts +484 -0
- package/src/legacy/addPlugins.ts +21 -0
- package/src/legacy/addRoute.ts +29 -0
- package/src/legacy/createHandlerBoundToURL.ts +30 -0
- package/src/legacy/fallbacks.ts +94 -0
- package/src/legacy/getCacheKeyForURL.ts +32 -0
- package/src/legacy/handlePrecaching.ts +86 -0
- package/src/legacy/installSerwist.ts +19 -0
- package/src/legacy/matchPrecache.ts +26 -0
- package/src/legacy/precache.ts +31 -0
- package/src/legacy/precacheAndRoute.ts +28 -0
- package/src/legacy/registerRoute.ts +27 -0
- package/src/legacy/registerRuntimeCaching.ts +17 -0
- package/src/legacy/setCatchHandler.ts +21 -0
- package/src/legacy/setDefaultHandler.ts +24 -0
- package/src/legacy/singletonPrecacheController.ts +53 -0
- package/src/legacy/singletonRouter.ts +70 -0
- package/src/legacy/unregisterRoute.ts +12 -0
- package/src/legacy/utils/PrecacheCacheKeyPlugin.ts +33 -0
- package/src/legacy/utils/getCacheKeyForURL.ts +36 -0
- package/src/models/messages/messageGenerator.ts +29 -0
- package/src/models/messages/messages.ts +233 -0
- package/src/models/pluginEvents.ts +17 -0
- package/src/models/quotaErrorCallbacks.ts +13 -0
- package/src/navigationPreload.ts +68 -0
- package/src/parseRoute.ts +78 -0
- package/src/plugins/backgroundSync/BackgroundSyncPlugin.ts +38 -0
- package/src/plugins/backgroundSync/Queue.ts +440 -0
- package/src/plugins/backgroundSync/QueueDb.ts +176 -0
- package/src/plugins/backgroundSync/QueueStore.ts +160 -0
- package/src/plugins/backgroundSync/StorableRequest.ts +142 -0
- package/src/plugins/broadcastUpdate/BroadcastCacheUpdate.ts +161 -0
- package/src/plugins/broadcastUpdate/BroadcastUpdatePlugin.ts +42 -0
- package/src/plugins/broadcastUpdate/constants.ts +12 -0
- package/src/plugins/broadcastUpdate/responsesAreSame.ts +49 -0
- package/src/plugins/broadcastUpdate/types.ts +37 -0
- package/src/plugins/cacheableResponse/CacheableResponse.ts +144 -0
- package/src/plugins/cacheableResponse/CacheableResponsePlugin.ts +45 -0
- package/src/plugins/expiration/CacheExpiration.ts +193 -0
- package/src/plugins/expiration/ExpirationPlugin.ts +300 -0
- package/src/plugins/expiration/models/CacheTimestampsModel.ts +184 -0
- package/src/plugins/googleAnalytics/constants.ts +22 -0
- package/src/plugins/googleAnalytics/initialize.ts +209 -0
- package/src/plugins/precaching/PrecacheFallbackPlugin.ts +83 -0
- package/src/plugins/rangeRequests/RangeRequestsPlugin.ts +38 -0
- package/src/plugins/rangeRequests/createPartialResponse.ts +93 -0
- package/src/plugins/rangeRequests/utils/calculateEffectiveBoundaries.ts +59 -0
- package/src/plugins/rangeRequests/utils/parseRangeHeader.ts +55 -0
- package/src/registerQuotaErrorCallback.ts +34 -0
- package/src/setCacheNameDetails.ts +53 -0
- package/src/strategies/CacheFirst.ts +88 -0
- package/src/strategies/CacheOnly.ts +59 -0
- package/src/strategies/NetworkFirst.ts +229 -0
- package/src/strategies/NetworkOnly.ts +98 -0
- package/src/strategies/StaleWhileRevalidate.ts +110 -0
- package/src/strategies/Strategy.ts +204 -0
- package/src/strategies/StrategyHandler.ts +554 -0
- package/src/strategies/plugins/cacheOkAndOpaquePlugin.ts +26 -0
- package/src/strategies/utils/messages.ts +21 -0
- package/src/types.ts +358 -0
- package/src/utils/Deferred.ts +33 -0
- package/src/utils/PrecacheCacheKeyPlugin.ts +33 -0
- package/src/utils/PrecacheInstallReportPlugin.ts +47 -0
- package/src/utils/SerwistError.ts +41 -0
- package/src/utils/assert.ts +89 -0
- package/src/utils/cacheMatchIgnoreParams.ts +54 -0
- package/src/utils/cacheNames.ts +87 -0
- package/src/utils/canConstructReadableStream.ts +34 -0
- package/src/utils/canConstructResponseFromBodyStream.ts +37 -0
- package/src/utils/createCacheKey.ts +68 -0
- package/src/utils/deleteOutdatedCaches.ts +40 -0
- package/src/utils/dontWaitFor.ts +16 -0
- package/src/utils/executeQuotaErrorCallbacks.ts +33 -0
- package/src/utils/generateURLVariations.ts +55 -0
- package/src/utils/getFriendlyURL.ts +16 -0
- package/src/utils/logger.ts +95 -0
- package/src/utils/normalizeHandler.ts +40 -0
- package/src/utils/pluginUtils.ts +15 -0
- package/src/utils/printCleanupDetails.ts +38 -0
- package/src/utils/printInstallDetails.ts +53 -0
- package/src/utils/removeIgnoredSearchParams.ts +29 -0
- package/src/utils/resultingClientExists.ts +58 -0
- package/src/utils/timeout.ts +19 -0
- package/src/utils/waitUntil.ts +21 -0
- package/src/utils/welcome.ts +19 -0
package/src/Serwist.ts
ADDED
|
@@ -0,0 +1,920 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RouteHandler,
|
|
3
|
+
RouteHandlerCallback,
|
|
4
|
+
RouteHandlerCallbackOptions,
|
|
5
|
+
RouteHandlerObject,
|
|
6
|
+
RouteMatchCallback,
|
|
7
|
+
RouteMatchCallbackOptions,
|
|
8
|
+
SerwistPlugin,
|
|
9
|
+
} from "./types.js";
|
|
10
|
+
import { clientsClaim as clientsClaimImpl } from "./clientsClaim.js";
|
|
11
|
+
import { setCacheNameDetails } from "./setCacheNameDetails.js";
|
|
12
|
+
import { assert } from "./utils/assert.js";
|
|
13
|
+
import { SerwistError } from "./utils/SerwistError.js";
|
|
14
|
+
import { getFriendlyURL } from "./utils/getFriendlyURL.js";
|
|
15
|
+
import { logger } from "./utils/logger.js";
|
|
16
|
+
import { cacheNames as privateCacheNames } from "./utils/cacheNames.js";
|
|
17
|
+
import { waitUntil } from "./utils/waitUntil.js";
|
|
18
|
+
import { parallel } from "@serwist/utils";
|
|
19
|
+
import { NavigationRoute } from "./NavigationRoute.js";
|
|
20
|
+
import { PrecacheRoute } from "./PrecacheRoute.js";
|
|
21
|
+
import { PrecacheStrategy } from "./PrecacheStrategy.js";
|
|
22
|
+
import type { Route } from "./Route.js";
|
|
23
|
+
import { cleanupOutdatedCaches as cleanupOutdatedCachesImpl } from "./cleanupOutdatedCaches.js";
|
|
24
|
+
import { type HTTPMethod, defaultMethod } from "./constants.js";
|
|
25
|
+
import { disableDevLogs as disableDevLogsImpl } from "./disableDevLogs.js";
|
|
26
|
+
import { enableNavigationPreload } from "./navigationPreload.js";
|
|
27
|
+
import { parseRoute } from "./parseRoute.js";
|
|
28
|
+
import { type GoogleAnalyticsInitializeOptions, initialize } from "./plugins/googleAnalytics/initialize.js";
|
|
29
|
+
import { type PrecacheFallbackEntry, PrecacheFallbackPlugin } from "./plugins/precaching/PrecacheFallbackPlugin.js";
|
|
30
|
+
import { Strategy } from "./strategies/Strategy.js";
|
|
31
|
+
import type { PrecacheRouteOptions, RuntimeCaching } from "./types.js";
|
|
32
|
+
import type { CleanupResult, InstallResult, PrecacheEntry } from "./types.js";
|
|
33
|
+
import { PrecacheCacheKeyPlugin } from "./utils/PrecacheCacheKeyPlugin.js";
|
|
34
|
+
import { PrecacheInstallReportPlugin } from "./utils/PrecacheInstallReportPlugin.js";
|
|
35
|
+
import { createCacheKey } from "./utils/createCacheKey.js";
|
|
36
|
+
import { normalizeHandler } from "./utils/normalizeHandler.js";
|
|
37
|
+
import { printCleanupDetails } from "./utils/printCleanupDetails.js";
|
|
38
|
+
import { printInstallDetails } from "./utils/printInstallDetails.js";
|
|
39
|
+
|
|
40
|
+
declare const self: ServiceWorkerGlobalScope;
|
|
41
|
+
|
|
42
|
+
export interface FallbackEntry extends PrecacheFallbackEntry {}
|
|
43
|
+
|
|
44
|
+
export interface FallbacksOptions {
|
|
45
|
+
/**
|
|
46
|
+
* A list of fallback entries.
|
|
47
|
+
*/
|
|
48
|
+
entries: FallbackEntry[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface PrecacheOptions extends PrecacheRouteOptions {
|
|
52
|
+
/**
|
|
53
|
+
* The cache to use for precaching.
|
|
54
|
+
*/
|
|
55
|
+
cacheName?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface SerwistOptions {
|
|
59
|
+
/**
|
|
60
|
+
* A list of URLs that should be cached.
|
|
61
|
+
*/
|
|
62
|
+
precacheEntries?: (PrecacheEntry | string)[];
|
|
63
|
+
/**
|
|
64
|
+
* Options to customize how Serwist precaches the URLs in the precache list.
|
|
65
|
+
*/
|
|
66
|
+
precacheOptions?: PrecacheOptions;
|
|
67
|
+
/**
|
|
68
|
+
* Whether outdated caches should be removed.
|
|
69
|
+
*
|
|
70
|
+
* @default false
|
|
71
|
+
*/
|
|
72
|
+
cleanupOutdatedCaches?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* An URL that should point to a HTML file with which navigation requests for URLs that aren't
|
|
75
|
+
* precached will be fulfilled.
|
|
76
|
+
*/
|
|
77
|
+
navigateFallback?: string;
|
|
78
|
+
/**
|
|
79
|
+
* URLs that should be allowed to use the `navigateFallback` handler.
|
|
80
|
+
*/
|
|
81
|
+
navigateFallbackAllowlist?: RegExp[];
|
|
82
|
+
/**
|
|
83
|
+
* URLs that should not be allowed to use the `navigateFallback` handler. This takes precedence
|
|
84
|
+
* over `navigateFallbackAllowlist`.
|
|
85
|
+
*/
|
|
86
|
+
navigateFallbackDenylist?: RegExp[];
|
|
87
|
+
/**
|
|
88
|
+
* Plugins to use when precaching as well as responding to fetch
|
|
89
|
+
* events for precached assets.
|
|
90
|
+
*/
|
|
91
|
+
plugins?: SerwistPlugin[];
|
|
92
|
+
/**
|
|
93
|
+
* Whether to attempt to get the response from the network if there's
|
|
94
|
+
* a precache miss.
|
|
95
|
+
*/
|
|
96
|
+
fallbackToNetwork?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* The number of precache requests that should be made concurrently.
|
|
99
|
+
*
|
|
100
|
+
* @default 1
|
|
101
|
+
*/
|
|
102
|
+
concurrentPrecaching?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Forces the waiting service worker to become the active one.
|
|
105
|
+
*
|
|
106
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting
|
|
107
|
+
*/
|
|
108
|
+
skipWaiting?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Imports external scripts. They are executed in the order they
|
|
111
|
+
* are passed.
|
|
112
|
+
*
|
|
113
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts
|
|
114
|
+
*/
|
|
115
|
+
importScripts?: string[];
|
|
116
|
+
/**
|
|
117
|
+
* Enables navigation preloading if it is supported.
|
|
118
|
+
*
|
|
119
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/navigationPreload
|
|
120
|
+
*/
|
|
121
|
+
navigationPreload?: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Modifies the prefix of the default cache names used by Serwist packages.
|
|
124
|
+
*/
|
|
125
|
+
cacheId?: string | undefined;
|
|
126
|
+
/**
|
|
127
|
+
* Claims any currently available clients once the service worker
|
|
128
|
+
* becomes active. This is normally used in conjunction with `skipWaiting()`.
|
|
129
|
+
*
|
|
130
|
+
* @default false
|
|
131
|
+
*/
|
|
132
|
+
clientsClaim?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* A list of caching strategies.
|
|
135
|
+
*
|
|
136
|
+
* @see https://serwist.pages.dev/docs/sw/runtime-caching
|
|
137
|
+
*/
|
|
138
|
+
runtimeCaching?: RuntimeCaching[];
|
|
139
|
+
/**
|
|
140
|
+
* Your configuration for `@serwist/google-analytics`. This plugin is
|
|
141
|
+
* only initialized when this option is not `undefined` or `false`.
|
|
142
|
+
*/
|
|
143
|
+
offlineAnalyticsConfig?: Omit<GoogleAnalyticsInitializeOptions, "serwist"> | boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Disables Serwist's logging in development mode.
|
|
146
|
+
*
|
|
147
|
+
* @default false
|
|
148
|
+
*/
|
|
149
|
+
disableDevLogs?: boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Precaches routes so that they can be used as a fallback when
|
|
152
|
+
* a Strategy fails to generate a response.
|
|
153
|
+
*
|
|
154
|
+
* Note: This option mutates `runtimeCaching`. It also precaches the URLs
|
|
155
|
+
* defined in `entries`, so you must NOT precache any of them beforehand.
|
|
156
|
+
*
|
|
157
|
+
* @see https://serwist.pages.dev/docs/sw/abstractions/fallbacks
|
|
158
|
+
*/
|
|
159
|
+
fallbacks?: FallbacksOptions;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
type RequestArgs = string | [string, RequestInit?];
|
|
163
|
+
|
|
164
|
+
interface CacheURLsMessageData {
|
|
165
|
+
type: string;
|
|
166
|
+
payload: {
|
|
167
|
+
urlsToCache: RequestArgs[];
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* A class that helps bootstrap the service worker.
|
|
173
|
+
*/
|
|
174
|
+
export class Serwist {
|
|
175
|
+
private readonly _urlsToCacheKeys: Map<string, string> = new Map();
|
|
176
|
+
private readonly _urlsToCacheModes: Map<string, "reload" | "default" | "no-store" | "no-cache" | "force-cache" | "only-if-cached"> = new Map();
|
|
177
|
+
private readonly _cacheKeysToIntegrities: Map<string, string> = new Map();
|
|
178
|
+
private _concurrentPrecaching: number;
|
|
179
|
+
private readonly _precacheStrategy: Strategy;
|
|
180
|
+
private readonly _routes: Map<HTTPMethod, Route[]>;
|
|
181
|
+
private readonly _defaultHandlerMap: Map<HTTPMethod, RouteHandlerObject>;
|
|
182
|
+
private _catchHandler?: RouteHandlerObject;
|
|
183
|
+
|
|
184
|
+
constructor({
|
|
185
|
+
precacheEntries,
|
|
186
|
+
precacheOptions,
|
|
187
|
+
cleanupOutdatedCaches,
|
|
188
|
+
navigateFallback,
|
|
189
|
+
navigateFallbackAllowlist,
|
|
190
|
+
navigateFallbackDenylist,
|
|
191
|
+
plugins = [],
|
|
192
|
+
fallbackToNetwork = true,
|
|
193
|
+
concurrentPrecaching = 1,
|
|
194
|
+
skipWaiting = false,
|
|
195
|
+
importScripts,
|
|
196
|
+
navigationPreload = false,
|
|
197
|
+
cacheId,
|
|
198
|
+
clientsClaim = false,
|
|
199
|
+
runtimeCaching,
|
|
200
|
+
offlineAnalyticsConfig,
|
|
201
|
+
disableDevLogs = false,
|
|
202
|
+
fallbacks,
|
|
203
|
+
}: SerwistOptions = {}) {
|
|
204
|
+
this._concurrentPrecaching = concurrentPrecaching;
|
|
205
|
+
this._precacheStrategy = new PrecacheStrategy({
|
|
206
|
+
cacheName: privateCacheNames.getPrecacheName(precacheOptions?.cacheName),
|
|
207
|
+
plugins: [...plugins, new PrecacheCacheKeyPlugin({ precacheController: this })],
|
|
208
|
+
fallbackToNetwork,
|
|
209
|
+
});
|
|
210
|
+
this._routes = new Map();
|
|
211
|
+
this._defaultHandlerMap = new Map();
|
|
212
|
+
|
|
213
|
+
this.handleInstall = this.handleInstall.bind(this);
|
|
214
|
+
this.handleActivate = this.handleActivate.bind(this);
|
|
215
|
+
this.handleFetch = this.handleFetch.bind(this);
|
|
216
|
+
this.handleCache = this.handleCache.bind(this);
|
|
217
|
+
|
|
218
|
+
if (!!importScripts && importScripts.length > 0) self.importScripts(...importScripts);
|
|
219
|
+
|
|
220
|
+
if (navigationPreload) enableNavigationPreload();
|
|
221
|
+
|
|
222
|
+
if (cacheId !== undefined) {
|
|
223
|
+
setCacheNameDetails({
|
|
224
|
+
prefix: cacheId,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (skipWaiting) {
|
|
229
|
+
self.skipWaiting();
|
|
230
|
+
} else {
|
|
231
|
+
self.addEventListener("message", (event) => {
|
|
232
|
+
if (event.data && event.data.type === "SKIP_WAITING") {
|
|
233
|
+
self.skipWaiting();
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (clientsClaim) clientsClaimImpl();
|
|
239
|
+
|
|
240
|
+
this.registerRoute(new PrecacheRoute(this, precacheOptions));
|
|
241
|
+
|
|
242
|
+
if (!!precacheEntries && precacheEntries.length > 0) {
|
|
243
|
+
this.addToPrecacheList(precacheEntries);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (cleanupOutdatedCaches) {
|
|
247
|
+
cleanupOutdatedCachesImpl(precacheOptions?.cacheName);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (navigateFallback) {
|
|
251
|
+
this.registerRoute(
|
|
252
|
+
new NavigationRoute(this.createHandlerBoundToUrl(navigateFallback), {
|
|
253
|
+
allowlist: navigateFallbackAllowlist,
|
|
254
|
+
denylist: navigateFallbackDenylist,
|
|
255
|
+
}),
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (offlineAnalyticsConfig !== undefined) {
|
|
260
|
+
if (typeof offlineAnalyticsConfig === "boolean") {
|
|
261
|
+
offlineAnalyticsConfig && initialize({ serwist: this });
|
|
262
|
+
} else {
|
|
263
|
+
initialize({
|
|
264
|
+
...offlineAnalyticsConfig,
|
|
265
|
+
serwist: this,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (runtimeCaching !== undefined) {
|
|
270
|
+
if (fallbacks !== undefined) {
|
|
271
|
+
const fallbackPlugin = new PrecacheFallbackPlugin({
|
|
272
|
+
fallbackUrls: fallbacks.entries,
|
|
273
|
+
serwist: this,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
runtimeCaching.forEach((cacheEntry) => {
|
|
277
|
+
if (
|
|
278
|
+
cacheEntry.handler instanceof Strategy &&
|
|
279
|
+
// PrecacheFallbackPlugin also has `handlerDidError`, so we don't need to check for its instances.
|
|
280
|
+
!cacheEntry.handler.plugins.some((plugin) => "handlerDidError" in plugin)
|
|
281
|
+
) {
|
|
282
|
+
cacheEntry.handler.plugins.push(fallbackPlugin);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
for (const entry of runtimeCaching) {
|
|
287
|
+
this.registerCapture(entry.matcher, entry.handler, entry.method);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (disableDevLogs) disableDevLogsImpl();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* The strategy created by this controller and
|
|
296
|
+
* used to cache assets and respond to fetch events.
|
|
297
|
+
*/
|
|
298
|
+
get precacheStrategy(): Strategy {
|
|
299
|
+
return this._precacheStrategy;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* A `Map` of HTTP method name (`'GET'`, etc.) to an array of all the corresponding `Route`
|
|
303
|
+
* instances that are registered.
|
|
304
|
+
*/
|
|
305
|
+
get routes(): Map<HTTPMethod, Route[]> {
|
|
306
|
+
return this._routes;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* This function adds Serwist's event listeners for you. Before calling it, add your own listeners
|
|
311
|
+
* should you need to.
|
|
312
|
+
*/
|
|
313
|
+
addEventListeners() {
|
|
314
|
+
self.addEventListener("install", this.handleInstall);
|
|
315
|
+
self.addEventListener("activate", this.handleActivate);
|
|
316
|
+
self.addEventListener("fetch", this.handleFetch);
|
|
317
|
+
self.addEventListener("message", this.handleCache);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* This method will add items to the precache list, removing duplicates
|
|
322
|
+
* and ensuring the information is valid.
|
|
323
|
+
*
|
|
324
|
+
* @param entries Array of entries to precache.
|
|
325
|
+
*/
|
|
326
|
+
addToPrecacheList(entries: (PrecacheEntry | string)[]): void {
|
|
327
|
+
if (process.env.NODE_ENV !== "production") {
|
|
328
|
+
assert!.isArray(entries, {
|
|
329
|
+
moduleName: "serwist",
|
|
330
|
+
className: "Serwist",
|
|
331
|
+
funcName: "addToCacheList",
|
|
332
|
+
paramName: "entries",
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const urlsToWarnAbout: string[] = [];
|
|
337
|
+
for (const entry of entries) {
|
|
338
|
+
// See https://github.com/GoogleChrome/workbox/issues/2259
|
|
339
|
+
if (typeof entry === "string") {
|
|
340
|
+
urlsToWarnAbout.push(entry);
|
|
341
|
+
} else if (entry && !entry.integrity && entry.revision === undefined) {
|
|
342
|
+
urlsToWarnAbout.push(entry.url);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const { cacheKey, url } = createCacheKey(entry);
|
|
346
|
+
const cacheMode = typeof entry !== "string" && entry.revision ? "reload" : "default";
|
|
347
|
+
|
|
348
|
+
if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) {
|
|
349
|
+
throw new SerwistError("add-to-cache-list-conflicting-entries", {
|
|
350
|
+
firstEntry: this._urlsToCacheKeys.get(url),
|
|
351
|
+
secondEntry: cacheKey,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (typeof entry !== "string" && entry.integrity) {
|
|
356
|
+
if (this._cacheKeysToIntegrities.has(cacheKey) && this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity) {
|
|
357
|
+
throw new SerwistError("add-to-cache-list-conflicting-integrities", {
|
|
358
|
+
url,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
this._cacheKeysToIntegrities.set(cacheKey, entry.integrity);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
this._urlsToCacheKeys.set(url, cacheKey);
|
|
365
|
+
this._urlsToCacheModes.set(url, cacheMode);
|
|
366
|
+
|
|
367
|
+
if (urlsToWarnAbout.length > 0) {
|
|
368
|
+
const warningMessage = `Serwist is precaching URLs without revision info: ${urlsToWarnAbout.join(
|
|
369
|
+
", ",
|
|
370
|
+
)}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;
|
|
371
|
+
if (process.env.NODE_ENV === "production") {
|
|
372
|
+
// Use console directly to display this warning without bloating
|
|
373
|
+
// bundle sizes by pulling in all of the logger codebase in prod.
|
|
374
|
+
console.warn(warningMessage);
|
|
375
|
+
} else {
|
|
376
|
+
logger.warn(warningMessage);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Precaches new and updated assets. Call this method from the service worker's
|
|
384
|
+
* `install` event.
|
|
385
|
+
*
|
|
386
|
+
* Note: this method calls `event.waitUntil()` for you, so you do not need
|
|
387
|
+
* to call it yourself in your event handlers.
|
|
388
|
+
*
|
|
389
|
+
* @param event
|
|
390
|
+
* @returns
|
|
391
|
+
*/
|
|
392
|
+
handleInstall(event: ExtendableEvent): Promise<InstallResult> {
|
|
393
|
+
return waitUntil<InstallResult>(event, async () => {
|
|
394
|
+
const installReportPlugin = new PrecacheInstallReportPlugin();
|
|
395
|
+
this.precacheStrategy.plugins.push(installReportPlugin);
|
|
396
|
+
|
|
397
|
+
await parallel(this._concurrentPrecaching, Array.from(this._urlsToCacheKeys.entries()), async ([url, cacheKey]): Promise<void> => {
|
|
398
|
+
const integrity = this._cacheKeysToIntegrities.get(cacheKey);
|
|
399
|
+
const cacheMode = this._urlsToCacheModes.get(url);
|
|
400
|
+
|
|
401
|
+
const request = new Request(url, {
|
|
402
|
+
integrity,
|
|
403
|
+
cache: cacheMode,
|
|
404
|
+
credentials: "same-origin",
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
await Promise.all(
|
|
408
|
+
this.precacheStrategy.handleAll({
|
|
409
|
+
event,
|
|
410
|
+
request,
|
|
411
|
+
url: new URL(request.url),
|
|
412
|
+
params: { cacheKey },
|
|
413
|
+
}),
|
|
414
|
+
);
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
const { updatedURLs, notUpdatedURLs } = installReportPlugin;
|
|
418
|
+
|
|
419
|
+
if (process.env.NODE_ENV !== "production") {
|
|
420
|
+
printInstallDetails(updatedURLs, notUpdatedURLs);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return { updatedURLs, notUpdatedURLs };
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Deletes assets that are no longer present in the current precache manifest.
|
|
429
|
+
* Call this method from the service worker's `activate` event.
|
|
430
|
+
*
|
|
431
|
+
* Note: this method calls `event.waitUntil()` for you, so you do not need
|
|
432
|
+
* to call it yourself in your event handlers.
|
|
433
|
+
*
|
|
434
|
+
* @param event
|
|
435
|
+
* @returns
|
|
436
|
+
*/
|
|
437
|
+
handleActivate(event: ExtendableEvent): Promise<CleanupResult> {
|
|
438
|
+
return waitUntil<CleanupResult>(event, async () => {
|
|
439
|
+
const cache = await self.caches.open(this.precacheStrategy.cacheName);
|
|
440
|
+
const currentlyCachedRequests = await cache.keys();
|
|
441
|
+
const expectedCacheKeys = new Set(this._urlsToCacheKeys.values());
|
|
442
|
+
|
|
443
|
+
const deletedCacheRequests: string[] = [];
|
|
444
|
+
|
|
445
|
+
for (const request of currentlyCachedRequests) {
|
|
446
|
+
if (!expectedCacheKeys.has(request.url)) {
|
|
447
|
+
await cache.delete(request);
|
|
448
|
+
deletedCacheRequests.push(request.url);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (process.env.NODE_ENV !== "production") {
|
|
453
|
+
printCleanupDetails(deletedCacheRequests);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
return { deletedCacheRequests };
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Gets a `Response` from an appropriate `Route`'s handler. Call this method
|
|
462
|
+
* from the service worker's `fetch` event.
|
|
463
|
+
* @param event
|
|
464
|
+
*/
|
|
465
|
+
handleFetch(event: FetchEvent) {
|
|
466
|
+
const { request } = event;
|
|
467
|
+
const responsePromise = this.handleRequest({ request, event });
|
|
468
|
+
if (responsePromise) {
|
|
469
|
+
event.respondWith(responsePromise);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Caches new URLs on demand. Call this method from the service worker's
|
|
475
|
+
* `message` event. To trigger the handler, send a message of type `"CACHE_URLS"`
|
|
476
|
+
* alongside a list of URLs that should be cached as `urlsToCache`.
|
|
477
|
+
* @param event
|
|
478
|
+
*/
|
|
479
|
+
handleCache(event: ExtendableMessageEvent) {
|
|
480
|
+
if (event.data && event.data.type === "CACHE_URLS") {
|
|
481
|
+
const { payload }: CacheURLsMessageData = event.data;
|
|
482
|
+
|
|
483
|
+
if (process.env.NODE_ENV !== "production") {
|
|
484
|
+
logger.debug("Caching URLs from the window", payload.urlsToCache);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const requestPromises = Promise.all(
|
|
488
|
+
payload.urlsToCache.map((entry: string | [string, RequestInit?]) => {
|
|
489
|
+
let request: Request;
|
|
490
|
+
if (typeof entry === "string") {
|
|
491
|
+
request = new Request(entry);
|
|
492
|
+
} else {
|
|
493
|
+
request = new Request(...entry);
|
|
494
|
+
}
|
|
495
|
+
return this.handleRequest({ request, event });
|
|
496
|
+
}),
|
|
497
|
+
);
|
|
498
|
+
|
|
499
|
+
event.waitUntil(requestPromises);
|
|
500
|
+
|
|
501
|
+
// If a MessageChannel was used, reply to the message on success.
|
|
502
|
+
if (event.ports?.[0]) {
|
|
503
|
+
void requestPromises.then(() => event.ports[0].postMessage(true));
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Define a default `handler` that's called when no routes explicitly
|
|
510
|
+
* match the incoming request.
|
|
511
|
+
*
|
|
512
|
+
* Each HTTP method (`'GET'`, `'POST'`, etc.) gets its own default handler.
|
|
513
|
+
*
|
|
514
|
+
* Without a default handler, unmatched requests will go against the
|
|
515
|
+
* network as if there were no service worker present.
|
|
516
|
+
*
|
|
517
|
+
* @param handler A callback function that returns a `Promise` resulting in a `Response`.
|
|
518
|
+
* @param method The HTTP method to associate with this default handler. Each method
|
|
519
|
+
* has its own default. Defaults to `'GET'`.
|
|
520
|
+
*/
|
|
521
|
+
setDefaultHandler(handler: RouteHandler, method: HTTPMethod = defaultMethod): void {
|
|
522
|
+
this._defaultHandlerMap.set(method, normalizeHandler(handler));
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* If a `Route` throws an error while handling a request, this `handler`
|
|
527
|
+
* will be called and given a chance to provide a response.
|
|
528
|
+
*
|
|
529
|
+
* @param handler A callback function that returns a Promise resulting
|
|
530
|
+
* in a Response.
|
|
531
|
+
*/
|
|
532
|
+
setCatchHandler(handler: RouteHandler): void {
|
|
533
|
+
this._catchHandler = normalizeHandler(handler);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Registers a `RegExp`, string, or function with a caching
|
|
538
|
+
* strategy to the `Router`.
|
|
539
|
+
*
|
|
540
|
+
* @param capture If the capture param is a `Route`, all other arguments will be ignored.
|
|
541
|
+
* @param handler A callback function that returns a `Promise` resulting in a `Response`.
|
|
542
|
+
* This parameter is required if `capture` is not a `Route` object.
|
|
543
|
+
* @param method The HTTP method to match the Route against. Defaults to `'GET'`.
|
|
544
|
+
* @returns The generated `Route`.
|
|
545
|
+
*/
|
|
546
|
+
registerCapture(capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod): Route {
|
|
547
|
+
const route = parseRoute(capture, handler, method);
|
|
548
|
+
this.registerRoute(route);
|
|
549
|
+
return route;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Registers a `Route` with the router.
|
|
554
|
+
*
|
|
555
|
+
* @param route The `Route` to register.
|
|
556
|
+
*/
|
|
557
|
+
registerRoute(route: Route): void {
|
|
558
|
+
if (process.env.NODE_ENV !== "production") {
|
|
559
|
+
assert!.isType(route, "object", {
|
|
560
|
+
moduleName: "serwist",
|
|
561
|
+
className: "Serwist",
|
|
562
|
+
funcName: "registerRoute",
|
|
563
|
+
paramName: "route",
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
assert!.hasMethod(route, "match", {
|
|
567
|
+
moduleName: "serwist",
|
|
568
|
+
className: "Serwist",
|
|
569
|
+
funcName: "registerRoute",
|
|
570
|
+
paramName: "route",
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
assert!.isType(route.handler, "object", {
|
|
574
|
+
moduleName: "serwist",
|
|
575
|
+
className: "Serwist",
|
|
576
|
+
funcName: "registerRoute",
|
|
577
|
+
paramName: "route",
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
assert!.hasMethod(route.handler, "handle", {
|
|
581
|
+
moduleName: "serwist",
|
|
582
|
+
className: "Serwist",
|
|
583
|
+
funcName: "registerRoute",
|
|
584
|
+
paramName: "route.handler",
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
assert!.isType(route.method, "string", {
|
|
588
|
+
moduleName: "serwist",
|
|
589
|
+
className: "Serwist",
|
|
590
|
+
funcName: "registerRoute",
|
|
591
|
+
paramName: "route.method",
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (!this._routes.has(route.method)) {
|
|
596
|
+
this._routes.set(route.method, []);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// Give precedence to all of the earlier routes by adding this additional
|
|
600
|
+
// route to the end of the array.
|
|
601
|
+
this._routes.get(route.method)!.push(route);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Unregisters a `Route` with the `Router`.
|
|
606
|
+
*
|
|
607
|
+
* @param route The `Route` to unregister.
|
|
608
|
+
*/
|
|
609
|
+
unregisterRoute(route: Route): void {
|
|
610
|
+
if (!this._routes.has(route.method)) {
|
|
611
|
+
throw new SerwistError("unregister-route-but-not-found-with-method", {
|
|
612
|
+
method: route.method,
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
const routeIndex = this._routes.get(route.method)!.indexOf(route);
|
|
617
|
+
if (routeIndex > -1) {
|
|
618
|
+
this._routes.get(route.method)!.splice(routeIndex, 1);
|
|
619
|
+
} else {
|
|
620
|
+
throw new SerwistError("unregister-route-route-not-registered");
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Returns a mapping of a precached URL to the corresponding cache key, taking
|
|
626
|
+
* into account the revision information for the URL.
|
|
627
|
+
*
|
|
628
|
+
* @returns A URL to cache key mapping.
|
|
629
|
+
*/
|
|
630
|
+
getUrlsToPrecacheKeys(): Map<string, string> {
|
|
631
|
+
return this._urlsToCacheKeys;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Returns a list of all the URLs that have been precached by the current
|
|
636
|
+
* service worker.
|
|
637
|
+
*
|
|
638
|
+
* @returns The precached URLs.
|
|
639
|
+
*/
|
|
640
|
+
getPrecachedUrls(): string[] {
|
|
641
|
+
return [...this._urlsToCacheKeys.keys()];
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Returns the cache key used for storing a given URL. If that URL is
|
|
646
|
+
* unversioned, like `/index.html', then the cache key will be the original
|
|
647
|
+
* URL with a search parameter appended to it.
|
|
648
|
+
*
|
|
649
|
+
* @param url A URL whose cache key you want to look up.
|
|
650
|
+
* @returns The versioned URL that corresponds to a cache key
|
|
651
|
+
* for the original URL, or undefined if that URL isn't precached.
|
|
652
|
+
*/
|
|
653
|
+
getPrecacheKeyForUrl(url: string): string | undefined {
|
|
654
|
+
const urlObject = new URL(url, location.href);
|
|
655
|
+
return this._urlsToCacheKeys.get(urlObject.href);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* @param url A cache key whose SRI you want to look up.
|
|
660
|
+
* @returns The subresource integrity associated with the cache key,
|
|
661
|
+
* or undefined if it's not set.
|
|
662
|
+
*/
|
|
663
|
+
getIntegrityForPrecacheKey(cacheKey: string): string | undefined {
|
|
664
|
+
return this._cacheKeysToIntegrities.get(cacheKey);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* This acts as a drop-in replacement for
|
|
669
|
+
* [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
|
|
670
|
+
* with the following differences:
|
|
671
|
+
*
|
|
672
|
+
* - It knows what the name of the precache is, and only checks in that cache.
|
|
673
|
+
* - It allows you to pass in an "original" URL without versioning parameters,
|
|
674
|
+
* and it will automatically look up the correct cache key for the currently
|
|
675
|
+
* active revision of that URL.
|
|
676
|
+
*
|
|
677
|
+
* E.g., `matchPrecache('index.html')` will find the correct precached
|
|
678
|
+
* response for the currently active service worker, even if the actual cache
|
|
679
|
+
* key is `'/index.html?__WB_REVISION__=1234abcd'`.
|
|
680
|
+
*
|
|
681
|
+
* @param request The key (without revisioning parameters)
|
|
682
|
+
* to look up in the precache.
|
|
683
|
+
* @returns
|
|
684
|
+
*/
|
|
685
|
+
async matchPrecache(request: string | Request): Promise<Response | undefined> {
|
|
686
|
+
const url = request instanceof Request ? request.url : request;
|
|
687
|
+
const cacheKey = this.getPrecacheKeyForUrl(url);
|
|
688
|
+
if (cacheKey) {
|
|
689
|
+
const cache = await self.caches.open(this.precacheStrategy.cacheName);
|
|
690
|
+
return cache.match(cacheKey);
|
|
691
|
+
}
|
|
692
|
+
return undefined;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Returns a function that looks up `url` in the precache (taking into
|
|
697
|
+
* account revision information), and returns the corresponding `Response`.
|
|
698
|
+
*
|
|
699
|
+
* @param url The precached URL which will be used to lookup the response.
|
|
700
|
+
* @return
|
|
701
|
+
*/
|
|
702
|
+
createHandlerBoundToUrl(url: string): RouteHandlerCallback {
|
|
703
|
+
const cacheKey = this.getPrecacheKeyForUrl(url);
|
|
704
|
+
if (!cacheKey) {
|
|
705
|
+
throw new SerwistError("non-precached-url", { url });
|
|
706
|
+
}
|
|
707
|
+
return (options) => {
|
|
708
|
+
options.request = new Request(url);
|
|
709
|
+
options.params = { cacheKey, ...options.params };
|
|
710
|
+
|
|
711
|
+
return this.precacheStrategy.handle(options);
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Apply the routing rules to a `FetchEvent` object to get a `Response` from an
|
|
717
|
+
* appropriate `Route`'s handler.
|
|
718
|
+
*
|
|
719
|
+
* @param options
|
|
720
|
+
* @returns A promise is returned if a registered route can handle the request.
|
|
721
|
+
* If there is no matching route and there's no `defaultHandler`, `undefined`
|
|
722
|
+
* is returned.
|
|
723
|
+
*/
|
|
724
|
+
handleRequest({
|
|
725
|
+
request,
|
|
726
|
+
event,
|
|
727
|
+
}: {
|
|
728
|
+
/**
|
|
729
|
+
* The request to handle.
|
|
730
|
+
*/
|
|
731
|
+
request: Request;
|
|
732
|
+
/**
|
|
733
|
+
* The event that triggered the request.
|
|
734
|
+
*/
|
|
735
|
+
event: ExtendableEvent;
|
|
736
|
+
}): Promise<Response> | undefined {
|
|
737
|
+
if (process.env.NODE_ENV !== "production") {
|
|
738
|
+
assert!.isInstance(request, Request, {
|
|
739
|
+
moduleName: "serwist",
|
|
740
|
+
className: "Serwist",
|
|
741
|
+
funcName: "handleRequest",
|
|
742
|
+
paramName: "options.request",
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
const url = new URL(request.url, location.href);
|
|
747
|
+
if (!url.protocol.startsWith("http")) {
|
|
748
|
+
if (process.env.NODE_ENV !== "production") {
|
|
749
|
+
logger.debug("Router only supports URLs that start with 'http'.");
|
|
750
|
+
}
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
const sameOrigin = url.origin === location.origin;
|
|
755
|
+
const { params, route } = this.findMatchingRoute({
|
|
756
|
+
event,
|
|
757
|
+
request,
|
|
758
|
+
sameOrigin,
|
|
759
|
+
url,
|
|
760
|
+
});
|
|
761
|
+
let handler = route?.handler;
|
|
762
|
+
|
|
763
|
+
const debugMessages = [];
|
|
764
|
+
if (process.env.NODE_ENV !== "production") {
|
|
765
|
+
if (handler) {
|
|
766
|
+
debugMessages.push(["Found a route to handle this request:", route]);
|
|
767
|
+
|
|
768
|
+
if (params) {
|
|
769
|
+
debugMessages.push([`Passing the following params to the route's handler:`, params]);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// If we don't have a handler because there was no matching route, then
|
|
775
|
+
// fall back to defaultHandler if that's defined.
|
|
776
|
+
const method = request.method as HTTPMethod;
|
|
777
|
+
if (!handler && this._defaultHandlerMap.has(method)) {
|
|
778
|
+
if (process.env.NODE_ENV !== "production") {
|
|
779
|
+
debugMessages.push(`Failed to find a matching route. Falling back to the default handler for ${method}.`);
|
|
780
|
+
}
|
|
781
|
+
handler = this._defaultHandlerMap.get(method);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
if (!handler) {
|
|
785
|
+
if (process.env.NODE_ENV !== "production") {
|
|
786
|
+
// No handler so Serwist will do nothing. If logs is set of debug
|
|
787
|
+
// i.e. verbose, we should print out this information.
|
|
788
|
+
logger.debug(`No route found for: ${getFriendlyURL(url)}`);
|
|
789
|
+
}
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (process.env.NODE_ENV !== "production") {
|
|
794
|
+
// We have a handler, meaning Serwist is going to handle the route.
|
|
795
|
+
// print the routing details to the console.
|
|
796
|
+
logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`);
|
|
797
|
+
|
|
798
|
+
for (const msg of debugMessages) {
|
|
799
|
+
if (Array.isArray(msg)) {
|
|
800
|
+
logger.log(...msg);
|
|
801
|
+
} else {
|
|
802
|
+
logger.log(msg);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
logger.groupEnd();
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Wrap in try and catch in case the handle method throws a synchronous
|
|
810
|
+
// error. It should still callback to the catch handler.
|
|
811
|
+
let responsePromise: Promise<Response>;
|
|
812
|
+
try {
|
|
813
|
+
responsePromise = handler.handle({ url, request, event, params });
|
|
814
|
+
} catch (err) {
|
|
815
|
+
responsePromise = Promise.reject(err);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// Get route's catch handler, if it exists
|
|
819
|
+
const catchHandler = route?.catchHandler;
|
|
820
|
+
|
|
821
|
+
if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) {
|
|
822
|
+
responsePromise = responsePromise.catch(async (err) => {
|
|
823
|
+
// If there's a route catch handler, process that first
|
|
824
|
+
if (catchHandler) {
|
|
825
|
+
if (process.env.NODE_ENV !== "production") {
|
|
826
|
+
// Still include URL here as it will be async from the console group
|
|
827
|
+
// and may not make sense without the URL
|
|
828
|
+
logger.groupCollapsed(`Error thrown when responding to: ${getFriendlyURL(url)}. Falling back to route's Catch Handler.`);
|
|
829
|
+
logger.error("Error thrown by:", route);
|
|
830
|
+
logger.error(err);
|
|
831
|
+
logger.groupEnd();
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
try {
|
|
835
|
+
return await catchHandler.handle({ url, request, event, params });
|
|
836
|
+
} catch (catchErr) {
|
|
837
|
+
if (catchErr instanceof Error) {
|
|
838
|
+
err = catchErr;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
if (this._catchHandler) {
|
|
844
|
+
if (process.env.NODE_ENV !== "production") {
|
|
845
|
+
// Still include URL here as it will be async from the console group
|
|
846
|
+
// and may not make sense without the URL
|
|
847
|
+
logger.groupCollapsed(`Error thrown when responding to: ${getFriendlyURL(url)}. Falling back to global Catch Handler.`);
|
|
848
|
+
logger.error("Error thrown by:", route);
|
|
849
|
+
logger.error(err);
|
|
850
|
+
logger.groupEnd();
|
|
851
|
+
}
|
|
852
|
+
return this._catchHandler.handle({ url, request, event });
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
throw err;
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
return responsePromise;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Checks a request and URL (and optionally an event) against the list of
|
|
864
|
+
* registered routes, and if there's a match, returns the corresponding
|
|
865
|
+
* route along with any params generated by the match.
|
|
866
|
+
*
|
|
867
|
+
* @param options
|
|
868
|
+
* @returns An object with `route` and `params` properties. They are populated
|
|
869
|
+
* if a matching route was found or `undefined` otherwise.
|
|
870
|
+
*/
|
|
871
|
+
findMatchingRoute({ url, sameOrigin, request, event }: RouteMatchCallbackOptions): {
|
|
872
|
+
route?: Route;
|
|
873
|
+
params?: RouteHandlerCallbackOptions["params"];
|
|
874
|
+
} {
|
|
875
|
+
const routes = this._routes.get(request.method as HTTPMethod) || [];
|
|
876
|
+
for (const route of routes) {
|
|
877
|
+
let params: Promise<any> | undefined;
|
|
878
|
+
// route.match returns type any, not possible to change right now.
|
|
879
|
+
const matchResult = route.match({ url, sameOrigin, request, event });
|
|
880
|
+
if (matchResult) {
|
|
881
|
+
if (process.env.NODE_ENV !== "production") {
|
|
882
|
+
// Warn developers that using an async matchCallback is almost always
|
|
883
|
+
// not the right thing to do.
|
|
884
|
+
if (matchResult instanceof Promise) {
|
|
885
|
+
logger.warn(
|
|
886
|
+
`While routing ${getFriendlyURL(
|
|
887
|
+
url,
|
|
888
|
+
)}, an async matchCallback function was used. Please convert the following route to use a synchronous matchCallback function:`,
|
|
889
|
+
route,
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// See https://github.com/GoogleChrome/workbox/issues/2079
|
|
895
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
896
|
+
params = matchResult;
|
|
897
|
+
if (Array.isArray(params) && params.length === 0) {
|
|
898
|
+
// Instead of passing an empty array in as params, use undefined.
|
|
899
|
+
params = undefined;
|
|
900
|
+
} else if (
|
|
901
|
+
matchResult.constructor === Object && // eslint-disable-line
|
|
902
|
+
Object.keys(matchResult).length === 0
|
|
903
|
+
) {
|
|
904
|
+
// Instead of passing an empty object in as params, use undefined.
|
|
905
|
+
params = undefined;
|
|
906
|
+
} else if (typeof matchResult === "boolean") {
|
|
907
|
+
// For the boolean value true (rather than just something truth-y),
|
|
908
|
+
// don't set params.
|
|
909
|
+
// See https://github.com/GoogleChrome/workbox/pull/2134#issuecomment-513924353
|
|
910
|
+
params = undefined;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// Return early if have a match.
|
|
914
|
+
return { route, params };
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
// If no match was found above, return and empty object.
|
|
918
|
+
return {};
|
|
919
|
+
}
|
|
920
|
+
}
|