{
  "version": 3,
  "sources": ["<define:self.__SW_MANIFEST>", "node_modules/serwist/src/utils/cacheNames.ts", "node_modules/serwist/src/utils/canConstructResponseFromBodyStream.ts", "node_modules/serwist/src/models/messages/messages.ts", "node_modules/serwist/src/models/messages/messageGenerator.ts", "node_modules/serwist/src/utils/SerwistError.ts", "node_modules/serwist/src/utils/assert.ts", "node_modules/serwist/src/utils/getFriendlyURL.ts", "node_modules/serwist/src/utils/logger.ts", "node_modules/serwist/src/utils/timeout.ts", "node_modules/serwist/src/models/quotaErrorCallbacks.ts", "node_modules/serwist/src/utils/cacheMatchIgnoreParams.ts", "node_modules/serwist/src/utils/Deferred.ts", "node_modules/serwist/src/utils/executeQuotaErrorCallbacks.ts", "node_modules/serwist/src/utils/deleteOutdatedCaches.ts", "node_modules/serwist/src/utils/cleanupOutdatedCaches.ts", "node_modules/serwist/src/utils/clientsClaim.ts", "node_modules/serwist/src/utils/waitUntil.ts", "node_modules/serwist/node_modules/idb/build/index.js", "node_modules/serwist/src/copyResponse.ts", "node_modules/serwist/src/disableDevLogs.ts", "node_modules/serwist/src/lib/backgroundSync/BackgroundSyncQueueDb.ts", "node_modules/serwist/src/lib/backgroundSync/BackgroundSyncQueueStore.ts", "node_modules/serwist/src/lib/backgroundSync/StorableRequest.ts", "node_modules/serwist/src/lib/backgroundSync/BackgroundSyncQueue.ts", "node_modules/serwist/src/lib/backgroundSync/BackgroundSyncPlugin.ts", "node_modules/serwist/src/lib/strategies/plugins/cacheOkAndOpaquePlugin.ts", "node_modules/serwist/src/lib/strategies/StrategyHandler.ts", "node_modules/serwist/src/lib/strategies/Strategy.ts", "node_modules/serwist/src/lib/strategies/utils/messages.ts", "node_modules/serwist/src/lib/strategies/NetworkFirst.ts", "node_modules/serwist/src/lib/strategies/NetworkOnly.ts", "node_modules/serwist/src/constants.ts", "node_modules/serwist/src/utils/normalizeHandler.ts", "node_modules/serwist/src/Route.ts", "node_modules/serwist/src/lib/strategies/PrecacheStrategy.ts", "node_modules/serwist/src/NavigationRoute.ts", "node_modules/serwist/src/navigationPreload.ts", "node_modules/serwist/src/utils/removeIgnoredSearchParams.ts", "node_modules/serwist/src/utils/generateURLVariations.ts", "node_modules/serwist/src/RegExpRoute.ts", "node_modules/serwist/src/setCacheNameDetails.ts", "node_modules/serwist/src/utils/createCacheKey.ts", "node_modules/serwist/src/utils/PrecacheInstallReportPlugin.ts", "node_modules/serwist/src/utils/parseRoute.ts", "node_modules/serwist/src/utils/printCleanupDetails.ts", "node_modules/serwist/src/utils/printInstallDetails.ts", "node_modules/@serwist/utils/src/non-nullable.ts", "node_modules/@serwist/utils/src/parallel.ts", "node_modules/@serwist/utils/src/to-unix.ts", "node_modules/@serwist/utils/src/compare.ts", "node_modules/@serwist/utils/src/constants.ts", "node_modules/@serwist/utils/src/semver.ts", "node_modules/@serwist/utils/src/browserslist.ts", "node_modules/serwist/src/cacheNames.ts", "node_modules/serwist/src/lib/broadcastUpdate/constants.ts", "node_modules/serwist/src/lib/broadcastUpdate/responsesAreSame.ts", "node_modules/serwist/src/lib/broadcastUpdate/BroadcastCacheUpdate.ts", "node_modules/serwist/src/lib/broadcastUpdate/BroadcastUpdatePlugin.ts", "node_modules/serwist/src/lib/cacheableResponse/CacheableResponse.ts", "node_modules/serwist/src/lib/cacheableResponse/CacheableResponsePlugin.ts", "node_modules/serwist/src/lib/expiration/models/CacheTimestampsModel.ts", "node_modules/serwist/src/lib/expiration/CacheExpiration.ts", "node_modules/serwist/src/registerQuotaErrorCallback.ts", "node_modules/serwist/src/lib/expiration/ExpirationPlugin.ts", "node_modules/serwist/src/lib/googleAnalytics/constants.ts", "node_modules/serwist/src/lib/googleAnalytics/initializeGoogleAnalytics.ts", "node_modules/serwist/src/lib/precaching/PrecacheFallbackPlugin.ts", "node_modules/serwist/src/lib/rangeRequests/utils/calculateEffectiveBoundaries.ts", "node_modules/serwist/src/lib/rangeRequests/utils/parseRangeHeader.ts", "node_modules/serwist/src/lib/rangeRequests/createPartialResponse.ts", "node_modules/serwist/src/lib/rangeRequests/RangeRequestsPlugin.ts", "node_modules/serwist/src/lib/strategies/CacheFirst.ts", "node_modules/serwist/src/lib/strategies/CacheOnly.ts", "node_modules/serwist/src/lib/strategies/StaleWhileRevalidate.ts", "node_modules/serwist/src/PrecacheRoute.ts", "node_modules/serwist/src/utils/PrecacheCacheKeyPlugin.ts", "node_modules/serwist/src/utils/parsePrecacheOptions.ts", "node_modules/serwist/src/Serwist.ts", "src/app/sw.ts"],
  "sourcesContent": ["[\n  {\n    \"url\": \"/_next/static/chunks/turbopack-e6405a0457a6c6db.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-d7d6a9052f4b0863.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-d0c93faafbb627aa.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-bde4fc944909bc98.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-bd8f510e9968e7d7.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-9ad44f7c074eb730.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-996928524e7e41c9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-98239cba683fcdbb.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-8acec2fb84c17a06.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-7ef8ca126acd9327.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-7e72fe5a5382a512.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-78839ddb29798959.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-67286d8bc919cc18.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-56819e6f4ed96f20.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-55aca3b6a1ec02ce.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-3c11a5992422fafa.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-2fb0cf6ef9d1a5f5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-28eb12d8caf4d8d7.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-28011496ede0eea9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-242a5cd6dd4b0f7f.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-2403f7cb21035fe2.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-1b7a162408e2b621.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-085124ab4516fb65.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/turbopack-06a96355101f87a9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/febd23f07b4e493c.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/fb04574417f959b3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/fa9f09c9b623e051.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/ee321b3beaf147e6.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/ec59e0c5369e8242.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/e4f49275da9ddb2b.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/e376b434f11e3b44.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/e293cfeacbb1b7f5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/e2074449472acbe7.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/e0cefc89191be17f.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/dbdac595fe41aefb.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/da974f4f723ad5c3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/da09ebc35fc63ddd.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/d5e33d4f6685d9f5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/d57c1345735eefef.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/d41af7ea6bb3eb2a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/d3f3c8e4581fdb8e.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/ce5b3ee5b799492a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/ccc2ed8bb5ff2411.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/c9a85284c5dd9950.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/c64919a20554626d.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/bed53869972f022d.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/b84438feef07e2cf.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/b83e1f70da679c2e.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/b5383b8f49cee9a4.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/b37b290a211e2949.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/a6dad97d9634a72d.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/a6a812a2029135c0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/a235ab9f2ecd3c3e.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/a0565ccd49c59b8a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/9d38a94dcbc00a0b.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/9c9bc731146aa4c3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/9b42ae611de006ea.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/9982a83acd7d023b.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/990c1d53aaf03511.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/96e6d7de2ca8932b.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/96a62d72bbadd8ab.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/9687c38040097372.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/8fd779637f90feaa.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/8a2f5585be18a35e.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/8928cac8b8698d81.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/88a088697a560f81.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/86b23f47fb8abc4a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/84881aa80ee7aeab.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/832c337e90173ebb.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/7ff2f1a7bcf67297.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/79937e4f952b9027.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/78381f7d99966c65.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/75004d1e6e7ecbaf.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/74ea49c3067f4b27.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/74c5f56026d87676.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/6dbdb6e9a8e1a4d0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/6db623e87e911d39.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/6a8c65dcf43db1c9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/697667712177e7a0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/68653a704658ab9f.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/66edf820a711babc.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/66aa5eac694004f8.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/5f698429727a19e6.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/5f6010b8ee8d1b02.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/5bbca41c2ba5e74b.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/5af61f318dc4ece0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/5ad61bcb30567c57.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/5a0b1a2d0e4ad654.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/57557aac1cde7450.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/5472d4550f9d01e6.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/5073b7ac15bdc14e.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/4ae5a8079f70333b.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/4910182dd0a21631.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/46ed392c3e92f836.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/46bb66ebcf0e96ed.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/467ec3767e21da8f.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/44974ce52047f9f6.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/4396c8f48f1c7189.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/422e96499fe82a2e.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/4209e319b20dcc48.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/4047848b4251daa4.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/3d226135b41772a4.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/3ac9e2d4a718ec32.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/3765ab09be98290a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/28b8a536b989c8ec.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/281027c39004426f.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/1fe3b6ecfff2d044.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/1a86719687edeb9a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/17d0ac2a8f77db67.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/106a94478e937589.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/1021befaa79f5b58.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0e51b633e117972f.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0cd946e80f5a6a10.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0b5b7d8dc6f3065f.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/09a5b327cec9d478.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0797b52bd17aa9f3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0719de430146848d.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/02c54ae036aacb01.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0251e39f7f1ee59a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/4DbtZsCkU5nCXruA84qO9/_ssgManifest.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/4DbtZsCkU5nCXruA84qO9/_clientMiddlewareManifest.json\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/4DbtZsCkU5nCXruA84qO9/_buildManifest.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/manifest.json\",\n    \"revision\": \"d2e96cf41e641815ec612edc05d5873c\"\n  },\n  {\n    \"url\": \"/favicon.ico\",\n    \"revision\": \"bdbc317416fb8fe9f412f0cbb0c6d1ab\"\n  },\n  {\n    \"url\": \"/images/trophy.png\",\n    \"revision\": \"be8919896a7da9cce954fa11d6583559\"\n  },\n  {\n    \"url\": \"/images/super-trophy.png\",\n    \"revision\": \"cf2a1b1e45279298a6a9eb07a4a3a9b9\"\n  },\n  {\n    \"url\": \"/images/rf4_logo_lite.png\",\n    \"revision\": \"f27817468d44c5ee3eef18b79f87da45\"\n  },\n  {\n    \"url\": \"/images/rf4_logo.png\",\n    \"revision\": \"91e111a2e7afd27146a3a26f912a0615\"\n  },\n  {\n    \"url\": \"/images/marker-shadow.png\",\n    \"revision\": \"44a526eed258222515aa21eaffd14a96\"\n  },\n  {\n    \"url\": \"/images/marker-icon.png\",\n    \"revision\": \"2273e3d8ad9264b7daa5bdbf8e6b47f8\"\n  },\n  {\n    \"url\": \"/images/marker-icon-2x.png\",\n    \"revision\": \"401d815dc206b8dc1b17cd0e37695975\"\n  },\n  {\n    \"url\": \"/images/layers.png\",\n    \"revision\": \"a6137456ed160d7606981aa57c559898\"\n  },\n  {\n    \"url\": \"/images/layers-2x.png\",\n    \"revision\": \"4f0283c6ce28e888000e978e537a6a56\"\n  },\n  {\n    \"url\": \"/images/it_IT.png\",\n    \"revision\": \"ad489ca177d082a1b854d66462b6b9cb\"\n  },\n  {\n    \"url\": \"/images/favicon_blured.png\",\n    \"revision\": \"2c7f18735037a5a77dea4c6c3c016df4\"\n  },\n  {\n    \"url\": \"/images/favicon.png\",\n    \"revision\": \"7d5cedbf9509a5e0e47a1651674c5902\"\n  },\n  {\n    \"url\": \"/images/en_US.png\",\n    \"revision\": \"decf409ce6a075d8246e125e63348da0\"\n  },\n  {\n    \"url\": \"/images/donate.png\",\n    \"revision\": \"5f97d0505de9a0d8bd9e71b71ba50fcd\"\n  },\n  {\n    \"url\": \"/icons/icon-512x512.png\",\n    \"revision\": \"6d843f610d1a05f759bf313d604822f0\"\n  },\n  {\n    \"url\": \"/icons/icon-192x192.png\",\n    \"revision\": \"f9cae6d41e0e76f3b7766260fe9d4b87\"\n  },\n  {\n    \"url\": \"/icons/favicon-32x32.png\",\n    \"revision\": \"bbef84051f1ca1d7dfc4c2d2b35a0d1a\"\n  },\n  {\n    \"url\": \"/icons/favicon-16x16.png\",\n    \"revision\": \"9687a2f10248b547046b697214c3138f\"\n  },\n  {\n    \"url\": \"/icons/apple-touch-icon.png\",\n    \"revision\": \"ee05f9aa11b87b009745333fc28f1e40\"\n  }\n]", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\ndeclare let registration: ServiceWorkerRegistration | undefined;\n\nexport interface CacheNameDetails {\n  googleAnalytics: string;\n  precache: string;\n  prefix: string;\n  runtime: string;\n  suffix: string;\n}\n\nexport interface PartialCacheNameDetails {\n  /**\n   * The string to add to the beginning of the precache and runtime cache names.\n   */\n  prefix?: string;\n  /**\n   * The string to add to the end of the precache and runtime cache names.\n   */\n  suffix?: string;\n  /**\n   * The cache name to use for precache caching.\n   */\n  precache?: string;\n  /**\n   * The cache name to use for runtime caching.\n   */\n  runtime?: string;\n  /**\n   * The cache name to use for {@linkcode initializeGoogleAnalytics}.\n   */\n  googleAnalytics?: string;\n  [propName: string]: string | undefined;\n}\n\nexport type CacheNameDetailsProp = \"googleAnalytics\" | \"precache\" | \"prefix\" | \"runtime\" | \"suffix\";\n\nconst _cacheNameDetails: CacheNameDetails = {\n  googleAnalytics: \"googleAnalytics\",\n  precache: \"precache-v2\",\n  prefix: \"serwist\",\n  runtime: \"runtime\",\n  suffix: typeof registration !== \"undefined\" ? registration.scope : \"\",\n};\n\nconst _createCacheName = (cacheName: string): string => {\n  return [_cacheNameDetails.prefix, cacheName, _cacheNameDetails.suffix].filter((value) => value && value.length > 0).join(\"-\");\n};\n\nconst eachCacheNameDetail = (fn: (key: CacheNameDetailsProp) => void): void => {\n  for (const key of Object.keys(_cacheNameDetails)) {\n    fn(key as CacheNameDetailsProp);\n  }\n};\n\nexport const cacheNames = {\n  updateDetails: (details: PartialCacheNameDetails): void => {\n    eachCacheNameDetail((key: CacheNameDetailsProp): void => {\n      const detail = details[key];\n      if (typeof detail === \"string\") {\n        _cacheNameDetails[key] = detail;\n      }\n    });\n  },\n  getGoogleAnalyticsName: (userCacheName?: string): string => {\n    return userCacheName || _createCacheName(_cacheNameDetails.googleAnalytics);\n  },\n  getPrecacheName: (userCacheName?: string): string => {\n    return userCacheName || _createCacheName(_cacheNameDetails.precache);\n  },\n  getPrefix: (): string => {\n    return _cacheNameDetails.prefix;\n  },\n  getRuntimeName: (userCacheName?: string): string => {\n    return userCacheName || _createCacheName(_cacheNameDetails.runtime);\n  },\n  getSuffix: (): string => {\n    return _cacheNameDetails.suffix;\n  },\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nlet supportStatus: boolean | undefined;\n\n/**\n * A utility function that determines whether the current browser supports\n * constructing a new response from a `response.body` stream.\n *\n * @returns `true`, if the current browser can successfully construct\n * a response from a `response.body` stream, `false` otherwise.\n * @private\n */\nfunction canConstructResponseFromBodyStream(): boolean {\n  if (supportStatus === undefined) {\n    const testResponse = new Response(\"\");\n\n    if (\"body\" in testResponse) {\n      try {\n        new Response(testResponse.body);\n        supportStatus = true;\n      } catch {\n        supportStatus = false;\n      }\n    }\n    supportStatus = false;\n  }\n\n  return supportStatus;\n}\n\nexport { canConstructResponseFromBodyStream };\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\ninterface LoggableObject {\n  [key: string]: string | number;\n}\ninterface MessageMap {\n  [messageID: string]: (param: LoggableObject) => string;\n}\n\nexport const messages = {\n  \"invalid-value\": ({ paramName, validValueDescription, value }) => {\n    if (!paramName || !validValueDescription) {\n      throw new Error(`Unexpected input to 'invalid-value' error.`);\n    }\n    return (\n      `The '${paramName}' parameter was given a value with an ` +\n      `unexpected value. ${validValueDescription} Received a value of ` +\n      `${JSON.stringify(value)}.`\n    );\n  },\n\n  \"not-an-array\": ({ moduleName, className, funcName, paramName }) => {\n    if (!moduleName || !className || !funcName || !paramName) {\n      throw new Error(`Unexpected input to 'not-an-array' error.`);\n    }\n    return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className}.${funcName}()' must be an array.`;\n  },\n\n  \"incorrect-type\": ({ expectedType, paramName, moduleName, className, funcName }) => {\n    if (!expectedType || !paramName || !moduleName || !funcName) {\n      throw new Error(`Unexpected input to 'incorrect-type' error.`);\n    }\n    const classNameStr = className ? `${className}.` : \"\";\n    return `The parameter '${paramName}' passed into ` + `'${moduleName}.${classNameStr}` + `${funcName}()' must be of type ${expectedType}.`;\n  },\n\n  \"incorrect-class\": ({ expectedClassName, paramName, moduleName, className, funcName, isReturnValueProblem }) => {\n    if (!expectedClassName || !moduleName || !funcName) {\n      throw new Error(`Unexpected input to 'incorrect-class' error.`);\n    }\n    const classNameStr = className ? `${className}.` : \"\";\n    if (isReturnValueProblem) {\n      return `The return value from '${moduleName}.${classNameStr}${funcName}()' must be an instance of class ${expectedClassName}.`;\n    }\n\n    return (\n      `The parameter '${paramName}' passed into ` +\n      `'${moduleName}.${classNameStr}${funcName}()' ` +\n      `must be an instance of class ${expectedClassName}.`\n    );\n  },\n\n  \"missing-a-method\": ({ expectedMethod, paramName, moduleName, className, funcName }) => {\n    if (!expectedMethod || !paramName || !moduleName || !className || !funcName) {\n      throw new Error(`Unexpected input to 'missing-a-method' error.`);\n    }\n    return `${moduleName}.${className}.${funcName}() expected the ` + `'${paramName}' parameter to expose a '${expectedMethod}' method.`;\n  },\n\n  \"add-to-cache-list-unexpected-type\": ({ entry }) => {\n    return `An unexpected entry was passed to 'serwist.Serwist.addToPrecacheList()' The entry '${JSON.stringify(\n      entry,\n    )}' isn't supported. You must supply an array of strings with one or more characters, objects with a url property or Request objects.`;\n  },\n\n  \"add-to-cache-list-conflicting-entries\": ({ firstEntry, secondEntry }) => {\n    if (!firstEntry || !secondEntry) {\n      throw new Error(\"Unexpected input to \" + `'add-to-cache-list-duplicate-entries' error.`);\n    }\n\n    return `Two of the entries passed to 'serwist.Serwist.addToPrecacheList()' had the URL ${firstEntry} but different revision details. Serwist is unable to cache and version the asset correctly. Please remove one of the entries.`;\n  },\n\n  \"plugin-error-request-will-fetch\": ({ thrownErrorMessage }) => {\n    if (!thrownErrorMessage) {\n      throw new Error(\"Unexpected input to \" + `'plugin-error-request-will-fetch', error.`);\n    }\n\n    return `An error was thrown by a plugin's 'requestWillFetch()' method. The thrown error message was: '${thrownErrorMessage}'.`;\n  },\n\n  \"invalid-cache-name\": ({ cacheNameId, value }) => {\n    if (!cacheNameId) {\n      throw new Error(`Expected a 'cacheNameId' for error 'invalid-cache-name'`);\n    }\n\n    return `You must provide a name containing at least one character for setCacheDetails({${cacheNameId}: '...'}). Received a value of '${JSON.stringify(\n      value,\n    )}'`;\n  },\n\n  \"unregister-route-but-not-found-with-method\": ({ method }) => {\n    if (!method) {\n      throw new Error(\"Unexpected input to \" + `'unregister-route-but-not-found-with-method' error.`);\n    }\n\n    return `The route you're trying to unregister was not  previously registered for the method type '${method}'.`;\n  },\n\n  \"unregister-route-route-not-registered\": () => {\n    return `The route you're trying to unregister was not previously ` + \"registered.\";\n  },\n\n  \"queue-replay-failed\": ({ name }) => {\n    return `Replaying the background sync queue '${name}' failed.`;\n  },\n\n  \"duplicate-queue-name\": ({ name }) => {\n    return `The queue name '${name}' is already being used. All instances of 'serwist.BackgroundSyncQueue' must be given unique names.`;\n  },\n\n  \"expired-test-without-max-age\": ({ methodName, paramName }) => {\n    return `The '${methodName}()' method can only be used when the ` + `'${paramName}' is used in the constructor.`;\n  },\n\n  \"unsupported-route-type\": ({ moduleName, className, funcName, paramName }) => {\n    return `The supplied '${paramName}' parameter was an unsupported type. Please check the docs for ${moduleName}.${className}.${funcName} for valid input types.`;\n  },\n\n  \"not-array-of-class\": ({ value, expectedClass, moduleName, className, funcName, paramName }) => {\n    return `The supplied '${paramName}' parameter must be an array of '${expectedClass}' objects. Received '${JSON.stringify(\n      value,\n    )},'. Please check the call to ${moduleName}.${className}.${funcName}() to fix the issue.`;\n  },\n\n  \"max-entries-or-age-required\": ({ moduleName, className, funcName }) => {\n    return `You must define either 'config.maxEntries' or 'config.maxAgeSeconds' in '${moduleName}.${className}.${funcName}'`;\n  },\n\n  \"statuses-or-headers-required\": ({ moduleName, className, funcName }) => {\n    return `You must define either 'config.statuses' or 'config.headers' in '${moduleName}.${className}.${funcName}'`;\n  },\n\n  \"invalid-string\": ({ moduleName, funcName, paramName }) => {\n    if (!paramName || !moduleName || !funcName) {\n      throw new Error(`Unexpected input to 'invalid-string' error.`);\n    }\n    return `When using strings, the '${paramName}' parameter must start with 'http' (for cross-origin matches) or '/' (for same-origin matches). Please see the docs for ${moduleName}.${funcName}() for more info.`;\n  },\n\n  \"channel-name-required\": () => {\n    return \"You must provide a channelName to construct a \" + \"BroadcastCacheUpdate instance.\";\n  },\n\n  \"invalid-responses-are-same-args\": () => {\n    return \"The arguments passed into responsesAreSame() appear to be \" + \"invalid. Please ensure valid Responses are used.\";\n  },\n\n  \"expire-custom-caches-only\": () => {\n    return `You must provide a 'cacheName' property when using the ` + \"expiration plugin with a runtime caching strategy.\";\n  },\n\n  \"unit-must-be-bytes\": ({ normalizedRangeHeader }) => {\n    if (!normalizedRangeHeader) {\n      throw new Error(`Unexpected input to 'unit-must-be-bytes' error.`);\n    }\n    return `The 'unit' portion of the Range header must be set to 'bytes'. The Range header provided was \"${normalizedRangeHeader}\"`;\n  },\n\n  \"single-range-only\": ({ normalizedRangeHeader }) => {\n    if (!normalizedRangeHeader) {\n      throw new Error(`Unexpected input to 'single-range-only' error.`);\n    }\n    return `Multiple ranges are not supported. Please use a  single start value, and optional end value. The Range header provided was \"${normalizedRangeHeader}\"`;\n  },\n\n  \"invalid-range-values\": ({ normalizedRangeHeader }) => {\n    if (!normalizedRangeHeader) {\n      throw new Error(`Unexpected input to 'invalid-range-values' error.`);\n    }\n    return `The Range header is missing both start and end values. At least one of those values is needed. The Range header provided was \"${normalizedRangeHeader}\"`;\n  },\n\n  \"no-range-header\": () => {\n    return \"No Range header was found in the Request provided.\";\n  },\n\n  \"range-not-satisfiable\": ({ size, start, end }) => {\n    return `The start (${start}) and end (${end}) values in the Range are ` + `not satisfiable by the cached response, which is ${size} bytes.`;\n  },\n\n  \"attempt-to-cache-non-get-request\": ({ url, method }) => {\n    return `Unable to cache '${url}' because it is a '${method}' request and only 'GET' requests can be cached.`;\n  },\n\n  \"cache-put-with-no-response\": ({ url }) => {\n    return `There was an attempt to cache '${url}' but the response was not defined.`;\n  },\n\n  \"no-response\": ({ url, error }) => {\n    let message = `The strategy could not generate a response for '${url}'.`;\n    if (error) {\n      message += ` The underlying error is ${error}.`;\n    }\n    return message;\n  },\n\n  \"bad-precaching-response\": ({ url, status }) => {\n    return `The precaching request for '${url}' failed${status ? ` with an HTTP status of ${status}.` : \".\"}`;\n  },\n\n  \"non-precached-url\": ({ url }) => {\n    return `'createHandlerBoundToURL(\"${url}\")' was called, but that URL is not precached. Please pass in a URL that is precached instead.`;\n  },\n\n  \"add-to-cache-list-conflicting-integrities\": ({ url }) => {\n    return `Two of the entries passed to 'serwist.Serwist.addToPrecacheList()' had the URL ${url} with different integrity values. Please remove one of them.`;\n  },\n\n  \"missing-precache-entry\": ({ cacheName, url }) => {\n    return `Unable to find a precached response in ${cacheName} for ${url}.`;\n  },\n\n  \"cross-origin-copy-response\": ({ origin }) => {\n    return `'@serwist/core.copyResponse()' can only be used with same-origin responses. It was passed a response with origin ${origin}.`;\n  },\n\n  \"opaque-streams-source\": ({ type }) => {\n    const message = `One of the '@serwist/streams' sources resulted in an '${type}' response.`;\n    if (type === \"opaqueredirect\") {\n      return `${message} Please do not use a navigation request that results in a redirect as a source.`;\n    }\n    return `${message} Please ensure your sources are CORS-enabled.`;\n  },\n} satisfies MessageMap;\n\nexport type MessageKey = keyof typeof messages;\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { MapLikeObject } from \"../../types.js\";\nimport { type MessageKey, messages } from \"./messages.js\";\n\nconst fallback = (code: string, ...args: any[]) => {\n  let msg = code;\n  if (args.length > 0) {\n    msg += ` :: ${JSON.stringify(args)}`;\n  }\n  return msg;\n};\n\nconst generatorFunction = (code: MessageKey, details: MapLikeObject = {}) => {\n  const message = messages[code];\n  if (!message) {\n    throw new Error(`Unable to find message for code '${code}'.`);\n  }\n\n  return message(details);\n};\n\nexport const messageGenerator = process.env.NODE_ENV === \"production\" ? fallback : generatorFunction;\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { messageGenerator } from \"../models/messages/messageGenerator.js\";\nimport type { MessageKey } from \"../models/messages/messages.js\";\nimport type { MapLikeObject } from \"../types.js\";\n\n/**\n * Serwist errors should be thrown with this class.\n * This allows use to ensure the type easily in tests,\n * helps developers identify errors from Serwist\n * easily and allows use to optimise error\n * messages correctly.\n *\n * @private\n */\nexport class SerwistError extends Error {\n  details?: MapLikeObject;\n\n  /**\n   *\n   * @param errorCode The error code that\n   * identifies this particular error.\n   * @param details Any relevant arguments\n   * that will help developers identify issues should\n   * be added as a key on the context object.\n   */\n  constructor(errorCode: MessageKey, details?: MapLikeObject) {\n    const message = messageGenerator(errorCode, details);\n\n    super(message);\n\n    this.name = errorCode;\n    this.details = details;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { MapLikeObject } from \"../types.js\";\nimport { SerwistError } from \"./SerwistError.js\";\n\n/*\n * This method throws if the supplied value is not an array.\n * The destructed values are required to produce a meaningful error for users.\n * The destructed and restructured object is so it's clear what is\n * needed.\n */\nconst isArray = (value: any[], details: MapLikeObject) => {\n  if (!Array.isArray(value)) {\n    throw new SerwistError(\"not-an-array\", details);\n  }\n};\n\nconst hasMethod = (object: MapLikeObject, expectedMethod: string, details: MapLikeObject) => {\n  const type = typeof object[expectedMethod];\n  if (type !== \"function\") {\n    details.expectedMethod = expectedMethod;\n    throw new SerwistError(\"missing-a-method\", details);\n  }\n};\n\nconst isType = (object: unknown, expectedType: string, details: MapLikeObject) => {\n  if (typeof object !== expectedType) {\n    details.expectedType = expectedType;\n    throw new SerwistError(\"incorrect-type\", details);\n  }\n};\n\nconst isInstance = (\n  object: unknown,\n  // biome-ignore lint/complexity/noBannedTypes: Need the general type to do the check later.\n  expectedClass: Function,\n  details: MapLikeObject,\n) => {\n  if (!(object instanceof expectedClass)) {\n    details.expectedClassName = expectedClass.name;\n    throw new SerwistError(\"incorrect-class\", details);\n  }\n};\n\nconst isOneOf = (value: any, validValues: any[], details: MapLikeObject) => {\n  if (!validValues.includes(value)) {\n    details.validValueDescription = `Valid values are ${JSON.stringify(validValues)}.`;\n    throw new SerwistError(\"invalid-value\", details);\n  }\n};\n\nconst isArrayOfClass = (\n  value: any,\n  // biome-ignore lint/complexity/noBannedTypes: Need general type to do check later.\n  expectedClass: Function,\n  details: MapLikeObject,\n) => {\n  const error = new SerwistError(\"not-array-of-class\", details);\n  if (!Array.isArray(value)) {\n    throw error;\n  }\n\n  for (const item of value) {\n    if (!(item instanceof expectedClass)) {\n      throw error;\n    }\n  }\n};\n\nconst finalAssertExports =\n  process.env.NODE_ENV === \"production\"\n    ? null\n    : {\n        hasMethod,\n        isArray,\n        isInstance,\n        isOneOf,\n        isType,\n        isArrayOfClass,\n      };\n\nexport { finalAssertExports as assert };\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nconst getFriendlyURL = (url: URL | string): string => {\n  const urlObj = new URL(String(url), location.href);\n  // See https://github.com/GoogleChrome/workbox/issues/2323\n  // We want to include everything, except for the origin if it's same-origin.\n  return urlObj.href.replace(new RegExp(`^${location.origin}`), \"\");\n};\n\nexport { getFriendlyURL };\n", "/*\n  Copyright 2019 Google LLC\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n// logger is used inside of both service workers and the window global scope.\ndeclare global {\n  interface WorkerGlobalScope {\n    __WB_DISABLE_DEV_LOGS: boolean;\n  }\n\n  interface Window {\n    __WB_DISABLE_DEV_LOGS: boolean;\n  }\n}\n\n/**\n * The logger used by Serwist inside of both service workers and the window global scope.\n *\n * Note: This is forcibly `null` in production mode to reduce bundle size. Do check whether\n * you are currently in development mode (by using `process.env.NODE_ENV !== \"production\"`)\n * before using it.\n */\nexport const logger =\n  process.env.NODE_ENV === \"production\" || typeof self === \"undefined\"\n    ? null!\n    : (() => {\n        // Don't overwrite this value if it's already set.\n        // See https://github.com/GoogleChrome/workbox/pull/2284#issuecomment-560470923\n        if (!(\"__WB_DISABLE_DEV_LOGS\" in globalThis)) {\n          self.__WB_DISABLE_DEV_LOGS = false;\n        }\n\n        let inGroup = false;\n\n        const methodToColorMap = {\n          debug: \"#7f8c8d\", // Gray\n          log: \"#2ecc71\", // Green\n          warn: \"#f39c12\", // Yellow\n          error: \"#c0392b\", // Red\n          groupCollapsed: \"#3498db\", // Blue\n          groupEnd: null, // No colored prefix on groupEnd\n        };\n\n        type LoggerMethods = keyof typeof methodToColorMap;\n\n        const print = (method: LoggerMethods, args: any[]) => {\n          if (self.__WB_DISABLE_DEV_LOGS) {\n            return;\n          }\n\n          if (method === \"groupCollapsed\") {\n            // Safari doesn't print all console.groupCollapsed() arguments:\n            // https://bugs.webkit.org/show_bug.cgi?id=182754\n            if (typeof navigator !== \"undefined\" && /^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {\n              console[method](...args);\n              return;\n            }\n          }\n\n          const styles = [\n            `background: ${methodToColorMap[method]!}`,\n            \"border-radius: 0.5em\",\n            \"color: white\",\n            \"font-weight: bold\",\n            \"padding: 2px 0.5em\",\n          ];\n\n          // When in a group, the serwist prefix is not displayed.\n          const logPrefix = inGroup ? [] : [\"%cserwist\", styles.join(\";\")];\n\n          console[method](...logPrefix, ...args);\n\n          if (method === \"groupCollapsed\") {\n            inGroup = true;\n          }\n          if (method === \"groupEnd\") {\n            inGroup = false;\n          }\n        };\n\n        const loggerMethods = Object.keys(methodToColorMap) as LoggerMethods[];\n\n        return loggerMethods.reduce(\n          (api, method) => {\n            api[method] = (...args: any[]) => {\n              print(method, args);\n            };\n            return api;\n          },\n          {} as { [method in LoggerMethods]: (...args: any[]) => void },\n        );\n      })();\n", "/*\n  Copyright 2019 Google LLC\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n/**\n * Returns a promise that resolves and the passed number of milliseconds.\n * This utility is an async/await-friendly version of `setTimeout`.\n *\n * @param ms\n * @returns\n * @private\n */\n\nexport function timeout(ms: number): Promise<unknown> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n// Callbacks to be executed whenever there's a quota error.\n// biome-ignore lint/complexity/noBannedTypes: Can't change Function type right now.\nconst quotaErrorCallbacks: Set<Function> = new Set();\n\nexport { quotaErrorCallbacks };\n", "/*\n  Copyright 2020 Google LLC\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nfunction stripParams(fullURL: string, ignoreParams: string[]) {\n  const strippedURL = new URL(fullURL);\n  for (const param of ignoreParams) {\n    strippedURL.searchParams.delete(param);\n  }\n  return strippedURL.href;\n}\n\n/**\n * Matches an item in the cache, ignoring specific URL params. This is similar\n * to the `ignoreSearch` option, but it allows you to ignore just specific\n * params (while continuing to match on the others).\n *\n * @private\n * @param cache\n * @param request\n * @param matchOptions\n * @param ignoreParams\n * @returns\n */\nasync function cacheMatchIgnoreParams(\n  cache: Cache,\n  request: Request,\n  ignoreParams: string[],\n  matchOptions?: CacheQueryOptions,\n): Promise<Response | undefined> {\n  const strippedRequestURL = stripParams(request.url, ignoreParams);\n\n  // If the request doesn't include any ignored params, match as normal.\n  if (request.url === strippedRequestURL) {\n    return cache.match(request, matchOptions);\n  }\n\n  // Otherwise, match by comparing keys\n  const keysOptions = { ...matchOptions, ignoreSearch: true };\n  const cacheKeys = await cache.keys(request, keysOptions);\n\n  for (const cacheKey of cacheKeys) {\n    const strippedCacheKeyURL = stripParams(cacheKey.url, ignoreParams);\n    if (strippedRequestURL === strippedCacheKeyURL) {\n      return cache.match(cacheKey, matchOptions);\n    }\n  }\n  return;\n}\n\nexport { cacheMatchIgnoreParams };\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n/**\n * The Deferred class composes Promises in a way that allows for them to be\n * resolved or rejected from outside the constructor. In most cases promises\n * should be used directly, but Deferreds can be necessary when the logic to\n * resolve a promise must be separate.\n *\n * @private\n */\nclass Deferred<T> {\n  promise: Promise<T>;\n  resolve!: (value: T) => void;\n  reject!: (reason?: any) => void;\n\n  /**\n   * Creates a promise and exposes its resolve and reject functions as methods.\n   */\n  constructor() {\n    this.promise = new Promise((resolve, reject) => {\n      this.resolve = resolve;\n      this.reject = reject;\n    });\n  }\n}\n\nexport { Deferred };\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { quotaErrorCallbacks } from \"../models/quotaErrorCallbacks.js\";\nimport { logger } from \"./logger.js\";\n\n/**\n * Runs all of the callback functions, one at a time sequentially, in the order\n * in which they were registered.\n *\n * @private\n */\nexport const executeQuotaErrorCallbacks = async (): Promise<void> => {\n  if (process.env.NODE_ENV !== \"production\") {\n    logger.log(`About to run ${quotaErrorCallbacks.size} callbacks to clean up caches.`);\n  }\n\n  for (const callback of quotaErrorCallbacks) {\n    await callback();\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(callback, \"is complete.\");\n    }\n  }\n\n  if (process.env.NODE_ENV !== \"production\") {\n    logger.log(\"Finished running callbacks.\");\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n// Give TypeScript the correct global.\ndeclare const self: ServiceWorkerGlobalScope;\n\nconst SUBSTRING_TO_FIND = \"-precache-\";\n\n/**\n * Cleans up incompatible precaches that were created by older versions of\n * Serwist, by a service worker registered under the current scope.\n *\n * This is meant to be called as part of the `activate` event.\n *\n * This should be safe to use as long as you don't include `substringToFind`\n * (defaulting to `-precache-`) in your non-precache cache names.\n *\n * @param currentPrecacheName The cache name currently in use for\n * precaching. This cache won't be deleted.\n * @param substringToFind Cache names which include this\n * substring will be deleted (excluding `currentPrecacheName`).\n * @returns A list of all the cache names that were deleted.\n * @private\n */\nexport const deleteOutdatedCaches = async (currentPrecacheName: string, substringToFind: string = SUBSTRING_TO_FIND): Promise<string[]> => {\n  const cacheNames = await self.caches.keys();\n\n  const cacheNamesToDelete = cacheNames.filter((cacheName) => {\n    return cacheName.includes(substringToFind) && cacheName.includes(self.registration.scope) && cacheName !== currentPrecacheName;\n  });\n\n  await Promise.all(cacheNamesToDelete.map((cacheName) => self.caches.delete(cacheName)));\n\n  return cacheNamesToDelete;\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { cacheNames as privateCacheNames } from \"./cacheNames.js\";\nimport { deleteOutdatedCaches } from \"./deleteOutdatedCaches.js\";\nimport { logger } from \"./logger.js\";\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n/**\n * Adds an `activate` event listener which will clean up incompatible\n * precaches that were created by older versions of Serwist.\n */\nexport const cleanupOutdatedCaches = (cacheName?: string): void => {\n  self.addEventListener(\"activate\", (event: ExtendableEvent) => {\n    event.waitUntil(\n      deleteOutdatedCaches(privateCacheNames.getPrecacheName(cacheName)).then((cachesDeleted) => {\n        if (process.env.NODE_ENV !== \"production\") {\n          if (cachesDeleted.length > 0) {\n            logger.log(\"The following out-of-date precaches were cleaned up automatically:\", cachesDeleted);\n          }\n        }\n      }),\n    );\n  });\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n// Give TypeScript the correct global.\ndeclare let self: ServiceWorkerGlobalScope;\n\n/**\n * Claims any currently available clients once the service worker\n * becomes active. This is normally used in conjunction with `skipWaiting()`.\n */\nexport const clientsClaim = (): void => {\n  self.addEventListener(\"activate\", () => self.clients.claim());\n};\n", "/*\n  Copyright 2020 Google LLC\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n/**\n * A utility method that makes it easier to use `event.waitUntil` with\n * async functions and return the result.\n *\n * @param event\n * @param asyncFn\n * @returns\n * @private\n */\nexport const waitUntil = <T = any>(event: ExtendableEvent, asyncFn: () => Promise<T>): Promise<T> => {\n  const returnPromise = asyncFn();\n  event.waitUntil(returnPromise);\n  return returnPromise;\n};\n", "const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);\n\nlet idbProxyableTypes;\nlet cursorAdvanceMethods;\n// This is a function to prevent it throwing up in node environments.\nfunction getIdbProxyableTypes() {\n    return (idbProxyableTypes ||\n        (idbProxyableTypes = [\n            IDBDatabase,\n            IDBObjectStore,\n            IDBIndex,\n            IDBCursor,\n            IDBTransaction,\n        ]));\n}\n// This is a function to prevent it throwing up in node environments.\nfunction getCursorAdvanceMethods() {\n    return (cursorAdvanceMethods ||\n        (cursorAdvanceMethods = [\n            IDBCursor.prototype.advance,\n            IDBCursor.prototype.continue,\n            IDBCursor.prototype.continuePrimaryKey,\n        ]));\n}\nconst transactionDoneMap = new WeakMap();\nconst transformCache = new WeakMap();\nconst reverseTransformCache = new WeakMap();\nfunction promisifyRequest(request) {\n    const promise = new Promise((resolve, reject) => {\n        const unlisten = () => {\n            request.removeEventListener('success', success);\n            request.removeEventListener('error', error);\n        };\n        const success = () => {\n            resolve(wrap(request.result));\n            unlisten();\n        };\n        const error = () => {\n            reject(request.error);\n            unlisten();\n        };\n        request.addEventListener('success', success);\n        request.addEventListener('error', error);\n    });\n    // This mapping exists in reverseTransformCache but doesn't exist in transformCache. This\n    // is because we create many promises from a single IDBRequest.\n    reverseTransformCache.set(promise, request);\n    return promise;\n}\nfunction cacheDonePromiseForTransaction(tx) {\n    // Early bail if we've already created a done promise for this transaction.\n    if (transactionDoneMap.has(tx))\n        return;\n    const done = new Promise((resolve, reject) => {\n        const unlisten = () => {\n            tx.removeEventListener('complete', complete);\n            tx.removeEventListener('error', error);\n            tx.removeEventListener('abort', error);\n        };\n        const complete = () => {\n            resolve();\n            unlisten();\n        };\n        const error = () => {\n            reject(tx.error || new DOMException('AbortError', 'AbortError'));\n            unlisten();\n        };\n        tx.addEventListener('complete', complete);\n        tx.addEventListener('error', error);\n        tx.addEventListener('abort', error);\n    });\n    // Cache it for later retrieval.\n    transactionDoneMap.set(tx, done);\n}\nlet idbProxyTraps = {\n    get(target, prop, receiver) {\n        if (target instanceof IDBTransaction) {\n            // Special handling for transaction.done.\n            if (prop === 'done')\n                return transactionDoneMap.get(target);\n            // Make tx.store return the only store in the transaction, or undefined if there are many.\n            if (prop === 'store') {\n                return receiver.objectStoreNames[1]\n                    ? undefined\n                    : receiver.objectStore(receiver.objectStoreNames[0]);\n            }\n        }\n        // Else transform whatever we get back.\n        return wrap(target[prop]);\n    },\n    set(target, prop, value) {\n        target[prop] = value;\n        return true;\n    },\n    has(target, prop) {\n        if (target instanceof IDBTransaction &&\n            (prop === 'done' || prop === 'store')) {\n            return true;\n        }\n        return prop in target;\n    },\n};\nfunction replaceTraps(callback) {\n    idbProxyTraps = callback(idbProxyTraps);\n}\nfunction wrapFunction(func) {\n    // Due to expected object equality (which is enforced by the caching in `wrap`), we\n    // only create one new func per func.\n    // Cursor methods are special, as the behaviour is a little more different to standard IDB. In\n    // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the\n    // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense\n    // with real promises, so each advance methods returns a new promise for the cursor object, or\n    // undefined if the end of the cursor has been reached.\n    if (getCursorAdvanceMethods().includes(func)) {\n        return function (...args) {\n            // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n            // the original object.\n            func.apply(unwrap(this), args);\n            return wrap(this.request);\n        };\n    }\n    return function (...args) {\n        // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n        // the original object.\n        return wrap(func.apply(unwrap(this), args));\n    };\n}\nfunction transformCachableValue(value) {\n    if (typeof value === 'function')\n        return wrapFunction(value);\n    // This doesn't return, it just creates a 'done' promise for the transaction,\n    // which is later returned for transaction.done (see idbObjectHandler).\n    if (value instanceof IDBTransaction)\n        cacheDonePromiseForTransaction(value);\n    if (instanceOfAny(value, getIdbProxyableTypes()))\n        return new Proxy(value, idbProxyTraps);\n    // Return the same value back if we're not going to transform it.\n    return value;\n}\nfunction wrap(value) {\n    // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because\n    // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.\n    if (value instanceof IDBRequest)\n        return promisifyRequest(value);\n    // If we've already transformed this value before, reuse the transformed value.\n    // This is faster, but it also provides object equality.\n    if (transformCache.has(value))\n        return transformCache.get(value);\n    const newValue = transformCachableValue(value);\n    // Not all types are transformed.\n    // These may be primitive types, so they can't be WeakMap keys.\n    if (newValue !== value) {\n        transformCache.set(value, newValue);\n        reverseTransformCache.set(newValue, value);\n    }\n    return newValue;\n}\nconst unwrap = (value) => reverseTransformCache.get(value);\n\n/**\n * Open a database.\n *\n * @param name Name of the database.\n * @param version Schema version.\n * @param callbacks Additional callbacks.\n */\nfunction openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {\n    const request = indexedDB.open(name, version);\n    const openPromise = wrap(request);\n    if (upgrade) {\n        request.addEventListener('upgradeneeded', (event) => {\n            upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);\n        });\n    }\n    if (blocked) {\n        request.addEventListener('blocked', (event) => blocked(\n        // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n        event.oldVersion, event.newVersion, event));\n    }\n    openPromise\n        .then((db) => {\n        if (terminated)\n            db.addEventListener('close', () => terminated());\n        if (blocking) {\n            db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));\n        }\n    })\n        .catch(() => { });\n    return openPromise;\n}\n/**\n * Delete a database.\n *\n * @param name Name of the database.\n */\nfunction deleteDB(name, { blocked } = {}) {\n    const request = indexedDB.deleteDatabase(name);\n    if (blocked) {\n        request.addEventListener('blocked', (event) => blocked(\n        // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n        event.oldVersion, event));\n    }\n    return wrap(request).then(() => undefined);\n}\n\nconst readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];\nconst writeMethods = ['put', 'add', 'delete', 'clear'];\nconst cachedMethods = new Map();\nfunction getMethod(target, prop) {\n    if (!(target instanceof IDBDatabase &&\n        !(prop in target) &&\n        typeof prop === 'string')) {\n        return;\n    }\n    if (cachedMethods.get(prop))\n        return cachedMethods.get(prop);\n    const targetFuncName = prop.replace(/FromIndex$/, '');\n    const useIndex = prop !== targetFuncName;\n    const isWrite = writeMethods.includes(targetFuncName);\n    if (\n    // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.\n    !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||\n        !(isWrite || readMethods.includes(targetFuncName))) {\n        return;\n    }\n    const method = async function (storeName, ...args) {\n        // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(\n        const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');\n        let target = tx.store;\n        if (useIndex)\n            target = target.index(args.shift());\n        // Must reject if op rejects.\n        // If it's a write operation, must reject if tx.done rejects.\n        // Must reject with op rejection first.\n        // Must resolve with op value.\n        // Must handle both promises (no unhandled rejections)\n        return (await Promise.all([\n            target[targetFuncName](...args),\n            isWrite && tx.done,\n        ]))[0];\n    };\n    cachedMethods.set(prop, method);\n    return method;\n}\nreplaceTraps((oldTraps) => ({\n    ...oldTraps,\n    get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),\n    has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),\n}));\n\nconst advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];\nconst methodMap = {};\nconst advanceResults = new WeakMap();\nconst ittrProxiedCursorToOriginalProxy = new WeakMap();\nconst cursorIteratorTraps = {\n    get(target, prop) {\n        if (!advanceMethodProps.includes(prop))\n            return target[prop];\n        let cachedFunc = methodMap[prop];\n        if (!cachedFunc) {\n            cachedFunc = methodMap[prop] = function (...args) {\n                advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));\n            };\n        }\n        return cachedFunc;\n    },\n};\nasync function* iterate(...args) {\n    // tslint:disable-next-line:no-this-assignment\n    let cursor = this;\n    if (!(cursor instanceof IDBCursor)) {\n        cursor = await cursor.openCursor(...args);\n    }\n    if (!cursor)\n        return;\n    cursor = cursor;\n    const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);\n    ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);\n    // Map this double-proxy back to the original, so other cursor methods work.\n    reverseTransformCache.set(proxiedCursor, unwrap(cursor));\n    while (cursor) {\n        yield proxiedCursor;\n        // If one of the advancing methods was not called, call continue().\n        cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());\n        advanceResults.delete(proxiedCursor);\n    }\n}\nfunction isIteratorProp(target, prop) {\n    return ((prop === Symbol.asyncIterator &&\n        instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor])) ||\n        (prop === 'iterate' && instanceOfAny(target, [IDBIndex, IDBObjectStore])));\n}\nreplaceTraps((oldTraps) => ({\n    ...oldTraps,\n    get(target, prop, receiver) {\n        if (isIteratorProp(target, prop))\n            return iterate;\n        return oldTraps.get(target, prop, receiver);\n    },\n    has(target, prop) {\n        return isIteratorProp(target, prop) || oldTraps.has(target, prop);\n    },\n}));\n\nexport { deleteDB, openDB, unwrap, wrap };\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { canConstructResponseFromBodyStream } from \"./utils/canConstructResponseFromBodyStream.js\";\nimport { SerwistError } from \"./utils/SerwistError.js\";\n\n/**\n * Allows developers to copy a response and modify its `headers`, `status`,\n * or `statusText` values (the [valid options](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response#options)\n * when constructing a `Response` object).\n * To modify these values, pass a function as the second argument. That\n * function will be invoked with the options of the initial `Response` object.\n * The return value of this function will be used as the options for the new `Response` object.\n * To change the values either modify the passed parameter(s) and return it or return a totally\n * new object.\n *\n * This method is intentionally limited to same-origin responses, regardless of\n * whether CORS was used or not.\n *\n * @param response The initial response.\n * @param modifier The function used to modify the options of the `Response` object.\n */\nexport const copyResponse = async (response: Response, modifier?: (responseInit: ResponseInit) => ResponseInit): Promise<Response> => {\n  let origin = null;\n  // If response.url isn't set, assume it's cross-origin and keep origin null.\n  if (response.url) {\n    const responseURL = new URL(response.url);\n    origin = responseURL.origin;\n  }\n\n  if (origin !== self.location.origin) {\n    throw new SerwistError(\"cross-origin-copy-response\", { origin });\n  }\n\n  const clonedResponse = response.clone();\n\n  // Create a fresh `ResponseInit` object by cloning the headers.\n  const responseInit: ResponseInit = {\n    headers: new Headers(clonedResponse.headers),\n    status: clonedResponse.status,\n    statusText: clonedResponse.statusText,\n  };\n\n  // Apply any user modifications.\n  const modifiedResponseInit = modifier ? modifier(responseInit) : responseInit;\n\n  // Create the new response from the body stream and `ResponseInit`\n  // modifications. Note: not all browsers support the Response.body stream,\n  // so fall back to reading the entire body into memory as a blob.\n  const body = canConstructResponseFromBodyStream() ? clonedResponse.body : await clonedResponse.blob();\n\n  return new Response(body, modifiedResponseInit);\n};\n", "declare const self: ServiceWorkerGlobalScope;\n\n/**\n * Disables Serwist's logging in development mode.\n *\n * @see https://serwist.pages.dev/docs/serwist/core/disable-dev-logs\n */\nexport const disableDevLogs = (): void => {\n  self.__WB_DISABLE_DEV_LOGS = true;\n};\n", "/*\n  Copyright 2021 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { DBSchema, IDBPDatabase } from \"idb\";\nimport { openDB } from \"idb\";\n\nimport type { RequestData } from \"./StorableRequest.js\";\n\ninterface BackgroundSyncQueueDBSchema extends DBSchema {\n  requests: {\n    key: number;\n    value: BackgroundSyncQueueStoreEntry;\n    indexes: { queueName: string };\n  };\n}\n\nconst BACKGROUND_SYNC_DB_VERSION = 3;\nconst BACKGROUND_SYNC_DB_NAME = \"serwist-background-sync\";\nconst REQUEST_OBJECT_STORE_NAME = \"requests\";\nconst QUEUE_NAME_INDEX = \"queueName\";\n\nexport interface UnidentifiedQueueStoreEntry {\n  requestData: RequestData;\n  timestamp: number;\n  id?: number;\n  queueName?: string;\n  metadata?: Record<string, unknown>;\n}\n\nexport interface BackgroundSyncQueueStoreEntry extends UnidentifiedQueueStoreEntry {\n  id: number;\n}\n\n/**\n * A class to interact directly an IndexedDB created specifically to save and\n * retrieve QueueStoreEntries. This class encapsulates all the schema details\n * to store the representation of a Queue.\n *\n * @private\n */\n\nexport class BackgroundSyncQueueDb {\n  private _db: IDBPDatabase<BackgroundSyncQueueDBSchema> | null = null;\n\n  /**\n   * Add QueueStoreEntry to underlying db.\n   *\n   * @param entry\n   */\n  async addEntry(entry: UnidentifiedQueueStoreEntry): Promise<void> {\n    const db = await this.getDb();\n    const tx = db.transaction(REQUEST_OBJECT_STORE_NAME, \"readwrite\", {\n      durability: \"relaxed\",\n    });\n    await tx.store.add(entry as BackgroundSyncQueueStoreEntry);\n    await tx.done;\n  }\n\n  /**\n   * Returns the first entry id in the ObjectStore.\n   *\n   * @returns\n   */\n  async getFirstEntryId(): Promise<number | undefined> {\n    const db = await this.getDb();\n    const cursor = await db.transaction(REQUEST_OBJECT_STORE_NAME).store.openCursor();\n    return cursor?.value.id;\n  }\n\n  /**\n   * Get all the entries filtered by index\n   *\n   * @param queueName\n   * @returns\n   */\n  async getAllEntriesByQueueName(queueName: string): Promise<BackgroundSyncQueueStoreEntry[]> {\n    const db = await this.getDb();\n    const results = await db.getAllFromIndex(REQUEST_OBJECT_STORE_NAME, QUEUE_NAME_INDEX, IDBKeyRange.only(queueName));\n    return results ? results : ([] as BackgroundSyncQueueStoreEntry[]);\n  }\n\n  /**\n   * Returns the number of entries filtered by index\n   *\n   * @param queueName\n   * @returns\n   */\n  async getEntryCountByQueueName(queueName: string): Promise<number> {\n    const db = await this.getDb();\n    return db.countFromIndex(REQUEST_OBJECT_STORE_NAME, QUEUE_NAME_INDEX, IDBKeyRange.only(queueName));\n  }\n\n  /**\n   * Deletes a single entry by id.\n   *\n   * @param id the id of the entry to be deleted\n   */\n  async deleteEntry(id: number): Promise<void> {\n    const db = await this.getDb();\n    await db.delete(REQUEST_OBJECT_STORE_NAME, id);\n  }\n\n  /**\n   *\n   * @param queueName\n   * @returns\n   */\n  async getFirstEntryByQueueName(queueName: string): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), \"next\");\n  }\n\n  /**\n   *\n   * @param queueName\n   * @returns\n   */\n  async getLastEntryByQueueName(queueName: string): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), \"prev\");\n  }\n\n  /**\n   * Returns either the first or the last entries, depending on direction.\n   * Filtered by index.\n   *\n   * @param direction\n   * @param query\n   * @returns\n   * @private\n   */\n  async getEndEntryFromIndex(query: IDBKeyRange, direction: IDBCursorDirection): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    const db = await this.getDb();\n\n    const cursor = await db.transaction(REQUEST_OBJECT_STORE_NAME).store.index(QUEUE_NAME_INDEX).openCursor(query, direction);\n    return cursor?.value;\n  }\n\n  /**\n   * Returns an open connection to the database.\n   *\n   * @private\n   */\n  private async getDb() {\n    if (!this._db) {\n      this._db = await openDB(BACKGROUND_SYNC_DB_NAME, BACKGROUND_SYNC_DB_VERSION, {\n        upgrade: this._upgradeDb,\n      });\n    }\n    return this._db;\n  }\n\n  /**\n   * Upgrades QueueDB\n   *\n   * @param db\n   * @param oldVersion\n   * @private\n   */\n  private _upgradeDb(db: IDBPDatabase<BackgroundSyncQueueDBSchema>, oldVersion: number) {\n    if (oldVersion > 0 && oldVersion < BACKGROUND_SYNC_DB_VERSION) {\n      if (db.objectStoreNames.contains(REQUEST_OBJECT_STORE_NAME)) {\n        db.deleteObjectStore(REQUEST_OBJECT_STORE_NAME);\n      }\n    }\n\n    const objStore = db.createObjectStore(REQUEST_OBJECT_STORE_NAME, {\n      autoIncrement: true,\n      keyPath: \"id\",\n    });\n    objStore.createIndex(QUEUE_NAME_INDEX, QUEUE_NAME_INDEX, { unique: false });\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\nimport { assert } from \"../../utils/assert.js\";\nimport type { BackgroundSyncQueueStoreEntry, UnidentifiedQueueStoreEntry } from \"./BackgroundSyncQueueDb.js\";\nimport { BackgroundSyncQueueDb } from \"./BackgroundSyncQueueDb.js\";\n\n/**\n * A class to manage storing requests from a Queue in IndexedDB,\n * indexed by their queue name for easier access.\n *\n * Most developers will not need to access this class directly;\n * it is exposed for advanced use cases.\n */\nexport class BackgroundSyncQueueStore {\n  private readonly _queueName: string;\n  private readonly _queueDb: BackgroundSyncQueueDb;\n\n  /**\n   * Associates this instance with a Queue instance, so entries added can be\n   * identified by their queue name.\n   *\n   * @param queueName\n   */\n  constructor(queueName: string) {\n    this._queueName = queueName;\n    this._queueDb = new BackgroundSyncQueueDb();\n  }\n\n  /**\n   * Append an entry last in the queue.\n   *\n   * @param entry\n   */\n  async pushEntry(entry: UnidentifiedQueueStoreEntry): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(entry, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueueStore\",\n        funcName: \"pushEntry\",\n        paramName: \"entry\",\n      });\n      assert!.isType(entry.requestData, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueueStore\",\n        funcName: \"pushEntry\",\n        paramName: \"entry.requestData\",\n      });\n    }\n\n    delete entry.id;\n    entry.queueName = this._queueName;\n\n    await this._queueDb.addEntry(entry);\n  }\n\n  /**\n   * Prepend an entry first in the queue.\n   *\n   * @param entry\n   */\n  async unshiftEntry(entry: UnidentifiedQueueStoreEntry): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(entry, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueueStore\",\n        funcName: \"unshiftEntry\",\n        paramName: \"entry\",\n      });\n      assert!.isType(entry.requestData, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueueStore\",\n        funcName: \"unshiftEntry\",\n        paramName: \"entry.requestData\",\n      });\n    }\n\n    const firstId = await this._queueDb.getFirstEntryId();\n\n    if (firstId) {\n      // Pick an ID one less than the lowest ID in the object store.\n      entry.id = firstId - 1;\n    } else {\n      delete entry.id;\n    }\n    entry.queueName = this._queueName;\n\n    await this._queueDb.addEntry(entry);\n  }\n\n  /**\n   * Removes and returns the last entry in the queue matching the `queueName`.\n   *\n   * @returns\n   */\n  async popEntry(): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    return this._removeEntry(await this._queueDb.getLastEntryByQueueName(this._queueName));\n  }\n\n  /**\n   * Removes and returns the first entry in the queue matching the `queueName`.\n   *\n   * @returns\n   */\n  async shiftEntry(): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    return this._removeEntry(await this._queueDb.getFirstEntryByQueueName(this._queueName));\n  }\n\n  /**\n   * Returns all entries in the store matching the `queueName`.\n   *\n   * @returns\n   */\n  async getAll(): Promise<BackgroundSyncQueueStoreEntry[]> {\n    return await this._queueDb.getAllEntriesByQueueName(this._queueName);\n  }\n\n  /**\n   * Returns the number of entries in the store matching the `queueName`.\n   *\n   * @returns\n   */\n  async size(): Promise<number> {\n    return await this._queueDb.getEntryCountByQueueName(this._queueName);\n  }\n\n  /**\n   * Deletes the entry for the given ID.\n   *\n   * WARNING: this method does not ensure the deleted entry belongs to this\n   * queue (i.e. matches the `queueName`). But this limitation is acceptable\n   * as this class is not publicly exposed. An additional check would make\n   * this method slower than it needs to be.\n   *\n   * @param id\n   */\n  async deleteEntry(id: number): Promise<void> {\n    await this._queueDb.deleteEntry(id);\n  }\n\n  /**\n   * Removes and returns the first or last entry in the queue (based on the\n   * `direction` argument) matching the `queueName`.\n   *\n   * @returns\n   * @private\n   */\n  async _removeEntry(entry?: BackgroundSyncQueueStoreEntry): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    if (entry) {\n      await this.deleteEntry(entry.id);\n    }\n    return entry;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { MapLikeObject } from \"../../types.js\";\nimport { assert } from \"../../utils/assert.js\";\n\ntype SerializableProperties = \"method\" | \"referrer\" | \"referrerPolicy\" | \"mode\" | \"credentials\" | \"cache\" | \"redirect\" | \"integrity\" | \"keepalive\";\n\nconst serializableProperties: SerializableProperties[] = [\n  \"method\",\n  \"referrer\",\n  \"referrerPolicy\",\n  \"mode\",\n  \"credentials\",\n  \"cache\",\n  \"redirect\",\n  \"integrity\",\n  \"keepalive\",\n];\n\nexport interface RequestData extends MapLikeObject {\n  url: string;\n  headers: MapLikeObject;\n  body?: ArrayBuffer;\n}\n\n/**\n * A class to make it easier to serialize and de-serialize requests so they\n * can be stored in IndexedDB.\n *\n * Most developers will not need to access this class directly;\n * it is exposed for advanced use cases.\n */\nexport class StorableRequest {\n  private readonly _requestData: RequestData;\n\n  /**\n   * Converts a Request object to a plain object that can be structured\n   * cloned or stringified to JSON.\n   *\n   * @param request\n   * @returns\n   */\n  static async fromRequest(request: Request): Promise<StorableRequest> {\n    const requestData: RequestData = {\n      url: request.url,\n      headers: {},\n    };\n\n    // Set the body if present.\n    if (request.method !== \"GET\") {\n      // Use ArrayBuffer to support non-text request bodies.\n      // NOTE: we can't use Blobs becuse Safari doesn't support storing\n      // Blobs in IndexedDB in some cases:\n      // https://github.com/dfahlander/Dexie.js/issues/618#issuecomment-398348457\n      requestData.body = await request.clone().arrayBuffer();\n    }\n\n    request.headers.forEach((value, key) => {\n      requestData.headers[key] = value;\n    });\n\n    // Add all other serializable request properties\n    for (const prop of serializableProperties) {\n      if (request[prop] !== undefined) {\n        requestData[prop] = request[prop];\n      }\n    }\n\n    return new StorableRequest(requestData);\n  }\n\n  /**\n   * Accepts an object of request data that can be used to construct a\n   * `Request` object but can also be stored in IndexedDB.\n   *\n   * @param requestData An object of request data that includes the `url` plus any relevant property of\n   * [`requestInit`](https://fetch.spec.whatwg.org/#requestinit).\n   */\n  constructor(requestData: RequestData) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(requestData, \"object\", {\n        moduleName: \"serwist\",\n        className: \"StorableRequest\",\n        funcName: \"constructor\",\n        paramName: \"requestData\",\n      });\n      assert!.isType(requestData.url, \"string\", {\n        moduleName: \"serwist\",\n        className: \"StorableRequest\",\n        funcName: \"constructor\",\n        paramName: \"requestData.url\",\n      });\n    }\n\n    // If the request's mode is `navigate`, convert it to `same-origin` since\n    // navigation requests can't be constructed via script.\n    if (requestData.mode === \"navigate\") {\n      requestData.mode = \"same-origin\";\n    }\n\n    this._requestData = requestData;\n  }\n\n  /**\n   * Returns a deep clone of the instance's `requestData` object.\n   *\n   * @returns\n   */\n  toObject(): RequestData {\n    const requestData = Object.assign({}, this._requestData);\n    requestData.headers = Object.assign({}, this._requestData.headers);\n    if (requestData.body) {\n      requestData.body = requestData.body.slice(0);\n    }\n\n    return requestData;\n  }\n\n  /**\n   * Converts this instance to a Request.\n   *\n   * @returns\n   */\n  toRequest(): Request {\n    return new Request(this._requestData.url, this._requestData);\n  }\n\n  /**\n   * Creates and returns a deep clone of the instance.\n   *\n   * @returns\n   */\n  clone(): StorableRequest {\n    return new StorableRequest(this.toObject());\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\nimport { assert } from \"../../utils/assert.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport type { BackgroundSyncQueueStoreEntry, UnidentifiedQueueStoreEntry } from \"./BackgroundSyncQueueDb.js\";\nimport { BackgroundSyncQueueStore } from \"./BackgroundSyncQueueStore.js\";\nimport { StorableRequest } from \"./StorableRequest.js\";\n\n// See https://github.com/GoogleChrome/workbox/issues/2946\ninterface SyncManager {\n  getTags(): Promise<string[]>;\n  register(tag: string): Promise<void>;\n}\n\ndeclare global {\n  interface ServiceWorkerRegistration {\n    readonly sync: SyncManager;\n  }\n\n  interface SyncEvent extends ExtendableEvent {\n    readonly lastChance: boolean;\n    readonly tag: string;\n  }\n\n  interface ServiceWorkerGlobalScopeEventMap {\n    sync: SyncEvent;\n  }\n}\n\n// Give TypeScript the correct global.\ndeclare const self: ServiceWorkerGlobalScope;\n\ninterface OnSyncCallbackOptions {\n  queue: BackgroundSyncQueue;\n}\n\ntype OnSyncCallback = (options: OnSyncCallbackOptions) => void | Promise<void>;\n\nexport interface BackgroundSyncQueueOptions {\n  /**\n   * If `true`, instead of attempting to use background sync events, always attempt\n   * to replay queued request at service worker startup. Most folks will not need\n   * this, unless you explicitly target a runtime like Electron that exposes the\n   * interfaces for background sync, but does not have a working implementation.\n   *\n   * @default false\n   */\n  forceSyncFallback?: boolean;\n  /**\n   * The amount of time (in minutes) a request may be retried. After this amount\n   * of time has passed, the request will be deleted from the queue.\n   *\n   * @default 60 * 24 * 7\n   */\n  maxRetentionTime?: number;\n  /**\n   * A function that gets invoked whenever the 'sync' event fires. The function\n   * is invoked with an object containing the `queue` property (referencing this\n   * instance), and you can use the callback to customize the replay behavior of\n   * the queue. When not set the `replayRequests()` method is called. Note: if the\n   * replay fails after a sync event, make sure you throw an error, so the browser\n   * knows to retry the sync event later.\n   */\n  onSync?: OnSyncCallback;\n}\n\nexport interface BackgroundSyncQueueEntry {\n  /**\n   * The request to store in the queue.\n   */\n  request: Request;\n  /**\n   * The timestamp (Epoch time in milliseconds) when the request was first added\n   * to the queue. This is used along with `maxRetentionTime` to remove outdated\n   * requests. In general you don't need to set this value, as it's automatically\n   * set for you (defaulting to `Date.now()`), but you can update it if you don't\n   * want particular requests to expire.\n   */\n  timestamp?: number;\n  /**\n   * Any metadata you want associated with the stored request. When requests are\n   * replayed you'll have access to this metadata object in case you need to modify\n   * the request beforehand.\n   */\n  metadata?: Record<string, unknown>;\n}\n\nconst TAG_PREFIX = \"serwist-background-sync\";\nconst MAX_RETENTION_TIME = 60 * 24 * 7; // 7 days in minutes\n\nconst queueNames = new Set<string>();\n\n/**\n * Converts a QueueStore entry into the format exposed by Queue. This entails\n * converting the request data into a real request and omitting the `id` and\n * `queueName` properties.\n *\n * @param queueStoreEntry\n * @returns\n * @private\n */\nconst convertEntry = (queueStoreEntry: UnidentifiedQueueStoreEntry): BackgroundSyncQueueEntry => {\n  const queueEntry: BackgroundSyncQueueEntry = {\n    request: new StorableRequest(queueStoreEntry.requestData).toRequest(),\n    timestamp: queueStoreEntry.timestamp,\n  };\n  if (queueStoreEntry.metadata) {\n    queueEntry.metadata = queueStoreEntry.metadata;\n  }\n  return queueEntry;\n};\n\n/**\n * A class to manage storing failed requests in IndexedDB and retrying them\n * later. All parts of the storing and replaying process are observable via\n * callbacks.\n */\nexport class BackgroundSyncQueue {\n  private readonly _name: string;\n  private readonly _onSync: OnSyncCallback;\n  private readonly _maxRetentionTime: number;\n  private readonly _queueStore: BackgroundSyncQueueStore;\n  private readonly _forceSyncFallback: boolean;\n  private _syncInProgress = false;\n  private _requestsAddedDuringSync = false;\n\n  /**\n   * Creates an instance of Queue with the given options\n   *\n   * @param name The unique name for this queue. This name must be\n   * unique as it's used to register sync events and store requests\n   * in IndexedDB specific to this instance. An error will be thrown if\n   * a duplicate name is detected.\n   * @param options\n   */\n  constructor(name: string, { forceSyncFallback, onSync, maxRetentionTime }: BackgroundSyncQueueOptions = {}) {\n    // Ensure the store name is not already being used\n    if (queueNames.has(name)) {\n      throw new SerwistError(\"duplicate-queue-name\", { name });\n    }\n    queueNames.add(name);\n\n    this._name = name;\n    this._onSync = onSync || this.replayRequests;\n    this._maxRetentionTime = maxRetentionTime || MAX_RETENTION_TIME;\n    this._forceSyncFallback = Boolean(forceSyncFallback);\n    this._queueStore = new BackgroundSyncQueueStore(this._name);\n\n    this._addSyncListener();\n  }\n\n  /**\n   * @returns\n   */\n  get name(): string {\n    return this._name;\n  }\n\n  /**\n   * Stores the passed request in IndexedDB (with its timestamp and any\n   * metadata) at the end of the queue.\n   *\n   * @param entry\n   */\n  async pushRequest(entry: BackgroundSyncQueueEntry): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(entry, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueue\",\n        funcName: \"pushRequest\",\n        paramName: \"entry\",\n      });\n      assert!.isInstance(entry.request, Request, {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueue\",\n        funcName: \"pushRequest\",\n        paramName: \"entry.request\",\n      });\n    }\n\n    await this._addRequest(entry, \"push\");\n  }\n\n  /**\n   * Stores the passed request in IndexedDB (with its timestamp and any\n   * metadata) at the beginning of the queue.\n   *\n   * @param entry\n   */\n  async unshiftRequest(entry: BackgroundSyncQueueEntry): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(entry, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueue\",\n        funcName: \"unshiftRequest\",\n        paramName: \"entry\",\n      });\n      assert!.isInstance(entry.request, Request, {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueue\",\n        funcName: \"unshiftRequest\",\n        paramName: \"entry.request\",\n      });\n    }\n\n    await this._addRequest(entry, \"unshift\");\n  }\n\n  /**\n   * Removes and returns the last request in the queue (along with its\n   * timestamp and any metadata).\n   *\n   * @returns\n   */\n  async popRequest(): Promise<BackgroundSyncQueueEntry | undefined> {\n    return this._removeRequest(\"pop\");\n  }\n\n  /**\n   * Removes and returns the first request in the queue (along with its\n   * timestamp and any metadata).\n   *\n   * @returns\n   */\n  async shiftRequest(): Promise<BackgroundSyncQueueEntry | undefined> {\n    return this._removeRequest(\"shift\");\n  }\n\n  /**\n   * Returns all the entries that have not expired (per `maxRetentionTime`).\n   * Any expired entries are removed from the queue.\n   *\n   * @returns\n   */\n  async getAll(): Promise<BackgroundSyncQueueEntry[]> {\n    const allEntries = await this._queueStore.getAll();\n    const now = Date.now();\n\n    const unexpiredEntries = [];\n    for (const entry of allEntries) {\n      // Ignore requests older than maxRetentionTime. Call this function\n      // recursively until an unexpired request is found.\n      const maxRetentionTimeInMs = this._maxRetentionTime * 60 * 1000;\n      if (now - entry.timestamp > maxRetentionTimeInMs) {\n        await this._queueStore.deleteEntry(entry.id);\n      } else {\n        unexpiredEntries.push(convertEntry(entry));\n      }\n    }\n\n    return unexpiredEntries;\n  }\n\n  /**\n   * Returns the number of entries present in the queue.\n   * Note that expired entries (per `maxRetentionTime`) are also included in this count.\n   *\n   * @returns\n   */\n  async size(): Promise<number> {\n    return await this._queueStore.size();\n  }\n\n  /**\n   * Adds the entry to the QueueStore and registers for a sync event.\n   *\n   * @param entry\n   * @param operation\n   * @private\n   */\n  async _addRequest({ request, metadata, timestamp = Date.now() }: BackgroundSyncQueueEntry, operation: \"push\" | \"unshift\"): Promise<void> {\n    const storableRequest = await StorableRequest.fromRequest(request.clone());\n    const entry: UnidentifiedQueueStoreEntry = {\n      requestData: storableRequest.toObject(),\n      timestamp,\n    };\n\n    // Only include metadata if it's present.\n    if (metadata) {\n      entry.metadata = metadata;\n    }\n\n    switch (operation) {\n      case \"push\":\n        await this._queueStore.pushEntry(entry);\n        break;\n      case \"unshift\":\n        await this._queueStore.unshiftEntry(entry);\n        break;\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(`Request for '${getFriendlyURL(request.url)}' has ` + `been added to background sync queue '${this._name}'.`);\n    }\n\n    // Don't register for a sync if we're in the middle of a sync. Instead,\n    // we wait until the sync is complete and call register if\n    // `this._requestsAddedDuringSync` is true.\n    if (this._syncInProgress) {\n      this._requestsAddedDuringSync = true;\n    } else {\n      await this.registerSync();\n    }\n  }\n\n  /**\n   * Removes and returns the first or last (depending on `operation`) entry\n   * from the {@linkcode BackgroundSyncQueueStore} that's not older than the `maxRetentionTime`.\n   *\n   * @param operation\n   * @returns\n   * @private\n   */\n  async _removeRequest(operation: \"pop\" | \"shift\"): Promise<BackgroundSyncQueueEntry | undefined> {\n    const now = Date.now();\n    let entry: BackgroundSyncQueueStoreEntry | undefined;\n    switch (operation) {\n      case \"pop\":\n        entry = await this._queueStore.popEntry();\n        break;\n      case \"shift\":\n        entry = await this._queueStore.shiftEntry();\n        break;\n    }\n\n    if (entry) {\n      // Ignore requests older than maxRetentionTime. Call this function\n      // recursively until an unexpired request is found.\n      const maxRetentionTimeInMs = this._maxRetentionTime * 60 * 1000;\n      if (now - entry.timestamp > maxRetentionTimeInMs) {\n        return this._removeRequest(operation);\n      }\n\n      return convertEntry(entry);\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Loops through each request in the queue and attempts to re-fetch it.\n   * If any request fails to re-fetch, it's put back in the same position in\n   * the queue (which registers a retry for the next sync event).\n   */\n  async replayRequests(): Promise<void> {\n    let entry: BackgroundSyncQueueEntry | undefined;\n    while ((entry = await this.shiftRequest())) {\n      try {\n        await fetch(entry.request.clone());\n\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(`Request for '${getFriendlyURL(entry.request.url)}' ` + `has been replayed in queue '${this._name}'`);\n        }\n      } catch {\n        await this.unshiftRequest(entry);\n\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(`Request for '${getFriendlyURL(entry.request.url)}' ` + `failed to replay, putting it back in queue '${this._name}'`);\n        }\n        throw new SerwistError(\"queue-replay-failed\", { name: this._name });\n      }\n    }\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(`All requests in queue '${this.name}' have successfully replayed; the queue is now empty!`);\n    }\n  }\n\n  /**\n   * Registers a sync event with a tag unique to this instance.\n   */\n  async registerSync(): Promise<void> {\n    // See https://github.com/GoogleChrome/workbox/issues/2393\n    if (\"sync\" in self.registration && !this._forceSyncFallback) {\n      try {\n        await self.registration.sync.register(`${TAG_PREFIX}:${this._name}`);\n      } catch (err) {\n        // This means the registration failed for some reason, possibly due to\n        // the user disabling it.\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.warn(`Unable to register sync event for '${this._name}'.`, err);\n        }\n      }\n    }\n  }\n\n  /**\n   * In sync-supporting browsers, this adds a listener for the sync event.\n   * In non-sync-supporting browsers, or if _forceSyncFallback is true, this\n   * will retry the queue on service worker startup.\n   *\n   * @private\n   */\n  private _addSyncListener() {\n    // See https://github.com/GoogleChrome/workbox/issues/2393\n    if (\"sync\" in self.registration && !this._forceSyncFallback) {\n      self.addEventListener(\"sync\", (event: SyncEvent) => {\n        if (event.tag === `${TAG_PREFIX}:${this._name}`) {\n          if (process.env.NODE_ENV !== \"production\") {\n            logger.log(`Background sync for tag '${event.tag}' has been received`);\n          }\n\n          const syncComplete = async () => {\n            this._syncInProgress = true;\n\n            let syncError: Error | undefined;\n            try {\n              await this._onSync({ queue: this });\n            } catch (error) {\n              if (error instanceof Error) {\n                syncError = error;\n\n                // Rethrow the error. Note: the logic in the finally clause\n                // will run before this gets rethrown.\n                throw syncError;\n              }\n            } finally {\n              // New items may have been added to the queue during the sync,\n              // so we need to register for a new sync if that's happened...\n              // Unless there was an error during the sync, in which\n              // case the browser will automatically retry later, as long\n              // as `event.lastChance` is not true.\n              if (this._requestsAddedDuringSync && !(syncError && !event.lastChance)) {\n                await this.registerSync();\n              }\n\n              this._syncInProgress = false;\n              this._requestsAddedDuringSync = false;\n            }\n          };\n          event.waitUntil(syncComplete());\n        }\n      });\n    } else {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.log(\"Background sync replaying without background sync event\");\n      }\n      // If the browser doesn't support background sync, or the developer has\n      // opted-in to not using it, retry every time the service worker starts up\n      // as a fallback.\n      void this._onSync({ queue: this });\n    }\n  }\n\n  /**\n   * Returns the set of queue names. This is primarily used to reset the list\n   * of queue names in tests.\n   *\n   * @returns\n   * @private\n   */\n  static get _queueNames(): Set<string> {\n    return queueNames;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { FetchDidFailCallbackParam, SerwistPlugin } from \"../../types.js\";\nimport type { BackgroundSyncQueueOptions } from \"./BackgroundSyncQueue.js\";\nimport { BackgroundSyncQueue } from \"./BackgroundSyncQueue.js\";\n\n/**\n * A class implementing the `fetchDidFail` lifecycle callback. This makes it\n * easier to add failed requests to a {@linkcode BackgroundSyncQueue}.\n */\nexport class BackgroundSyncPlugin implements SerwistPlugin {\n  private readonly _queue: BackgroundSyncQueue;\n\n  /**\n   * @param name See the {@linkcode BackgroundSyncQueue}\n   * documentation for parameter details.\n   * @param options See the {@linkcode BackgroundSyncQueue}\n   * documentation for parameter details.\n   * @see https://serwist.pages.dev/docs/serwist/core/background-sync-queue\n   */\n  constructor(name: string, options?: BackgroundSyncQueueOptions) {\n    this._queue = new BackgroundSyncQueue(name, options);\n  }\n\n  /**\n   * @param options\n   * @private\n   */\n  async fetchDidFail({ request }: FetchDidFailCallbackParam) {\n    await this._queue.pushRequest({ request });\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { SerwistPlugin } from \"../../../types.js\";\n\nexport const cacheOkAndOpaquePlugin: SerwistPlugin = {\n  /**\n   * Returns a valid response (to allow caching) if the status is 200 (OK) or\n   * 0 (opaque).\n   *\n   * @param options\n   * @returns\n   * @private\n   */\n  cacheWillUpdate: async ({ response }) => {\n    if (response.status === 200 || response.status === 0) {\n      return response;\n    }\n    return null;\n  },\n};\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { Route } from \"../../Route.js\";\nimport type { HandlerCallbackOptions, MapLikeObject, SerwistPlugin, SerwistPluginCallbackParam } from \"../../types.js\";\nimport { assert } from \"../../utils/assert.js\";\nimport { cacheMatchIgnoreParams } from \"../../utils/cacheMatchIgnoreParams.js\";\nimport { Deferred } from \"../../utils/Deferred.js\";\nimport { executeQuotaErrorCallbacks } from \"../../utils/executeQuotaErrorCallbacks.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { timeout } from \"../../utils/timeout.js\";\nimport type { Strategy } from \"./Strategy.js\";\n\nfunction toRequest(input: RequestInfo) {\n  return typeof input === \"string\" ? new Request(input) : input;\n}\n\n/**\n * A class created every time a {@linkcode Strategy} instance calls {@linkcode Strategy.handle} or\n * {@linkcode Strategy.handleAll} that wraps all fetch and cache actions around plugin callbacks\n * and keeps track of when the strategy is \"done\" (i.e. when all added `event.waitUntil()` promises\n * have resolved).\n */\nexport class StrategyHandler {\n  /**\n   * The event associated with this request.\n   */\n  public event: ExtendableEvent;\n  /**\n   * The request the strategy is processing (passed to the strategy's\n   * `handle()` or `handleAll()` method).\n   */\n  public request: Request;\n  /**\n   * A `URL` instance of `request.url` (if passed to the strategy's\n   * `handle()` or `handleAll()` method).\n   * Note: the `url` param will be present if the strategy is invoked\n   * from a {@linkcode Route} object.\n   */\n  public url?: URL;\n  /**\n   * Some additional params (if passed to the strategy's\n   * `handle()` or `handleAll()` method).\n   *\n   * Note: the `params` param will be present if the strategy is invoked\n   * from a {@linkcode Route} object and that route's matcher returned a truthy\n   * value (it will be that value).\n   */\n  public params?: string[] | MapLikeObject;\n\n  private _cacheKeys: Record<string, Request> = {};\n  private readonly _strategy: Strategy;\n  private readonly _handlerDeferred: Deferred<any>;\n  private readonly _extendLifetimePromises: Promise<any>[];\n  private readonly _plugins: SerwistPlugin[];\n  private readonly _pluginStateMap: Map<SerwistPlugin, MapLikeObject>;\n\n  /**\n   * Creates a new instance associated with the passed strategy and event\n   * that's handling the request.\n   *\n   * The constructor also initializes the state that will be passed to each of\n   * the plugins handling this request.\n   *\n   * @param strategy\n   * @param options\n   */\n  constructor(\n    strategy: Strategy,\n    options: HandlerCallbackOptions & {\n      request: HandlerCallbackOptions[\"request\"] & Request;\n    },\n  ) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(options.event, ExtendableEvent, {\n        moduleName: \"serwist\",\n        className: \"StrategyHandler\",\n        funcName: \"constructor\",\n        paramName: \"options.event\",\n      });\n      assert!.isInstance(options.request, Request, {\n        moduleName: \"serwist\",\n        className: \"StrategyHandler\",\n        funcName: \"constructor\",\n        paramName: \"options.request\",\n      });\n    }\n\n    this.event = options.event;\n    this.request = options.request;\n    if (options.url) {\n      this.url = options.url;\n      this.params = options.params;\n    }\n    this._strategy = strategy;\n    this._handlerDeferred = new Deferred();\n    this._extendLifetimePromises = [];\n\n    // Copy the plugins list (since it's mutable on the strategy),\n    // so any mutations don't affect this handler instance.\n    this._plugins = [...strategy.plugins];\n    this._pluginStateMap = new Map();\n    for (const plugin of this._plugins) {\n      this._pluginStateMap.set(plugin, {});\n    }\n\n    this.event.waitUntil(this._handlerDeferred.promise);\n  }\n\n  /**\n   * Fetches a given request (and invokes any applicable plugin callback\n   * methods), taking the `fetchOptions` (for non-navigation requests) and\n   * `plugins` provided to the {@linkcode Strategy} object into account.\n   *\n   * The following plugin lifecycle methods are invoked when using this method:\n   * - `requestWillFetch()`\n   * - `fetchDidSucceed()`\n   * - `fetchDidFail()`\n   *\n   * @param input The URL or request to fetch.\n   * @returns\n   */\n  async fetch(input: RequestInfo): Promise<Response> {\n    const { event } = this;\n    let request: Request = toRequest(input);\n\n    const preloadResponse = await this.getPreloadResponse();\n\n    if (preloadResponse) {\n      return preloadResponse;\n    }\n\n    // If there is a fetchDidFail plugin, we need to save a clone of the\n    // original request before it's either modified by a requestWillFetch\n    // plugin or before the original request's body is consumed via fetch().\n    const originalRequest = this.hasCallback(\"fetchDidFail\") ? request.clone() : null;\n\n    try {\n      for (const cb of this.iterateCallbacks(\"requestWillFetch\")) {\n        request = await cb({ request: request.clone(), event });\n      }\n    } catch (err) {\n      if (err instanceof Error) {\n        throw new SerwistError(\"plugin-error-request-will-fetch\", {\n          thrownErrorMessage: err.message,\n        });\n      }\n    }\n\n    // The request can be altered by plugins with `requestWillFetch` making\n    // the original request (most likely from a `fetch` event) different\n    // from the Request we make. Pass both to `fetchDidFail` to aid debugging.\n    const pluginFilteredRequest: Request = request.clone();\n\n    try {\n      let fetchResponse: Response;\n\n      // See https://github.com/GoogleChrome/workbox/issues/1796\n      fetchResponse = await fetch(request, request.mode === \"navigate\" ? undefined : this._strategy.fetchOptions);\n\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(`Network request for '${getFriendlyURL(request.url)}' returned a response with status '${fetchResponse.status}'.`);\n      }\n\n      for (const callback of this.iterateCallbacks(\"fetchDidSucceed\")) {\n        fetchResponse = await callback({\n          event,\n          request: pluginFilteredRequest,\n          response: fetchResponse,\n        });\n      }\n      return fetchResponse;\n    } catch (error) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.log(`Network request for '${getFriendlyURL(request.url)}' threw an error.`, error);\n      }\n\n      // `originalRequest` will only exist if a `fetchDidFail` callback\n      // is being used (see above).\n      if (originalRequest) {\n        await this.runCallbacks(\"fetchDidFail\", {\n          error: error as Error,\n          event,\n          originalRequest: originalRequest.clone(),\n          request: pluginFilteredRequest.clone(),\n        });\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * Calls `this.fetch()` and (in the background) caches the generated response.\n   *\n   * The call to `this.cachePut()` automatically invokes `this.waitUntil()`,\n   * so you do not have to call `waitUntil()` yourself.\n   *\n   * @param input The request or URL to fetch and cache.\n   * @returns\n   */\n  async fetchAndCachePut(input: RequestInfo): Promise<Response> {\n    const response = await this.fetch(input);\n    const responseClone = response.clone();\n\n    void this.waitUntil(this.cachePut(input, responseClone));\n\n    return response;\n  }\n\n  /**\n   * Matches a request from the cache (and invokes any applicable plugin\n   * callback method) using the `cacheName`, `matchOptions`, and `plugins`\n   * provided to the `Strategy` object.\n   *\n   * The following lifecycle methods are invoked when using this method:\n   * - `cacheKeyWillBeUsed`\n   * - `cachedResponseWillBeUsed`\n   *\n   * @param key The `Request` or `URL` object to use as the cache key.\n   * @returns A matching response, if found.\n   */\n  async cacheMatch(key: RequestInfo): Promise<Response | undefined> {\n    const request: Request = toRequest(key);\n    let cachedResponse: Response | undefined;\n    const { cacheName, matchOptions } = this._strategy;\n\n    const effectiveRequest = await this.getCacheKey(request, \"read\");\n    const multiMatchOptions = { ...matchOptions, ...{ cacheName } };\n\n    cachedResponse = await caches.match(effectiveRequest, multiMatchOptions);\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (cachedResponse) {\n        logger.debug(`Found a cached response in '${cacheName}'.`);\n      } else {\n        logger.debug(`No cached response found in '${cacheName}'.`);\n      }\n    }\n\n    for (const callback of this.iterateCallbacks(\"cachedResponseWillBeUsed\")) {\n      cachedResponse =\n        (await callback({\n          cacheName,\n          matchOptions,\n          cachedResponse,\n          request: effectiveRequest,\n          event: this.event,\n        })) || undefined;\n    }\n    return cachedResponse;\n  }\n\n  /**\n   * Puts a request/response pair into the cache (and invokes any applicable\n   * plugin callback method) using the `cacheName` and `plugins` provided to\n   * the {@linkcode Strategy} object.\n   *\n   * The following plugin lifecycle methods are invoked when using this method:\n   * - `cacheKeyWillBeUsed`\n   * - `cacheWillUpdate`\n   * - `cacheDidUpdate`\n   *\n   * @param key The request or URL to use as the cache key.\n   * @param response The response to cache.\n   * @returns `false` if a `cacheWillUpdate` caused the response to\n   * not be cached, and `true` otherwise.\n   */\n  async cachePut(key: RequestInfo, response: Response): Promise<boolean> {\n    const request: Request = toRequest(key);\n\n    // Run in the next task to avoid blocking other cache reads.\n    // https://github.com/w3c/ServiceWorker/issues/1397\n    await timeout(0);\n\n    const effectiveRequest = await this.getCacheKey(request, \"write\");\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (effectiveRequest.method && effectiveRequest.method !== \"GET\") {\n        throw new SerwistError(\"attempt-to-cache-non-get-request\", {\n          url: getFriendlyURL(effectiveRequest.url),\n          method: effectiveRequest.method,\n        });\n      }\n    }\n\n    if (!response) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.error(`Cannot cache non-existent response for '${getFriendlyURL(effectiveRequest.url)}'.`);\n      }\n\n      throw new SerwistError(\"cache-put-with-no-response\", {\n        url: getFriendlyURL(effectiveRequest.url),\n      });\n    }\n\n    const responseToCache = await this._ensureResponseSafeToCache(response);\n\n    if (!responseToCache) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(`Response '${getFriendlyURL(effectiveRequest.url)}' will not be cached.`, responseToCache);\n      }\n      return false;\n    }\n\n    const { cacheName, matchOptions } = this._strategy;\n    const cache = await self.caches.open(cacheName);\n\n    if (process.env.NODE_ENV !== \"production\") {\n      // See https://github.com/GoogleChrome/workbox/issues/2818\n      const vary = response.headers.get(\"Vary\");\n      if (vary && matchOptions?.ignoreVary !== true) {\n        logger.debug(\n          `The response for ${getFriendlyURL(\n            effectiveRequest.url,\n          )} has a 'Vary: ${vary}' header. Consider setting the {ignoreVary: true} option on your strategy to ensure cache matching and deletion works as expected.`,\n        );\n      }\n    }\n\n    const hasCacheUpdateCallback = this.hasCallback(\"cacheDidUpdate\");\n    const oldResponse = hasCacheUpdateCallback\n      ? await cacheMatchIgnoreParams(\n          // TODO(philipwalton): the `__WB_REVISION__` param is a precaching\n          // feature. Consider into ways to only add this behavior if using\n          // precaching.\n          cache,\n          effectiveRequest.clone(),\n          [\"__WB_REVISION__\"],\n          matchOptions,\n        )\n      : null;\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.debug(`Updating the '${cacheName}' cache with a new Response for ${getFriendlyURL(effectiveRequest.url)}.`);\n    }\n\n    try {\n      await cache.put(effectiveRequest, hasCacheUpdateCallback ? responseToCache.clone() : responseToCache);\n    } catch (error) {\n      if (error instanceof Error) {\n        // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError\n        if (error.name === \"QuotaExceededError\") {\n          await executeQuotaErrorCallbacks();\n        }\n        throw error;\n      }\n    }\n\n    for (const callback of this.iterateCallbacks(\"cacheDidUpdate\")) {\n      await callback({\n        cacheName,\n        oldResponse,\n        newResponse: responseToCache.clone(),\n        request: effectiveRequest,\n        event: this.event,\n      });\n    }\n\n    return true;\n  }\n\n  /**\n   * Checks the `plugins` provided to the {@linkcode Strategy} object for `cacheKeyWillBeUsed`\n   * callbacks and executes found callbacks in sequence. The final `Request`\n   * object returned by the last plugin is treated as the cache key for cache\n   * reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have\n   * been registered, the passed request is returned unmodified.\n   *\n   * @param request\n   * @param mode\n   * @returns\n   */\n  async getCacheKey(request: Request, mode: \"read\" | \"write\"): Promise<Request> {\n    const key = `${request.url} | ${mode}`;\n    if (!this._cacheKeys[key]) {\n      let effectiveRequest = request;\n\n      for (const callback of this.iterateCallbacks(\"cacheKeyWillBeUsed\")) {\n        effectiveRequest = toRequest(\n          await callback({\n            mode,\n            request: effectiveRequest,\n            event: this.event,\n            params: this.params,\n          }),\n        );\n      }\n\n      this._cacheKeys[key] = effectiveRequest;\n    }\n    return this._cacheKeys[key];\n  }\n\n  /**\n   * Returns `true` if the strategy has at least one plugin with the given\n   * callback.\n   *\n   * @param name The name of the callback to check for.\n   * @returns\n   */\n  hasCallback<C extends keyof SerwistPlugin>(name: C): boolean {\n    for (const plugin of this._strategy.plugins) {\n      if (name in plugin) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Runs all plugin callbacks matching the given name, in order, passing the\n   * given param object as the only argument.\n   *\n   * Note: since this method runs all plugins, it's not suitable for cases\n   * where the return value of a callback needs to be applied prior to calling\n   * the next callback. See {@linkcode StrategyHandler.iterateCallbacks} for how to handle that case.\n   *\n   * @param name The name of the callback to run within each plugin.\n   * @param param The object to pass as the first (and only) param when executing each callback. This object will be merged with the\n   * current plugin state prior to callback execution.\n   */\n  async runCallbacks<C extends keyof NonNullable<SerwistPlugin>>(name: C, param: Omit<SerwistPluginCallbackParam[C], \"state\">): Promise<void> {\n    for (const callback of this.iterateCallbacks(name)) {\n      // TODO(philipwalton): not sure why `any` is needed. It seems like\n      // this should work with `as SerwistPluginCallbackParam[C]`.\n      await callback(param as any);\n    }\n  }\n\n  /**\n   * Accepts a callback name and returns an iterable of matching plugin callbacks.\n   *\n   * @param name The name fo the callback to run\n   * @returns\n   */\n  *iterateCallbacks<C extends keyof SerwistPlugin>(name: C): Generator<NonNullable<SerwistPlugin[C]>> {\n    for (const plugin of this._strategy.plugins) {\n      if (typeof plugin[name] === \"function\") {\n        const state = this._pluginStateMap.get(plugin);\n        const statefulCallback = (param: Omit<SerwistPluginCallbackParam[C], \"state\">) => {\n          const statefulParam = { ...param, state };\n\n          // TODO(philipwalton): not sure why `any` is needed. It seems like\n          // this should work with `as WorkboxPluginCallbackParam[C]`.\n          return plugin[name]!(statefulParam as any);\n        };\n        yield statefulCallback as NonNullable<SerwistPlugin[C]>;\n      }\n    }\n  }\n\n  /**\n   * Adds a promise to the\n   * [extend lifetime promises](https://w3c.github.io/ServiceWorker/#extendableevent-extend-lifetime-promises)\n   * of the event event associated with the request being handled (usually a `FetchEvent`).\n   *\n   * Note: you can await {@linkcode StrategyHandler.doneWaiting} to know when all added promises have settled.\n   *\n   * @param promise A promise to add to the extend lifetime promises of\n   * the event that triggered the request.\n   */\n  waitUntil<T>(promise: Promise<T>): Promise<T> {\n    this._extendLifetimePromises.push(promise);\n    return promise;\n  }\n\n  /**\n   * Returns a promise that resolves once all promises passed to\n   * `this.waitUntil()` have settled.\n   *\n   * Note: any work done after `doneWaiting()` settles should be manually\n   * passed to an event's `waitUntil()` method (not `this.waitUntil()`), otherwise\n   * the service worker thread may be killed prior to your work completing.\n   */\n  async doneWaiting(): Promise<void> {\n    let promise: Promise<any> | undefined;\n    while ((promise = this._extendLifetimePromises.shift())) {\n      await promise;\n    }\n  }\n\n  /**\n   * Stops running the strategy and immediately resolves any pending\n   * `waitUntil()` promise.\n   */\n  destroy(): void {\n    this._handlerDeferred.resolve(null);\n  }\n\n  /**\n   * This method checks if the navigation preload `Response` is available.\n   *\n   * @param request\n   * @param event\n   * @returns\n   */\n  async getPreloadResponse(): Promise<Response | undefined> {\n    if (this.event instanceof FetchEvent && this.event.request.mode === \"navigate\" && \"preloadResponse\" in this.event) {\n      try {\n        const possiblePreloadResponse = (await this.event.preloadResponse) as Response | undefined;\n        if (possiblePreloadResponse) {\n          if (process.env.NODE_ENV !== \"production\") {\n            logger.log(`Using a preloaded navigation response for '${getFriendlyURL(this.event.request.url)}'`);\n          }\n          return possiblePreloadResponse;\n        }\n      } catch (error) {\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.error(error);\n        }\n        return undefined;\n      }\n    }\n    return undefined;\n  }\n\n  /**\n   * This method will call `cacheWillUpdate` on the available plugins (or use\n   * status === 200) to determine if the response is safe and valid to cache.\n   *\n   * @param response\n   * @returns\n   * @private\n   */\n  async _ensureResponseSafeToCache(response: Response): Promise<Response | undefined> {\n    let responseToCache: Response | undefined = response;\n    let pluginsUsed = false;\n\n    for (const callback of this.iterateCallbacks(\"cacheWillUpdate\")) {\n      responseToCache =\n        (await callback({\n          request: this.request,\n          response: responseToCache,\n          event: this.event,\n        })) || undefined;\n      pluginsUsed = true;\n\n      if (!responseToCache) {\n        break;\n      }\n    }\n\n    if (!pluginsUsed) {\n      if (responseToCache && responseToCache.status !== 200) {\n        if (process.env.NODE_ENV !== \"production\") {\n          if (responseToCache.status === 0) {\n            logger.warn(\n              `The response for '${this.request.url}' is an opaque response. The caching strategy that you're using will not cache opaque responses by default.`,\n            );\n          } else {\n            logger.debug(`The response for '${this.request.url}' returned a status code of '${response.status}' and won't be cached as a result.`);\n          }\n        }\n        responseToCache = undefined;\n      }\n    }\n\n    return responseToCache;\n  }\n}\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { HandlerCallbackOptions, RouteHandlerObject, SerwistPlugin } from \"../../types.js\";\nimport { cacheNames as privateCacheNames } from \"../../utils/cacheNames.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { StrategyHandler } from \"./StrategyHandler.js\";\n\nexport interface StrategyOptions {\n  /**\n   * Cache name to store and retrieve requests. Defaults to Serwist's default cache names.\n   */\n  cacheName?: string;\n  /**\n   * [Plugins](https://serwist.pages.dev/docs/serwist/runtime-caching/plugins) to use in conjunction with this caching strategy.\n   */\n  plugins?: SerwistPlugin[];\n  /**\n   * Options passed to [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) `fetch()` calls made by\n   * this strategy.\n   */\n  fetchOptions?: RequestInit;\n  /**\n   * The [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions)\n   * passed to any `cache.match()` or `cache.put()` call made by this strategy.\n   */\n  matchOptions?: CacheQueryOptions;\n}\n\n/**\n * Abstract class for implementing runtime caching strategies.\n *\n * Custom strategies should extend this class and leverage `StrategyHandler`, which will ensure all relevant cache options,\n * fetch options, and plugins are used (per the current strategy instance), to perform all fetching and caching logic.\n */\nexport abstract class Strategy implements RouteHandlerObject {\n  cacheName: string;\n  plugins: SerwistPlugin[];\n  fetchOptions?: RequestInit;\n  matchOptions?: CacheQueryOptions;\n\n  protected abstract _handle(request: Request, handler: StrategyHandler): Promise<Response | undefined>;\n\n  /**\n   * Creates a new instance of the strategy and sets all documented option\n   * properties as public instance properties.\n   *\n   * Note: if a custom strategy class extends the base Strategy class and does\n   * not need more than these properties, it does not need to define its own\n   * constructor.\n   *\n   * @param options\n   */\n  constructor(options: StrategyOptions = {}) {\n    this.cacheName = privateCacheNames.getRuntimeName(options.cacheName);\n    this.plugins = options.plugins || [];\n    this.fetchOptions = options.fetchOptions;\n    this.matchOptions = options.matchOptions;\n  }\n\n  /**\n   * Performs a request strategy and returns a promise that will resolve to\n   * a response, invoking all relevant plugin callbacks.\n   *\n   * When a strategy instance is registered with a route, this method is automatically\n   * called when the route matches.\n   *\n   * Alternatively, this method can be used in a standalone `fetch` event\n   * listener by passing it to `event.respondWith()`.\n   *\n   * @param options A `FetchEvent` or an object with the properties listed below.\n   * @param options.request A request to run this strategy for.\n   * @param options.event The event associated with the request.\n   * @param options.url\n   * @param options.params\n   */\n  handle(options: FetchEvent | HandlerCallbackOptions): Promise<Response> {\n    const [responseDone] = this.handleAll(options);\n    return responseDone;\n  }\n\n  /**\n   * Similar to `handle()`, but instead of just returning a promise that\n   * resolves to a response, it will return an tuple of `[response, done]` promises,\n   * where `response` is equivalent to what `handle()` returns, and `done` is a\n   * promise that will resolve once all promises added to `event.waitUntil()` as a part\n   * of performing the strategy have completed.\n   *\n   * You can await the `done` promise to ensure any extra work performed by\n   * the strategy (usually caching responses) completes successfully.\n   *\n   * @param options A `FetchEvent` or `HandlerCallbackOptions` object.\n   * @returns A tuple of [response, done] promises that can be used to determine when the response resolves as\n   * well as when the handler has completed all its work.\n   */\n  handleAll(options: FetchEvent | HandlerCallbackOptions): [Promise<Response>, Promise<void>] {\n    // Allow for flexible options to be passed.\n    if (options instanceof FetchEvent) {\n      options = {\n        event: options,\n        request: options.request,\n      };\n    }\n\n    const event = options.event;\n    const request = typeof options.request === \"string\" ? new Request(options.request) : options.request;\n\n    const handler = new StrategyHandler(this, options.url ? { event, request, url: options.url, params: options.params } : { event, request });\n\n    const responseDone = this._getResponse(handler, request, event);\n    const handlerDone = this._awaitComplete(responseDone, handler, request, event);\n\n    // Return an array of promises, suitable for use with Promise.all().\n    return [responseDone, handlerDone];\n  }\n\n  async _getResponse(handler: StrategyHandler, request: Request, event: ExtendableEvent): Promise<Response> {\n    await handler.runCallbacks(\"handlerWillStart\", { event, request });\n\n    let response: Response | undefined;\n    try {\n      response = await this._handle(request, handler);\n      // The \"official\" Strategy subclasses all throw this error automatically,\n      // but in case a third-party Strategy doesn't, ensure that we have a\n      // consistent failure when there's no response or an error response.\n      if (response === undefined || response.type === \"error\") {\n        throw new SerwistError(\"no-response\", { url: request.url });\n      }\n    } catch (error) {\n      if (error instanceof Error) {\n        for (const callback of handler.iterateCallbacks(\"handlerDidError\")) {\n          response = await callback({ error, event, request });\n          if (response !== undefined) {\n            break;\n          }\n        }\n      }\n\n      if (!response) {\n        throw error;\n      }\n      if (process.env.NODE_ENV !== \"production\") {\n        throw logger.log(\n          `While responding to '${getFriendlyURL(request.url)}', an ${\n            error instanceof Error ? error.toString() : \"\"\n          } error occurred. Using a fallback response provided by a handlerDidError plugin.`,\n        );\n      }\n    }\n\n    for (const callback of handler.iterateCallbacks(\"handlerWillRespond\")) {\n      response = (await callback({ event, request, response })) as Response;\n    }\n\n    return response;\n  }\n\n  async _awaitComplete(responseDone: Promise<Response>, handler: StrategyHandler, request: Request, event: ExtendableEvent): Promise<void> {\n    let response: Response | undefined;\n    let error: Error | undefined;\n\n    try {\n      response = await responseDone;\n    } catch {\n      // Ignore errors, as response errors should be caught via the `response`\n      // promise above. The `done` promise will only throw for errors in\n      // promises passed to `handler.waitUntil()`.\n    }\n\n    try {\n      await handler.runCallbacks(\"handlerDidRespond\", {\n        event,\n        request,\n        response,\n      });\n      await handler.doneWaiting();\n    } catch (waitUntilError) {\n      if (waitUntilError instanceof Error) {\n        error = waitUntilError;\n      }\n    }\n\n    await handler.runCallbacks(\"handlerDidComplete\", {\n      event,\n      request,\n      response,\n      error,\n    });\n    handler.destroy();\n\n    if (error) {\n      throw error;\n    }\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { getFriendlyURL } from \"../../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../../utils/logger.js\";\n\nexport const messages = {\n  strategyStart: (strategyName: string, request: Request): string => `Using ${strategyName} to respond to '${getFriendlyURL(request.url)}'`,\n  printFinalResponse: (response?: Response): void => {\n    if (response) {\n      logger.groupCollapsed(\"View the final response here.\");\n      logger.log(response || \"[No response returned]\");\n      logger.groupEnd();\n    }\n  },\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { cacheOkAndOpaquePlugin } from \"./plugins/cacheOkAndOpaquePlugin.js\";\nimport type { StrategyOptions } from \"./Strategy.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\nexport interface NetworkFirstOptions extends StrategyOptions {\n  /**\n   * If set, any network requests that fail to respond within the timeout will fallback to the cache.\n   */\n  networkTimeoutSeconds?: number;\n}\n\n/**\n * An implementation of the [network first](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#network_first_falling_back_to_cache)\n * request strategy.\n *\n * By default, this strategy will cache responses with a 200 status code as\n * well as [opaque responses](https://developer.chrome.com/docs/workbox/caching-resources-during-runtime/#opaque_responses).\n * Opaque responses are are cross-origin requests where the response doesn't\n * support [CORS](https://enable-cors.org/).\n *\n * If the network request fails, and there is no cache match, this will throw\n * a {@linkcode SerwistError} exception.\n */\nexport class NetworkFirst extends Strategy {\n  private readonly _networkTimeoutSeconds: number;\n  /**\n   * @param options\n   * This option can be used to combat\n   * \"[lie-fi](https://developers.google.com/web/fundamentals/performance/poor-connectivity/#lie-fi)\"\n   * scenarios.\n   */\n  constructor(options: NetworkFirstOptions = {}) {\n    super(options);\n\n    // If this instance contains no plugins with a 'cacheWillUpdate' callback,\n    // prepend the `cacheOkAndOpaquePlugin` plugin to the plugins list.\n    if (!this.plugins.some((p) => \"cacheWillUpdate\" in p)) {\n      this.plugins.unshift(cacheOkAndOpaquePlugin);\n    }\n\n    this._networkTimeoutSeconds = options.networkTimeoutSeconds || 0;\n    if (process.env.NODE_ENV !== \"production\") {\n      if (this._networkTimeoutSeconds) {\n        assert!.isType(this._networkTimeoutSeconds, \"number\", {\n          moduleName: \"serwist\",\n          className: this.constructor.name,\n          funcName: \"constructor\",\n          paramName: \"networkTimeoutSeconds\",\n        });\n      }\n    }\n  }\n\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    const logs: any[] = [];\n\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"handle\",\n        paramName: \"makeRequest\",\n      });\n    }\n\n    const promises: Promise<Response | undefined>[] = [];\n    let timeoutId: number | undefined;\n\n    if (this._networkTimeoutSeconds) {\n      const { id, promise } = this._getTimeoutPromise({\n        request,\n        logs,\n        handler,\n      });\n      timeoutId = id;\n      promises.push(promise);\n    }\n\n    const networkPromise = this._getNetworkPromise({\n      timeoutId,\n      request,\n      logs,\n      handler,\n    });\n\n    promises.push(networkPromise);\n\n    const response = await handler.waitUntil(\n      (async () => {\n        // Promise.race() will resolve as soon as the first promise resolves.\n        return (\n          (await handler.waitUntil(Promise.race(promises))) ||\n          // If Promise.race() resolved with null, it might be due to a network\n          // timeout + a cache miss. If that were to happen, we'd rather wait until\n          // the networkPromise resolves instead of returning null.\n          // Note that it's fine to await an already-resolved promise, so we don't\n          // have to check to see if it's still \"in flight\".\n          (await networkPromise)\n        );\n      })(),\n    );\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      for (const log of logs) {\n        logger.log(log);\n      }\n      messages.printFinalResponse(response);\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url });\n    }\n    return response;\n  }\n\n  /**\n   * @param options\n   * @returns\n   * @private\n   */\n  private _getTimeoutPromise({\n    request,\n    logs,\n    handler,\n  }: {\n    request: Request;\n    /**\n     * A reference to the logs array.\n     */\n    logs: any[];\n    handler: StrategyHandler;\n  }): { promise: Promise<Response | undefined>; id?: number } {\n    // biome-ignore lint/suspicious/noImplicitAnyLet: setTimeout is typed with Node.js's typings, so we can't use number | undefined here.\n    let timeoutId;\n    const timeoutPromise: Promise<Response | undefined> = new Promise((resolve) => {\n      const onNetworkTimeout = async () => {\n        if (process.env.NODE_ENV !== \"production\") {\n          logs.push(`Timing out the network response at ${this._networkTimeoutSeconds} seconds.`);\n        }\n        resolve(await handler.cacheMatch(request));\n      };\n      timeoutId = setTimeout(onNetworkTimeout, this._networkTimeoutSeconds * 1000);\n    });\n\n    return {\n      promise: timeoutPromise,\n      id: timeoutId,\n    };\n  }\n\n  /**\n   * @param options\n   * @param options.timeoutId\n   * @param options.request\n   * @param options.logs A reference to the logs Array.\n   * @param options.event\n   * @returns\n   *\n   * @private\n   */\n  async _getNetworkPromise({\n    timeoutId,\n    request,\n    logs,\n    handler,\n  }: {\n    request: Request;\n    logs: any[];\n    timeoutId?: number;\n    handler: StrategyHandler;\n  }): Promise<Response | undefined> {\n    let error: Error | undefined;\n    let response: Response | undefined;\n    try {\n      response = await handler.fetchAndCachePut(request);\n    } catch (fetchError) {\n      if (fetchError instanceof Error) {\n        error = fetchError;\n      }\n    }\n\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (response) {\n        logs.push(\"Got response from network.\");\n      } else {\n        logs.push(\"Unable to get a response from the network. Will respond \" + \"with a cached response.\");\n      }\n    }\n\n    if (error || !response) {\n      response = await handler.cacheMatch(request);\n\n      if (process.env.NODE_ENV !== \"production\") {\n        if (response) {\n          logs.push(`Found a cached response in the '${this.cacheName}' cache.`);\n        } else {\n          logs.push(`No response found in the '${this.cacheName}' cache.`);\n        }\n      }\n    }\n\n    return response;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { timeout } from \"../../utils/timeout.js\";\nimport type { StrategyOptions } from \"./Strategy.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\nexport interface NetworkOnlyOptions extends Omit<StrategyOptions, \"cacheName\" | \"matchOptions\"> {\n  /**\n   * If set, any network requests that fail to respond within the timeout will result in a network error.\n   */\n  networkTimeoutSeconds?: number;\n}\n\n/**\n * An implementation of the [network only](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#network_only)\n * request strategy.\n *\n * This class is useful if you require specific requests to only be fulfilled from the network.\n *\n * If the network request fails, this will throw a {@linkcode SerwistError} exception.\n */\nexport class NetworkOnly extends Strategy {\n  private readonly _networkTimeoutSeconds: number;\n\n  /**\n   * @param options\n   */\n  constructor(options: NetworkOnlyOptions = {}) {\n    super(options);\n\n    this._networkTimeoutSeconds = options.networkTimeoutSeconds || 0;\n  }\n\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"_handle\",\n        paramName: \"request\",\n      });\n    }\n\n    let error: Error | undefined;\n    let response: Response | undefined;\n\n    try {\n      const promises: Promise<Response | undefined>[] = [handler.fetch(request)];\n\n      if (this._networkTimeoutSeconds) {\n        const timeoutPromise = timeout(this._networkTimeoutSeconds * 1000) as Promise<undefined>;\n        promises.push(timeoutPromise);\n      }\n\n      response = await Promise.race(promises);\n      if (!response) {\n        throw new Error(`Timed out the network response after ${this._networkTimeoutSeconds} seconds.`);\n      }\n    } catch (err) {\n      if (err instanceof Error) {\n        error = err;\n      }\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      if (response) {\n        logger.log(\"Got response from network.\");\n      } else {\n        logger.log(\"Unable to get a response from the network.\");\n      }\n      messages.printFinalResponse(response);\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url, error });\n    }\n    return response;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nexport type HTTPMethod = \"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\" | \"OPTIONS\";\n\n/**\n * The default HTTP method, 'GET', used when there's no specific method\n * configured for a route.\n *\n * @private\n */\nexport const defaultMethod = \"GET\" satisfies HTTPMethod;\n\n/**\n * The list of valid HTTP methods associated with requests that could be routed.\n *\n * @private\n */\nexport const validMethods = [\"DELETE\", \"GET\", \"HEAD\", \"PATCH\", \"POST\", \"PUT\"] satisfies HTTPMethod[];\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { RouteHandler, RouteHandlerObject } from \"../types.js\";\nimport { assert } from \"./assert.js\";\n\n/**\n * @param handler Either a function, or an object with a\n * 'handle' method.\n * @returns An object with a handle method.\n *\n * @private\n */\nexport const normalizeHandler = (handler: RouteHandler): RouteHandlerObject => {\n  if (handler && typeof handler === \"object\") {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.hasMethod(handler, \"handle\", {\n        moduleName: \"serwist\",\n        className: \"Route\",\n        funcName: \"constructor\",\n        paramName: \"handler\",\n      });\n    }\n    return handler;\n  }\n  if (process.env.NODE_ENV !== \"production\") {\n    assert!.isType(handler, \"function\", {\n      moduleName: \"serwist\",\n      className: \"Route\",\n      funcName: \"constructor\",\n      paramName: \"handler\",\n    });\n  }\n  return { handle: handler };\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { HTTPMethod } from \"./constants.js\";\nimport { defaultMethod, validMethods } from \"./constants.js\";\nimport type { RouteHandler, RouteHandlerObject, RouteMatchCallback } from \"./types.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { normalizeHandler } from \"./utils/normalizeHandler.js\";\n\n/**\n * A `Route` consists of a pair of callback functions, `match` and `handler`.\n * The `match` callback determines if a route should be used to handle a\n * request by returning a truthy value if it can. The `handler` callback\n * is called when the route matches and should return a promise that resolves\n * to a response.\n */\nexport class Route {\n  handler: RouteHandlerObject;\n  match: RouteMatchCallback;\n  method: HTTPMethod;\n  catchHandler?: RouteHandlerObject;\n\n  /**\n   * Constructor for Route class.\n   *\n   * @param match A callback function that determines whether the\n   * route matches a given `fetch` event by returning a truthy value.\n   * @param handler A callback function that returns a `Promise` resolving\n   * to a `Response`.\n   * @param method The HTTP method to match the route against. Defaults\n   * to `GET`.\n   */\n  constructor(match: RouteMatchCallback, handler: RouteHandler, method: HTTPMethod = defaultMethod) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(match, \"function\", {\n        moduleName: \"serwist\",\n        className: \"Route\",\n        funcName: \"constructor\",\n        paramName: \"match\",\n      });\n\n      if (method) {\n        assert!.isOneOf(method, validMethods, { paramName: \"method\" });\n      }\n    }\n\n    // These values are referenced directly by Router so cannot be\n    // altered by minificaton.\n    this.handler = normalizeHandler(handler);\n    this.match = match;\n    this.method = method;\n  }\n\n  /**\n   *\n   * @param handler A callback function that returns a Promise resolving\n   * to a Response.\n   */\n  setCatchHandler(handler: RouteHandler): void {\n    this.catchHandler = normalizeHandler(handler);\n  }\n}\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { copyResponse } from \"../../copyResponse.js\";\nimport type { Serwist } from \"../../Serwist.js\";\nimport type { SerwistPlugin } from \"../../types.js\";\nimport { cacheNames as privateCacheNames } from \"../../utils/cacheNames.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport type { StrategyOptions } from \"./Strategy.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\n\nexport interface PrecacheStrategyOptions extends StrategyOptions {\n  /**\n   * Plugins to use when precaching as well as responding to `fetch` events for precached assets.\n   */\n  plugins?: StrategyOptions[\"plugins\"];\n  /**\n   * Whether to attempt to get the response from the network\n   * if there's a precache miss.\n   */\n  fallbackToNetwork?: boolean;\n}\n\n/**\n * A {@linkcode Strategy} implementation specifically designed to both cache\n * and fetch precached assets.\n *\n * Note: an instance of this class is created automatically when creating a\n * {@linkcode Serwist} instance; it's generally not necessary to create this yourself.\n */\nexport class PrecacheStrategy extends Strategy {\n  private readonly _fallbackToNetwork: boolean;\n\n  static readonly defaultPrecacheCacheabilityPlugin: SerwistPlugin = {\n    async cacheWillUpdate({ response }) {\n      if (!response || response.status >= 400) {\n        return null;\n      }\n\n      return response;\n    },\n  };\n\n  static readonly copyRedirectedCacheableResponsesPlugin: SerwistPlugin = {\n    async cacheWillUpdate({ response }) {\n      return response.redirected ? await copyResponse(response) : response;\n    },\n  };\n\n  /**\n   * @param options\n   */\n  constructor(options: PrecacheStrategyOptions = {}) {\n    options.cacheName = privateCacheNames.getPrecacheName(options.cacheName);\n\n    super(options);\n\n    this._fallbackToNetwork = options.fallbackToNetwork !== false;\n\n    // Redirected responses cannot be used to satisfy a navigation request, so\n    // any redirected response must be \"copied\" rather than cloned, so the new\n    // response doesn't contain the `redirected` flag. See:\n    // https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1\n    this.plugins.push(PrecacheStrategy.copyRedirectedCacheableResponsesPlugin);\n  }\n\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    const preloadResponse = await handler.getPreloadResponse();\n\n    if (preloadResponse) {\n      return preloadResponse;\n    }\n\n    const response = await handler.cacheMatch(request);\n\n    if (response) {\n      return response;\n    }\n\n    // If this is an `install` event for an entry that isn't already cached,\n    // then populate the cache.\n    if (handler.event && handler.event.type === \"install\") {\n      return await this._handleInstall(request, handler);\n    }\n\n    // Getting here means something went wrong. An entry that should have been\n    // precached wasn't found in the cache.\n    return await this._handleFetch(request, handler);\n  }\n\n  async _handleFetch(request: Request, handler: StrategyHandler): Promise<Response> {\n    let response: Response | undefined;\n\n    const params = (handler.params || {}) as {\n      cacheKey?: string;\n      integrity?: string;\n    };\n\n    // Fallback to the network if we're configured to do so.\n    if (this._fallbackToNetwork) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.warn(`The precached response for ${getFriendlyURL(request.url)} in ${this.cacheName} was not found. Falling back to the network.`);\n      }\n\n      const integrityInManifest = params.integrity;\n      const integrityInRequest = request.integrity;\n      const noIntegrityConflict = !integrityInRequest || integrityInRequest === integrityInManifest;\n\n      // Do not add integrity if the original request is no-cors\n      // See https://github.com/GoogleChrome/workbox/issues/3096\n      response = await handler.fetch(\n        new Request(request, {\n          integrity: request.mode !== \"no-cors\" ? integrityInRequest || integrityInManifest : undefined,\n        }),\n      );\n\n      // It's only \"safe\" to repair the cache if we're using SRI to guarantee\n      // that the response matches the precache manifest's expectations,\n      // and there's either a) no integrity property in the incoming request\n      // or b) there is an integrity, and it matches the precache manifest.\n      // See https://github.com/GoogleChrome/workbox/issues/2858\n      // Also if the original request users no-cors we don't use integrity.\n      // See https://github.com/GoogleChrome/workbox/issues/3096\n      if (integrityInManifest && noIntegrityConflict && request.mode !== \"no-cors\") {\n        this._useDefaultCacheabilityPluginIfNeeded();\n        const wasCached = await handler.cachePut(request, response.clone());\n        if (process.env.NODE_ENV !== \"production\") {\n          if (wasCached) {\n            logger.log(`A response for ${getFriendlyURL(request.url)} was used to \"repair\" the precache.`);\n          }\n        }\n      }\n    } else {\n      // This shouldn't normally happen, but there are edge cases:\n      // https://github.com/GoogleChrome/workbox/issues/1441\n      throw new SerwistError(\"missing-precache-entry\", {\n        cacheName: this.cacheName,\n        url: request.url,\n      });\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      const cacheKey = params.cacheKey || (await handler.getCacheKey(request, \"read\"));\n\n      // Serwist is going to handle the route.\n      // print the routing details to the console.\n      logger.groupCollapsed(`Precaching is responding to: ${getFriendlyURL(request.url)}`);\n      logger.log(`Serving the precached url: ${getFriendlyURL(cacheKey instanceof Request ? cacheKey.url : cacheKey)}`);\n\n      logger.groupCollapsed(\"View request details here.\");\n      logger.log(request);\n      logger.groupEnd();\n\n      logger.groupCollapsed(\"View response details here.\");\n      logger.log(response);\n      logger.groupEnd();\n\n      logger.groupEnd();\n    }\n\n    return response;\n  }\n\n  async _handleInstall(request: Request, handler: StrategyHandler): Promise<Response> {\n    this._useDefaultCacheabilityPluginIfNeeded();\n\n    const response = await handler.fetch(request);\n\n    // Make sure we defer cachePut() until after we know the response\n    // should be cached; see https://github.com/GoogleChrome/workbox/issues/2737\n    const wasCached = await handler.cachePut(request, response.clone());\n\n    if (!wasCached) {\n      // Throwing here will lead to the `install` handler failing, which\n      // we want to do if *any* of the responses aren't safe to cache.\n      throw new SerwistError(\"bad-precaching-response\", {\n        url: request.url,\n        status: response.status,\n      });\n    }\n\n    return response;\n  }\n\n  /**\n   * This method is complex, as there a number of things to account for:\n   *\n   * The `plugins` array can be set at construction, and/or it might be added to\n   * to at any time before the strategy is used.\n   *\n   * At the time the strategy is used (i.e. during an `install` event), there\n   * needs to be at least one plugin that implements `cacheWillUpdate` in the\n   * array, other than `copyRedirectedCacheableResponsesPlugin`.\n   *\n   * - If this method is called and there are no suitable `cacheWillUpdate`\n   * plugins, we need to add `defaultPrecacheCacheabilityPlugin`.\n   *\n   * - If this method is called and there is exactly one `cacheWillUpdate`, then\n   * we don't have to do anything (this might be a previously added\n   * `defaultPrecacheCacheabilityPlugin`, or it might be a custom plugin).\n   *\n   * - If this method is called and there is more than one `cacheWillUpdate`,\n   * then we need to check if one is `defaultPrecacheCacheabilityPlugin`. If so,\n   * we need to remove it. (This situation is unlikely, but it could happen if\n   * the strategy is used multiple times, the first without a `cacheWillUpdate`,\n   * and then later on after manually adding a custom `cacheWillUpdate`.)\n   *\n   * See https://github.com/GoogleChrome/workbox/issues/2737 for more context.\n   *\n   * @private\n   */\n  _useDefaultCacheabilityPluginIfNeeded(): void {\n    let defaultPluginIndex: number | null = null;\n    let cacheWillUpdatePluginCount = 0;\n\n    for (const [index, plugin] of this.plugins.entries()) {\n      // Ignore the copy redirected plugin when determining what to do.\n      if (plugin === PrecacheStrategy.copyRedirectedCacheableResponsesPlugin) {\n        continue;\n      }\n\n      // Save the default plugin's index, in case it needs to be removed.\n      if (plugin === PrecacheStrategy.defaultPrecacheCacheabilityPlugin) {\n        defaultPluginIndex = index;\n      }\n\n      if (plugin.cacheWillUpdate) {\n        cacheWillUpdatePluginCount++;\n      }\n    }\n\n    if (cacheWillUpdatePluginCount === 0) {\n      this.plugins.push(PrecacheStrategy.defaultPrecacheCacheabilityPlugin);\n    } else if (cacheWillUpdatePluginCount > 1 && defaultPluginIndex !== null) {\n      // Only remove the default plugin; multiple custom plugins are allowed.\n      this.plugins.splice(defaultPluginIndex, 1);\n    }\n    // Nothing needs to be done if cacheWillUpdatePluginCount is 1\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { Route } from \"./Route.js\";\nimport type { RouteHandler, RouteMatchCallbackOptions } from \"./types.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { logger } from \"./utils/logger.js\";\n\nexport interface NavigationRouteMatchOptions {\n  /**\n   * If any of these patterns\n   * match the URL's pathname and search parameter, the route will handle the\n   * request (assuming the denylist doesn't match).\n   *\n   * @default [/./]\n   */\n  allowlist?: RegExp[];\n  /**\n   * If any of these patterns match, the route will not handle the request (even if a allowlist RegExp matches).\n   */\n  denylist?: RegExp[];\n}\n\n/**\n * A class that makes it easy to create a {@linkcode Route} object that matches navigation requests.\n *\n * It will only match incoming requests whose [`mode`](https://fetch.spec.whatwg.org/#concept-request-mode) is set to `\"navigate\"`.\n *\n * You can optionally only apply this route to a subset of navigation requests\n * by using one or both of the `denylist` and `allowlist` parameters.\n */\nexport class NavigationRoute extends Route {\n  private readonly _allowlist: RegExp[];\n  private readonly _denylist: RegExp[];\n\n  /**\n   * If both `denylist` and `allowlist` are provided, `denylist` will\n   * take precedence.\n   *\n   * The regular expressions in `allowlist` and `denylist`\n   * are matched against the concatenated\n   * [`pathname`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname)\n   * and [`search`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search)\n   * portions of the requested URL.\n   *\n   * *Note*: These RegExps may be evaluated against every destination URL during\n   * a navigation. Avoid using\n   * [complex RegExps](https://github.com/GoogleChrome/workbox/issues/3077),\n   * or else your users may see delays when navigating your site.\n   *\n   * @param handler A callback function that returns a `Promise` resulting in a `Response`.\n   * @param options\n   */\n  constructor(handler: RouteHandler, { allowlist = [/./], denylist = [] }: NavigationRouteMatchOptions = {}) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isArrayOfClass(allowlist, RegExp, {\n        moduleName: \"serwist\",\n        className: \"NavigationRoute\",\n        funcName: \"constructor\",\n        paramName: \"options.allowlist\",\n      });\n      assert!.isArrayOfClass(denylist, RegExp, {\n        moduleName: \"serwist\",\n        className: \"NavigationRoute\",\n        funcName: \"constructor\",\n        paramName: \"options.denylist\",\n      });\n    }\n\n    super((options: RouteMatchCallbackOptions) => this._match(options), handler);\n\n    this._allowlist = allowlist;\n    this._denylist = denylist;\n  }\n\n  /**\n   * Routes match handler.\n   *\n   * @param options\n   * @returns\n   * @private\n   */\n  private _match({ url, request }: RouteMatchCallbackOptions): boolean {\n    if (request && request.mode !== \"navigate\") {\n      return false;\n    }\n\n    const pathnameAndSearch = url.pathname + url.search;\n\n    for (const regExp of this._denylist) {\n      if (regExp.test(pathnameAndSearch)) {\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(\n            `The navigation route ${pathnameAndSearch} is not being used, since the URL matches this denylist pattern: ${regExp.toString()}`,\n          );\n        }\n        return false;\n      }\n    }\n\n    if (this._allowlist.some((regExp) => regExp.test(pathnameAndSearch))) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(`The navigation route ${pathnameAndSearch} is being used.`);\n      }\n      return true;\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(`The navigation route ${pathnameAndSearch} is not being used, since the URL being navigated to doesn't match the allowlist.`);\n    }\n    return false;\n  }\n}\n", "import { logger } from \"./utils/logger.js\";\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n/**\n * Checks whether the current browser supports\n * navigation preloading.\n *\n * @returns\n * @see https://serwist.pages.dev/docs/serwist/core/is-navigation-preload-supported\n */\nexport const isNavigationPreloadSupported = (): boolean => {\n  return Boolean(self.registration?.navigationPreload);\n};\n\n/**\n * If the browser supports navigation preloading, then this will enable it.\n *\n * @param headerValue Optional. Allows developers to override the value of\n * the `Service-Worker-Navigation-Preload` header which will be sent to the\n * server when making the navigation request.\n * @see https://serwist.pages.dev/docs/serwist/core/enable-navigation-preload\n */\nexport const enableNavigationPreload = (headerValue?: string): void => {\n  if (isNavigationPreloadSupported()) {\n    self.addEventListener(\"activate\", (event) => {\n      event.waitUntil(\n        self.registration.navigationPreload.enable().then(() => {\n          // Defaults to Service-Worker-Navigation-Preload: true if not set.\n          if (headerValue) {\n            void self.registration.navigationPreload.setHeaderValue(headerValue);\n          }\n\n          if (process.env.NODE_ENV !== \"production\") {\n            logger.log(\"Navigation preloading is enabled.\");\n          }\n        }),\n      );\n    });\n  } else {\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(\"Navigation preloading is not supported in this browser.\");\n    }\n  }\n};\n\n/**\n * If the browser supports navigation preloading, then this will disable it.\n *\n * @see https://serwist.pages.dev/docs/serwist/core/disable-navigation-preload\n */\nexport const disableNavigationPreload = (): void => {\n  if (isNavigationPreloadSupported()) {\n    self.addEventListener(\"activate\", (event: ExtendableEvent) => {\n      event.waitUntil(\n        self.registration.navigationPreload.disable().then(() => {\n          if (process.env.NODE_ENV !== \"production\") {\n            logger.log(\"Navigation preloading is disabled.\");\n          }\n        }),\n      );\n    });\n  } else {\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(\"Navigation preloading is not supported in this browser.\");\n    }\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n/**\n * Removes any URL search parameters that should be ignored.\n *\n * @param urlObject The original URL.\n * @param ignoreURLParametersMatching RegExps to test against\n * each search parameter name. Matches mean that the search parameter should be\n * ignored.\n * @returns The URL with any ignored search parameters removed.\n * @private\n */\nexport const removeIgnoredSearchParams = (urlObject: URL, ignoreURLParametersMatching: RegExp[] = []): URL => {\n  // Convert the iterable into an array at the start of the loop to make sure\n  // deletion doesn't mess up iteration.\n  for (const paramName of [...urlObject.searchParams.keys()]) {\n    if (ignoreURLParametersMatching.some((regExp) => regExp.test(paramName))) {\n      urlObject.searchParams.delete(paramName);\n    }\n  }\n\n  return urlObject;\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { PrecacheRouteOptions } from \"../types.js\";\nimport { removeIgnoredSearchParams } from \"./removeIgnoredSearchParams.js\";\n\n/**\n * Generator function that yields possible variations on the original URL to\n * check, one at a time.\n *\n * @param url\n * @param options\n *\n * @private\n */\nexport function* generateURLVariations(\n  url: string,\n  {\n    directoryIndex = \"index.html\",\n    ignoreURLParametersMatching = [/^utm_/, /^fbclid$/],\n    cleanURLs = true,\n    urlManipulation,\n  }: PrecacheRouteOptions = {},\n): Generator<string, void, unknown> {\n  const urlObject = new URL(url, location.href);\n  urlObject.hash = \"\";\n  yield urlObject.href;\n\n  const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching);\n  yield urlWithoutIgnoredParams.href;\n\n  if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith(\"/\")) {\n    const directoryURL = new URL(urlWithoutIgnoredParams.href);\n    directoryURL.pathname += directoryIndex;\n    yield directoryURL.href;\n  }\n\n  if (cleanURLs) {\n    const cleanURL = new URL(urlWithoutIgnoredParams.href);\n    cleanURL.pathname += \".html\";\n    yield cleanURL.href;\n  }\n\n  if (urlManipulation) {\n    const additionalURLs = urlManipulation({ url: urlObject });\n    for (const urlToAttempt of additionalURLs) {\n      yield urlToAttempt.href;\n    }\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { HTTPMethod } from \"./constants.js\";\nimport { Route } from \"./Route.js\";\nimport type { RouteHandler, RouteMatchCallback, RouteMatchCallbackOptions } from \"./types.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { logger } from \"./utils/logger.js\";\n\n/**\n * A class that makes it easy to create a {@linkcode Route} object with a regular expression.\n *\n * For same-origin requests the `RegExp` only needs to match part of the URL. For\n * requests against third-party servers, you must define a `RegExp` that matches\n * the start of the URL.\n */\nexport class RegExpRoute extends Route {\n  /**\n   * If the regular expression contains\n   * [capture groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references),\n   * the captured values will be passed to the `params` argument.\n   *\n   * @param regExp The regular expression to match against URLs.\n   * @param handler A callback function that returns a `Promise` resulting in a `Response`.\n   * @param method The HTTP method to match the {@linkcode Route} against. Defaults to `GET`.\n   * against.\n   */\n  constructor(regExp: RegExp, handler: RouteHandler, method?: HTTPMethod) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(regExp, RegExp, {\n        moduleName: \"serwist\",\n        className: \"RegExpRoute\",\n        funcName: \"constructor\",\n        paramName: \"pattern\",\n      });\n    }\n\n    const match: RouteMatchCallback = ({ url }: RouteMatchCallbackOptions) => {\n      const result = regExp.exec(url.href);\n\n      // Return immediately if there's no match.\n      if (!result) {\n        return;\n      }\n\n      // Require that the match start at the first character in the URL string\n      // if it's a cross-origin request.\n      // See https://github.com/GoogleChrome/workbox/issues/281 for the context\n      // behind this behavior.\n      if (url.origin !== location.origin && result.index !== 0) {\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.debug(\n            `The regular expression '${regExp.toString()}' only partially matched against the cross-origin URL '${url.toString()}'. RegExpRoute's will only handle cross-origin requests if they match the entire URL.`,\n          );\n        }\n\n        return;\n      }\n\n      // If the route matches, but there aren't any capture groups defined, then\n      // this will return [], which is truthy and therefore sufficient to\n      // indicate a match.\n      // If there are capture groups, then it will return their values.\n      return result.slice(1);\n    };\n\n    super(match, handler, method);\n  }\n}\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"./utils/assert.js\";\nimport type { PartialCacheNameDetails } from \"./utils/cacheNames.js\";\nimport { cacheNames } from \"./utils/cacheNames.js\";\nimport { SerwistError } from \"./utils/SerwistError.js\";\n\n/**\n * Modifies the default cache names used by Serwist packages.\n * Cache names are generated as `<prefix>-<Cache Name>-<suffix>`.\n *\n * @param details\n */\nexport const setCacheNameDetails = (details: PartialCacheNameDetails): void => {\n  if (process.env.NODE_ENV !== \"production\") {\n    for (const key of Object.keys(details)) {\n      assert!.isType(details[key], \"string\", {\n        moduleName: \"@serwist/core\",\n        funcName: \"setCacheNameDetails\",\n        paramName: `details.${key}`,\n      });\n    }\n\n    if (details.precache?.length === 0) {\n      throw new SerwistError(\"invalid-cache-name\", {\n        cacheNameId: \"precache\",\n        value: details.precache,\n      });\n    }\n\n    if (details.runtime?.length === 0) {\n      throw new SerwistError(\"invalid-cache-name\", {\n        cacheNameId: \"runtime\",\n        value: details.runtime,\n      });\n    }\n\n    if (details.googleAnalytics?.length === 0) {\n      throw new SerwistError(\"invalid-cache-name\", {\n        cacheNameId: \"googleAnalytics\",\n        value: details.googleAnalytics,\n      });\n    }\n  }\n\n  cacheNames.updateDetails(details);\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { PrecacheEntry } from \"../types.js\";\nimport { SerwistError } from \"./SerwistError.js\";\n\ninterface CacheKey {\n  cacheKey: string;\n  url: string;\n}\n\n// Name of the search parameter used to store revision info.\nconst REVISION_SEARCH_PARAM = \"__WB_REVISION__\";\n\n/**\n * Converts a manifest entry into a versioned URL suitable for precaching.\n *\n * @param entry\n * @returns A URL with versioning info.\n *\n * @private\n */\nexport const createCacheKey = (entry: PrecacheEntry | string): CacheKey => {\n  if (!entry) {\n    throw new SerwistError(\"add-to-cache-list-unexpected-type\", { entry });\n  }\n\n  // If a precache manifest entry is a string, it's assumed to be a versioned\n  // URL, like '/app.abcd1234.js'. Return as-is.\n  if (typeof entry === \"string\") {\n    const urlObject = new URL(entry, location.href);\n    return {\n      cacheKey: urlObject.href,\n      url: urlObject.href,\n    };\n  }\n\n  const { revision, url } = entry;\n  if (!url) {\n    throw new SerwistError(\"add-to-cache-list-unexpected-type\", { entry });\n  }\n\n  // If there's just a URL and no revision, then it's also assumed to be a\n  // versioned URL.\n  if (!revision) {\n    const urlObject = new URL(url, location.href);\n    return {\n      cacheKey: urlObject.href,\n      url: urlObject.href,\n    };\n  }\n\n  // Otherwise, construct a properly versioned URL using the custom Serwist\n  // search parameter along with the revision info.\n  const cacheKeyURL = new URL(url, location.href);\n  const originalURL = new URL(url, location.href);\n  cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision);\n  return {\n    cacheKey: cacheKeyURL.href,\n    url: originalURL.href,\n  };\n};\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { SerwistPlugin, SerwistPluginCallbackParam } from \"../types.js\";\n\n/**\n * A plugin designed to determine the number of assets that were updated (or not updated)\n * during the `install` event.\n *\n * @private\n */\nexport class PrecacheInstallReportPlugin implements SerwistPlugin {\n  updatedURLs: string[] = [];\n  notUpdatedURLs: string[] = [];\n\n  handlerWillStart: SerwistPlugin[\"handlerWillStart\"] = async ({ request, state }: SerwistPluginCallbackParam[\"handlerWillStart\"]) => {\n    // TODO: `state` should never be undefined...\n    if (state) {\n      state.originalRequest = request;\n    }\n  };\n\n  cachedResponseWillBeUsed: SerwistPlugin[\"cachedResponseWillBeUsed\"] = async ({\n    event,\n    state,\n    cachedResponse,\n  }: SerwistPluginCallbackParam[\"cachedResponseWillBeUsed\"]) => {\n    if (event.type === \"install\") {\n      if (state?.originalRequest && state.originalRequest instanceof Request) {\n        // TODO: `state` should never be undefined...\n        const url = state.originalRequest.url;\n\n        if (cachedResponse) {\n          this.notUpdatedURLs.push(url);\n        } else {\n          this.updatedURLs.push(url);\n        }\n      }\n    }\n    return cachedResponse;\n  };\n}\n", "import type { HTTPMethod } from \"../constants.js\";\nimport { RegExpRoute } from \"../RegExpRoute.js\";\nimport { Route } from \"../Route.js\";\nimport type { RouteHandler, RouteMatchCallback } from \"../types.js\";\nimport { logger } from \"./logger.js\";\nimport { SerwistError } from \"./SerwistError.js\";\n\n/**\n * Parses a `RegExp`, string, or function with a caching strategy into a {@linkcode Route}. This is for\n * when you want to create a {@linkcode Route}, but you don't want to register it just yet: sometimes\n * you want to call {@linkcode Route.setCatchHandler} first, for example.\n *\n * @param capture If the capture param is a {@linkcode Route} object, all other arguments will be ignored.\n * @param handler A callback function that returns a promise resulting in a response.\n * This parameter is required if `capture` is not a {@linkcode Route} object.\n * @param method The HTTP method to match the route against. Defaults to `'GET'`.\n * @returns The generated {@linkcode Route}.\n */\nexport const parseRoute = (capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod): Route => {\n  if (typeof capture === \"string\") {\n    const captureUrl = new URL(capture, location.href);\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (!(capture.startsWith(\"/\") || capture.startsWith(\"http\"))) {\n        throw new SerwistError(\"invalid-string\", {\n          moduleName: \"serwist\",\n          funcName: \"parseRoute\",\n          paramName: \"capture\",\n        });\n      }\n\n      // We want to check if Express-style wildcards are in the pathname only.\n      // TODO: Remove this log message in v4.\n      const valueToCheck = capture.startsWith(\"http\") ? captureUrl.pathname : capture;\n\n      // See https://github.com/pillarjs/path-to-regexp#parameters\n      const wildcards = \"[*:?+]\";\n      if (new RegExp(`${wildcards}`).exec(valueToCheck)) {\n        logger.debug(\n          `The '$capture' parameter contains an Express-style wildcard character (${wildcards}). Strings are now always interpreted as exact matches; use a RegExp for partial or wildcard matches.`,\n        );\n      }\n    }\n\n    const matchCallback: RouteMatchCallback = ({ url }) => {\n      if (process.env.NODE_ENV !== \"production\") {\n        if (url.pathname === captureUrl.pathname && url.origin !== captureUrl.origin) {\n          logger.debug(\n            `${capture} only partially matches the cross-origin URL ${url.toString()}. This route will only handle cross-origin requests if they match the entire URL.`,\n          );\n        }\n      }\n\n      return url.href === captureUrl.href;\n    };\n\n    // If `capture` is a string then `handler` and `method` must be present.\n    return new Route(matchCallback, handler!, method);\n  }\n  if (capture instanceof RegExp) {\n    // If `capture` is a `RegExp` then `handler` and `method` must be present.\n    return new RegExpRoute(capture, handler!, method);\n  }\n  if (typeof capture === \"function\") {\n    // If `capture` is a function then `handler` and `method` must be present.\n    return new Route(capture, handler!, method);\n  }\n  if (capture instanceof Route) {\n    return capture;\n  }\n  throw new SerwistError(\"unsupported-route-type\", {\n    moduleName: \"serwist\",\n    funcName: \"parseRoute\",\n    paramName: \"capture\",\n  });\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { logger } from \"./logger.js\";\n\n/**\n * @param groupTitle\n * @param deletedURLs\n *\n * @private\n */\nconst logGroup = (groupTitle: string, deletedURLs: string[]) => {\n  logger.groupCollapsed(groupTitle);\n\n  for (const url of deletedURLs) {\n    logger.log(url);\n  }\n\n  logger.groupEnd();\n};\n\n/**\n * @param deletedURLs\n * @private\n */\nexport const printCleanupDetails = (deletedURLs: string[]): void => {\n  const deletionCount = deletedURLs.length;\n  if (deletionCount > 0) {\n    logger.groupCollapsed(`During precaching cleanup, ${deletionCount} cached request${deletionCount === 1 ? \" was\" : \"s were\"} deleted.`);\n    logGroup(\"Deleted Cache Requests\", deletedURLs);\n    logger.groupEnd();\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { logger } from \"./logger.js\";\n\n/**\n * @param groupTitle\n * @param urls\n *\n * @private\n */\nfunction _nestedGroup(groupTitle: string, urls: string[]): void {\n  if (urls.length === 0) {\n    return;\n  }\n\n  logger.groupCollapsed(groupTitle);\n\n  for (const url of urls) {\n    logger.log(url);\n  }\n\n  logger.groupEnd();\n}\n\n/**\n * @param urlsToPrecache\n * @param  urlsAlreadyPrecached\n * @private\n */\nexport const printInstallDetails = (urlsToPrecache: string[], urlsAlreadyPrecached: string[]): void => {\n  const precachedCount = urlsToPrecache.length;\n  const alreadyPrecachedCount = urlsAlreadyPrecached.length;\n\n  if (precachedCount || alreadyPrecachedCount) {\n    let message = `Precaching ${precachedCount} file${precachedCount === 1 ? \"\" : \"s\"}.`;\n\n    if (alreadyPrecachedCount > 0) {\n      message += ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? \" is\" : \"s are\"} already cached.`;\n    }\n\n    logger.groupCollapsed(message);\n\n    _nestedGroup(\"View newly precached URLs.\", urlsToPrecache);\n    _nestedGroup(\"View previously precached URLs.\", urlsAlreadyPrecached);\n    logger.groupEnd();\n  }\n};\n", "export const nonNullable = <T>(value: T): value is NonNullable<T> => value !== null && value !== undefined;\n", "// Source code: https://github.com/rayepps/radash/blob/03dd3152f560414e933cedcd3bda3c6db3e8306b/src/async.ts#L112-L147\n// License: MIT\n// Author: rayepps\ninterface ItemResult<K> {\n  index: number;\n  result: K;\n}\n\n/**\n * Executes many async functions in parallel. Returns the\n * results from all functions as an array. Does not handle\n * any error.\n */\nexport const parallel = async <T, K>(limit: number, array: readonly T[], func: (item: T) => Promise<K>): Promise<K[]> => {\n  const work = array.map((item, index) => ({\n    index,\n    item,\n  }));\n  // Process array items\n  const processor = async (res: (value: ItemResult<K>[]) => void) => {\n    const results: ItemResult<K>[] = [];\n    while (true) {\n      const next = work.pop();\n      if (!next) {\n        return res(results);\n      }\n      const result = await func(next.item);\n      results.push({\n        result: result,\n        index: next.index,\n      });\n    }\n  };\n  // Create queues\n  const queues = Array.from({ length: limit }, () => new Promise(processor));\n  // Wait for all queues to complete\n  const results = (await Promise.all(queues))\n    .flat()\n    .sort((a, b) => (a.index < b.index ? -1 : 1))\n    .map((res) => res.result);\n  return results;\n};\n", "export const toUnix = (p: string) => p.replace(/\\\\/g, \"/\").replace(/(?<!^)\\/+/g, \"/\");\n", "export const compare = <T extends string | number>(a: T, b: T) => {\n  if (a < b) return -1;\n  if (a > b) return +1;\n  return 0;\n};\n", "/** @see https://esbuild.github.io/api/#target */\nexport const SUPPORTED_ESBUILD_TARGETS = [\"chrome\", \"deno\", \"edge\", \"firefox\", \"hermes\", \"ie\", \"ios\", \"node\", \"opera\", \"rhino\", \"safari\"];\n\nexport const UNSUPPORTED_BROWSERLIST_TARGETS = [\"android 4\", \"android 3\", \"android 2\"];\n", "// Source: https://github.com/browserslist/browserslist/blob/5cad191bc1a1e5beb7768ca263503cc15d0dcc7d/index.js#L139-L151\n// License: MIT\nimport { compare } from \"./compare.js\";\n\nexport const compareSemver = (a: string[], b: string[]) => {\n  return (\n    compare(Number.parseInt(a[0], 10), Number.parseInt(b[0], 10)) ||\n    compare(Number.parseInt(a[1] || \"0\", 10), Number.parseInt(b[1] || \"0\", 10)) ||\n    compare(Number.parseInt(a[2] || \"0\", 10), Number.parseInt(b[2] || \"0\", 10))\n  );\n};\n", "import type Browserslist from \"browserslist\";\nimport { compare } from \"./compare.js\";\nimport { SUPPORTED_ESBUILD_TARGETS, UNSUPPORTED_BROWSERLIST_TARGETS } from \"./constants.js\";\nimport { compareSemver } from \"./semver.js\";\n\n// Original: https://github.com/marcofugaro/browserslist-to-esbuild/blob/0875f1a4ec71f206a634ba406c3528ca5ecf04de/src/index.js\n// License: MIT\n/**\n * Loads and converts Browserslist into esbuild's `target` option.\n *\n * @param cwd\n * @returns\n */\nexport const browserslistToEsbuild = (browserslist: typeof Browserslist, cwd: string, defaultBrowserslist: string[]): string[] => {\n  const browserslistConfig = browserslist.loadConfig({ path: cwd }) ?? defaultBrowserslist;\n  return (\n    browserslist(browserslistConfig)\n      // Filter out legacy Android webview to avoid converting them into Chrome targets\n      .filter((query) => !UNSUPPORTED_BROWSERLIST_TARGETS.some((target) => query.startsWith(target)))\n      .map((query) => {\n        const modified = query === \"safari TP\" ? browserslist(\"last 1 safari version\")[0] : query;\n        const split = modified.split(\" \");\n        // https://github.com/browserslist/browserslist/blob/5cad191bc1a1e5beb7768ca263503cc15d0dcc7d/README.md?plain=1#L329-L350\n        // https://esbuild.github.io/api/#target\n        if (split[0] === \"android\" || split[0] === \"and_chr\") {\n          split[0] = \"chrome\";\n        }\n        if (split[0] === \"and_ff\") {\n          split[0] = \"firefox\";\n        }\n        if (split[0] === \"ios_saf\" || split[0] === \"ios\") {\n          split[0] = \"safari\";\n        }\n        // Remove upper version bound\n        if (split[1].includes(\"-\")) {\n          split[1] = split[1].slice(0, split[1].indexOf(\"-\"));\n        }\n        // Trim ending .0\n        if (split[1].endsWith(\".0\")) {\n          split[1] = split[1].slice(0, -2);\n        }\n        return split;\n      })\n      // Remove unsupported browsers and invalid versions\n      .filter((split) => SUPPORTED_ESBUILD_TARGETS.includes(split[0]) && /^\\d+(\\.\\d+)*$/.test(split[1]))\n      // Re-sort the result such that the oldest versions end up the latest, same as how\n      // Browserslist does it.\n      .sort((a, b) => {\n        if (a[0] === b[0]) {\n          return compareSemver(b[1].split(\".\"), a[1].split(\".\"));\n        } else {\n          return compare(a[0], b[0]);\n        }\n      })\n      // Only pick the oldest included version for each browser to avoid duplications.\n      .reduce((acc, browser) => {\n        const existingIndex = acc.findIndex((br) => br[0] === browser[0]);\n        if (existingIndex !== -1) {\n          acc[existingIndex][1] = browser[1];\n        } else {\n          acc.push(browser);\n        }\n        return acc;\n      }, [] as string[][])\n      .map((split) => split.join(\"\"))\n  );\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { cacheNames as privateCacheNames } from \"./utils/cacheNames.js\";\n\n/**\n * Get the current cache names and prefix/suffix used by Serwist.\n *\n * `cacheNames.precache` is used for precached assets,\n * `cacheNames.googleAnalytics` is used by `@serwist/google-analytics` to\n * store `analytics.js`, and `cacheNames.runtime` is used for everything else.\n *\n * `cacheNames.prefix` can be used to retrieve just the current prefix value.\n * `cacheNames.suffix` can be used to retrieve just the current suffix value.\n *\n * @returns An object with `precache`, `runtime`, `prefix`, and `googleAnalytics` properties.\n */\nexport const cacheNames = {\n  get googleAnalytics(): string {\n    return privateCacheNames.getGoogleAnalyticsName();\n  },\n  get precache(): string {\n    return privateCacheNames.getPrecacheName();\n  },\n  get prefix(): string {\n    return privateCacheNames.getPrefix();\n  },\n  get runtime(): string {\n    return privateCacheNames.getRuntimeName();\n  },\n  get suffix(): string {\n    return privateCacheNames.getSuffix();\n  },\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nexport const BROADCAST_UPDATE_MESSAGE_TYPE = \"CACHE_UPDATED\";\nexport const BROADCAST_UPDATE_MESSAGE_META = \"serwist-broadcast-update\";\nexport const BROADCAST_UPDATE_DEFAULT_NOTIFY = true;\nexport const BROADCAST_UPDATE_DEFAULT_HEADERS = [\"content-length\", \"etag\", \"last-modified\"];\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\n\n/**\n * Given two responses, compares several header values to see if they are\n * the same or not.\n *\n * @param firstResponse The first response.\n * @param secondResponse The second response.\n * @param headersToCheck A list of headers to check.\n * @returns\n */\nexport const responsesAreSame = (firstResponse: Response, secondResponse: Response, headersToCheck: string[]): boolean => {\n  if (process.env.NODE_ENV !== \"production\") {\n    if (!(firstResponse instanceof Response && secondResponse instanceof Response)) {\n      throw new SerwistError(\"invalid-responses-are-same-args\");\n    }\n  }\n\n  const atLeastOneHeaderAvailable = headersToCheck.some((header) => {\n    return firstResponse.headers.has(header) && secondResponse.headers.has(header);\n  });\n\n  if (!atLeastOneHeaderAvailable) {\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.warn(\"Unable to determine where the response has been updated because none of the headers that would be checked are present.\");\n      logger.debug(\"Attempting to compare the following: \", firstResponse, secondResponse, headersToCheck);\n    }\n\n    // Just return true, indicating the that responses are the same, since we\n    // can't determine otherwise.\n    return true;\n  }\n\n  return headersToCheck.every((header) => {\n    const headerStateComparison = firstResponse.headers.has(header) === secondResponse.headers.has(header);\n    const headerValueComparison = firstResponse.headers.get(header) === secondResponse.headers.get(header);\n\n    return headerStateComparison && headerValueComparison;\n  });\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { CacheDidUpdateCallbackParam } from \"../../types.js\";\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { resultingClientExists } from \"../../utils/resultingClientExists.js\";\nimport { timeout } from \"../../utils/timeout.js\";\nimport {\n  BROADCAST_UPDATE_DEFAULT_HEADERS,\n  BROADCAST_UPDATE_DEFAULT_NOTIFY,\n  BROADCAST_UPDATE_MESSAGE_META,\n  BROADCAST_UPDATE_MESSAGE_TYPE,\n} from \"./constants.js\";\nimport { responsesAreSame } from \"./responsesAreSame.js\";\nimport type { BroadcastCacheUpdateOptions, BroadcastMessage, BroadcastPayload, BroadcastPayloadGenerator } from \"./types.js\";\n\n// UA-sniff Safari: https://stackoverflow.com/questions/7944460/detect-safari-browser\n// TODO(philipwalton): remove once this Safari bug fix has been released.\n// https://bugs.webkit.org/show_bug.cgi?id=201169\nconst isSafari = typeof navigator !== \"undefined\" && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n\n// Give TypeScript the correct global.\ndeclare const self: ServiceWorkerGlobalScope;\n/**\n * Generates the default payload used in update messages. By default the\n * payload includes the `cacheName` and `updatedURL` fields.\n *\n * @returns\n * @private\n */\nconst defaultPayloadGenerator = (data: CacheDidUpdateCallbackParam): BroadcastPayload => {\n  return {\n    cacheName: data.cacheName,\n    updatedURL: data.request.url,\n  };\n};\n\n/**\n * A class that uses the `postMessage()` API to inform any open windows/tabs when\n * a cached response has been updated.\n *\n * For efficiency's sake, the underlying response bodies are not compared;\n * only specific response headers are checked.\n */\nexport class BroadcastCacheUpdate {\n  private readonly _headersToCheck: string[];\n  private readonly _generatePayload: BroadcastPayloadGenerator;\n  private readonly _notifyAllClients: boolean;\n\n  /**\n   * Construct an instance of `BroadcastCacheUpdate`.\n   *\n   * @param options\n   */\n  constructor({ generatePayload, headersToCheck, notifyAllClients }: BroadcastCacheUpdateOptions = {}) {\n    this._headersToCheck = headersToCheck || BROADCAST_UPDATE_DEFAULT_HEADERS;\n    this._generatePayload = generatePayload || defaultPayloadGenerator;\n    this._notifyAllClients = notifyAllClients ?? BROADCAST_UPDATE_DEFAULT_NOTIFY;\n  }\n\n  /**\n   * Compares two responses and sends a message (via `postMessage()`) to all window clients if the\n   * responses differ. Neither of the Responses can be opaque.\n   *\n   * The message that's posted has the following format (where `payload` can\n   * be customized via the `generatePayload` option the instance is created\n   * with):\n   *\n   * ```\n   * {\n   *   type: 'CACHE_UPDATED',\n   *   meta: 'workbox-broadcast-update',\n   *   payload: {\n   *     cacheName: 'the-cache-name',\n   *     updatedURL: 'https://example.com/'\n   *   }\n   * }\n   * ```\n   *\n   * @param options\n   * @returns Resolves once the update is sent.\n   */\n  async notifyIfUpdated(options: CacheDidUpdateCallbackParam): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(options.cacheName, \"string\", {\n        moduleName: \"serwist\",\n        className: \"BroadcastCacheUpdate\",\n        funcName: \"notifyIfUpdated\",\n        paramName: \"cacheName\",\n      });\n      assert!.isInstance(options.newResponse, Response, {\n        moduleName: \"serwist\",\n        className: \"BroadcastCacheUpdate\",\n        funcName: \"notifyIfUpdated\",\n        paramName: \"newResponse\",\n      });\n      assert!.isInstance(options.request, Request, {\n        moduleName: \"serwist\",\n        className: \"BroadcastCacheUpdate\",\n        funcName: \"notifyIfUpdated\",\n        paramName: \"request\",\n      });\n    }\n\n    // Without two responses there is nothing to compare.\n    if (!options.oldResponse) {\n      return;\n    }\n\n    if (!responsesAreSame(options.oldResponse, options.newResponse, this._headersToCheck)) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.log(\"Newer response found (and cached) for:\", options.request.url);\n      }\n\n      const messageData = {\n        type: BROADCAST_UPDATE_MESSAGE_TYPE,\n        meta: BROADCAST_UPDATE_MESSAGE_META,\n        payload: this._generatePayload(options),\n      } satisfies BroadcastMessage;\n\n      // For navigation requests, wait until the new window client exists\n      // before sending the message\n      if (options.request.mode === \"navigate\") {\n        let resultingClientId: string | undefined;\n        if (options.event instanceof FetchEvent) {\n          resultingClientId = options.event.resultingClientId;\n        }\n\n        const resultingWin = await resultingClientExists(resultingClientId);\n\n        // Safari does not currently implement postMessage buffering and\n        // there's no good way to feature detect that, so to increase the\n        // chances of the message being delivered in Safari, we add a timeout.\n        // We also do this if `resultingClientExists()` didn't return a client,\n        // which means it timed out, so it's worth waiting a bit longer.\n        if (!resultingWin || isSafari) {\n          // 3500 is chosen because (according to CrUX data) 80% of mobile\n          // websites hit the DOMContentLoaded event in less than 3.5 seconds.\n          // And presumably sites implementing service worker are on the\n          // higher end of the performance spectrum.\n          await timeout(3500);\n        }\n      }\n\n      if (this._notifyAllClients) {\n        const windows = await self.clients.matchAll({ type: \"window\" });\n        for (const win of windows) {\n          win.postMessage(messageData);\n        }\n      } else {\n        // See https://github.com/GoogleChrome/workbox/issues/2895\n        if (options.event instanceof FetchEvent) {\n          const client = await self.clients.get(options.event.clientId);\n          client?.postMessage(messageData);\n        }\n      }\n    }\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { CacheDidUpdateCallbackParam, SerwistPlugin } from \"../../types.js\";\nimport { BroadcastCacheUpdate } from \"./BroadcastCacheUpdate.js\";\nimport type { BroadcastCacheUpdateOptions } from \"./types.js\";\n\n/**\n * A class implementing the `cacheDidUpdate` lifecycle callback. It will automatically\n * broadcast a message whenever a cached response is updated.\n */\nexport class BroadcastUpdatePlugin implements SerwistPlugin {\n  private readonly _broadcastUpdate: BroadcastCacheUpdate;\n\n  /**\n   * Construct a {@linkcode BroadcastCacheUpdate} instance with\n   * the passed options and calls its {@linkcode BroadcastCacheUpdate.notifyIfUpdated}\n   * method whenever the plugin's {@linkcode BroadcastUpdatePlugin.cacheDidUpdate} callback\n   * is invoked.\n   *\n   * @param options\n   */\n  constructor(options?: BroadcastCacheUpdateOptions) {\n    this._broadcastUpdate = new BroadcastCacheUpdate(options);\n  }\n\n  /**\n   * @private\n   * @param options The input object to this function.\n   */\n  cacheDidUpdate(options: CacheDidUpdateCallbackParam) {\n    void this._broadcastUpdate.notifyIfUpdated(options);\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\n\nexport interface CacheableResponseOptions {\n  /**\n   * One or more HTTP status codes that a response can have to be considered cacheable.\n   */\n  statuses?: number[];\n  /**\n   * A mapping of header names and expected values that a response can have and be\n   * considered cacheable. If multiple headers are provided, only one needs to be present.\n   */\n  headers?: HeadersInit;\n}\n\n/**\n * Allows you to set up rules determining what status codes and/or headers need\n * to be present in order for a [response](https://developer.mozilla.org/en-US/docs/Web/API/Response)\n * to be considered cacheable.\n */\nexport class CacheableResponse {\n  private readonly _statuses?: CacheableResponseOptions[\"statuses\"];\n  private readonly _headers?: Headers;\n\n  /**\n   * To construct a new `CacheableResponse` instance you must provide at least\n   * one of the `config` properties.\n   *\n   * If both `statuses` and `headers` are specified, then both conditions must\n   * be met for the response to be considered cacheable.\n   *\n   * @param config\n   */\n  constructor(config: CacheableResponseOptions = {}) {\n    if (process.env.NODE_ENV !== \"production\") {\n      if (!(config.statuses || config.headers)) {\n        throw new SerwistError(\"statuses-or-headers-required\", {\n          moduleName: \"serwist\",\n          className: \"CacheableResponse\",\n          funcName: \"constructor\",\n        });\n      }\n\n      if (config.statuses) {\n        assert!.isArray(config.statuses, {\n          moduleName: \"serwist\",\n          className: \"CacheableResponse\",\n          funcName: \"constructor\",\n          paramName: \"config.statuses\",\n        });\n      }\n\n      if (config.headers) {\n        assert!.isType(config.headers, \"object\", {\n          moduleName: \"serwist\",\n          className: \"CacheableResponse\",\n          funcName: \"constructor\",\n          paramName: \"config.headers\",\n        });\n      }\n    }\n\n    this._statuses = config.statuses;\n    if (config.headers) {\n      this._headers = new Headers(config.headers);\n    }\n  }\n\n  /**\n   * Checks a response to see whether it's cacheable or not.\n   *\n   * @param response The response whose cacheability is being\n   * checked.\n   * @returns `true` if the response is cacheable, and `false`\n   * otherwise.\n   */\n  isResponseCacheable(response: Response): boolean {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(response, Response, {\n        moduleName: \"serwist\",\n        className: \"CacheableResponse\",\n        funcName: \"isResponseCacheable\",\n        paramName: \"response\",\n      });\n    }\n\n    let cacheable = true;\n\n    if (this._statuses) {\n      cacheable = this._statuses.includes(response.status);\n    }\n\n    if (this._headers && cacheable) {\n      for (const [headerName, headerValue] of this._headers.entries()) {\n        if (response.headers.get(headerName) !== headerValue) {\n          cacheable = false;\n          break;\n        }\n      }\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (!cacheable) {\n        logger.groupCollapsed(\n          `The request for '${getFriendlyURL(response.url)}' returned a response that does not meet the criteria for being cached.`,\n        );\n\n        logger.groupCollapsed(\"View cacheability criteria here.\");\n        logger.log(`Cacheable statuses: ${JSON.stringify(this._statuses)}`);\n        logger.log(`Cacheable headers: ${JSON.stringify(this._headers, null, 2)}`);\n        logger.groupEnd();\n\n        const logFriendlyHeaders: { [key: string]: string } = {};\n        response.headers.forEach((value, key) => {\n          logFriendlyHeaders[key] = value;\n        });\n\n        logger.groupCollapsed(\"View response status and headers here.\");\n        logger.log(`Response status: ${response.status}`);\n        logger.log(`Response headers: ${JSON.stringify(logFriendlyHeaders, null, 2)}`);\n        logger.groupEnd();\n\n        logger.groupCollapsed(\"View full response details here.\");\n        logger.log(response.headers);\n        logger.log(response);\n        logger.groupEnd();\n\n        logger.groupEnd();\n      }\n    }\n\n    return cacheable;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { SerwistPlugin } from \"../../types.js\";\nimport type { CacheableResponseOptions } from \"./CacheableResponse.js\";\nimport { CacheableResponse } from \"./CacheableResponse.js\";\n\n/**\n * A class implementing the `cacheWillUpdate` lifecycle callback. This makes it\n * easier to add in cacheability checks to requests made via Serwist's built-in\n * strategies.\n */\nexport class CacheableResponsePlugin implements SerwistPlugin {\n  private readonly _cacheableResponse: CacheableResponse;\n\n  /**\n   * To construct a new `CacheableResponsePlugin` instance you must provide at\n   * least one of the `config` properties.\n   *\n   * If both `statuses` and `headers` are specified, then both conditions must\n   * be met for the response to be considered cacheable.\n   *\n   * @param config\n   */\n  constructor(config: CacheableResponseOptions) {\n    this._cacheableResponse = new CacheableResponse(config);\n  }\n\n  /**\n   * @param options\n   * @returns\n   * @private\n   */\n  cacheWillUpdate: SerwistPlugin[\"cacheWillUpdate\"] = async ({ response }) => {\n    if (this._cacheableResponse.isResponseCacheable(response)) {\n      return response;\n    }\n    return null;\n  };\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { DBSchema, IDBPDatabase } from \"idb\";\nimport { deleteDB, openDB } from \"idb\";\n\nconst DB_NAME = \"serwist-expiration\";\nconst CACHE_OBJECT_STORE = \"cache-entries\";\n\nconst normalizeURL = (unNormalizedUrl: string) => {\n  const url = new URL(unNormalizedUrl, location.href);\n  url.hash = \"\";\n\n  return url.href;\n};\n\ninterface CacheTimestampsModelEntry {\n  id: string;\n  cacheName: string;\n  url: string;\n  timestamp: number;\n}\n\ninterface CacheDbSchema extends DBSchema {\n  \"cache-entries\": {\n    key: string;\n    value: CacheTimestampsModelEntry;\n    indexes: { cacheName: string; timestamp: number };\n  };\n}\n\n/**\n * Returns the timestamp model.\n *\n * @private\n */\nexport class CacheTimestampsModel {\n  private readonly _cacheName: string;\n  private _db: IDBPDatabase<CacheDbSchema> | null = null;\n\n  /**\n   *\n   * @param cacheName\n   *\n   * @private\n   */\n  constructor(cacheName: string) {\n    this._cacheName = cacheName;\n  }\n\n  /**\n   * Takes a URL and returns an ID that will be unique in the object store.\n   *\n   * @param url\n   * @returns\n   * @private\n   */\n  private _getId(url: string): string {\n    return `${this._cacheName}|${normalizeURL(url)}`;\n  }\n\n  /**\n   * Performs an upgrade of indexedDB.\n   *\n   * @param db\n   *\n   * @private\n   */\n  private _upgradeDb(db: IDBPDatabase<CacheDbSchema>) {\n    const objStore = db.createObjectStore(CACHE_OBJECT_STORE, {\n      keyPath: \"id\",\n    });\n\n    // TODO(philipwalton): once we don't have to support EdgeHTML, we can\n    // create a single index with the keyPath `['cacheName', 'timestamp']`\n    // instead of doing both these indexes.\n    objStore.createIndex(\"cacheName\", \"cacheName\", { unique: false });\n    objStore.createIndex(\"timestamp\", \"timestamp\", { unique: false });\n  }\n\n  /**\n   * Performs an upgrade of indexedDB and deletes deprecated DBs.\n   *\n   * @param db\n   *\n   * @private\n   */\n  private _upgradeDbAndDeleteOldDbs(db: IDBPDatabase<CacheDbSchema>) {\n    this._upgradeDb(db);\n    if (this._cacheName) {\n      void deleteDB(this._cacheName);\n    }\n  }\n\n  /**\n   * @param url\n   * @param timestamp\n   *\n   * @private\n   */\n  async setTimestamp(url: string, timestamp: number): Promise<void> {\n    url = normalizeURL(url);\n\n    const entry = {\n      id: this._getId(url),\n      cacheName: this._cacheName,\n      url,\n      timestamp,\n    } satisfies CacheTimestampsModelEntry;\n    const db = await this.getDb();\n    const tx = db.transaction(CACHE_OBJECT_STORE, \"readwrite\", {\n      durability: \"relaxed\",\n    });\n    await tx.store.put(entry);\n    await tx.done;\n  }\n\n  /**\n   * Returns the timestamp stored for a given URL.\n   *\n   * @param url\n   * @returns\n   * @private\n   */\n  async getTimestamp(url: string): Promise<number | undefined> {\n    const db = await this.getDb();\n    const entry = await db.get(CACHE_OBJECT_STORE, this._getId(url));\n    return entry?.timestamp;\n  }\n\n  /**\n   * Iterates through all the entries in the object store (from newest to\n   * oldest) and removes entries once either `maxCount` is reached or the\n   * entry's timestamp is less than `minTimestamp`.\n   *\n   * @param minTimestamp\n   * @param maxCount\n   * @returns\n   * @private\n   */\n  async expireEntries(minTimestamp: number, maxCount?: number): Promise<string[]> {\n    const db = await this.getDb();\n    let cursor = await db.transaction(CACHE_OBJECT_STORE, \"readwrite\").store.index(\"timestamp\").openCursor(null, \"prev\");\n    const urlsDeleted: string[] = [];\n    let entriesNotDeletedCount = 0;\n    while (cursor) {\n      const result = cursor.value;\n      // TODO(philipwalton): once we can use a multi-key index, we\n      // won't have to check `cacheName` here.\n      if (result.cacheName === this._cacheName) {\n        // Delete an entry if it's older than the max age or\n        // if we already have the max number allowed.\n        if ((minTimestamp && result.timestamp < minTimestamp) || (maxCount && entriesNotDeletedCount >= maxCount)) {\n          cursor.delete();\n          urlsDeleted.push(result.url);\n        } else {\n          entriesNotDeletedCount++;\n        }\n      }\n      cursor = await cursor.continue();\n    }\n\n    return urlsDeleted;\n  }\n\n  /**\n   * Returns an open connection to the database.\n   *\n   * @private\n   */\n  private async getDb() {\n    if (!this._db) {\n      this._db = await openDB(DB_NAME, 1, {\n        upgrade: this._upgradeDbAndDeleteOldDbs.bind(this),\n      });\n    }\n    return this._db;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { CacheTimestampsModel } from \"./models/CacheTimestampsModel.js\";\n\ninterface CacheExpirationConfig {\n  /**\n   * The maximum number of entries to cache. Entries used least recently will\n   * be removed as the maximum is reached.\n   */\n  maxEntries?: number;\n  /**\n   * The maximum age of an entry before it's treated as stale and removed.\n   */\n  maxAgeSeconds?: number;\n  /**\n   * The [`CacheQueryOptions`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete#Parameters)\n   * that will be used when calling `delete()` on the cache.\n   */\n  matchOptions?: CacheQueryOptions;\n}\n\n/**\n * Allows you to expires cached responses based on age or maximum number of entries.\n * @see https://serwist.pages.dev/docs/serwist/core/cache-expiration\n */\nexport class CacheExpiration {\n  private _isRunning = false;\n  private _rerunRequested = false;\n  private readonly _maxEntries?: number;\n  private readonly _maxAgeSeconds?: number;\n  private readonly _matchOptions?: CacheQueryOptions;\n  private readonly _cacheName: string;\n  private readonly _timestampModel: CacheTimestampsModel;\n\n  /**\n   * To construct a new `CacheExpiration` instance you must provide at least\n   * one of the `config` properties.\n   *\n   * @param cacheName Name of the cache to apply restrictions to.\n   * @param config\n   */\n  constructor(cacheName: string, config: CacheExpirationConfig = {}) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(cacheName, \"string\", {\n        moduleName: \"serwist\",\n        className: \"CacheExpiration\",\n        funcName: \"constructor\",\n        paramName: \"cacheName\",\n      });\n\n      if (!(config.maxEntries || config.maxAgeSeconds)) {\n        throw new SerwistError(\"max-entries-or-age-required\", {\n          moduleName: \"serwist\",\n          className: \"CacheExpiration\",\n          funcName: \"constructor\",\n        });\n      }\n\n      if (config.maxEntries) {\n        assert!.isType(config.maxEntries, \"number\", {\n          moduleName: \"serwist\",\n          className: \"CacheExpiration\",\n          funcName: \"constructor\",\n          paramName: \"config.maxEntries\",\n        });\n      }\n\n      if (config.maxAgeSeconds) {\n        assert!.isType(config.maxAgeSeconds, \"number\", {\n          moduleName: \"serwist\",\n          className: \"CacheExpiration\",\n          funcName: \"constructor\",\n          paramName: \"config.maxAgeSeconds\",\n        });\n      }\n    }\n\n    this._maxEntries = config.maxEntries;\n    this._maxAgeSeconds = config.maxAgeSeconds;\n    this._matchOptions = config.matchOptions;\n    this._cacheName = cacheName;\n    this._timestampModel = new CacheTimestampsModel(cacheName);\n  }\n\n  /**\n   * Expires entries for the given cache and given criteria.\n   */\n  async expireEntries(): Promise<void> {\n    if (this._isRunning) {\n      this._rerunRequested = true;\n      return;\n    }\n    this._isRunning = true;\n\n    const minTimestamp = this._maxAgeSeconds ? Date.now() - this._maxAgeSeconds * 1000 : 0;\n\n    const urlsExpired = await this._timestampModel.expireEntries(minTimestamp, this._maxEntries);\n\n    // Delete URLs from the cache\n    const cache = await self.caches.open(this._cacheName);\n    for (const url of urlsExpired) {\n      await cache.delete(url, this._matchOptions);\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (urlsExpired.length > 0) {\n        logger.groupCollapsed(\n          `Expired ${urlsExpired.length} ` +\n            `${urlsExpired.length === 1 ? \"entry\" : \"entries\"} and removed ` +\n            `${urlsExpired.length === 1 ? \"it\" : \"them\"} from the ` +\n            `'${this._cacheName}' cache.`,\n        );\n        logger.log(`Expired the following ${urlsExpired.length === 1 ? \"URL\" : \"URLs\"}:`);\n        for (const url of urlsExpired) {\n          logger.log(`    ${url}`);\n        }\n        logger.groupEnd();\n      } else {\n        logger.debug(\"Cache expiration ran and found no entries to remove.\");\n      }\n    }\n\n    this._isRunning = false;\n    if (this._rerunRequested) {\n      this._rerunRequested = false;\n      void this.expireEntries();\n    }\n  }\n\n  /**\n   * Updates the timestamp for the given URL, allowing it to be correctly\n   * tracked by the class.\n   *\n   * @param url\n   */\n  async updateTimestamp(url: string): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(url, \"string\", {\n        moduleName: \"serwist\",\n        className: \"CacheExpiration\",\n        funcName: \"updateTimestamp\",\n        paramName: \"url\",\n      });\n    }\n\n    await this._timestampModel.setTimestamp(url, Date.now());\n  }\n\n  /**\n   * Checks if a URL has expired or not before it's used.\n   *\n   * This looks the timestamp up in IndexedDB and can be slow.\n   *\n   * Note: This method does not remove an expired entry, call\n   * `expireEntries()` to remove such entries instead.\n   *\n   * @param url\n   * @returns\n   */\n  async isURLExpired(url: string): Promise<boolean> {\n    if (!this._maxAgeSeconds) {\n      if (process.env.NODE_ENV !== \"production\") {\n        throw new SerwistError(\"expired-test-without-max-age\", {\n          methodName: \"isURLExpired\",\n          paramName: \"maxAgeSeconds\",\n        });\n      }\n      return false;\n    }\n    const timestamp = await this._timestampModel.getTimestamp(url);\n    const expireOlderThan = Date.now() - this._maxAgeSeconds * 1000;\n    return timestamp !== undefined ? timestamp < expireOlderThan : true;\n  }\n\n  /**\n   * Removes the IndexedDB used to keep track of cache expiration metadata.\n   */\n  async delete(): Promise<void> {\n    // Make sure we don't attempt another rerun if we're called in the middle of\n    // a cache expiration.\n    this._rerunRequested = false;\n    await this._timestampModel.expireEntries(Number.POSITIVE_INFINITY); // Expires all.\n  }\n}\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { quotaErrorCallbacks } from \"./models/quotaErrorCallbacks.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { logger } from \"./utils/logger.js\";\n\n/**\n * Adds a function to the set of quotaErrorCallbacks that will be executed if\n * there's a quota error.\n *\n * @param callback\n */\n// biome-ignore lint/complexity/noBannedTypes: Can't change Function type\nexport const registerQuotaErrorCallback = (callback: Function): void => {\n  if (process.env.NODE_ENV !== \"production\") {\n    assert!.isType(callback, \"function\", {\n      moduleName: \"@serwist/core\",\n      funcName: \"register\",\n      paramName: \"callback\",\n    });\n  }\n\n  quotaErrorCallbacks.add(callback);\n\n  if (process.env.NODE_ENV !== \"production\") {\n    logger.log(\"Registered a callback to respond to quota errors.\", callback);\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { registerQuotaErrorCallback } from \"../../registerQuotaErrorCallback.js\";\nimport type { CacheDidUpdateCallbackParam, CachedResponseWillBeUsedCallbackParam, SerwistPlugin } from \"../../types.js\";\nimport { assert } from \"../../utils/assert.js\";\nimport { cacheNames as privateCacheNames } from \"../../utils/cacheNames.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport type { Strategy } from \"../strategies/Strategy.js\";\nimport { CacheExpiration } from \"./CacheExpiration.js\";\n\nexport interface ExpirationPluginOptions {\n  /**\n   * The maximum number of entries to cache. Entries used (if `maxAgeFrom` is\n   * `\"last-used\"`) or fetched from the network (if `maxAgeFrom` is `\"last-fetched\"`)\n   * least recently will be removed as the maximum is reached.\n   */\n  maxEntries?: number;\n  /**\n   * The maximum number of seconds before an entry is treated as stale and removed.\n   */\n  maxAgeSeconds?: number;\n  /**\n   * Determines whether `maxAgeSeconds` should be calculated from when an\n   * entry was last fetched or when it was last used.\n   *\n   * @default \"last-fetched\"\n   */\n  maxAgeFrom?: \"last-fetched\" | \"last-used\";\n  /**\n   * The [`CacheQueryOptions`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete#Parameters)\n   * that will be used when calling `delete()` on the cache.\n   */\n  matchOptions?: CacheQueryOptions;\n  /**\n   * Whether to opt this cache into automatic deletion if the available storage quota has been exceeded.\n   */\n  purgeOnQuotaError?: boolean;\n}\n\n/**\n * This plugin can be used in a {@linkcode Strategy} to regularly enforce a\n * limit on the age and/or the number of cached requests.\n *\n * It can only be used with {@linkcode Strategy} instances that have a custom `cacheName` property set.\n * In other words, it can't be used to expire entries in strategies that use the default runtime\n * cache name.\n *\n * Whenever a cached response is used or updated, this plugin will look\n * at the associated cache and remove any old or extra responses.\n *\n * When using `maxAgeSeconds`, responses may be used *once* after expiring\n * because the expiration clean up will not have occurred until *after* the\n * cached response has been used. If the response has a \"Date\" header, then a lightweight expiration\n * check is performed, and the response will not be used immediately.\n *\n * When using `maxEntries`, the least recently requested entry will be removed\n * from the cache.\n *\n * @see https://serwist.pages.dev/docs/serwist/runtime-caching/plugins/expiration-plugin\n */\nexport class ExpirationPlugin implements SerwistPlugin {\n  private readonly _config: ExpirationPluginOptions;\n  private _cacheExpirations: Map<string, CacheExpiration>;\n\n  /**\n   * @param config\n   */\n  constructor(config: ExpirationPluginOptions = {}) {\n    if (process.env.NODE_ENV !== \"production\") {\n      if (!(config.maxEntries || config.maxAgeSeconds)) {\n        throw new SerwistError(\"max-entries-or-age-required\", {\n          moduleName: \"serwist\",\n          className: \"ExpirationPlugin\",\n          funcName: \"constructor\",\n        });\n      }\n\n      if (config.maxEntries) {\n        assert!.isType(config.maxEntries, \"number\", {\n          moduleName: \"serwist\",\n          className: \"ExpirationPlugin\",\n          funcName: \"constructor\",\n          paramName: \"config.maxEntries\",\n        });\n      }\n\n      if (config.maxAgeSeconds) {\n        assert!.isType(config.maxAgeSeconds, \"number\", {\n          moduleName: \"serwist\",\n          className: \"ExpirationPlugin\",\n          funcName: \"constructor\",\n          paramName: \"config.maxAgeSeconds\",\n        });\n      }\n\n      if (config.maxAgeFrom) {\n        assert!.isType(config.maxAgeFrom, \"string\", {\n          moduleName: \"serwist\",\n          className: \"ExpirationPlugin\",\n          funcName: \"constructor\",\n          paramName: \"config.maxAgeFrom\",\n        });\n      }\n    }\n\n    this._config = config;\n    this._cacheExpirations = new Map();\n\n    if (!this._config.maxAgeFrom) {\n      this._config.maxAgeFrom = \"last-fetched\";\n    }\n\n    if (this._config.purgeOnQuotaError) {\n      registerQuotaErrorCallback(() => this.deleteCacheAndMetadata());\n    }\n  }\n\n  /**\n   * A simple helper method to return a CacheExpiration instance for a given\n   * cache name.\n   *\n   * @param cacheName\n   * @returns\n   * @private\n   */\n  private _getCacheExpiration(cacheName: string): CacheExpiration {\n    if (cacheName === privateCacheNames.getRuntimeName()) {\n      throw new SerwistError(\"expire-custom-caches-only\");\n    }\n\n    let cacheExpiration = this._cacheExpirations.get(cacheName);\n    if (!cacheExpiration) {\n      cacheExpiration = new CacheExpiration(cacheName, this._config);\n      this._cacheExpirations.set(cacheName, cacheExpiration);\n    }\n    return cacheExpiration;\n  }\n\n  /**\n   * A lifecycle callback that will be triggered automatically when a\n   * response is about to be returned from a [`Cache`](https://developer.mozilla.org/en-US/docs/Web/API/Cache).\n   * It allows the response to be inspected for freshness and\n   * prevents it from being used if the response's `Date` header value is\n   * older than the configured `maxAgeSeconds`.\n   *\n   * @param options\n   * @returns `cachedResponse` if it is fresh and `null` if it is stale or\n   * not available.\n   * @private\n   */\n  cachedResponseWillBeUsed({ event, cacheName, request, cachedResponse }: CachedResponseWillBeUsedCallbackParam) {\n    if (!cachedResponse) {\n      return null;\n    }\n\n    const isFresh = this._isResponseDateFresh(cachedResponse);\n\n    // Expire entries to ensure that even if the expiration date has\n    // expired, it'll only be used once.\n    const cacheExpiration = this._getCacheExpiration(cacheName);\n\n    const isMaxAgeFromLastUsed = this._config.maxAgeFrom === \"last-used\";\n\n    const done = (async () => {\n      // Update the metadata for the request URL to the current timestamp.\n      // Only applies if `maxAgeFrom` is `\"last-used\"`, since the current\n      // lifecycle callback is `cachedResponseWillBeUsed`.\n      // This needs to be called before `expireEntries()` so as to avoid\n      // this URL being marked as expired.\n      if (isMaxAgeFromLastUsed) {\n        await cacheExpiration.updateTimestamp(request.url);\n      }\n      await cacheExpiration.expireEntries();\n    })();\n    try {\n      event.waitUntil(done);\n    } catch {\n      if (process.env.NODE_ENV !== \"production\") {\n        if (event instanceof FetchEvent) {\n          logger.warn(`Unable to ensure service worker stays alive when updating cache entry for '${getFriendlyURL(event.request.url)}'.`);\n        }\n      }\n    }\n\n    return isFresh ? cachedResponse : null;\n  }\n\n  /**\n   * @param cachedResponse\n   * @returns\n   * @private\n   */\n  private _isResponseDateFresh(cachedResponse: Response): boolean {\n    const isMaxAgeFromLastUsed = this._config.maxAgeFrom === \"last-used\";\n    // If `maxAgeFrom` is `\"last-used\"`, the `Date` header doesn't really\n    // matter since it is about when the response was created.\n    if (isMaxAgeFromLastUsed) {\n      return true;\n    }\n    const now = Date.now();\n    if (!this._config.maxAgeSeconds) {\n      return true;\n    }\n    // Check if the `Date` header will suffice a quick expiration check.\n    // See https://github.com/GoogleChromeLabs/sw-toolbox/issues/164 for\n    // discussion.\n    const dateHeaderTimestamp = this._getDateHeaderTimestamp(cachedResponse);\n    if (dateHeaderTimestamp === null) {\n      // Unable to parse date, so assume it's fresh.\n      return true;\n    }\n    // If we have a valid headerTime, then our response is fresh if the\n    // headerTime plus maxAgeSeconds is greater than the current time.\n    return dateHeaderTimestamp >= now - this._config.maxAgeSeconds * 1000;\n  }\n\n  /**\n   * Extracts the `Date` header and parse it into an useful value.\n   *\n   * @param cachedResponse\n   * @returns\n   * @private\n   */\n  private _getDateHeaderTimestamp(cachedResponse: Response): number | null {\n    if (!cachedResponse.headers.has(\"date\")) {\n      return null;\n    }\n\n    const dateHeader = cachedResponse.headers.get(\"date\")!;\n    const parsedDate = new Date(dateHeader);\n    const headerTime = parsedDate.getTime();\n\n    // If the `Date` header is invalid for some reason, `parsedDate.getTime()`\n    // will return NaN.\n    if (Number.isNaN(headerTime)) {\n      return null;\n    }\n\n    return headerTime;\n  }\n\n  /**\n   * A lifecycle callback that will be triggered automatically when an entry is added\n   * to a cache.\n   *\n   * @param options\n   * @private\n   */\n  async cacheDidUpdate({ cacheName, request }: CacheDidUpdateCallbackParam) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(cacheName, \"string\", {\n        moduleName: \"serwist\",\n        className: \"Plugin\",\n        funcName: \"cacheDidUpdate\",\n        paramName: \"cacheName\",\n      });\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: \"Plugin\",\n        funcName: \"cacheDidUpdate\",\n        paramName: \"request\",\n      });\n    }\n\n    const cacheExpiration = this._getCacheExpiration(cacheName);\n    await cacheExpiration.updateTimestamp(request.url);\n    await cacheExpiration.expireEntries();\n  }\n\n  /**\n   * Deletes the underlying `Cache` instance associated with this instance and the metadata\n   * from IndexedDB used to keep track of expiration details for each `Cache` instance.\n   *\n   * When using cache expiration, calling this method is preferable to calling\n   * `caches.delete()` directly, since this will ensure that the IndexedDB\n   * metadata is also cleanly removed and that open IndexedDB instances are deleted.\n   *\n   * Note that if you're *not* using cache expiration for a given cache, calling\n   * `caches.delete()` and passing in the cache's name should be sufficient.\n   * There is no Serwist-specific method needed for cleanup in that case.\n   */\n  async deleteCacheAndMetadata(): Promise<void> {\n    // Do this one at a time instead of all at once via `Promise.all()` to\n    // reduce the chance of inconsistency if a promise rejects.\n    for (const [cacheName, cacheExpiration] of this._cacheExpirations) {\n      await self.caches.delete(cacheName);\n      await cacheExpiration.delete();\n    }\n\n    // Reset this._cacheExpirations to its initial state.\n    this._cacheExpirations = new Map();\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nexport const QUEUE_NAME = \"serwist-google-analytics\";\nexport const MAX_RETENTION_TIME = 60 * 48; // Two days in minutes\nexport const GOOGLE_ANALYTICS_HOST = \"www.google-analytics.com\";\nexport const GTM_HOST = \"www.googletagmanager.com\";\nexport const ANALYTICS_JS_PATH = \"/analytics.js\";\nexport const GTAG_JS_PATH = \"/gtag/js\";\nexport const GTM_JS_PATH = \"/gtm.js\";\nexport const COLLECT_DEFAULT_PATH = \"/collect\";\n\n// This RegExp matches all known Measurement Protocol single-hit collect\n// endpoints. Most of the time the default path (/collect) is used, but\n// occasionally an experimental endpoint is used when testing new features,\n// (e.g. /r/collect or /j/collect)\nexport const COLLECT_PATHS_REGEX = /^\\/(\\w+\\/)?collect/;\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { NetworkFirst } from \"../../lib/strategies/NetworkFirst.js\";\nimport { NetworkOnly } from \"../../lib/strategies/NetworkOnly.js\";\nimport { Route } from \"../../Route.js\";\nimport type { Serwist } from \"../../Serwist.js\";\nimport type { RouteMatchCallbackOptions } from \"../../types.js\";\nimport { cacheNames as privateCacheNames } from \"../../utils/cacheNames.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { BackgroundSyncPlugin } from \"../backgroundSync/BackgroundSyncPlugin.js\";\nimport type { BackgroundSyncQueue, BackgroundSyncQueueEntry } from \"../backgroundSync/BackgroundSyncQueue.js\";\nimport {\n  ANALYTICS_JS_PATH,\n  COLLECT_PATHS_REGEX,\n  GOOGLE_ANALYTICS_HOST,\n  GTAG_JS_PATH,\n  GTM_HOST,\n  GTM_JS_PATH,\n  MAX_RETENTION_TIME,\n  QUEUE_NAME,\n} from \"./constants.js\";\n\nexport interface GoogleAnalyticsInitializeOptions {\n  serwist: Serwist;\n  /**\n   * The cache name to store and retrieve analytics.js. Defaults to Serwist's default cache names.\n   */\n  cacheName?: string;\n  /**\n   * [Measurement Protocol parameters](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters),\n   * expressed as key/value pairs, to be added to replayed Google Analytics\n   * requests. This can be used to, e.g., set a custom dimension indicating\n   * that the request was replayed.\n   */\n  parameterOverrides?: { [paramName: string]: string };\n  /**\n   * A function that allows you to modify the hit parameters prior to replaying\n   * the hit. The function is invoked with the original hit's URLSearchParams\n   * object as its only argument.\n   */\n  hitFilter?: (params: URLSearchParams) => void;\n}\n\n/**\n * Creates the requestWillDequeue callback to be used with the background\n * sync plugin. The callback takes the failed request and adds the\n * `qt` param based on the current time, as well as applies any other\n * user-defined hit modifications.\n *\n * @param config\n * @returns The requestWillDequeue callback function.\n * @private\n */\nconst createOnSyncCallback = (config: Pick<GoogleAnalyticsInitializeOptions, \"parameterOverrides\" | \"hitFilter\">) => {\n  return async ({ queue }: { queue: BackgroundSyncQueue }) => {\n    let entry: BackgroundSyncQueueEntry | undefined;\n    while ((entry = await queue.shiftRequest())) {\n      const { request, timestamp } = entry;\n      const url = new URL(request.url);\n\n      try {\n        // Measurement protocol requests can set their payload parameters in\n        // either the URL query string (for GET requests) or the POST body.\n        const params = request.method === \"POST\" ? new URLSearchParams(await request.clone().text()) : url.searchParams;\n\n        // Calculate the qt param, accounting for the fact that an existing\n        // qt param may be present and should be updated rather than replaced.\n        const originalHitTime = timestamp! - (Number(params.get(\"qt\")) || 0);\n        const queueTime = Date.now() - originalHitTime;\n\n        // Set the qt param prior to applying hitFilter or parameterOverrides.\n        params.set(\"qt\", String(queueTime));\n\n        // Apply `parameterOverrides`, if set.\n        if (config.parameterOverrides) {\n          for (const param of Object.keys(config.parameterOverrides)) {\n            const value = config.parameterOverrides[param];\n            params.set(param, value);\n          }\n        }\n\n        // Apply `hitFilter`, if set.\n        if (typeof config.hitFilter === \"function\") {\n          config.hitFilter.call(null, params);\n        }\n\n        // Retry the fetch. Ignore URL search params from the URL as they're\n        // now in the post body.\n        await fetch(\n          new Request(url.origin + url.pathname, {\n            body: params.toString(),\n            method: \"POST\",\n            mode: \"cors\",\n            credentials: \"omit\",\n            headers: { \"Content-Type\": \"text/plain\" },\n          }),\n        );\n\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(`Request for '${getFriendlyURL(url.href)}' has been replayed`);\n        }\n      } catch (err) {\n        await queue.unshiftRequest(entry);\n\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(`Request for '${getFriendlyURL(url.href)}' failed to replay, putting it back in the queue.`);\n        }\n        throw err;\n      }\n    }\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(\"All Google Analytics request successfully replayed; \" + \"the queue is now empty!\");\n    }\n  };\n};\n\n/**\n * Creates GET and POST routes to catch failed Measurement Protocol hits.\n *\n * @param bgSyncPlugin\n * @returns The created routes.\n * @private\n */\nconst createCollectRoutes = (bgSyncPlugin: BackgroundSyncPlugin) => {\n  const match = ({ url }: RouteMatchCallbackOptions) => url.hostname === GOOGLE_ANALYTICS_HOST && COLLECT_PATHS_REGEX.test(url.pathname);\n\n  const handler = new NetworkOnly({\n    plugins: [bgSyncPlugin],\n  });\n\n  return [new Route(match, handler, \"GET\"), new Route(match, handler, \"POST\")];\n};\n\n/**\n * Creates a route with a network first strategy for the analytics.js script.\n *\n * @param cacheName\n * @returns The created route.\n * @private\n */\nconst createAnalyticsJsRoute = (cacheName: string) => {\n  const match = ({ url }: RouteMatchCallbackOptions) => url.hostname === GOOGLE_ANALYTICS_HOST && url.pathname === ANALYTICS_JS_PATH;\n\n  const handler = new NetworkFirst({ cacheName });\n\n  return new Route(match, handler, \"GET\");\n};\n\n/**\n * Creates a route with a network first strategy for the gtag.js script.\n *\n * @param cacheName\n * @returns The created route.\n * @private\n */\nconst createGtagJsRoute = (cacheName: string) => {\n  const match = ({ url }: RouteMatchCallbackOptions) => url.hostname === GTM_HOST && url.pathname === GTAG_JS_PATH;\n\n  const handler = new NetworkFirst({ cacheName });\n\n  return new Route(match, handler, \"GET\");\n};\n\n/**\n * Creates a route with a network first strategy for the gtm.js script.\n *\n * @param cacheName\n * @returns The created route.\n * @private\n */\nconst createGtmJsRoute = (cacheName: string) => {\n  const match = ({ url }: RouteMatchCallbackOptions) => url.hostname === GTM_HOST && url.pathname === GTM_JS_PATH;\n\n  const handler = new NetworkFirst({ cacheName });\n\n  return new Route(match, handler, \"GET\");\n};\n\n/**\n * Initialize Serwist's offline Google Analytics v3 support.\n *\n * @param options\n */\nexport const initializeGoogleAnalytics = ({ serwist, cacheName, ...options }: GoogleAnalyticsInitializeOptions): void => {\n  const resolvedCacheName = privateCacheNames.getGoogleAnalyticsName(cacheName);\n\n  const bgSyncPlugin = new BackgroundSyncPlugin(QUEUE_NAME, {\n    maxRetentionTime: MAX_RETENTION_TIME,\n    onSync: createOnSyncCallback(options),\n  });\n\n  const routes = [\n    createGtmJsRoute(resolvedCacheName),\n    createAnalyticsJsRoute(resolvedCacheName),\n    createGtagJsRoute(resolvedCacheName),\n    ...createCollectRoutes(bgSyncPlugin),\n  ];\n\n  for (const route of routes) {\n    serwist.registerRoute(route);\n  }\n};\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { Serwist } from \"../../Serwist.js\";\nimport type { HandlerDidErrorCallbackParam, SerwistPlugin } from \"../../types.js\";\n\nexport interface PrecacheFallbackEntry {\n  /**\n   * A precached URL to be used as a fallback.\n   */\n  url: string;\n  /**\n   * A function that checks whether the fallback entry can be used\n   * for a request.\n   */\n  matcher: (param: HandlerDidErrorCallbackParam) => boolean;\n}\n\nexport interface PrecacheFallbackPluginOptions {\n  /**\n   * Precached URLs to be used as the fallback\n   * if the associated strategy can't generate a response.\n   */\n  fallbackUrls: (string | PrecacheFallbackEntry)[];\n  /**\n   * A {@linkcode Serwist} instance.\n   */\n  serwist: Serwist;\n}\n\n/**\n * Allows you to specify offline fallbacks to be used when a given strategy\n * is unable to generate a response.\n *\n * It does this by intercepting the `handlerDidError` plugin callback\n * and returning a precached response, taking the expected revision parameter\n * into account automatically.\n */\nexport class PrecacheFallbackPlugin implements SerwistPlugin {\n  private readonly _fallbackUrls: (string | PrecacheFallbackEntry)[];\n  private readonly _serwist: Serwist;\n\n  /**\n   * Constructs a new instance with the associated `fallbackUrls`.\n   *\n   * @param config\n   */\n  constructor({ fallbackUrls, serwist }: PrecacheFallbackPluginOptions) {\n    this._fallbackUrls = fallbackUrls;\n    this._serwist = serwist;\n  }\n\n  /**\n   * @returns The precache response for one of the fallback URLs, or `undefined` if\n   * nothing satisfies the conditions.\n   * @private\n   */\n  async handlerDidError(param: HandlerDidErrorCallbackParam) {\n    for (const fallback of this._fallbackUrls) {\n      if (typeof fallback === \"string\") {\n        const fallbackResponse = await this._serwist.matchPrecache(fallback);\n        if (fallbackResponse !== undefined) {\n          return fallbackResponse;\n        }\n      } else if (fallback.matcher(param)) {\n        const fallbackResponse = await this._serwist.matchPrecache(fallback.url);\n        if (fallbackResponse !== undefined) {\n          return fallbackResponse;\n        }\n      }\n    }\n    return undefined;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../../utils/assert.js\";\nimport { SerwistError } from \"../../../utils/SerwistError.js\";\n\n/**\n * @param blob A source blob.\n * @param start The offset to use as the start of the\n * slice.\n * @param end The offset to use as the end of the slice.\n * @returns An object with `start` and `end` properties, reflecting\n * the effective boundaries to use given the size of the blob.\n * @private\n */\nexport const calculateEffectiveBoundaries = (blob: Blob, start?: number, end?: number): { start: number; end: number } => {\n  if (process.env.NODE_ENV !== \"production\") {\n    assert!.isInstance(blob, Blob, {\n      moduleName: \"@serwist/range-requests\",\n      funcName: \"calculateEffectiveBoundaries\",\n      paramName: \"blob\",\n    });\n  }\n\n  const blobSize = blob.size;\n\n  if ((end && end > blobSize) || (start && start < 0)) {\n    throw new SerwistError(\"range-not-satisfiable\", {\n      size: blobSize,\n      end,\n      start,\n    });\n  }\n\n  let effectiveStart: number;\n  let effectiveEnd: number;\n\n  if (start !== undefined && end !== undefined) {\n    effectiveStart = start;\n    // Range values are inclusive, so add 1 to the value.\n    effectiveEnd = end + 1;\n  } else if (start !== undefined && end === undefined) {\n    effectiveStart = start;\n    effectiveEnd = blobSize;\n  } else if (end !== undefined && start === undefined) {\n    effectiveStart = blobSize - end;\n    effectiveEnd = blobSize;\n  }\n\n  return {\n    start: effectiveStart!,\n    end: effectiveEnd!,\n  };\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../../utils/assert.js\";\nimport { SerwistError } from \"../../../utils/SerwistError.js\";\n\n/**\n * @param rangeHeader A `Range` header value.\n * @returns An object with `start` and `end` properties, reflecting\n * the parsed value of the `Range` header. If either the `start` or `end` are\n * omitted, then `null` will be returned.\n * @private\n */\nexport const parseRangeHeader = (\n  rangeHeader: string,\n): {\n  start?: number;\n  end?: number;\n} => {\n  if (process.env.NODE_ENV !== \"production\") {\n    assert!.isType(rangeHeader, \"string\", {\n      moduleName: \"@serwist/range-requests\",\n      funcName: \"parseRangeHeader\",\n      paramName: \"rangeHeader\",\n    });\n  }\n\n  const normalizedRangeHeader = rangeHeader.trim().toLowerCase();\n  if (!normalizedRangeHeader.startsWith(\"bytes=\")) {\n    throw new SerwistError(\"unit-must-be-bytes\", { normalizedRangeHeader });\n  }\n\n  // Specifying multiple ranges separate by commas is valid syntax, but this\n  // library only attempts to handle a single, contiguous sequence of bytes.\n  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range#Syntax\n  if (normalizedRangeHeader.includes(\",\")) {\n    throw new SerwistError(\"single-range-only\", { normalizedRangeHeader });\n  }\n\n  const rangeParts = /(\\d*)-(\\d*)/.exec(normalizedRangeHeader);\n  // We need either at least one of the start or end values.\n  if (!rangeParts || !(rangeParts[1] || rangeParts[2])) {\n    throw new SerwistError(\"invalid-range-values\", { normalizedRangeHeader });\n  }\n\n  return {\n    start: rangeParts[1] === \"\" ? undefined : Number(rangeParts[1]),\n    end: rangeParts[2] === \"\" ? undefined : Number(rangeParts[2]),\n  };\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { calculateEffectiveBoundaries } from \"./utils/calculateEffectiveBoundaries.js\";\nimport { parseRangeHeader } from \"./utils/parseRangeHeader.js\";\n\n/**\n * Given a request and a response, this will return a\n * promise that resolves to a partial response.\n *\n * If the original response already contains partial content (i.e. it has\n * a status of 206), then this assumes it already fulfills the `Range`\n * requirements, and will return it as-is.\n *\n * @param request A request, which should contain a `Range`\n * header.\n * @param originalResponse A response.\n * @returns Either a `206 Partial Content` response, with\n * the response body set to the slice of content specified by the request's\n * `Range` header, or a `416 Range Not Satisfiable` response if the\n * conditions of the `Range` header can't be met.\n */\nexport const createPartialResponse = async (request: Request, originalResponse: Response): Promise<Response> => {\n  try {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"@serwist/range-requests\",\n        funcName: \"createPartialResponse\",\n        paramName: \"request\",\n      });\n\n      assert!.isInstance(originalResponse, Response, {\n        moduleName: \"@serwist/range-requests\",\n        funcName: \"createPartialResponse\",\n        paramName: \"originalResponse\",\n      });\n    }\n\n    if (originalResponse.status === 206) {\n      // If we already have a 206, then just pass it through as-is;\n      // see https://github.com/GoogleChrome/workbox/issues/1720\n      return originalResponse;\n    }\n\n    const rangeHeader = request.headers.get(\"range\");\n    if (!rangeHeader) {\n      throw new SerwistError(\"no-range-header\");\n    }\n\n    const boundaries = parseRangeHeader(rangeHeader);\n    const originalBlob = await originalResponse.blob();\n\n    const effectiveBoundaries = calculateEffectiveBoundaries(originalBlob, boundaries.start, boundaries.end);\n\n    const slicedBlob = originalBlob.slice(effectiveBoundaries.start, effectiveBoundaries.end);\n    const slicedBlobSize = slicedBlob.size;\n\n    const slicedResponse = new Response(slicedBlob, {\n      // Status code 206 is for a Partial Content response.\n      // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206\n      status: 206,\n      statusText: \"Partial Content\",\n      headers: originalResponse.headers,\n    });\n\n    slicedResponse.headers.set(\"Content-Length\", String(slicedBlobSize));\n    slicedResponse.headers.set(\"Content-Range\", `bytes ${effectiveBoundaries.start}-${effectiveBoundaries.end - 1}/` + `${originalBlob.size}`);\n\n    return slicedResponse;\n  } catch (error) {\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.warn(\"Unable to construct a partial response; returning a \" + \"416 Range Not Satisfiable response instead.\");\n      logger.groupCollapsed(\"View details here.\");\n      logger.log(error);\n      logger.log(request);\n      logger.log(originalResponse);\n      logger.groupEnd();\n    }\n\n    return new Response(\"\", {\n      status: 416,\n      statusText: \"Range Not Satisfiable\",\n    });\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { SerwistPlugin } from \"../../types.js\";\nimport { createPartialResponse } from \"./createPartialResponse.js\";\n\n/**\n * Makes it easy for a request with a `Range` header to be fulfilled by a cached response.\n *\n * It does this by intercepting the `cachedResponseWillBeUsed` plugin callback\n * and returning the appropriate subset of the cached response body.\n */\nexport class RangeRequestsPlugin implements SerwistPlugin {\n  /**\n   * @param options\n   * @returns If request contains a `Range` header, then a\n   * partial response whose body is a subset of `cachedResponse` is\n   * returned. Otherwise, `cachedResponse` is returned as-is.\n   * @private\n   */\n  cachedResponseWillBeUsed: SerwistPlugin[\"cachedResponseWillBeUsed\"] = async ({ request, cachedResponse }) => {\n    // Only return a sliced response if there's something valid in the cache,\n    // and there's a Range: header in the request.\n    if (cachedResponse && request.headers.has(\"range\")) {\n      return await createPartialResponse(request, cachedResponse);\n    }\n\n    // If there was no Range: header, or if cachedResponse wasn't valid, just\n    // pass it through as-is.\n    return cachedResponse;\n  };\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\n/**\n * An implementation of the [cache first](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#cache_first_falling_back_to_network)\n * request strategy.\n *\n * A cache first strategy is useful for assets that have been revisioned,\n * such as URLs like \"/styles/example.a8f5f1.css\", since they\n * can be cached for long periods of time.\n *\n * If the network request fails, and there is no cache match, this will throw\n * a {@linkcode SerwistError} exception.\n */\nexport class CacheFirst extends Strategy {\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    const logs = [];\n\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"makeRequest\",\n        paramName: \"request\",\n      });\n    }\n\n    let response = await handler.cacheMatch(request);\n\n    let error: Error | undefined;\n    if (!response) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logs.push(`No response found in the '${this.cacheName}' cache. Will respond with a network request.`);\n      }\n      try {\n        response = await handler.fetchAndCachePut(request);\n      } catch (err) {\n        if (err instanceof Error) {\n          error = err;\n        }\n      }\n\n      if (process.env.NODE_ENV !== \"production\") {\n        if (response) {\n          logs.push(\"Got response from network.\");\n        } else {\n          logs.push(\"Unable to get a response from the network.\");\n        }\n      }\n    } else {\n      if (process.env.NODE_ENV !== \"production\") {\n        logs.push(`Found a cached response in the '${this.cacheName}' cache.`);\n      }\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      for (const log of logs) {\n        logger.log(log);\n      }\n      messages.printFinalResponse(response);\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url, error });\n    }\n    return response;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\n/**\n * An implementation of the [cache only](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#cache_only)\n * request strategy.\n *\n * This class is useful if you already have your own precaching step.\n *\n * If there is no cache match, this will throw a {@linkcode SerwistError} exception.\n */\nexport class CacheOnly extends Strategy {\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"makeRequest\",\n        paramName: \"request\",\n      });\n    }\n\n    const response = await handler.cacheMatch(request);\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      if (response) {\n        logger.log(`Found a cached response in the '${this.cacheName}' cache.`);\n        messages.printFinalResponse(response);\n      } else {\n        logger.log(`No response found in the '${this.cacheName}' cache.`);\n      }\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url });\n    }\n    return response;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { cacheOkAndOpaquePlugin } from \"./plugins/cacheOkAndOpaquePlugin.js\";\nimport type { StrategyOptions } from \"./Strategy.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\n/**\n * An implementation of the\n * [stale-while-revalidate](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#stale_while_revalidate)\n * request strategy.\n *\n * Resources are requested from both the cache and the network in parallel.\n * The strategy will respond with the cached version if available, otherwise\n * wait for the network response. The cache is updated with the network response\n * with each successful request.\n *\n * By default, this strategy will cache responses with a 200 status code as\n * well as [opaque responses](https://developer.chrome.com/docs/workbox/caching-resources-during-runtime/#opaque-responses).\n * Opaque responses are cross-origin requests where the response doesn't\n * support [CORS](https://enable-cors.org/).\n *\n * If the network request fails, and there is no cache match, this will throw\n * a {@linkcode SerwistError} exception.\n */\nexport class StaleWhileRevalidate extends Strategy {\n  /**\n   * @param options\n   */\n  constructor(options: StrategyOptions = {}) {\n    super(options);\n\n    // If this instance contains no plugins with a 'cacheWillUpdate' callback,\n    // prepend the `cacheOkAndOpaquePlugin` plugin to the plugins list.\n    if (!this.plugins.some((p) => \"cacheWillUpdate\" in p)) {\n      this.plugins.unshift(cacheOkAndOpaquePlugin);\n    }\n  }\n\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    const logs = [];\n\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"handle\",\n        paramName: \"request\",\n      });\n    }\n\n    const fetchAndCachePromise = handler.fetchAndCachePut(request).catch(() => {\n      // Swallow this error because a 'no-response' error will be thrown in\n      // main handler return flow. This will be in the `waitUntil()` flow.\n    });\n    void handler.waitUntil(fetchAndCachePromise);\n\n    let response = await handler.cacheMatch(request);\n\n    let error: Error | undefined;\n    if (response) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logs.push(`Found a cached response in the '${this.cacheName}' cache. Will update with the network response in the background.`);\n      }\n    } else {\n      if (process.env.NODE_ENV !== \"production\") {\n        logs.push(`No response found in the '${this.cacheName}' cache. Will wait for the network response.`);\n      }\n      try {\n        // NOTE(philipwalton): Really annoying that we have to type cast here.\n        // https://github.com/microsoft/TypeScript/issues/20006\n        response = (await fetchAndCachePromise) as Response | undefined;\n      } catch (err) {\n        if (err instanceof Error) {\n          error = err;\n        }\n      }\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      for (const log of logs) {\n        logger.log(log);\n      }\n      messages.printFinalResponse(response);\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url, error });\n    }\n    return response;\n  }\n}\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { Route } from \"./Route.js\";\nimport type { Serwist } from \"./Serwist.js\";\nimport type { PrecacheRouteOptions, RouteMatchCallback, RouteMatchCallbackOptions } from \"./types.js\";\nimport { generateURLVariations } from \"./utils/generateURLVariations.js\";\nimport { getFriendlyURL } from \"./utils/getFriendlyURL.js\";\nimport { logger } from \"./utils/logger.js\";\n\n/**\n * A subclass of {@linkcode Route} that takes a {@linkcode Serwist} instance and uses it to match\n * incoming requests and handle fetching responses from the precache.\n */\nexport class PrecacheRoute extends Route {\n  /**\n   * @param serwist A {@linkcode Serwist} instance.\n   * @param options Options to control how requests are matched\n   * against the list of precached URLs.\n   */\n  constructor(serwist: Serwist, options?: PrecacheRouteOptions) {\n    const match: RouteMatchCallback = ({ request }: RouteMatchCallbackOptions) => {\n      const urlsToCacheKeys = serwist.getUrlsToPrecacheKeys();\n      for (const possibleURL of generateURLVariations(request.url, options)) {\n        const cacheKey = urlsToCacheKeys.get(possibleURL);\n        if (cacheKey) {\n          const integrity = serwist.getIntegrityForPrecacheKey(cacheKey);\n          return { cacheKey, integrity };\n        }\n      }\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(`Precaching did not find a match for ${getFriendlyURL(request.url)}.`);\n      }\n      return;\n    };\n\n    super(match, serwist.precacheStrategy);\n  }\n}\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { Serwist } from \"../Serwist.js\";\nimport type { SerwistPlugin, SerwistPluginCallbackParam } from \"../types.js\";\n\n/**\n * A plugin, designed to be used with PrecacheController, to translate URLs into\n * the corresponding cache key, based on the current revision info.\n *\n * @private\n */\nexport class PrecacheCacheKeyPlugin implements SerwistPlugin {\n  private readonly _precacheController: Serwist;\n\n  constructor({ precacheController }: { precacheController: Serwist }) {\n    this._precacheController = precacheController;\n  }\n\n  cacheKeyWillBeUsed: SerwistPlugin[\"cacheKeyWillBeUsed\"] = async ({ request, params }: SerwistPluginCallbackParam[\"cacheKeyWillBeUsed\"]) => {\n    // Params is type any, can't change right now.\n    const cacheKey = params?.cacheKey || this._precacheController.getPrecacheKeyForUrl(request.url);\n\n    return cacheKey ? new Request(cacheKey, { headers: request.headers }) : request;\n  };\n}\n", "import { privateCacheNames } from \"../index.internal.js\";\nimport type { PrecacheStrategyOptions } from \"../lib/strategies/PrecacheStrategy.js\";\nimport type { Serwist } from \"../Serwist.js\";\nimport type { PrecacheOptions, PrecacheRouteOptions } from \"../types.js\";\nimport { PrecacheCacheKeyPlugin } from \"./PrecacheCacheKeyPlugin.js\";\n\nexport const parsePrecacheOptions = (serwist: Serwist, precacheOptions: PrecacheOptions = {}) => {\n  const {\n    cacheName: precacheCacheName,\n    plugins: precachePlugins = [],\n    fetchOptions: precacheFetchOptions,\n    matchOptions: precacheMatchOptions,\n    fallbackToNetwork: precacheFallbackToNetwork,\n    directoryIndex: precacheDirectoryIndex,\n    ignoreURLParametersMatching: precacheIgnoreUrls,\n    cleanURLs: precacheCleanUrls,\n    urlManipulation: precacheUrlManipulation,\n    cleanupOutdatedCaches,\n    concurrency = 10,\n    navigateFallback,\n    navigateFallbackAllowlist,\n    navigateFallbackDenylist,\n  } = precacheOptions ?? {};\n\n  return {\n    precacheStrategyOptions: {\n      cacheName: privateCacheNames.getPrecacheName(precacheCacheName),\n      plugins: [...precachePlugins, new PrecacheCacheKeyPlugin({ precacheController: serwist })],\n      fetchOptions: precacheFetchOptions,\n      matchOptions: precacheMatchOptions,\n      fallbackToNetwork: precacheFallbackToNetwork,\n    } satisfies PrecacheStrategyOptions,\n    precacheRouteOptions: {\n      directoryIndex: precacheDirectoryIndex,\n      ignoreURLParametersMatching: precacheIgnoreUrls,\n      cleanURLs: precacheCleanUrls,\n      urlManipulation: precacheUrlManipulation,\n    } satisfies PrecacheRouteOptions,\n    precacheMiscOptions: {\n      cleanupOutdatedCaches,\n      concurrency,\n      navigateFallback,\n      navigateFallbackAllowlist,\n      navigateFallbackDenylist,\n    },\n  };\n};\n", "import { parallel } from \"@serwist/utils\";\nimport { defaultMethod, type HTTPMethod } from \"./constants.js\";\nimport { disableDevLogs as disableDevLogsImpl } from \"./disableDevLogs.js\";\nimport { type GoogleAnalyticsInitializeOptions, initializeGoogleAnalytics } from \"./lib/googleAnalytics/initializeGoogleAnalytics.js\";\nimport { type PrecacheFallbackEntry, PrecacheFallbackPlugin } from \"./lib/precaching/PrecacheFallbackPlugin.js\";\nimport { PrecacheStrategy } from \"./lib/strategies/PrecacheStrategy.js\";\nimport { Strategy } from \"./lib/strategies/Strategy.js\";\nimport { NavigationRoute } from \"./NavigationRoute.js\";\nimport { enableNavigationPreload } from \"./navigationPreload.js\";\nimport { PrecacheRoute } from \"./PrecacheRoute.js\";\nimport type { Route } from \"./Route.js\";\nimport { setCacheNameDetails } from \"./setCacheNameDetails.js\";\nimport type {\n  CleanupResult,\n  InstallEvent,\n  InstallResult,\n  PrecacheEntry,\n  PrecacheOptions,\n  RequestRule,\n  RouteHandler,\n  RouteHandlerCallback,\n  RouteHandlerCallbackOptions,\n  RouteHandlerObject,\n  RouteMatchCallback,\n  RouteMatchCallbackOptions,\n  RuntimeCaching,\n} from \"./types.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { cleanupOutdatedCaches as cleanupOutdatedCachesImpl } from \"./utils/cleanupOutdatedCaches.js\";\nimport { clientsClaim as clientsClaimImpl } from \"./utils/clientsClaim.js\";\nimport { createCacheKey } from \"./utils/createCacheKey.js\";\nimport { getFriendlyURL } from \"./utils/getFriendlyURL.js\";\nimport { logger } from \"./utils/logger.js\";\nimport { normalizeHandler } from \"./utils/normalizeHandler.js\";\nimport { PrecacheInstallReportPlugin } from \"./utils/PrecacheInstallReportPlugin.js\";\nimport { parsePrecacheOptions } from \"./utils/parsePrecacheOptions.js\";\nimport { parseRoute } from \"./utils/parseRoute.js\";\nimport { printCleanupDetails } from \"./utils/printCleanupDetails.js\";\nimport { printInstallDetails } from \"./utils/printInstallDetails.js\";\nimport { SerwistError } from \"./utils/SerwistError.js\";\nimport { waitUntil } from \"./utils/waitUntil.js\";\n\ndeclare const self: ServiceWorkerGlobalScope;\n\nexport interface FallbackEntry extends PrecacheFallbackEntry {}\n\nexport interface FallbacksOptions {\n  /**\n   * A list of fallback entries.\n   */\n  entries: FallbackEntry[];\n}\n\nexport interface SerwistOptions {\n  /**\n   * A list of URLs that should be cached.\n   */\n  precacheEntries?: (PrecacheEntry | string)[];\n  /**\n   * Options to customize how Serwist precaches the URLs in the precache list.\n   */\n  precacheOptions?: PrecacheOptions;\n  /**\n   * Forces the waiting service worker to become the active one.\n   *\n   * @see https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting\n   */\n  skipWaiting?: boolean;\n  /**\n   * Imports external scripts. They are executed in the order they\n   * are passed.\n   *\n   * @see https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts\n   */\n  importScripts?: string[];\n  /**\n   * Enables navigation preloading if it is supported.\n   *\n   * @see https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/navigationPreload\n   */\n  navigationPreload?: boolean;\n  /**\n   * Modifies the prefix of the default cache names used by Serwist packages.\n   */\n  cacheId?: string | undefined;\n  /**\n   * Claims any currently available clients once the service worker\n   * becomes active. This is normally used in conjunction with `skipWaiting()`.\n   *\n   * @default false\n   */\n  clientsClaim?: boolean;\n  /**\n   * A list of caching strategies.\n   */\n  runtimeCaching?: RuntimeCaching[];\n  /**\n   * Request rules that define how certain resources should be fetched\n   * before the service worker starts up.\n   *\n   * @see https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent/addRoutes\n   * @experimental\n   */\n  requestRules?: RequestRule | RequestRule[];\n  /**\n   * Your configuration for {@linkcode initializeGoogleAnalytics}. This plugin is\n   * only initialized when this option is not `undefined` or `false`.\n   */\n  offlineAnalyticsConfig?: Omit<GoogleAnalyticsInitializeOptions, \"serwist\"> | boolean;\n  /**\n   * Disables Serwist's logging in development mode.\n   *\n   * @default false\n   */\n  disableDevLogs?: boolean;\n  /**\n   * Precaches routes so that they can be used as a fallback when\n   * a {@linkcode Strategy} fails to generate a response.\n   *\n   * Note: This option mutates `runtimeCaching`. It also expects the URLs\n   * defined in `entries` to have been precached beforehand.\n   */\n  fallbacks?: FallbacksOptions;\n}\n\ntype RequestArgs = string | [string, RequestInit?];\n\ninterface CacheURLsMessageData {\n  type: string;\n  payload: {\n    urlsToCache: RequestArgs[];\n  };\n}\n\n/**\n * A class that helps bootstrap the service worker.\n *\n * @see https://serwist.pages.dev/docs/serwist/core/serwist\n */\nexport class Serwist {\n  private readonly _urlsToCacheKeys: Map<string, string> = new Map();\n  private readonly _urlsToCacheModes: Map<string, \"reload\" | \"default\" | \"no-store\" | \"no-cache\" | \"force-cache\" | \"only-if-cached\"> = new Map();\n  private readonly _cacheKeysToIntegrities: Map<string, string> = new Map();\n  private _concurrentPrecaching: number;\n  private readonly _precacheStrategy: Strategy;\n  private readonly _routes: Map<HTTPMethod, Route[]>;\n  private readonly _defaultHandlerMap: Map<HTTPMethod, RouteHandlerObject>;\n  private _catchHandler?: RouteHandlerObject;\n  private _requestRules?: RequestRule | RequestRule[];\n\n  constructor({\n    precacheEntries,\n    precacheOptions,\n    skipWaiting = false,\n    importScripts,\n    navigationPreload = false,\n    cacheId,\n    clientsClaim = false,\n    runtimeCaching,\n    offlineAnalyticsConfig,\n    disableDevLogs = false,\n    fallbacks,\n    requestRules,\n  }: SerwistOptions = {}) {\n    const { precacheStrategyOptions, precacheRouteOptions, precacheMiscOptions } = parsePrecacheOptions(this, precacheOptions);\n\n    this._concurrentPrecaching = precacheMiscOptions.concurrency;\n    this._precacheStrategy = new PrecacheStrategy(precacheStrategyOptions);\n    this._routes = new Map();\n    this._defaultHandlerMap = new Map();\n    this._requestRules = requestRules;\n\n    this.handleInstall = this.handleInstall.bind(this);\n    this.handleActivate = this.handleActivate.bind(this);\n    this.handleFetch = this.handleFetch.bind(this);\n    this.handleCache = this.handleCache.bind(this);\n\n    if (!!importScripts && importScripts.length > 0) self.importScripts(...importScripts);\n\n    if (navigationPreload) enableNavigationPreload();\n\n    if (cacheId !== undefined) {\n      setCacheNameDetails({\n        prefix: cacheId,\n      });\n    }\n\n    if (skipWaiting) {\n      self.skipWaiting();\n    } else {\n      self.addEventListener(\"message\", (event) => {\n        if (event.data && event.data.type === \"SKIP_WAITING\") {\n          self.skipWaiting();\n        }\n      });\n    }\n\n    if (clientsClaim) clientsClaimImpl();\n\n    if (!!precacheEntries && precacheEntries.length > 0) {\n      this.addToPrecacheList(precacheEntries);\n    }\n\n    if (precacheMiscOptions.cleanupOutdatedCaches) {\n      cleanupOutdatedCachesImpl(precacheStrategyOptions.cacheName);\n    }\n\n    this.registerRoute(new PrecacheRoute(this, precacheRouteOptions));\n\n    if (precacheMiscOptions.navigateFallback) {\n      this.registerRoute(\n        new NavigationRoute(this.createHandlerBoundToUrl(precacheMiscOptions.navigateFallback), {\n          allowlist: precacheMiscOptions.navigateFallbackAllowlist,\n          denylist: precacheMiscOptions.navigateFallbackDenylist,\n        }),\n      );\n    }\n\n    if (offlineAnalyticsConfig !== undefined) {\n      if (typeof offlineAnalyticsConfig === \"boolean\") {\n        offlineAnalyticsConfig && initializeGoogleAnalytics({ serwist: this });\n      } else {\n        initializeGoogleAnalytics({\n          ...offlineAnalyticsConfig,\n          serwist: this,\n        });\n      }\n    }\n\n    if (runtimeCaching !== undefined) {\n      if (fallbacks !== undefined) {\n        const fallbackPlugin = new PrecacheFallbackPlugin({\n          fallbackUrls: fallbacks.entries,\n          serwist: this,\n        });\n\n        runtimeCaching.forEach((cacheEntry) => {\n          if (\n            cacheEntry.handler instanceof Strategy &&\n            // This also filters entries with `PrecacheFallbackPlugin` as it also has `handlerDidError`.\n            !cacheEntry.handler.plugins.some((plugin) => \"handlerDidError\" in plugin)\n          ) {\n            cacheEntry.handler.plugins.push(fallbackPlugin);\n          }\n        });\n      }\n      for (const entry of runtimeCaching) {\n        this.registerCapture(entry.matcher, entry.handler, entry.method);\n      }\n    }\n\n    if (disableDevLogs) disableDevLogsImpl();\n  }\n\n  /**\n   * The strategy used to precache assets and respond to `fetch` events.\n   */\n  get precacheStrategy(): Strategy {\n    return this._precacheStrategy;\n  }\n  /**\n   * A `Map` of HTTP method name (`'GET'`, etc.) to an array of all corresponding registered {@linkcode Route}\n   * instances.\n   */\n  get routes(): Map<HTTPMethod, Route[]> {\n    return this._routes;\n  }\n\n  /**\n   * Adds Serwist's event listeners for you. Before calling it, add your own listeners should you need to.\n   */\n  addEventListeners() {\n    self.addEventListener(\"install\", this.handleInstall);\n    self.addEventListener(\"activate\", this.handleActivate);\n    self.addEventListener(\"fetch\", this.handleFetch);\n    self.addEventListener(\"message\", this.handleCache);\n  }\n\n  /**\n   * Adds items to the precache list, removing duplicates and ensuring the information is valid.\n   *\n   * @param entries Array of entries to precache.\n   */\n  addToPrecacheList(entries: (PrecacheEntry | string)[]): void {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isArray(entries, {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"addToCacheList\",\n        paramName: \"entries\",\n      });\n    }\n\n    const urlsToWarnAbout: string[] = [];\n    for (const entry of entries) {\n      // See https://github.com/GoogleChrome/workbox/issues/2259\n      if (typeof entry === \"string\") {\n        urlsToWarnAbout.push(entry);\n      } else if (entry && !entry.integrity && entry.revision === undefined) {\n        urlsToWarnAbout.push(entry.url);\n      }\n\n      const { cacheKey, url } = createCacheKey(entry);\n      const cacheMode = typeof entry !== \"string\" && entry.revision ? \"reload\" : \"default\";\n\n      if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) {\n        throw new SerwistError(\"add-to-cache-list-conflicting-entries\", {\n          firstEntry: this._urlsToCacheKeys.get(url),\n          secondEntry: cacheKey,\n        });\n      }\n\n      if (typeof entry !== \"string\" && entry.integrity) {\n        if (this._cacheKeysToIntegrities.has(cacheKey) && this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity) {\n          throw new SerwistError(\"add-to-cache-list-conflicting-integrities\", {\n            url,\n          });\n        }\n        this._cacheKeysToIntegrities.set(cacheKey, entry.integrity);\n      }\n\n      this._urlsToCacheKeys.set(url, cacheKey);\n      this._urlsToCacheModes.set(url, cacheMode);\n    }\n    if (urlsToWarnAbout.length > 0) {\n      const warningMessage = `Serwist is precaching URLs without revision info: ${urlsToWarnAbout.join(\n        \", \",\n      )}\\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;\n      if (process.env.NODE_ENV === \"production\") {\n        // Use console directly to display this warning without bloating\n        // bundle sizes by pulling in all of the logger codebase in prod.\n        console.warn(warningMessage);\n      } else {\n        logger.warn(warningMessage);\n      }\n    }\n  }\n\n  /**\n   * Precaches new and updated assets. Call this method from the service worker's\n   * `install` event.\n   *\n   * Note: this method calls `event.waitUntil()` for you, so you do not need\n   * to call it yourself in your event handlers.\n   *\n   * @param event\n   * @returns\n   */\n  handleInstall(event: InstallEvent): Promise<InstallResult> {\n    void this.registerRequestRules(event);\n\n    return waitUntil<InstallResult>(event, async () => {\n      const installReportPlugin = new PrecacheInstallReportPlugin();\n      this.precacheStrategy.plugins.push(installReportPlugin);\n\n      await parallel(this._concurrentPrecaching, Array.from(this._urlsToCacheKeys.entries()), async ([url, cacheKey]): Promise<void> => {\n        const integrity = this._cacheKeysToIntegrities.get(cacheKey);\n        const cacheMode = this._urlsToCacheModes.get(url);\n\n        const request = new Request(url, {\n          integrity,\n          cache: cacheMode,\n          credentials: \"same-origin\",\n        });\n\n        await Promise.all(\n          this.precacheStrategy.handleAll({\n            event,\n            request,\n            url: new URL(request.url),\n            params: { cacheKey },\n          }),\n        );\n      });\n\n      const { updatedURLs, notUpdatedURLs } = installReportPlugin;\n\n      if (process.env.NODE_ENV !== \"production\") {\n        printInstallDetails(updatedURLs, notUpdatedURLs);\n      }\n\n      return { updatedURLs, notUpdatedURLs };\n    });\n  }\n\n  /**\n   * Registers request rules using the experimental `InstallEvent.addRoutes()` API.\n   * These rules allow bypassing the service worker for specific requests to improve performance.\n   *\n   * @param event The event object of an `install` event handler.\n   * @throws {Error} When the route rules are invalid\n   */\n  async registerRequestRules(event: InstallEvent): Promise<void> {\n    if (!this._requestRules) {\n      return;\n    }\n\n    // Check if both the API and route rules are available\n    if (!event?.addRoutes) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.warn(\n          \"Request rules ignored as the Static Routing API is not supported in this browser. \" +\n            \"See https://caniuse.com/mdn-api_installevent_addroutes for more information.\",\n        );\n      }\n      return;\n    }\n\n    try {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.warn(\n          \"Request rules may not be supported in all browsers as the Static Routing API is experimental. \" +\n            \"This feature allows bypassing the service worker for specific requests to improve performance. \" +\n            \"See https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent/addRoutes for more information.\",\n        );\n      }\n\n      await event.addRoutes(this._requestRules);\n\n      // Free up the rules object.\n      this._requestRules = undefined;\n    } catch (error) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.error(\n          `Failed to register request rules: ${error instanceof Error ? error.message : String(error)}. ` +\n            \"This may occur if the browser doesn't support the Static Routing API or if the request rules are invalid.\",\n        );\n      }\n\n      throw error;\n    }\n  }\n\n  /**\n   * Deletes assets that are no longer present in the current precache manifest.\n   * Call this method from the service worker's `activate` event.\n   *\n   * Note: this method calls `event.waitUntil()` for you, so you do not need\n   * to call it yourself in your event handlers.\n   *\n   * @param event\n   * @returns\n   */\n  handleActivate(event: ExtendableEvent): Promise<CleanupResult> {\n    return waitUntil<CleanupResult>(event, async () => {\n      const cache = await self.caches.open(this.precacheStrategy.cacheName);\n      const currentlyCachedRequests = await cache.keys();\n      const expectedCacheKeys = new Set(this._urlsToCacheKeys.values());\n\n      const deletedCacheRequests: string[] = [];\n\n      for (const request of currentlyCachedRequests) {\n        if (!expectedCacheKeys.has(request.url)) {\n          await cache.delete(request);\n          deletedCacheRequests.push(request.url);\n        }\n      }\n\n      if (process.env.NODE_ENV !== \"production\") {\n        printCleanupDetails(deletedCacheRequests);\n      }\n\n      return { deletedCacheRequests };\n    });\n  }\n\n  /**\n   * Gets a `Response` from an appropriate `Route`'s handler. Call this method\n   * from the service worker's `fetch` event.\n   * @param event\n   */\n  handleFetch(event: FetchEvent) {\n    const { request } = event;\n    const responsePromise = this.handleRequest({ request, event });\n    if (responsePromise) {\n      event.respondWith(responsePromise);\n    }\n  }\n\n  /**\n   * Caches new URLs on demand. Call this method from the service worker's\n   * `message` event. To trigger the handler, send a message of type `\"CACHE_URLS\"`\n   * alongside a list of URLs that should be cached as `urlsToCache`.\n   * @param event\n   */\n  handleCache(event: ExtendableMessageEvent) {\n    if (event.data && event.data.type === \"CACHE_URLS\") {\n      const { payload }: CacheURLsMessageData = event.data;\n\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(\"Caching URLs from the window\", payload.urlsToCache);\n      }\n\n      const requestPromises = Promise.all(\n        payload.urlsToCache.map((entry: string | [string, RequestInit?]) => {\n          let request: Request;\n          if (typeof entry === \"string\") {\n            request = new Request(entry);\n          } else {\n            request = new Request(...entry);\n          }\n          return this.handleRequest({ request, event });\n        }),\n      );\n\n      event.waitUntil(requestPromises);\n\n      // If a MessageChannel was used, reply to the message on success.\n      if (event.ports?.[0]) {\n        void requestPromises.then(() => event.ports[0].postMessage(true));\n      }\n    }\n  }\n\n  /**\n   * Define a default handler that's called when no routes explicitly\n   * match the incoming request.\n   *\n   * Each HTTP method (`'GET'`, `'POST'`, etc.) gets its own default handler.\n   *\n   * Without a default handler, unmatched requests will go against the\n   * network as if there were no service worker present.\n   *\n   * @param handler A callback function that returns a `Promise` resulting in a `Response`.\n   * @param method The HTTP method to associate with this default handler. Each method\n   * has its own default. Defaults to `'GET'`.\n   */\n  setDefaultHandler(handler: RouteHandler, method: HTTPMethod = defaultMethod): void {\n    this._defaultHandlerMap.set(method, normalizeHandler(handler));\n  }\n\n  /**\n   * If a {@linkcode Route} throws an error while handling a request, this handler\n   * will be called and given a chance to provide a response.\n   *\n   * @param handler A callback function that returns a `Promise` resulting\n   * in a `Response`.\n   */\n  setCatchHandler(handler: RouteHandler): void {\n    this._catchHandler = normalizeHandler(handler);\n  }\n\n  /**\n   * Registers a `RegExp`, string, or function with a caching\n   * strategy to the router.\n   *\n   * @param capture If the capture param is a {@linkcode Route} object, all other arguments will be ignored.\n   * @param handler A callback function that returns a `Promise` resulting in a `Response`.\n   * This parameter is required if `capture` is not a {@linkcode Route} object.\n   * @param method The HTTP method to match the route against. Defaults to `'GET'`.\n   * @returns The generated {@linkcode Route} object.\n   */\n  registerCapture<T extends RegExp | string | RouteMatchCallback | Route>(\n    capture: T,\n    handler?: T extends Route ? never : RouteHandler,\n    method?: T extends Route ? never : HTTPMethod,\n  ): Route {\n    const route = parseRoute(capture, handler, method);\n    this.registerRoute(route);\n    return route;\n  }\n\n  /**\n   * Registers a {@linkcode Route} with the router.\n   *\n   * @param route The {@linkcode Route} to register.\n   */\n  registerRoute(route: Route): void {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(route, \"object\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route\",\n      });\n\n      assert!.hasMethod(route, \"match\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route\",\n      });\n\n      assert!.isType(route.handler, \"object\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route\",\n      });\n\n      assert!.hasMethod(route.handler, \"handle\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route.handler\",\n      });\n\n      assert!.isType(route.method, \"string\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route.method\",\n      });\n    }\n\n    if (!this._routes.has(route.method)) {\n      this._routes.set(route.method, []);\n    }\n\n    // Give precedence to all of the earlier routes by adding this additional\n    // route to the end of the array.\n    this._routes.get(route.method)!.push(route);\n  }\n\n  /**\n   * Unregisters a route from the router.\n   *\n   * @param route The {@linkcode Route} object to unregister.\n   */\n  unregisterRoute(route: Route): void {\n    if (!this._routes.has(route.method)) {\n      throw new SerwistError(\"unregister-route-but-not-found-with-method\", {\n        method: route.method,\n      });\n    }\n\n    const routeIndex = this._routes.get(route.method)!.indexOf(route);\n    if (routeIndex > -1) {\n      this._routes.get(route.method)!.splice(routeIndex, 1);\n    } else {\n      throw new SerwistError(\"unregister-route-route-not-registered\");\n    }\n  }\n\n  /**\n   * Returns a mapping of a precached URL to the corresponding cache key, taking\n   * into account the revision information for the URL.\n   *\n   * @returns A URL to cache key mapping.\n   */\n  getUrlsToPrecacheKeys(): Map<string, string> {\n    return this._urlsToCacheKeys;\n  }\n\n  /**\n   * Returns a list of all the URLs that have been precached by the current\n   * service worker.\n   *\n   * @returns The precached URLs.\n   */\n  getPrecachedUrls(): string[] {\n    return [...this._urlsToCacheKeys.keys()];\n  }\n\n  /**\n   * Returns the cache key used for storing a given URL. If that URL is\n   * unversioned, like \"/index.html\", then the cache key will be the original\n   * URL with a search parameter appended to it.\n   *\n   * @param url A URL whose cache key you want to look up.\n   * @returns The versioned URL that corresponds to a cache key\n   * for the original URL, or undefined if that URL isn't precached.\n   */\n  getPrecacheKeyForUrl(url: string): string | undefined {\n    const urlObject = new URL(url, location.href);\n    return this._urlsToCacheKeys.get(urlObject.href);\n  }\n\n  /**\n   * @param url A cache key whose SRI you want to look up.\n   * @returns The subresource integrity associated with the cache key,\n   * or undefined if it's not set.\n   */\n  getIntegrityForPrecacheKey(cacheKey: string): string | undefined {\n    return this._cacheKeysToIntegrities.get(cacheKey);\n  }\n\n  /**\n   * This acts as a drop-in replacement for\n   * [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)\n   * with the following differences:\n   *\n   * - It knows what the name of the precache is, and only checks in that cache.\n   * - It allows you to pass in an \"original\" URL without versioning parameters,\n   * and it will automatically look up the correct cache key for the currently\n   * active revision of that URL.\n   *\n   * E.g., `matchPrecache('index.html')` will find the correct precached\n   * response for the currently active service worker, even if the actual cache\n   * key is `'/index.html?__WB_REVISION__=1234abcd'`.\n   *\n   * @param request The key (without revisioning parameters)\n   * to look up in the precache.\n   * @returns\n   */\n  async matchPrecache(request: string | Request): Promise<Response | undefined> {\n    const url = request instanceof Request ? request.url : request;\n    const cacheKey = this.getPrecacheKeyForUrl(url);\n    if (cacheKey) {\n      const cache = await self.caches.open(this.precacheStrategy.cacheName);\n      return cache.match(cacheKey);\n    }\n    return undefined;\n  }\n\n  /**\n   * Returns a function that looks up `url` in the precache (taking into\n   * account revision information), and returns the corresponding `Response`.\n   *\n   * @param url The precached URL which will be used to lookup the response.\n   * @return\n   */\n  createHandlerBoundToUrl(url: string): RouteHandlerCallback {\n    const cacheKey = this.getPrecacheKeyForUrl(url);\n    if (!cacheKey) {\n      throw new SerwistError(\"non-precached-url\", { url });\n    }\n    return (options) => {\n      options.request = new Request(url);\n      options.params = { cacheKey, ...options.params };\n\n      return this.precacheStrategy.handle(options);\n    };\n  }\n\n  /**\n   * Applies the routing rules to a `FetchEvent` object to get a response from an\n   * appropriate route.\n   *\n   * @param options\n   * @returns A promise is returned if a registered route can handle the request.\n   * If there is no matching route and there's no default handler, `undefined`\n   * is returned.\n   */\n  handleRequest({\n    request,\n    event,\n  }: {\n    /**\n     * The request to handle.\n     */\n    request: Request;\n    /**\n     * The event that triggered the request.\n     */\n    event: ExtendableEvent;\n  }): Promise<Response> | undefined {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"handleRequest\",\n        paramName: \"options.request\",\n      });\n    }\n\n    const url = new URL(request.url, location.href);\n    if (!url.protocol.startsWith(\"http\")) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(\"Router only supports URLs that start with 'http'.\");\n      }\n      return;\n    }\n\n    const sameOrigin = url.origin === location.origin;\n    const { params, route } = this.findMatchingRoute({\n      event,\n      request,\n      sameOrigin,\n      url,\n    });\n    let handler = route?.handler;\n\n    const debugMessages = [];\n    if (process.env.NODE_ENV !== \"production\") {\n      if (handler) {\n        debugMessages.push([\"Found a route to handle this request:\", route]);\n\n        if (params) {\n          debugMessages.push([`Passing the following params to the route's handler:`, params]);\n        }\n      }\n    }\n\n    // If we don't have a handler because there was no matching route, then\n    // fall back to defaultHandler if that's defined.\n    const method = request.method as HTTPMethod;\n    if (!handler && this._defaultHandlerMap.has(method)) {\n      if (process.env.NODE_ENV !== \"production\") {\n        debugMessages.push(`Failed to find a matching route. Falling back to the default handler for ${method}.`);\n      }\n      handler = this._defaultHandlerMap.get(method);\n    }\n\n    if (!handler) {\n      if (process.env.NODE_ENV !== \"production\") {\n        // No handler so Serwist will do nothing. If logs is set of debug\n        // i.e. verbose, we should print out this information.\n        logger.debug(`No route found for: ${getFriendlyURL(url)}`);\n      }\n      return;\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      // We have a handler, meaning Serwist is going to handle the route.\n      // print the routing details to the console.\n      logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`);\n\n      for (const msg of debugMessages) {\n        if (Array.isArray(msg)) {\n          logger.log(...msg);\n        } else {\n          logger.log(msg);\n        }\n      }\n\n      logger.groupEnd();\n    }\n\n    // Wrap in try and catch in case the handle method throws a synchronous\n    // error. It should still callback to the catch handler.\n    let responsePromise: Promise<Response>;\n    try {\n      responsePromise = handler.handle({ url, request, event, params });\n    } catch (err) {\n      responsePromise = Promise.reject(err);\n    }\n\n    // Get route's catch handler, if it exists\n    const catchHandler = route?.catchHandler;\n\n    if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) {\n      responsePromise = responsePromise.catch(async (err) => {\n        // If there's a route catch handler, process that first\n        if (catchHandler) {\n          if (process.env.NODE_ENV !== \"production\") {\n            // Still include URL here as it will be async from the console group\n            // and may not make sense without the URL\n            logger.groupCollapsed(`Error thrown when responding to:  ${getFriendlyURL(url)}. Falling back to route's Catch Handler.`);\n            logger.error(\"Error thrown by:\", route);\n            logger.error(err);\n            logger.groupEnd();\n          }\n\n          try {\n            return await catchHandler.handle({ url, request, event, params });\n          } catch (catchErr) {\n            if (catchErr instanceof Error) {\n              err = catchErr;\n            }\n          }\n        }\n\n        if (this._catchHandler) {\n          if (process.env.NODE_ENV !== \"production\") {\n            // Still include URL here as it will be async from the console group\n            // and may not make sense without the URL\n            logger.groupCollapsed(`Error thrown when responding to:  ${getFriendlyURL(url)}. Falling back to global Catch Handler.`);\n            logger.error(\"Error thrown by:\", route);\n            logger.error(err);\n            logger.groupEnd();\n          }\n          return this._catchHandler.handle({ url, request, event });\n        }\n\n        throw err;\n      });\n    }\n\n    return responsePromise;\n  }\n\n  /**\n   * Checks a request and URL (and optionally an event) against the list of\n   * registered routes, and if there's a match, returns the corresponding\n   * route along with any params generated by the match.\n   *\n   * @param options\n   * @returns An object with `route` and `params` properties. They are populated\n   * if a matching route was found or `undefined` otherwise.\n   */\n  findMatchingRoute({ url, sameOrigin, request, event }: RouteMatchCallbackOptions): {\n    route?: Route;\n    params?: RouteHandlerCallbackOptions[\"params\"];\n  } {\n    const routes = this._routes.get(request.method as HTTPMethod) || [];\n    for (const route of routes) {\n      let params: Promise<any> | undefined;\n      // route.match returns type any, not possible to change right now.\n      const matchResult = route.match({ url, sameOrigin, request, event });\n      if (matchResult) {\n        if (process.env.NODE_ENV !== \"production\") {\n          // Warn developers that using an async matchCallback is almost always\n          // not the right thing to do.\n          if (matchResult instanceof Promise) {\n            logger.warn(\n              `While routing ${getFriendlyURL(\n                url,\n              )}, an async matchCallback function was used. Please convert the following route to use a synchronous matchCallback function:`,\n              route,\n            );\n          }\n        }\n\n        // See https://github.com/GoogleChrome/workbox/issues/2079\n        params = matchResult;\n        if (Array.isArray(params) && params.length === 0) {\n          // Instead of passing an empty array in as params, use undefined.\n          params = undefined;\n        } else if (matchResult.constructor === Object && Object.keys(matchResult).length === 0) {\n          // Instead of passing an empty object in as params, use undefined.\n          params = undefined;\n        } else if (typeof matchResult === \"boolean\") {\n          // For the boolean value true (rather than just something truth-y),\n          // don't set params.\n          // See https://github.com/GoogleChrome/workbox/pull/2134#issuecomment-513924353\n          params = undefined;\n        }\n\n        // Return early if have a match.\n        return { route, params };\n      }\n    }\n    // If no match was found above, return and empty object.\n    return {};\n  }\n}\n", "import type { PrecacheEntry, SerwistGlobalConfig } from \"serwist\";\nimport { CacheableResponsePlugin, CacheFirst, ExpirationPlugin, NetworkFirst, Serwist, StaleWhileRevalidate } from \"serwist\";\n\ndeclare global {\n\tinterface WorkerGlobalScope extends SerwistGlobalConfig {\n\t\t__SW_MANIFEST: (PrecacheEntry | string)[] | undefined;\n\t}\n}\n\ndeclare const self: ServiceWorkerGlobalScope;\n\nconst serwist = new Serwist({\n\tprecacheEntries: self.__SW_MANIFEST,\n\tskipWaiting: true,\n\tclientsClaim: true,\n\tnavigationPreload: false,\n\truntimeCaching: [\n\t\t{\n\t\t\tmatcher: /^\\/images\\/map_tiles\\/.*\\.(jpg|jpeg)$/,\n\t\t\thandler: new CacheFirst({\n\t\t\t\tcacheName: \"map-tiles-cache\",\n\t\t\t\tplugins: [\n\t\t\t\t\tnew ExpirationPlugin({\n\t\t\t\t\t\tmaxEntries: 1500,\n\t\t\t\t\t\tmaxAgeSeconds: 60 * 60 * 24 * 30, // 30 days\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tmatcher: /\\/_next\\/data\\/.*\\.json/,\n\t\t\thandler: new StaleWhileRevalidate({\n\t\t\t\tcacheName: \"next-data-cache\",\n\t\t\t\tplugins: [\n\t\t\t\t\tnew ExpirationPlugin({\n\t\t\t\t\t\tmaxEntries: 100,\n\t\t\t\t\t\tmaxAgeSeconds: 60 * 60 * 24, // 1 day\n\t\t\t\t\t}),\n\t\t\t\t\tnew CacheableResponsePlugin({ statuses: [0, 200] }),\n\t\t\t\t],\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tmatcher: /\\.(?:png|jpg|jpeg|svg|webp|woff2?)$/,\n\t\t\thandler: new CacheFirst({\n\t\t\t\tcacheName: \"images\",\n\t\t\t\tplugins: [\n\t\t\t\t\tnew ExpirationPlugin({\n\t\t\t\t\t\tmaxEntries: 60,\n\t\t\t\t\t\tmaxAgeSeconds: 60 * 60 * 24 * 30, // 30 days\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tmatcher: /\\.(?:js|css)$/,\n\t\t\thandler: new StaleWhileRevalidate({\n\t\t\t\tcacheName: \"static-resources\",\n\t\t\t}),\n\t\t},\n\t\t// TRPC API\n\t\t{\n\t\t\tmatcher: /^\\/api\\/trpc\\/.*/,\n\t\t\thandler: new NetworkFirst({\n\t\t\t\tcacheName: \"trpc-cache\",\n\t\t\t\tnetworkTimeoutSeconds: 5,\n\t\t\t\tplugins: [\n\t\t\t\t\tnew ExpirationPlugin({\n\t\t\t\t\t\tmaxEntries: 100,\n\t\t\t\t\t\tmaxAgeSeconds: 60 * 5, // 5 minutes\n\t\t\t\t\t}),\n\t\t\t\t\tnew CacheableResponsePlugin({ statuses: [0, 200] }),\n\t\t\t\t],\n\t\t\t}),\n\t\t},\n\t],\n});\n\nserwist.addEventListeners();\n"],
  "mappings": "wKAAA,IAAAA,EAAA,CACE,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,4CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,4CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,4CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,2CACP,SAAY,IACd,EACA,CACE,IAAO,sDACP,SAAY,IACd,EACA,CACE,IAAO,qEACP,SAAY,IACd,EACA,CACE,IAAO,wDACP,SAAY,IACd,EACA,CACE,IAAO,iBACP,SAAY,kCACd,EACA,CACE,IAAO,eACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,2BACP,SAAY,kCACd,EACA,CACE,IAAO,4BACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,4BACP,SAAY,kCACd,EACA,CACE,IAAO,0BACP,SAAY,kCACd,EACA,CACE,IAAO,6BACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,wBACP,SAAY,kCACd,EACA,CACE,IAAO,oBACP,SAAY,kCACd,EACA,CACE,IAAO,6BACP,SAAY,kCACd,EACA,CACE,IAAO,sBACP,SAAY,kCACd,EACA,CACE,IAAO,oBACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,0BACP,SAAY,kCACd,EACA,CACE,IAAO,0BACP,SAAY,kCACd,EACA,CACE,IAAO,2BACP,SAAY,kCACd,EACA,CACE,IAAO,2BACP,SAAY,kCACd,EACA,CACE,IAAO,8BACP,SAAY,kCACd,CACF,EClhBA,IAAMC,EAAsC,CAC1C,gBAAiB,kBACjB,SAAU,cACV,OAAQ,UACR,QAAS,UACT,OAAQ,OAAO,aAAiB,IAAc,aAAa,MAAQ,EACrE,EAEMC,EAAoBC,GACjB,CAACF,EAAkB,OAAQE,EAAWF,EAAkB,MAAM,EAAE,OAAQG,GAAUA,GAASA,EAAM,OAAS,CAAC,EAAE,KAAK,GAAG,EAGxHC,GAAuBC,GAAkD,CAC7E,QAAWC,KAAO,OAAO,KAAKN,CAAiB,EAC7CK,EAAGC,CAA2B,CAElC,EAEaC,EAAa,CACxB,cAAgBC,GAA2C,CAC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",
  "names": ["define_self_SW_MANIFEST_default", "_cacheNameDetails", "_createCacheName", "cacheName", "value", "eachCacheNameDetail", "fn", "key", "cacheNames", "details", "detail", "userCacheName", "supportStatus", "canConstructResponseFromBodyStream", "testResponse", "e", "fallback", "code", "args", "msg", "messageGenerator", "fallback", "SerwistError", "errorCode", "details", "message", "__publicField", "getFriendlyURL", "url", "timeout", "ms", "resolve", "quotaErrorCallbacks", "stripParams", "fullURL", "ignoreParams", "strippedURL", "param", "cacheMatchIgnoreParams", "cache", "request", "matchOptions", "strippedRequestURL", "keysOptions", "cacheKeys", "cacheKey", "Deferred", "__publicField", "reject", "executeQuotaErrorCallbacks", "callback", "SUBSTRING_TO_FIND", "deleteOutdatedCaches", "currentPrecacheName", "substringToFind", "cacheNamesToDelete", "cacheName", "cleanupOutdatedCaches", "event", "privateCacheNames", "cachesDeleted", "clientsClaim", "waitUntil", "asyncFn", "returnPromise", "instanceOfAny", "object", "constructors", "c", "idbProxyableTypes", "cursorAdvanceMethods", "getIdbProxyableTypes", "getCursorAdvanceMethods", "transactionDoneMap", "transformCache", "reverseTransformCache", "promisifyRequest", "request", "promise", "resolve", "reject", "unlisten", "success", "error", "wrap", "cacheDonePromiseForTransaction", "tx", "done", "complete", "idbProxyTraps", "target", "prop", "receiver", "value", "replaceTraps", "callback", "wrapFunction", "func", "args", "unwrap", "transformCachableValue", "newValue", "openDB", "name", "version", "blocked", "upgrade", "blocking", "terminated", "openPromise", "event", "db", "deleteDB", "readMethods", "writeMethods", "cachedMethods", "getMethod", "targetFuncName", "useIndex", "isWrite", "method", "storeName", "oldTraps", "advanceMethodProps", "methodMap", "advanceResults", "ittrProxiedCursorToOriginalProxy", "cursorIteratorTraps", "cachedFunc", "iterate", "cursor", "proxiedCursor", "isIteratorProp", "copyResponse", "response", "modifier", "origin", "SerwistError", "clonedResponse", "responseInit", "modifiedResponseInit", "body", "canConstructResponseFromBodyStream", "disableDevLogs", "BACKGROUND_SYNC_DB_VERSION", "BACKGROUND_SYNC_DB_NAME", "REQUEST_OBJECT_STORE_NAME", "QUEUE_NAME_INDEX", "BackgroundSyncQueueDb", "__publicField", "entry", "tx", "_a", "queueName", "results", "id", "query", "direction", "openDB", "db", "oldVersion", "BackgroundSyncQueueStore", "firstId", "serializableProperties", "StorableRequest", "requestData", "request", "value", "key", "prop", "TAG_PREFIX", "MAX_RETENTION_TIME", "queueNames", "convertEntry", "queueStoreEntry", "queueEntry", "BackgroundSyncQueue", "name", "forceSyncFallback", "onSync", "maxRetentionTime", "allEntries", "now", "unexpiredEntries", "maxRetentionTimeInMs", "metadata", "timestamp", "operation", "e", "err", "event", "syncComplete", "syncError", "error", "BackgroundSyncPlugin", "options", "cacheOkAndOpaquePlugin", "toRequest", "input", "StrategyHandler", "strategy", "Deferred", "plugin", "preloadResponse", "originalRequest", "cb", "pluginFilteredRequest", "fetchResponse", "callback", "responseClone", "cachedResponse", "cacheName", "matchOptions", "effectiveRequest", "multiMatchOptions", "timeout", "getFriendlyURL", "responseToCache", "cache", "hasCacheUpdateCallback", "oldResponse", "cacheMatchIgnoreParams", "executeQuotaErrorCallbacks", "mode", "param", "state", "statefulParam", "promise", "possiblePreloadResponse", "pluginsUsed", "Strategy", "privateCacheNames", "responseDone", "handler", "waitUntilError", "NetworkFirst", "Strategy", "options", "__publicField", "p", "cacheOkAndOpaquePlugin", "request", "handler", "logs", "promises", "timeoutId", "id", "promise", "networkPromise", "response", "SerwistError", "resolve", "error", "fetchError", "NetworkOnly", "timeoutPromise", "timeout", "err", "normalizeHandler", "handler", "Route", "match", "method", "__publicField", "PrecacheStrategy", "_a", "Strategy", "options", "privateCacheNames", "request", "preloadResponse", "response", "params", "integrityInManifest", "integrityInRequest", "noIntegrityConflict", "wasCached", "SerwistError", "defaultPluginIndex", "cacheWillUpdatePluginCount", "index", "plugin", "copyResponse", "NavigationRoute", "allowlist", "denylist", "url", "pathnameAndSearch", "regExp", "isNavigationPreloadSupported", "enableNavigationPreload", "headerValue", "event", "removeIgnoredSearchParams", "urlObject", "ignoreURLParametersMatching", "paramName", "regExp", "generateURLVariations", "url", "directoryIndex", "cleanURLs", "urlManipulation", "urlWithoutIgnoredParams", "directoryURL", "cleanURL", "additionalURLs", "urlToAttempt", "RegExpRoute", "Route", "handler", "method", "match", "result", "setCacheNameDetails", "details", "cacheNames", "REVISION_SEARCH_PARAM", "createCacheKey", "entry", "SerwistError", "revision", "cacheKeyURL", "originalURL", "PrecacheInstallReportPlugin", "__publicField", "request", "state", "event", "cachedResponse", "parseRoute", "capture", "captureUrl", "matchCallback", "parallel", "limit", "array", "func", "work", "item", "index", "processor", "res", "results", "next", "result", "queues", "a", "b", "isSafari", "CacheableResponse", "config", "__publicField", "response", "cacheable", "headerName", "headerValue", "CacheableResponsePlugin", "DB_NAME", "CACHE_OBJECT_STORE", "normalizeURL", "unNormalizedUrl", "url", "CacheTimestampsModel", "cacheName", "db", "objStore", "deleteDB", "timestamp", "entry", "tx", "_a", "minTimestamp", "maxCount", "cursor", "urlsDeleted", "entriesNotDeletedCount", "result", "openDB", "CacheExpiration", "urlsExpired", "cache", "expireOlderThan", "registerQuotaErrorCallback", "callback", "quotaErrorCallbacks", "ExpirationPlugin", "privateCacheNames", "SerwistError", "cacheExpiration", "event", "request", "cachedResponse", "isFresh", "isMaxAgeFromLastUsed", "done", "e", "now", "dateHeaderTimestamp", "dateHeader", "headerTime", "QUEUE_NAME", "MAX_RETENTION_TIME", "COLLECT_PATHS_REGEX", "createOnSyncCallback", "queue", "params", "originalHitTime", "queueTime", "param", "value", "err", "createCollectRoutes", "bgSyncPlugin", "match", "handler", "NetworkOnly", "Route", "createAnalyticsJsRoute", "NetworkFirst", "createGtagJsRoute", "createGtmJsRoute", "initializeGoogleAnalytics", "serwist", "options", "resolvedCacheName", "BackgroundSyncPlugin", "routes", "route", "PrecacheFallbackPlugin", "fallbackUrls", "fallback", "fallbackResponse", "CacheFirst", "Strategy", "request", "handler", "logs", "response", "error", "err", "SerwistError", "StaleWhileRevalidate", "Strategy", "options", "p", "cacheOkAndOpaquePlugin", "request", "handler", "logs", "fetchAndCachePromise", "response", "error", "err", "SerwistError", "PrecacheRoute", "Route", "serwist", "match", "urlsToCacheKeys", "possibleURL", "generateURLVariations", "cacheKey", "PrecacheCacheKeyPlugin", "precacheController", "__publicField", "params", "parsePrecacheOptions", "precacheOptions", "precacheCacheName", "precachePlugins", "precacheFetchOptions", "precacheMatchOptions", "precacheFallbackToNetwork", "precacheDirectoryIndex", "precacheIgnoreUrls", "precacheCleanUrls", "precacheUrlManipulation", "cleanupOutdatedCaches", "concurrency", "navigateFallback", "navigateFallbackAllowlist", "navigateFallbackDenylist", "privateCacheNames", "Serwist", "precacheEntries", "skipWaiting", "importScripts", "navigationPreload", "cacheId", "clientsClaim$1", "runtimeCaching", "offlineAnalyticsConfig", "disableDevLogs$1", "fallbacks", "requestRules", "precacheStrategyOptions", "precacheRouteOptions", "precacheMiscOptions", "PrecacheStrategy", "enableNavigationPreload", "setCacheNameDetails", "event", "clientsClaim", "NavigationRoute", "initializeGoogleAnalytics", "fallbackPlugin", "PrecacheFallbackPlugin", "cacheEntry", "plugin", "entry", "disableDevLogs", "entries", "urlsToWarnAbout", "url", "createCacheKey", "cacheMode", "warningMessage", "waitUntil", "installReportPlugin", "PrecacheInstallReportPlugin", "parallel", "integrity", "updatedURLs", "notUpdatedURLs", "cache", "currentlyCachedRequests", "expectedCacheKeys", "deletedCacheRequests", "responsePromise", "payload", "requestPromises", "_a", "method", "normalizeHandler", "capture", "route", "parseRoute", "routeIndex", "urlObject", "sameOrigin", "debugMessages", "catchHandler", "catchErr", "routes", "matchResult", "serwist", "Serwist", "define_self_SW_MANIFEST_default", "CacheFirst", "ExpirationPlugin", "StaleWhileRevalidate", "CacheableResponsePlugin", "NetworkFirst"]
}
