{
  "version": 3,
  "sources": ["<define:self.__SW_MANIFEST>", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/cacheNames.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/canConstructResponseFromBodyStream.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/models/messages/messages.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/models/messages/messageGenerator.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/SerwistError.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/assert.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/getFriendlyURL.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/logger.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/timeout.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/models/quotaErrorCallbacks.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/cacheMatchIgnoreParams.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/Deferred.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/executeQuotaErrorCallbacks.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/deleteOutdatedCaches.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/cleanupOutdatedCaches.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/clientsClaim.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/waitUntil.ts", "node_modules/idb/build/index.js", "node_modules/@serwist/turbopack/node_modules/serwist/src/copyResponse.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/disableDevLogs.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/backgroundSync/BackgroundSyncQueueDb.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/backgroundSync/BackgroundSyncQueueStore.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/backgroundSync/StorableRequest.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/backgroundSync/BackgroundSyncQueue.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/backgroundSync/BackgroundSyncPlugin.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/plugins/cacheOkAndOpaquePlugin.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/StrategyHandler.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/Strategy.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/utils/messages.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/NetworkFirst.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/NetworkOnly.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/constants.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/normalizeHandler.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/Route.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/PrecacheStrategy.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/NavigationRoute.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/navigationPreload.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/removeIgnoredSearchParams.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/generateURLVariations.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/RegExpRoute.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/setCacheNameDetails.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/createCacheKey.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/PrecacheInstallReportPlugin.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/parseRoute.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/printCleanupDetails.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/printInstallDetails.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/cacheNames.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/broadcastUpdate/constants.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/broadcastUpdate/responsesAreSame.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/broadcastUpdate/BroadcastCacheUpdate.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/broadcastUpdate/BroadcastUpdatePlugin.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/cacheableResponse/CacheableResponse.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/cacheableResponse/CacheableResponsePlugin.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/expiration/models/CacheTimestampsModel.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/expiration/CacheExpiration.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/registerQuotaErrorCallback.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/expiration/ExpirationPlugin.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/googleAnalytics/constants.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/googleAnalytics/initializeGoogleAnalytics.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/precaching/PrecacheFallbackPlugin.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/rangeRequests/utils/calculateEffectiveBoundaries.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/rangeRequests/utils/parseRangeHeader.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/rangeRequests/createPartialResponse.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/rangeRequests/RangeRequestsPlugin.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/CacheFirst.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/CacheOnly.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/lib/strategies/StaleWhileRevalidate.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/PrecacheRoute.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/PrecacheCacheKeyPlugin.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/utils/parsePrecacheOptions.ts", "node_modules/@serwist/turbopack/node_modules/serwist/src/Serwist.ts", "node_modules/@serwist/turbopack/src/index.worker.ts", "node_modules/serwist/dist/chunks/waitUntil.js", "node_modules/serwist/dist/chunks/printInstallDetails.js", "node_modules/serwist/dist/index.js", "utils/service-worker-route-utils.ts", "constants/file-kind.ts", "utils/offline-routes.ts", "app/sw.ts"],
  "sourcesContent": ["[\n  {\n    \"url\": \"/_next/static/immutable/media/worker.penumbra-Bm-9K58b.3skjjj91j-k9x.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/verified.0oxlcprenmdxu.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/uniswap.42bfkbt3ds631.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/twitter-image.2o1-gkhq1fsmv.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/slide-4.0utkg1eef_gem.webp\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/slide-2.2ww6r2ztignuw.webp\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/saving-chain.0qxfc9kmbaxrf.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/safe.1t186zkp196bb.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/recovery-image.288ycj47swg44.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/opengraph-image.2o1-gkhq1fsmv.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/mobile-gp-image.3nodh1aj6k84c.jpg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/metamask.44_owuwjqrp8_.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/manifesto.0hy0jynppp3_j.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/local.2fdwzd9oh5mlr.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/infra-upgrade.054oj5awzc3is.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/img-self-sovereign-collaboration3.3mv2xbt9btd1j.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/img-self-sovereign collaboration2.072_3nmir2vrk.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/img-private-by-design.0oeay4080qo2n.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/img - no version history.0yy1400h3thrc.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/heroku.1s1e7ufealwht.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/gnosis.0kl29rshzgjvw.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/fileverse-smiley-upside-down.0edw5bo84y3sb.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/fileverse-logo-blink.1c88xqofjqk77.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/file-sad.10zavnpmqpgsz.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/favicon.2u_l2o0re9472.ico\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/ens.3hxa6_90xn-0i.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/ens-tick.0oxlcprenmdxu.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/editor-upgrades.2h90s797xpmhz.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/dev-final-guide.1d0s3-nofx3ka.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/defilamma.3o-9vi6gnek8e.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/dDocs.0dkrryhcf9h_7.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/cloudflare.1fj07hwth_jv8.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/blockscout.1xg2mu16t_oly.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/base.0q3rs1_pqc6yx.svg\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/media/apple-icon.0q172s5cl23ej.png\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/turbopack-worker-3xr8wf3in6jtp.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/turbopack-3h-u_7h861s8j.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/turbopack-2bgp6r34jljo5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/turbopack-1gcb471ks1g71.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/446m0dxta4065.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/43avgn5yxsb9i.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/42vbhhkkccp3d.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/40vxpk9hde_rd.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/40jggfo-n4tvt.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3yqtnuxj05j97.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3yk-rhkffsrxw.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3xxhm3m0u79pk.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3x6bfojkmqoap.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3uz5s5g_ci-hl.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3uwuaulvqfwil.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3uvzsgk05bb5u.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3uv42rscqplg-.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3uniyg6_fw3wk.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3tybzkm17buaa.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3t5grziiv18ot.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3sw11j2wqwgxh.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3s3rl8vd24ne8.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3rlda2gsok6_3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3qydoklap4mkj.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3qkthoseouzzr.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3q4nx5dz4zg6h.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3ppjhpfhkalab.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3phbsq8vmdydf.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3ph_irqt58bnw.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3pbj571y3tpxm.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3oqex2ucszoq0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3oo4qgamdns0o.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3nipmdop2_xwi.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3mmiu-_kpgvc9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3mjsnc11et-ig.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3mdj6zpb6q17t.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3m6icew3fwqsu.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3m28vvv_4j388.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3lxi4iih23bug.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3lu0sgzcudjdr.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3kzauowkj7ur8.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3kk292va6-mt2.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3k8j5a1c2d_86.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3k28t1mc-fxca.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3jfmj0gs2tley.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3j3c4ze6l8el-.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3ipjufpsggnuw.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3iooydho2w5tt.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3ii7i3n1istb0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3idg9oj31h7up.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3hu9vkfhh_vqg.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3gysre8yar6sh.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3gw0s646oe8im.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3fvda6k8tudcf.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3fiqiu8gj1ntz.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3ff8r370uzi7z.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3eymafaj6dl5j.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3esitrua7h5cx.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3e2lt3bu66tv5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3dnjrm8raqw_1.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3djtjx-1gs-yt.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3dciset-5y_vv.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3cl50-zh-n02a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3bym_uxanmtuq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3bwnuaxa1jlhc.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3b2brs4dkff14.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3b1bok-1w23q2.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3abnqgtb6x6-n.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3_yq206rp96g3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3_scj6t53ll5o.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3_ght0klbdy5o.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/39y54tswegqyc.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/39w4l1bsdu89g.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/39czbegxc-ftb.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/39-p86bm7di6f.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/383x1bt7cad3u.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/37qyo4egd0hzg.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/37nkyk2bv5_mx.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/36byon_hnkf9o.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/364tuawos2elx.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/34xmbz3vjgoru.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/34tf-v1lbgr0n.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/33s5l_ly5jwqi.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/33knr40p28zfe.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/335q83ucs0-ih.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/32g8zl8m8r-c3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/31fi1tjxp9tvq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/31_mr8i22nnwb.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/30wp83nhb0mod.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/30wdndhg36u97.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/30v7oj0ezcc4y.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/30p3aeo-0wchy.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/30j2k4khlguu3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3070_6y6wqy-k.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/3-9kobzgdntna.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2zppd734v-t3w.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2z_udb0b5gr76.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2z7wyv387g-8x.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2ymw0auudnv27.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2y1jq3ix_ubiy.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2w8q4l2purirk.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2w5y_qk8t2unr.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2w26fks5ylt61.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2vs_lekxs6ff0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2vo14edj2_9im.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2vcfdz1wbprfo.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2uuso0zl8dk24.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2ul9e9l9fghti.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2tkdtfhdmww7x.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2sdcfg62mnuqx.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2s7ggr695meyy.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2ro230_aa5wln.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2r-5z1enesmhs.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2oibuvo1zzczj.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2nfm-3snq06_n.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2nb123qm9iiys.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2lmlgj02r2exq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2lmklrq8grf05.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2k9wwvrg_nea8.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2k6euv4lq9vc2.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2k5p0qr-wf_k9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2j1qhqmjaorpv.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2ii-0zjfoo3_0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2ic6r2lvx1b17.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2hi86vvzgp6ns.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2hcf-zd_l7yij.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2h8l8e2h1q28p.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2h7cs071n1adt.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2guro2akdc3x4.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2gmfsn67meawd.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2gjvwbwh7l49q.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2fyrx6it88o-7.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2ece0r16gw4u0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2e792bcruk_rn.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2dxm4-kx9bbqh.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2dg0-ny8ft8of.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2cv4ikvwkq84h.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2cehvfg8m9ig5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2b5yxo4q-01n1.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2ax9_6s21ygq5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2awn-z-n7vh8u.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2a3hacbbar6as.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2_bdkdiw7jdn1.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/29hfp1qv5dqbh.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/285yl26779jjt.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/27xp6zbkei-69.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/27ubadcxiwy3g.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/27kepzgh7offj.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/26e8ka_s0f813.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/26c12tnx-5xeb.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/25xp252qvoi2_.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/25baq51z9efxa.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/254l35xr261hz.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/25-bjk__zay6r.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/22hdfxgnm4_ps.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/22b8zfyv-u4oa.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/21zxxbasa9pqn.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/217jnvi5juk_u.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2-cegep3580mi.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/2--1sbjjc4nq5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1zgp-pbm1cdii.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1z3urc6m26x_l.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1yrx646ma8--b.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1y0036hkva2k3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1wopjpdcwtpt3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1wlxv5h_dmm-g.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1w3pvf1hcl4d9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1w07uevgiggtk.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1vy2eypov8ol5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1uaj_8vw2kbm5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1tsv5rjaluc4x.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1tl4ut6d7kk5v.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1tb07ysp6mjib.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1sxbr-dg3zozc.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1sfo4l_wdq0nz.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1rwi3rha5xt5v.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1rte2znv7xbgd.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1rh7uzeu_j_ob.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1rfg_f2y32vso.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1q9ah7z6t3r82.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1q2-nydn8auwj.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1pd51b-9j4f78.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1p2u4swxj2pcj.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1omqsricwe-w4.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1ohte9t31sw1q.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1o7nlhx8i40pw.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1nr-jeiqbod7o.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1nippk3o5zpnq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1naiq8itmg7wd.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1n4036xuh3bry.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1mroea2rst42e.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1mdn0ca9i28-9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1m_su_fhylqbo.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1ltb1tzih1bwi.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1lrgyrpqfit4d.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1l3y9ca754042.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1k__5uqhn_fm0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1jefgrvroxcyk.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1iz07ppdzxs_6.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1il9hvg6itweb.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1g6pvft7os9hp.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1fp7jwf7t2ex9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1fb_k6im92lrx.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1f53m29w4p7bn.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1ey1r9js9g1tr.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1en_jpn9gokrr.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1efvtgjr61hfa.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1e0l-cq17_j7y.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1dtcv74vvcck2.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1dkjyvc6fzbln.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1dc9q_79at6jp.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1d9ocypv43mpy.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1chz2--y-ubgs.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1cgcjuk3jd5ll.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1cc14-8pyd5_o.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1bq3nd78xbb0_.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1bf11fh9c67t7.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1b1phxoswcr_g.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1asq2c5wkw9tp.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1ao_bjti9fms3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1_vyshsysc8un.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1_3umvt82v0rm.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1_274so7kue74.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/192481p12azj5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1921ntlog78q0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/18au1li2u1qog.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/181k1pcgw5r3h.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/17qax3x8r2wz0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/16snld66wu06s.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/16a5czaib5vry.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/15zotoikx-g9_.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/15uxvtnfcfj63.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/15fnlwx4u8t38.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/14qkdgqlybuc5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/13wf7h03p1u-y.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/131tbmwbwshh-.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/12y2f40sgg9t4.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/12uhj4me_z32c.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/12txyx-spgo1v.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/123uu7vnuxb1l.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/11ofuxhcztg41.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/11j_03_ycqd4w.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/11bhyftdiln4z.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/11_5ilf862tub.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/10yikutxtjiaw.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1088jqy8a3f3h.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/102q9wn32_f-t.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1-yysdhyhcb43.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1-uh3y5r3kjyk.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/1-rf31rl8zi8g.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0zi9fgmyy_t0x.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0z561qoz8guva.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0yx9fw90d3fbz.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0y2dylzjhr2_b.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0y0busi8t5xtq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0xnjxrpqas-r5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0xn95ldxrv4ix.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0xkih75pruu55.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0x17uvrjcuky2.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0wp-ihui9ci9_.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0w6f7s4_tp3l8.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0vibht_9ytptc.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0v-a1-6iqng4-.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0uu7ntq_vtv06.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0udhn__m-fz-p.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0td1bk2d9d5aw.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0t9i307qtp0t7.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0t5drcx1ano9p.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0s7xfn_q4fxzy.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0s0zru2s68hwq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0rt-c0lva5m2i.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0qk0b9gwm0jrl.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0pxzn-4go659v.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0pvm1r7psn1jc.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0opzrf1ylz3v2.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0ofvvhiy_3odf.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0ob-d9_hwdbao.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0o6ux17y_8zg0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0nc2a0a0k81dc.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0m8xljkp4h218.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0m0gkndwqbbob.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0lpo4k_cec3l-.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0l5xrnrv6q1j0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0l3wsjy3dhtav.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0l2q8--e7ml2a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0k30nt0kui-fb.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0jhvvuwg0_vcj.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0jdgg-ej0cz-y.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0ja1l4eoi6os4.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0ixjr9iaax5tq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0iw4es45q3e34.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0irsfsqlwzoxb.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0ibu375_ec56g.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0ia0gzdfkkt_y.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0hxephz2801nq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0gec3_l9o3l_c.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0dqclvmys3auq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0c_wg93h9zr3i.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0c0hxoamwjsbw.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0btmm2-13tyvc.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0bhubih2vosik.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0bc289hwxna3w.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0ayipjb-gdskg.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0atnkgivft_-5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0_6et273wvqp5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/08r7zltwxzz8a.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/08_fsj49frc_g.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/07tx8ga3e5b63.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/06d08p77smxl2.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/062r_3sdh-5t6.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/05oflco44v5j5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/04oa_jit0nb5p.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/04ngig13vayd0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/04jtkal9a2dt9.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/04d699ar8u_oa.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/033nln6vsxtqb.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/02i8_l9si7xgy.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/02cpojqyga-0n.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0279av8oaue_n.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/026dqsk0e_vq8.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/01t1pfn3xlv3x.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0106n0cm-j8em.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/00o74s9rjjbts.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/00hfhzxit22yv.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/00bnk5-xcltmk.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/00b_3ma_a9kq_.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0-uddo0s4epqa.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0-8iitn5-ivi3.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/immutable/chunks/0-6m8gomdqaut.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/build-TfctsWXpff2fKS/_ssgManifest.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/build-TfctsWXpff2fKS/_clientMiddlewareManifest.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/build-TfctsWXpff2fKS/_buildManifest.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/verified.svg\",\n    \"revision\": \"610f6f7db7afd146e0bb6dcf655733f1\"\n  },\n  {\n    \"url\": \"/vercel.svg\",\n    \"revision\": \"61c6b19abff40ea7acd577be818f3976\"\n  },\n  {\n    \"url\": \"/suggestion_mode.mp4\",\n    \"revision\": \"7a9f74c7fa5f3786ab7809b9113033a2\"\n  },\n  {\n    \"url\": \"/status-checker.png\",\n    \"revision\": \"0d3e59fc56e40e48cc36eb6eb27df096\"\n  },\n  {\n    \"url\": \"/spellcheck.gif\",\n    \"revision\": \"57dddd09706619a33d73fbe816a619b7\"\n  },\n  {\n    \"url\": \"/smile-anim.json\",\n    \"revision\": \"4b7a7bcdf9b891ccabbce766b336e888\"\n  },\n  {\n    \"url\": \"/slnav.mp4\",\n    \"revision\": \"7c3282ea2cae17356c74eb34c2ab958a\"\n  },\n  {\n    \"url\": \"/robots.txt\",\n    \"revision\": \"456c3dbacd70847d3c02063a70122472\"\n  },\n  {\n    \"url\": \"/publish-success.webm\",\n    \"revision\": \"82e836103d74762341348b4f499fa7d4\"\n  },\n  {\n    \"url\": \"/publish-success.mp4\",\n    \"revision\": \"693db905212210cca3cf609d1fd8b28b\"\n  },\n  {\n    \"url\": \"/offline.html\",\n    \"revision\": \"f815fb159bf0815d0cccd3399efb7f7b\"\n  },\n  {\n    \"url\": \"/next.svg\",\n    \"revision\": \"8e061864f388b47f33a1c3780831193e\"\n  },\n  {\n    \"url\": \"/mobile-gp-image.jpg\",\n    \"revision\": \"041cf3059f5f6f599678ed051c65e99f\"\n  },\n  {\n    \"url\": \"/logo-container.png\",\n    \"revision\": \"7d21902766d6205581c15188c3a0846e\"\n  },\n  {\n    \"url\": \"/img-workspace-join-release.png\",\n    \"revision\": \"a83a59b6e9239b62f9d78a582320831d\"\n  },\n  {\n    \"url\": \"/img-workspace-creation-preview.svg\",\n    \"revision\": \"234f6f7bbf6146d726254b3344afca8d\"\n  },\n  {\n    \"url\": \"/img-accept-invite-preview.png\",\n    \"revision\": \"74e3b86824b897c777b125e04f8ccac6\"\n  },\n  {\n    \"url\": \"/img - no version history.svg\",\n    \"revision\": \"3963e7e91bcd0065e319e4f25d8a9259\"\n  },\n  {\n    \"url\": \"/folder_announcement.jpg\",\n    \"revision\": \"ba0e9dd2cc2db2a85dbb0bf33f0bbf0d\"\n  },\n  {\n    \"url\": \"/ens.svg\",\n    \"revision\": \"b975109ab1bdc46ffe90304f35883aca\"\n  },\n  {\n    \"url\": \"/ens-bw.svg\",\n    \"revision\": \"e83e820b04f25ca96baf9fac9812045a\"\n  },\n  {\n    \"url\": \"/ddocs-logo-512px.png\",\n    \"revision\": \"50754d406124aae2df7d00e48afd8895\"\n  },\n  {\n    \"url\": \"/ddocs-logo-192px.png\",\n    \"revision\": \"145de7390831193abb3c8765f436ba02\"\n  },\n  {\n    \"url\": \"/assets/yellow-heart.png\",\n    \"revision\": \"ab5fe667f3e930a464020eb9224af333\"\n  },\n  {\n    \"url\": \"/assets/yellow-face.png\",\n    \"revision\": \"ff7cf6b882df18d2be845777e6220b11\"\n  },\n  {\n    \"url\": \"/assets/wizard.svg\",\n    \"revision\": \"9a00eaf478ef27b2dcc72138cf212064\"\n  },\n  {\n    \"url\": \"/assets/witch-halloween.svg\",\n    \"revision\": \"7aca3b0abd117f7631c113afbfb2e4e2\"\n  },\n  {\n    \"url\": \"/assets/walletconnect.svg\",\n    \"revision\": \"b4d127ca527e9640707b9d29c730da9b\"\n  },\n  {\n    \"url\": \"/assets/waku.svg\",\n    \"revision\": \"4b6f68f295c879ad43ce091239218404\"\n  },\n  {\n    \"url\": \"/assets/uniswap.svg\",\n    \"revision\": \"5dfebdb349fb5240478558a9aecce342\"\n  },\n  {\n    \"url\": \"/assets/twitter.svg\",\n    \"revision\": \"856eb5199856402cd95a516241c6b152\"\n  },\n  {\n    \"url\": \"/assets/speech.svg\",\n    \"revision\": \"816f39f9a5d032cdd4ae0ae3b211c0bb\"\n  },\n  {\n    \"url\": \"/assets/shadow.svg\",\n    \"revision\": \"6ddbcadee653552afbd8cfc8a06f27e3\"\n  },\n  {\n    \"url\": \"/assets/server.svg\",\n    \"revision\": \"142e5e6100ab00451c73ac63e5c1cc50\"\n  },\n  {\n    \"url\": \"/assets/saving-chain.svg\",\n    \"revision\": \"6d0caf69214e93c1c4b44f86dcc3c2bf\"\n  },\n  {\n    \"url\": \"/assets/safe.svg\",\n    \"revision\": \"28531f50d082fd04dfd291eb1dd9b970\"\n  },\n  {\n    \"url\": \"/assets/recovery-image.png\",\n    \"revision\": \"2da24f3a13abd4477d5c1f285f456d38\"\n  },\n  {\n    \"url\": \"/assets/rainbow.svg\",\n    \"revision\": \"a0d21018f07ce559e14962811e4aa0e0\"\n  },\n  {\n    \"url\": \"/assets/qrcode.svg\",\n    \"revision\": \"31c3b2f06a4684b53d8a09045da813c6\"\n  },\n  {\n    \"url\": \"/assets/pq-upgrade-hero.png\",\n    \"revision\": \"6027a092ecf0b57e04d7a3f1194340a6\"\n  },\n  {\n    \"url\": \"/assets/migration.svg\",\n    \"revision\": \"a02906984b4a8a6ba2fe499d7fb51a16\"\n  },\n  {\n    \"url\": \"/assets/metamask.svg\",\n    \"revision\": \"d206794f79a670efe19d23659fe7ccec\"\n  },\n  {\n    \"url\": \"/assets/manifesto.png\",\n    \"revision\": \"7610ad4feda65597f0ae388b9df81f3f\"\n  },\n  {\n    \"url\": \"/assets/mainLogo.svg\",\n    \"revision\": \"b0788069f0329ad57d412782f20ebd4e\"\n  },\n  {\n    \"url\": \"/assets/local.svg\",\n    \"revision\": \"dd7fe87321012a90e19fc01455b58db4\"\n  },\n  {\n    \"url\": \"/assets/lightmode.svg\",\n    \"revision\": \"ebb6e0a975e69b59bae12f541e0967b2\"\n  },\n  {\n    \"url\": \"/assets/key.svg\",\n    \"revision\": \"624cab291e647088c6a36f1107180707\"\n  },\n  {\n    \"url\": \"/assets/infra-upgrade.png\",\n    \"revision\": \"a1e65cde0f4a9413604c884b808af9cc\"\n  },\n  {\n    \"url\": \"/assets/img-self-sovereign-collaboration3.png\",\n    \"revision\": \"a1990a7a3c879be24e640eb2430721ae\"\n  },\n  {\n    \"url\": \"/assets/img-self-sovereign-collaboration.png\",\n    \"revision\": \"7d0df39faaa4aabfb5362b1aa44e56fd\"\n  },\n  {\n    \"url\": \"/assets/img-self-sovereign-collaboration-2.png\",\n    \"revision\": \"2b188eac220d0ea43d28248de0862651\"\n  },\n  {\n    \"url\": \"/assets/img-self-sovereign collaboration2.png\",\n    \"revision\": \"d53c0a27d2d8b9b344447f15876833ce\"\n  },\n  {\n    \"url\": \"/assets/img-private-by-design.png\",\n    \"revision\": \"b9c6b152dbebccf70b5b5bf35eb0428d\"\n  },\n  {\n    \"url\": \"/assets/heroku.svg\",\n    \"revision\": \"2ef1d6a389fd26d2d31c76c6df201586\"\n  },\n  {\n    \"url\": \"/assets/gnosis.svg\",\n    \"revision\": \"6d6fef377e4a640a9b722cd1ffae1220\"\n  },\n  {\n    \"url\": \"/assets/github.svg\",\n    \"revision\": \"64c5ab507042114e767e90da311fb01d\"\n  },\n  {\n    \"url\": \"/assets/ghost.png\",\n    \"revision\": \"1c1aaf76ae0458504c540520ef5298f9\"\n  },\n  {\n    \"url\": \"/assets/fileverse-smiley-upside-down.svg\",\n    \"revision\": \"0479a0daee5d0e229fbbc9fb6b0f566c\"\n  },\n  {\n    \"url\": \"/assets/fileverse-logo-smile.svg\",\n    \"revision\": \"b5c3d26da04bbaae662a77940b97738a\"\n  },\n  {\n    \"url\": \"/assets/fileverse-logo-smile.png\",\n    \"revision\": \"bc26d1c42f768231953a97262be4d0ff\"\n  },\n  {\n    \"url\": \"/assets/fileverse-logo-blink.svg\",\n    \"revision\": \"475c3085fd9a9ad09011ee6ecf37237b\"\n  },\n  {\n    \"url\": \"/assets/file-sad.svg\",\n    \"revision\": \"eb40b226b3f8dbfe4c0919e243e2e4fd\"\n  },\n  {\n    \"url\": \"/assets/face-kiss.svg\",\n    \"revision\": \"329447dded6931c81f9f2a550640070a\"\n  },\n  {\n    \"url\": \"/assets/ens-tick.svg\",\n    \"revision\": \"610f6f7db7afd146e0bb6dcf655733f1\"\n  },\n  {\n    \"url\": \"/assets/ens-modal.webp\",\n    \"revision\": \"eeb79f848b26d3f93b5b5c90f86f7da7\"\n  },\n  {\n    \"url\": \"/assets/dsheet.svg\",\n    \"revision\": \"8ae2d2a93eae71cd50e29b192444d3d2\"\n  },\n  {\n    \"url\": \"/assets/download_key.svg\",\n    \"revision\": \"9c214c7309b9d854592820ab14eb69ec\"\n  },\n  {\n    \"url\": \"/assets/discord.svg\",\n    \"revision\": \"147f41c95f6ad7574168c3d3a462c455\"\n  },\n  {\n    \"url\": \"/assets/dev-final-guide.svg\",\n    \"revision\": \"def486d4a17afb6132e5687c6e58bc0f\"\n  },\n  {\n    \"url\": \"/assets/defilamma.svg\",\n    \"revision\": \"fc010ff37fe2131229a2603c7b040372\"\n  },\n  {\n    \"url\": \"/assets/ddoc-locked.svg\",\n    \"revision\": \"226a210431d28b00807ec4160b24a186\"\n  },\n  {\n    \"url\": \"/assets/darkmode.svg\",\n    \"revision\": \"8fe8db81834929b81fe155464acb7610\"\n  },\n  {\n    \"url\": \"/assets/dDocs.svg\",\n    \"revision\": \"f13df5f0f19170b598b670a207fa9a95\"\n  },\n  {\n    \"url\": \"/assets/coinbase.svg\",\n    \"revision\": \"ffbed7f1a6fb0f2181ad288fe887c9a6\"\n  },\n  {\n    \"url\": \"/assets/cloudflare.svg\",\n    \"revision\": \"2dc06bad61bb673d6e738601ab9f4b4e\"\n  },\n  {\n    \"url\": \"/assets/byom.svg\",\n    \"revision\": \"d77b5bf6d69e2522ca3c284c9a0d43e4\"\n  },\n  {\n    \"url\": \"/assets/blog-tab-image.webp\",\n    \"revision\": \"ecbf7985fe0937b233cd2567d1aae403\"\n  },\n  {\n    \"url\": \"/assets/blockscout.svg\",\n    \"revision\": \"7071529610921de238d4ee0f67f96238\"\n  },\n  {\n    \"url\": \"/assets/base.svg\",\n    \"revision\": \"9dde3e09c450c327a509fb89f5795773\"\n  },\n  {\n    \"url\": \"/assets/access-lock-glyph.svg\",\n    \"revision\": \"7f183887b6cae06ef323c2b2f6cc759d\"\n  },\n  {\n    \"url\": \"/assets/access-lock-bg.svg\",\n    \"revision\": \"5a84874f280678ed7641747335e63ad4\"\n  },\n  {\n    \"url\": \"/assets/templates/fanfic-planner.png\",\n    \"revision\": \"72588800963e524790a2f01d2cee6bb1\"\n  },\n  {\n    \"url\": \"/assets/quick-tips/img-local.svg\",\n    \"revision\": \"c150005063703714b6f90a93e5999e7b\"\n  },\n  {\n    \"url\": \"/assets/quick-tips/img-llm.svg\",\n    \"revision\": \"a49f66fa7eee68f360c25b73c8c7ebc1\"\n  },\n  {\n    \"url\": \"/assets/quick-tips/img-generate-key.svg\",\n    \"revision\": \"47706d9c8672d778d3c6f4102b9606e4\"\n  },\n  {\n    \"url\": \"/assets/quick-tips/img-cloud.svg\",\n    \"revision\": \"06dc0f36f201ca531332f7a4f0f5bcd4\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-6.webp\",\n    \"revision\": \"bfbad400f54d24229bef8ffd029c6ae5\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-6.png\",\n    \"revision\": \"187802a12855123a20be71ed2f579d67\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-5.webp\",\n    \"revision\": \"442e1c156bd982b25d1d33b97afcdc17\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-5.png\",\n    \"revision\": \"13befec435d02218ede1f198263353fd\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-4.webp\",\n    \"revision\": \"a728e26389b6eaee1d1302ea1df47062\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-4.png\",\n    \"revision\": \"6d6d57d771ad96cbed9cca7e2e1dece4\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-3.webp\",\n    \"revision\": \"62365cdcd77cafe56f616d4ae15cf7c4\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-3.png\",\n    \"revision\": \"aa4211541b687e6a8d13b6f7bb53cfe2\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-2.webp\",\n    \"revision\": \"9dd37e42ffa8bc78cb898ce7038856a7\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-2.png\",\n    \"revision\": \"482ef22ff83d11ff33f0fb6e39a59e7f\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-1.webp\",\n    \"revision\": \"eaf2f8c4c5119b49abf2a1c2c603ff4c\"\n  },\n  {\n    \"url\": \"/assets/intro-modal/slide-1.png\",\n    \"revision\": \"9722a1da4c00fb933b34a5bc4174d13d\"\n  },\n  {\n    \"url\": \"/assets/feature-banner/new-share/slide-3.webm\",\n    \"revision\": \"a5a244552f7328b93a2d43ab0348b43d\"\n  },\n  {\n    \"url\": \"/assets/feature-banner/new-share/slide-3.mp4\",\n    \"revision\": \"950716c2e42d4643f95128f88074f2de\"\n  },\n  {\n    \"url\": \"/assets/feature-banner/new-share/slide-1.webm\",\n    \"revision\": \"831aacf9917b9a6243bc9afd6deceb55\"\n  },\n  {\n    \"url\": \"/assets/feature-banner/new-share/slide-1.mp4\",\n    \"revision\": \"bc0cada298e27ce6fab5758d0c8ec127\"\n  },\n  {\n    \"url\": \"/assets/anon-nudge/save-your-work.png\",\n    \"revision\": \"4cf32c50f9623ff6c25234586b11d475\"\n  },\n  {\n    \"url\": \"/assets/anon-nudge/folders-account.png\",\n    \"revision\": \"d25ac79348ba15a4886b6cd4be503b7e\"\n  },\n  {\n    \"url\": \"/assets/anon-nudge/docs-on-device.png\",\n    \"revision\": \"e255be0d400f280efc4b44d9ba6c2e9e\"\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", "/*\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 { RuntimeCaching } from \"serwist\";\nimport { CacheFirst, ExpirationPlugin, NetworkFirst, NetworkOnly, RangeRequestsPlugin, StaleWhileRevalidate } from \"serwist\";\n\nexport const PAGES_CACHE_NAME = {\n  rscPrefetch: \"pages-rsc-prefetch\",\n  rsc: \"pages-rsc\",\n  html: \"pages\",\n} as const;\n\n/**\n * The default, recommended list of caching strategies for applications\n * built with Next.js.\n *\n * @see https://serwist.pages.dev/docs/next/worker-exports#default-cache\n */\nexport const defaultCache: RuntimeCaching[] =\n  process.env.NODE_ENV !== \"production\"\n    ? [\n        {\n          matcher: /.*/i,\n          handler: new NetworkOnly(),\n        },\n      ]\n    : [\n        {\n          matcher: /^https:\\/\\/fonts\\.(?:gstatic)\\.com\\/.*/i,\n          handler: new CacheFirst({\n            cacheName: \"google-fonts-webfonts\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 4,\n                maxAgeSeconds: 365 * 24 * 60 * 60, // 365 days\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /^https:\\/\\/fonts\\.(?:googleapis)\\.com\\/.*/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"google-fonts-stylesheets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 4,\n                maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"static-font-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 4,\n                maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"static-image-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 64,\n                maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\/_next\\/static.+\\.js$/i,\n          handler: new CacheFirst({\n            cacheName: \"next-static-js-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 64,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\/_next\\/image\\?url=.+$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"next-image\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 64,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:mp3|wav|ogg)$/i,\n          handler: new CacheFirst({\n            cacheName: \"static-audio-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n              new RangeRequestsPlugin(),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:mp4|webm)$/i,\n          handler: new CacheFirst({\n            cacheName: \"static-video-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n              new RangeRequestsPlugin(),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:js)$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"static-js-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 48,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:css|less)$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"static-style-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\/_next\\/data\\/.+\\/.+\\.json$/i,\n          handler: new NetworkFirst({\n            cacheName: \"next-data\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:json|xml|csv)$/i,\n          handler: new NetworkFirst({\n            cacheName: \"static-data-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          // Exclude /api/auth/* to fix auth callback\n          // https://github.com/serwist/serwist/discussions/28\n          matcher: /\\/api\\/auth\\/.*/,\n          handler: new NetworkOnly({\n            networkTimeoutSeconds: 10, // fallback to cache if API does not response within 10 seconds\n          }),\n        },\n        {\n          matcher: ({ sameOrigin, url: { pathname } }) => sameOrigin && pathname.startsWith(\"/api/\"),\n          method: \"GET\",\n          handler: new NetworkFirst({\n            cacheName: \"apis\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 16,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n            networkTimeoutSeconds: 10, // fallback to cache if API does not response within 10 seconds\n          }),\n        },\n        {\n          matcher: ({ request, url: { pathname }, sameOrigin }) =>\n            request.headers.get(\"RSC\") === \"1\" && request.headers.get(\"Next-Router-Prefetch\") === \"1\" && sameOrigin && !pathname.startsWith(\"/api/\"),\n          handler: new NetworkFirst({\n            cacheName: PAGES_CACHE_NAME.rscPrefetch,\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: ({ request, url: { pathname }, sameOrigin }) => request.headers.get(\"RSC\") === \"1\" && sameOrigin && !pathname.startsWith(\"/api/\"),\n          handler: new NetworkFirst({\n            cacheName: PAGES_CACHE_NAME.rsc,\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: ({ request, url: { pathname }, sameOrigin }) =>\n            request.headers.get(\"Content-Type\")?.includes(\"text/html\") && sameOrigin && !pathname.startsWith(\"/api/\"),\n          handler: new NetworkFirst({\n            cacheName: PAGES_CACHE_NAME.html,\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: ({ url: { pathname }, sameOrigin }) => sameOrigin && !pathname.startsWith(\"/api/\"),\n          handler: new NetworkFirst({\n            cacheName: \"others\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: ({ sameOrigin }) => !sameOrigin,\n          handler: new NetworkFirst({\n            cacheName: \"cross-origin\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 60 * 60, // 1 hour\n              }),\n            ],\n            networkTimeoutSeconds: 10,\n          }),\n        },\n        {\n          matcher: /.*/i,\n          method: \"GET\",\n          handler: new NetworkOnly(),\n        },\n      ];\n", "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 `The '${paramName}' parameter was given a value with an ` + `unexpected value. ${validValueDescription} Received a value of ` + `${JSON.stringify(value)}.`;\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    \"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    \"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        return `The parameter '${paramName}' passed into ` + `'${moduleName}.${classNameStr}${funcName}()' ` + `must be an instance of class ${expectedClassName}.`;\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    \"add-to-cache-list-unexpected-type\": ({ entry })=>{\n        return `An unexpected entry was passed to 'serwist.Serwist.addToPrecacheList()' The entry '${JSON.stringify(entry)}' 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    \"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        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    \"plugin-error-request-will-fetch\": ({ thrownErrorMessage })=>{\n        if (!thrownErrorMessage) {\n            throw new Error(\"Unexpected input to \" + `'plugin-error-request-will-fetch', error.`);\n        }\n        return `An error was thrown by a plugin's 'requestWillFetch()' method. The thrown error message was: '${thrownErrorMessage}'.`;\n    },\n    \"invalid-cache-name\": ({ cacheNameId, value })=>{\n        if (!cacheNameId) {\n            throw new Error(`Expected a 'cacheNameId' for error 'invalid-cache-name'`);\n        }\n        return `You must provide a name containing at least one character for setCacheDetails({${cacheNameId}: '...'}). Received a value of '${JSON.stringify(value)}'`;\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        return `The route you're trying to unregister was not  previously registered for the method type '${method}'.`;\n    },\n    \"unregister-route-route-not-registered\": ()=>{\n        return `The route you're trying to unregister was not previously ` + \"registered.\";\n    },\n    \"queue-replay-failed\": ({ name })=>{\n        return `Replaying the background sync queue '${name}' failed.`;\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    \"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    \"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    \"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(value)},'. Please check the call to ${moduleName}.${className}.${funcName}() to fix the issue.`;\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    \"statuses-or-headers-required\": ({ moduleName, className, funcName })=>{\n        return `You must define either 'config.statuses' or 'config.headers' in '${moduleName}.${className}.${funcName}'`;\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    \"channel-name-required\": ()=>{\n        return \"You must provide a channelName to construct a \" + \"BroadcastCacheUpdate instance.\";\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    \"expire-custom-caches-only\": ()=>{\n        return `You must provide a 'cacheName' property when using the ` + \"expiration plugin with a runtime caching strategy.\";\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    \"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    \"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    \"no-range-header\": ()=>{\n        return \"No Range header was found in the Request provided.\";\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    \"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    \"cache-put-with-no-response\": ({ url })=>{\n        return `There was an attempt to cache '${url}' but the response was not defined.`;\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    \"bad-precaching-response\": ({ url, status })=>{\n        return `The precaching request for '${url}' failed${status ? ` with an HTTP status of ${status}.` : \".\"}`;\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    \"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    \"missing-precache-entry\": ({ cacheName, url })=>{\n        return `Unable to find a precached response in ${cacheName} for ${url}.`;\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    \"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};\n\nconst fallback = (code, ...args)=>{\n    let msg = code;\n    if (args.length > 0) {\n        msg += ` :: ${JSON.stringify(args)}`;\n    }\n    return msg;\n};\nconst generatorFunction = (code, details = {})=>{\n    const message = messages[code];\n    if (!message) {\n        throw new Error(`Unable to find message for code '${code}'.`);\n    }\n    return message(details);\n};\nconst messageGenerator = process.env.NODE_ENV === \"production\" ? fallback : generatorFunction;\n\nclass SerwistError extends Error {\n    details;\n    constructor(errorCode, details){\n        const message = messageGenerator(errorCode, details);\n        super(message);\n        this.name = errorCode;\n        this.details = details;\n    }\n}\n\nconst isArray = (value, details)=>{\n    if (!Array.isArray(value)) {\n        throw new SerwistError(\"not-an-array\", details);\n    }\n};\nconst hasMethod = (object, expectedMethod, details)=>{\n    const type = typeof object[expectedMethod];\n    if (type !== \"function\") {\n        details.expectedMethod = expectedMethod;\n        throw new SerwistError(\"missing-a-method\", details);\n    }\n};\nconst isType = (object, expectedType, details)=>{\n    if (typeof object !== expectedType) {\n        details.expectedType = expectedType;\n        throw new SerwistError(\"incorrect-type\", details);\n    }\n};\nconst isInstance = (object, expectedClass, details)=>{\n    if (!(object instanceof expectedClass)) {\n        details.expectedClassName = expectedClass.name;\n        throw new SerwistError(\"incorrect-class\", details);\n    }\n};\nconst isOneOf = (value, validValues, details)=>{\n    if (!validValues.includes(value)) {\n        details.validValueDescription = `Valid values are ${JSON.stringify(validValues)}.`;\n        throw new SerwistError(\"invalid-value\", details);\n    }\n};\nconst isArrayOfClass = (value, expectedClass, details)=>{\n    const error = new SerwistError(\"not-array-of-class\", details);\n    if (!Array.isArray(value)) {\n        throw error;\n    }\n    for (const item of value){\n        if (!(item instanceof expectedClass)) {\n            throw error;\n        }\n    }\n};\nconst finalAssertExports = process.env.NODE_ENV === \"production\" ? null : {\n    hasMethod,\n    isArray,\n    isInstance,\n    isOneOf,\n    isType,\n    isArrayOfClass\n};\n\nconst logger = process.env.NODE_ENV === \"production\" || typeof self === \"undefined\" ? null : (()=>{\n    if (!(\"__WB_DISABLE_DEV_LOGS\" in globalThis)) {\n        self.__WB_DISABLE_DEV_LOGS = false;\n    }\n    let inGroup = false;\n    const methodToColorMap = {\n        debug: \"#7f8c8d\",\n        log: \"#2ecc71\",\n        warn: \"#f39c12\",\n        error: \"#c0392b\",\n        groupCollapsed: \"#3498db\",\n        groupEnd: null\n    };\n    const print = (method, args)=>{\n        if (self.__WB_DISABLE_DEV_LOGS) {\n            return;\n        }\n        if (method === \"groupCollapsed\") {\n            if (typeof navigator !== \"undefined\" && /^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {\n                console[method](...args);\n                return;\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        const logPrefix = inGroup ? [] : [\n            \"%cserwist\",\n            styles.join(\";\")\n        ];\n        console[method](...logPrefix, ...args);\n        if (method === \"groupCollapsed\") {\n            inGroup = true;\n        }\n        if (method === \"groupEnd\") {\n            inGroup = false;\n        }\n    };\n    const loggerMethods = Object.keys(methodToColorMap);\n    return loggerMethods.reduce((api, method)=>{\n        api[method] = (...args)=>{\n            print(method, args);\n        };\n        return api;\n    }, {});\n})();\n\nconst getFriendlyURL = (url)=>{\n    const urlObj = new URL(String(url), location.href);\n    return urlObj.href.replace(new RegExp(`^${location.origin}`), \"\");\n};\n\nconst _cacheNameDetails = {\n    googleAnalytics: \"googleAnalytics\",\n    precache: \"precache-v2\",\n    prefix: \"serwist\",\n    runtime: \"runtime\",\n    suffix: typeof registration !== \"undefined\" ? registration.scope : \"\"\n};\nconst _createCacheName = (cacheName)=>{\n    return [\n        _cacheNameDetails.prefix,\n        cacheName,\n        _cacheNameDetails.suffix\n    ].filter((value)=>value && value.length > 0).join(\"-\");\n};\nconst eachCacheNameDetail = (fn)=>{\n    for (const key of Object.keys(_cacheNameDetails)){\n        fn(key);\n    }\n};\nconst cacheNames = {\n    updateDetails: (details)=>{\n        eachCacheNameDetail((key)=>{\n            const detail = details[key];\n            if (typeof detail === \"string\") {\n                _cacheNameDetails[key] = detail;\n            }\n        });\n    },\n    getGoogleAnalyticsName: (userCacheName)=>{\n        return userCacheName || _createCacheName(_cacheNameDetails.googleAnalytics);\n    },\n    getPrecacheName: (userCacheName)=>{\n        return userCacheName || _createCacheName(_cacheNameDetails.precache);\n    },\n    getPrefix: ()=>{\n        return _cacheNameDetails.prefix;\n    },\n    getRuntimeName: (userCacheName)=>{\n        return userCacheName || _createCacheName(_cacheNameDetails.runtime);\n    },\n    getSuffix: ()=>{\n        return _cacheNameDetails.suffix;\n    }\n};\n\nclass Deferred {\n    promise;\n    resolve;\n    reject;\n    constructor(){\n        this.promise = new Promise((resolve, reject)=>{\n            this.resolve = resolve;\n            this.reject = reject;\n        });\n    }\n}\n\nfunction stripParams(fullURL, ignoreParams) {\n    const strippedURL = new URL(fullURL);\n    for (const param of ignoreParams){\n        strippedURL.searchParams.delete(param);\n    }\n    return strippedURL.href;\n}\nasync function cacheMatchIgnoreParams(cache, request, ignoreParams, matchOptions) {\n    const strippedRequestURL = stripParams(request.url, ignoreParams);\n    if (request.url === strippedRequestURL) {\n        return cache.match(request, matchOptions);\n    }\n    const keysOptions = {\n        ...matchOptions,\n        ignoreSearch: true\n    };\n    const cacheKeys = await cache.keys(request, keysOptions);\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\nconst quotaErrorCallbacks = new Set();\n\nconst executeQuotaErrorCallbacks = async ()=>{\n    if (process.env.NODE_ENV !== \"production\") {\n        logger.log(`About to run ${quotaErrorCallbacks.size} callbacks to clean up caches.`);\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    if (process.env.NODE_ENV !== \"production\") {\n        logger.log(\"Finished running callbacks.\");\n    }\n};\n\nfunction timeout(ms) {\n    return new Promise((resolve)=>setTimeout(resolve, ms));\n}\n\nlet supportStatus;\nfunction canConstructResponseFromBodyStream() {\n    if (supportStatus === undefined) {\n        const testResponse = new Response(\"\");\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    return supportStatus;\n}\n\nconst SUBSTRING_TO_FIND = \"-precache-\";\nconst deleteOutdatedCaches = async (currentPrecacheName, substringToFind = SUBSTRING_TO_FIND)=>{\n    const cacheNames = await self.caches.keys();\n    const cacheNamesToDelete = cacheNames.filter((cacheName)=>{\n        return cacheName.includes(substringToFind) && cacheName.includes(self.registration.scope) && cacheName !== currentPrecacheName;\n    });\n    await Promise.all(cacheNamesToDelete.map((cacheName)=>self.caches.delete(cacheName)));\n    return cacheNamesToDelete;\n};\n\nconst cleanupOutdatedCaches = (cacheName)=>{\n    self.addEventListener(\"activate\", (event)=>{\n        event.waitUntil(deleteOutdatedCaches(cacheNames.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\nconst clientsClaim = ()=>{\n    self.addEventListener(\"activate\", ()=>self.clients.claim());\n};\n\nconst waitUntil = (event, asyncFn)=>{\n    const returnPromise = asyncFn();\n    event.waitUntil(returnPromise);\n    return returnPromise;\n};\n\nexport { Deferred as D, SerwistError as S, clientsClaim as a, cleanupOutdatedCaches as b, cacheNames as c, cacheMatchIgnoreParams as d, executeQuotaErrorCallbacks as e, finalAssertExports as f, getFriendlyURL as g, canConstructResponseFromBodyStream as h, logger as l, quotaErrorCallbacks as q, timeout as t, waitUntil as w };\n", "import { f as finalAssertExports, l as logger, D as Deferred, S as SerwistError, g as getFriendlyURL, t as timeout, d as cacheMatchIgnoreParams, e as executeQuotaErrorCallbacks, c as cacheNames, h as canConstructResponseFromBodyStream } from './waitUntil.js';\nimport { openDB } from 'idb';\n\nconst defaultMethod = \"GET\";\nconst validMethods = [\n    \"DELETE\",\n    \"GET\",\n    \"HEAD\",\n    \"PATCH\",\n    \"POST\",\n    \"PUT\"\n];\n\nconst normalizeHandler = (handler)=>{\n    if (handler && typeof handler === \"object\") {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.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        finalAssertExports.isType(handler, \"function\", {\n            moduleName: \"serwist\",\n            className: \"Route\",\n            funcName: \"constructor\",\n            paramName: \"handler\"\n        });\n    }\n    return {\n        handle: handler\n    };\n};\n\nclass Route {\n    handler;\n    match;\n    method;\n    catchHandler;\n    constructor(match, handler, method = defaultMethod){\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(match, \"function\", {\n                moduleName: \"serwist\",\n                className: \"Route\",\n                funcName: \"constructor\",\n                paramName: \"match\"\n            });\n            if (method) {\n                finalAssertExports.isOneOf(method, validMethods, {\n                    paramName: \"method\"\n                });\n            }\n        }\n        this.handler = normalizeHandler(handler);\n        this.match = match;\n        this.method = method;\n    }\n    setCatchHandler(handler) {\n        this.catchHandler = normalizeHandler(handler);\n    }\n}\n\nclass NavigationRoute extends Route {\n    _allowlist;\n    _denylist;\n    constructor(handler, { allowlist = [\n        /./\n    ], denylist = [] } = {}){\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isArrayOfClass(allowlist, RegExp, {\n                moduleName: \"serwist\",\n                className: \"NavigationRoute\",\n                funcName: \"constructor\",\n                paramName: \"options.allowlist\"\n            });\n            finalAssertExports.isArrayOfClass(denylist, RegExp, {\n                moduleName: \"serwist\",\n                className: \"NavigationRoute\",\n                funcName: \"constructor\",\n                paramName: \"options.denylist\"\n            });\n        }\n        super((options)=>this._match(options), handler);\n        this._allowlist = allowlist;\n        this._denylist = denylist;\n    }\n    _match({ url, request }) {\n        if (request && request.mode !== \"navigate\") {\n            return false;\n        }\n        const pathnameAndSearch = url.pathname + url.search;\n        for (const regExp of this._denylist){\n            if (regExp.test(pathnameAndSearch)) {\n                if (process.env.NODE_ENV !== \"production\") {\n                    logger.log(`The navigation route ${pathnameAndSearch} is not being used, since the URL matches this denylist pattern: ${regExp.toString()}`);\n                }\n                return false;\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        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\nconst removeIgnoredSearchParams = (urlObject, ignoreURLParametersMatching = [])=>{\n    for (const paramName of [\n        ...urlObject.searchParams.keys()\n    ]){\n        if (ignoreURLParametersMatching.some((regExp)=>regExp.test(paramName))) {\n            urlObject.searchParams.delete(paramName);\n        }\n    }\n    return urlObject;\n};\n\nfunction* generateURLVariations(url, { directoryIndex = \"index.html\", ignoreURLParametersMatching = [\n    /^utm_/,\n    /^fbclid$/\n], cleanURLs = true, urlManipulation } = {}) {\n    const urlObject = new URL(url, location.href);\n    urlObject.hash = \"\";\n    yield urlObject.href;\n    const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching);\n    yield urlWithoutIgnoredParams.href;\n    if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith(\"/\")) {\n        const directoryURL = new URL(urlWithoutIgnoredParams.href);\n        directoryURL.pathname += directoryIndex;\n        yield directoryURL.href;\n    }\n    if (cleanURLs) {\n        const cleanURL = new URL(urlWithoutIgnoredParams.href);\n        cleanURL.pathname += \".html\";\n        yield cleanURL.href;\n    }\n    if (urlManipulation) {\n        const additionalURLs = urlManipulation({\n            url: urlObject\n        });\n        for (const urlToAttempt of additionalURLs){\n            yield urlToAttempt.href;\n        }\n    }\n}\n\nclass RegExpRoute extends Route {\n    constructor(regExp, handler, method){\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(regExp, RegExp, {\n                moduleName: \"serwist\",\n                className: \"RegExpRoute\",\n                funcName: \"constructor\",\n                paramName: \"pattern\"\n            });\n        }\n        const match = ({ url })=>{\n            const result = regExp.exec(url.href);\n            if (!result) {\n                return;\n            }\n            if (url.origin !== location.origin && result.index !== 0) {\n                if (process.env.NODE_ENV !== \"production\") {\n                    logger.debug(`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                return;\n            }\n            return result.slice(1);\n        };\n        super(match, handler, method);\n    }\n}\n\nconst parallel = async (limit, array, func)=>{\n    const work = array.map((item, index)=>({\n            index,\n            item\n        }));\n    const processor = async (res)=>{\n        const results = [];\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    const queues = Array.from({\n        length: limit\n    }, ()=>new Promise(processor));\n    const results = (await Promise.all(queues)).flat().sort((a, b)=>a.index < b.index ? -1 : 1).map((res)=>res.result);\n    return results;\n};\n\nconst disableDevLogs = ()=>{\n    self.__WB_DISABLE_DEV_LOGS = true;\n};\n\nfunction toRequest(input) {\n    return typeof input === \"string\" ? new Request(input) : input;\n}\nclass StrategyHandler {\n    event;\n    request;\n    url;\n    params;\n    _cacheKeys = {};\n    _strategy;\n    _handlerDeferred;\n    _extendLifetimePromises;\n    _plugins;\n    _pluginStateMap;\n    constructor(strategy, options){\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(options.event, ExtendableEvent, {\n                moduleName: \"serwist\",\n                className: \"StrategyHandler\",\n                funcName: \"constructor\",\n                paramName: \"options.event\"\n            });\n            finalAssertExports.isInstance(options.request, Request, {\n                moduleName: \"serwist\",\n                className: \"StrategyHandler\",\n                funcName: \"constructor\",\n                paramName: \"options.request\"\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        this._plugins = [\n            ...strategy.plugins\n        ];\n        this._pluginStateMap = new Map();\n        for (const plugin of this._plugins){\n            this._pluginStateMap.set(plugin, {});\n        }\n        this.event.waitUntil(this._handlerDeferred.promise);\n    }\n    async fetch(input) {\n        const { event } = this;\n        let request = toRequest(input);\n        const preloadResponse = await this.getPreloadResponse();\n        if (preloadResponse) {\n            return preloadResponse;\n        }\n        const originalRequest = this.hasCallback(\"fetchDidFail\") ? request.clone() : null;\n        try {\n            for (const cb of this.iterateCallbacks(\"requestWillFetch\")){\n                request = await cb({\n                    request: request.clone(),\n                    event\n                });\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        const pluginFilteredRequest = request.clone();\n        try {\n            let fetchResponse;\n            fetchResponse = await fetch(request, request.mode === \"navigate\" ? undefined : this._strategy.fetchOptions);\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            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            if (originalRequest) {\n                await this.runCallbacks(\"fetchDidFail\", {\n                    error: error,\n                    event,\n                    originalRequest: originalRequest.clone(),\n                    request: pluginFilteredRequest.clone()\n                });\n            }\n            throw error;\n        }\n    }\n    async fetchAndCachePut(input) {\n        const response = await this.fetch(input);\n        const responseClone = response.clone();\n        void this.waitUntil(this.cachePut(input, responseClone));\n        return response;\n    }\n    async cacheMatch(key) {\n        const request = toRequest(key);\n        let cachedResponse;\n        const { cacheName, matchOptions } = this._strategy;\n        const effectiveRequest = await this.getCacheKey(request, \"read\");\n        const multiMatchOptions = {\n            ...matchOptions,\n            ...{\n                cacheName\n            }\n        };\n        cachedResponse = await caches.match(effectiveRequest, multiMatchOptions);\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        for (const callback of this.iterateCallbacks(\"cachedResponseWillBeUsed\")){\n            cachedResponse = await callback({\n                cacheName,\n                matchOptions,\n                cachedResponse,\n                request: effectiveRequest,\n                event: this.event\n            }) || undefined;\n        }\n        return cachedResponse;\n    }\n    async cachePut(key, response) {\n        const request = toRequest(key);\n        await timeout(0);\n        const effectiveRequest = await this.getCacheKey(request, \"write\");\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        if (!response) {\n            if (process.env.NODE_ENV !== \"production\") {\n                logger.error(`Cannot cache non-existent response for '${getFriendlyURL(effectiveRequest.url)}'.`);\n            }\n            throw new SerwistError(\"cache-put-with-no-response\", {\n                url: getFriendlyURL(effectiveRequest.url)\n            });\n        }\n        const responseToCache = await this._ensureResponseSafeToCache(response);\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        const { cacheName, matchOptions } = this._strategy;\n        const cache = await self.caches.open(cacheName);\n        if (process.env.NODE_ENV !== \"production\") {\n            const vary = response.headers.get(\"Vary\");\n            if (vary && matchOptions?.ignoreVary !== true) {\n                logger.debug(`The response for ${getFriendlyURL(effectiveRequest.url)} 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        const hasCacheUpdateCallback = this.hasCallback(\"cacheDidUpdate\");\n        const oldResponse = hasCacheUpdateCallback ? await cacheMatchIgnoreParams(cache, effectiveRequest.clone(), [\n            \"__WB_REVISION__\"\n        ], matchOptions) : null;\n        if (process.env.NODE_ENV !== \"production\") {\n            logger.debug(`Updating the '${cacheName}' cache with a new Response for ${getFriendlyURL(effectiveRequest.url)}.`);\n        }\n        try {\n            await cache.put(effectiveRequest, hasCacheUpdateCallback ? responseToCache.clone() : responseToCache);\n        } catch (error) {\n            if (error instanceof Error) {\n                if (error.name === \"QuotaExceededError\") {\n                    await executeQuotaErrorCallbacks();\n                }\n                throw error;\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        return true;\n    }\n    async getCacheKey(request, mode) {\n        const key = `${request.url} | ${mode}`;\n        if (!this._cacheKeys[key]) {\n            let effectiveRequest = request;\n            for (const callback of this.iterateCallbacks(\"cacheKeyWillBeUsed\")){\n                effectiveRequest = toRequest(await callback({\n                    mode,\n                    request: effectiveRequest,\n                    event: this.event,\n                    params: this.params\n                }));\n            }\n            this._cacheKeys[key] = effectiveRequest;\n        }\n        return this._cacheKeys[key];\n    }\n    hasCallback(name) {\n        for (const plugin of this._strategy.plugins){\n            if (name in plugin) {\n                return true;\n            }\n        }\n        return false;\n    }\n    async runCallbacks(name, param) {\n        for (const callback of this.iterateCallbacks(name)){\n            await callback(param);\n        }\n    }\n    *iterateCallbacks(name) {\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)=>{\n                    const statefulParam = {\n                        ...param,\n                        state\n                    };\n                    return plugin[name](statefulParam);\n                };\n                yield statefulCallback;\n            }\n        }\n    }\n    waitUntil(promise) {\n        this._extendLifetimePromises.push(promise);\n        return promise;\n    }\n    async doneWaiting() {\n        let promise;\n        while(promise = this._extendLifetimePromises.shift()){\n            await promise;\n        }\n    }\n    destroy() {\n        this._handlerDeferred.resolve(null);\n    }\n    async getPreloadResponse() {\n        if (this.event instanceof FetchEvent && this.event.request.mode === \"navigate\" && \"preloadResponse\" in this.event) {\n            try {\n                const possiblePreloadResponse = await this.event.preloadResponse;\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    async _ensureResponseSafeToCache(response) {\n        let responseToCache = response;\n        let pluginsUsed = false;\n        for (const callback of this.iterateCallbacks(\"cacheWillUpdate\")){\n            responseToCache = await callback({\n                request: this.request,\n                response: responseToCache,\n                event: this.event\n            }) || undefined;\n            pluginsUsed = true;\n            if (!responseToCache) {\n                break;\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(`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                    } 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        return responseToCache;\n    }\n}\n\nclass Strategy {\n    cacheName;\n    plugins;\n    fetchOptions;\n    matchOptions;\n    constructor(options = {}){\n        this.cacheName = cacheNames.getRuntimeName(options.cacheName);\n        this.plugins = options.plugins || [];\n        this.fetchOptions = options.fetchOptions;\n        this.matchOptions = options.matchOptions;\n    }\n    handle(options) {\n        const [responseDone] = this.handleAll(options);\n        return responseDone;\n    }\n    handleAll(options) {\n        if (options instanceof FetchEvent) {\n            options = {\n                event: options,\n                request: options.request\n            };\n        }\n        const event = options.event;\n        const request = typeof options.request === \"string\" ? new Request(options.request) : options.request;\n        const handler = new StrategyHandler(this, options.url ? {\n            event,\n            request,\n            url: options.url,\n            params: options.params\n        } : {\n            event,\n            request\n        });\n        const responseDone = this._getResponse(handler, request, event);\n        const handlerDone = this._awaitComplete(responseDone, handler, request, event);\n        return [\n            responseDone,\n            handlerDone\n        ];\n    }\n    async _getResponse(handler, request, event) {\n        await handler.runCallbacks(\"handlerWillStart\", {\n            event,\n            request\n        });\n        let response;\n        try {\n            response = await this._handle(request, handler);\n            if (response === undefined || response.type === \"error\") {\n                throw new SerwistError(\"no-response\", {\n                    url: request.url\n                });\n            }\n        } catch (error) {\n            if (error instanceof Error) {\n                for (const callback of handler.iterateCallbacks(\"handlerDidError\")){\n                    response = await callback({\n                        error,\n                        event,\n                        request\n                    });\n                    if (response !== undefined) {\n                        break;\n                    }\n                }\n            }\n            if (!response) {\n                throw error;\n            }\n            if (process.env.NODE_ENV !== \"production\") {\n                throw logger.log(`While responding to '${getFriendlyURL(request.url)}', an ${error instanceof Error ? error.toString() : \"\"} error occurred. Using a fallback response provided by a handlerDidError plugin.`);\n            }\n        }\n        for (const callback of handler.iterateCallbacks(\"handlerWillRespond\")){\n            response = await callback({\n                event,\n                request,\n                response\n            });\n        }\n        return response;\n    }\n    async _awaitComplete(responseDone, handler, request, event) {\n        let response;\n        let error;\n        try {\n            response = await responseDone;\n        } catch  {}\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        await handler.runCallbacks(\"handlerDidComplete\", {\n            event,\n            request,\n            response,\n            error\n        });\n        handler.destroy();\n        if (error) {\n            throw error;\n        }\n    }\n}\n\nconst cacheOkAndOpaquePlugin = {\n    cacheWillUpdate: async ({ response })=>{\n        if (response.status === 200 || response.status === 0) {\n            return response;\n        }\n        return null;\n    }\n};\n\nconst messages = {\n    strategyStart: (strategyName, request)=>`Using ${strategyName} to respond to '${getFriendlyURL(request.url)}'`,\n    printFinalResponse: (response)=>{\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\nclass NetworkFirst extends Strategy {\n    _networkTimeoutSeconds;\n    constructor(options = {}){\n        super(options);\n        if (!this.plugins.some((p)=>\"cacheWillUpdate\" in p)) {\n            this.plugins.unshift(cacheOkAndOpaquePlugin);\n        }\n        this._networkTimeoutSeconds = options.networkTimeoutSeconds || 0;\n        if (process.env.NODE_ENV !== \"production\") {\n            if (this._networkTimeoutSeconds) {\n                finalAssertExports.isType(this._networkTimeoutSeconds, \"number\", {\n                    moduleName: \"serwist\",\n                    className: this.constructor.name,\n                    funcName: \"constructor\",\n                    paramName: \"networkTimeoutSeconds\"\n                });\n            }\n        }\n    }\n    async _handle(request, handler) {\n        const logs = [];\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(request, Request, {\n                moduleName: \"serwist\",\n                className: this.constructor.name,\n                funcName: \"handle\",\n                paramName: \"makeRequest\"\n            });\n        }\n        const promises = [];\n        let timeoutId;\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        const networkPromise = this._getNetworkPromise({\n            timeoutId,\n            request,\n            logs,\n            handler\n        });\n        promises.push(networkPromise);\n        const response = await handler.waitUntil((async ()=>{\n            return await handler.waitUntil(Promise.race(promises)) || await networkPromise;\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        if (!response) {\n            throw new SerwistError(\"no-response\", {\n                url: request.url\n            });\n        }\n        return response;\n    }\n    _getTimeoutPromise({ request, logs, handler }) {\n        let timeoutId;\n        const timeoutPromise = 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        return {\n            promise: timeoutPromise,\n            id: timeoutId\n        };\n    }\n    async _getNetworkPromise({ timeoutId, request, logs, handler }) {\n        let error;\n        let response;\n        try {\n            response = await handler.fetchAndCachePut(request);\n        } catch (fetchError) {\n            if (fetchError instanceof Error) {\n                error = fetchError;\n            }\n        }\n        if (timeoutId) {\n            clearTimeout(timeoutId);\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        if (error || !response) {\n            response = await handler.cacheMatch(request);\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        return response;\n    }\n}\n\nclass NetworkOnly extends Strategy {\n    _networkTimeoutSeconds;\n    constructor(options = {}){\n        super(options);\n        this._networkTimeoutSeconds = options.networkTimeoutSeconds || 0;\n    }\n    async _handle(request, handler) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(request, Request, {\n                moduleName: \"serwist\",\n                className: this.constructor.name,\n                funcName: \"_handle\",\n                paramName: \"request\"\n            });\n        }\n        let error;\n        let response;\n        try {\n            const promises = [\n                handler.fetch(request)\n            ];\n            if (this._networkTimeoutSeconds) {\n                const timeoutPromise = timeout(this._networkTimeoutSeconds * 1000);\n                promises.push(timeoutPromise);\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        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        if (!response) {\n            throw new SerwistError(\"no-response\", {\n                url: request.url,\n                error\n            });\n        }\n        return response;\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\";\nclass BackgroundSyncQueueDb {\n    _db = null;\n    async addEntry(entry) {\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);\n        await tx.done;\n    }\n    async getFirstEntryId() {\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    async getAllEntriesByQueueName(queueName) {\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 : [];\n    }\n    async getEntryCountByQueueName(queueName) {\n        const db = await this.getDb();\n        return db.countFromIndex(REQUEST_OBJECT_STORE_NAME, QUEUE_NAME_INDEX, IDBKeyRange.only(queueName));\n    }\n    async deleteEntry(id) {\n        const db = await this.getDb();\n        await db.delete(REQUEST_OBJECT_STORE_NAME, id);\n    }\n    async getFirstEntryByQueueName(queueName) {\n        return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), \"next\");\n    }\n    async getLastEntryByQueueName(queueName) {\n        return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), \"prev\");\n    }\n    async getEndEntryFromIndex(query, direction) {\n        const db = await this.getDb();\n        const cursor = await db.transaction(REQUEST_OBJECT_STORE_NAME).store.index(QUEUE_NAME_INDEX).openCursor(query, direction);\n        return cursor?.value;\n    }\n    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    _upgradeDb(db, oldVersion) {\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        const objStore = db.createObjectStore(REQUEST_OBJECT_STORE_NAME, {\n            autoIncrement: true,\n            keyPath: \"id\"\n        });\n        objStore.createIndex(QUEUE_NAME_INDEX, QUEUE_NAME_INDEX, {\n            unique: false\n        });\n    }\n}\n\nclass BackgroundSyncQueueStore {\n    _queueName;\n    _queueDb;\n    constructor(queueName){\n        this._queueName = queueName;\n        this._queueDb = new BackgroundSyncQueueDb();\n    }\n    async pushEntry(entry) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(entry, \"object\", {\n                moduleName: \"serwist\",\n                className: \"BackgroundSyncQueueStore\",\n                funcName: \"pushEntry\",\n                paramName: \"entry\"\n            });\n            finalAssertExports.isType(entry.requestData, \"object\", {\n                moduleName: \"serwist\",\n                className: \"BackgroundSyncQueueStore\",\n                funcName: \"pushEntry\",\n                paramName: \"entry.requestData\"\n            });\n        }\n        delete entry.id;\n        entry.queueName = this._queueName;\n        await this._queueDb.addEntry(entry);\n    }\n    async unshiftEntry(entry) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(entry, \"object\", {\n                moduleName: \"serwist\",\n                className: \"BackgroundSyncQueueStore\",\n                funcName: \"unshiftEntry\",\n                paramName: \"entry\"\n            });\n            finalAssertExports.isType(entry.requestData, \"object\", {\n                moduleName: \"serwist\",\n                className: \"BackgroundSyncQueueStore\",\n                funcName: \"unshiftEntry\",\n                paramName: \"entry.requestData\"\n            });\n        }\n        const firstId = await this._queueDb.getFirstEntryId();\n        if (firstId) {\n            entry.id = firstId - 1;\n        } else {\n            delete entry.id;\n        }\n        entry.queueName = this._queueName;\n        await this._queueDb.addEntry(entry);\n    }\n    async popEntry() {\n        return this._removeEntry(await this._queueDb.getLastEntryByQueueName(this._queueName));\n    }\n    async shiftEntry() {\n        return this._removeEntry(await this._queueDb.getFirstEntryByQueueName(this._queueName));\n    }\n    async getAll() {\n        return await this._queueDb.getAllEntriesByQueueName(this._queueName);\n    }\n    async size() {\n        return await this._queueDb.getEntryCountByQueueName(this._queueName);\n    }\n    async deleteEntry(id) {\n        await this._queueDb.deleteEntry(id);\n    }\n    async _removeEntry(entry) {\n        if (entry) {\n            await this.deleteEntry(entry.id);\n        }\n        return entry;\n    }\n}\n\nconst serializableProperties = [\n    \"method\",\n    \"referrer\",\n    \"referrerPolicy\",\n    \"mode\",\n    \"credentials\",\n    \"cache\",\n    \"redirect\",\n    \"integrity\",\n    \"keepalive\"\n];\nclass StorableRequest {\n    _requestData;\n    static async fromRequest(request) {\n        const requestData = {\n            url: request.url,\n            headers: {}\n        };\n        if (request.method !== \"GET\") {\n            requestData.body = await request.clone().arrayBuffer();\n        }\n        request.headers.forEach((value, key)=>{\n            requestData.headers[key] = value;\n        });\n        for (const prop of serializableProperties){\n            if (request[prop] !== undefined) {\n                requestData[prop] = request[prop];\n            }\n        }\n        return new StorableRequest(requestData);\n    }\n    constructor(requestData){\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(requestData, \"object\", {\n                moduleName: \"serwist\",\n                className: \"StorableRequest\",\n                funcName: \"constructor\",\n                paramName: \"requestData\"\n            });\n            finalAssertExports.isType(requestData.url, \"string\", {\n                moduleName: \"serwist\",\n                className: \"StorableRequest\",\n                funcName: \"constructor\",\n                paramName: \"requestData.url\"\n            });\n        }\n        if (requestData.mode === \"navigate\") {\n            requestData.mode = \"same-origin\";\n        }\n        this._requestData = requestData;\n    }\n    toObject() {\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        return requestData;\n    }\n    toRequest() {\n        return new Request(this._requestData.url, this._requestData);\n    }\n    clone() {\n        return new StorableRequest(this.toObject());\n    }\n}\n\nconst TAG_PREFIX = \"serwist-background-sync\";\nconst MAX_RETENTION_TIME = 60 * 24 * 7;\nconst queueNames = new Set();\nconst convertEntry = (queueStoreEntry)=>{\n    const queueEntry = {\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};\nclass BackgroundSyncQueue {\n    _name;\n    _onSync;\n    _maxRetentionTime;\n    _queueStore;\n    _forceSyncFallback;\n    _syncInProgress = false;\n    _requestsAddedDuringSync = false;\n    constructor(name, { forceSyncFallback, onSync, maxRetentionTime } = {}){\n        if (queueNames.has(name)) {\n            throw new SerwistError(\"duplicate-queue-name\", {\n                name\n            });\n        }\n        queueNames.add(name);\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        this._addSyncListener();\n    }\n    get name() {\n        return this._name;\n    }\n    async pushRequest(entry) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(entry, \"object\", {\n                moduleName: \"serwist\",\n                className: \"BackgroundSyncQueue\",\n                funcName: \"pushRequest\",\n                paramName: \"entry\"\n            });\n            finalAssertExports.isInstance(entry.request, Request, {\n                moduleName: \"serwist\",\n                className: \"BackgroundSyncQueue\",\n                funcName: \"pushRequest\",\n                paramName: \"entry.request\"\n            });\n        }\n        await this._addRequest(entry, \"push\");\n    }\n    async unshiftRequest(entry) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(entry, \"object\", {\n                moduleName: \"serwist\",\n                className: \"BackgroundSyncQueue\",\n                funcName: \"unshiftRequest\",\n                paramName: \"entry\"\n            });\n            finalAssertExports.isInstance(entry.request, Request, {\n                moduleName: \"serwist\",\n                className: \"BackgroundSyncQueue\",\n                funcName: \"unshiftRequest\",\n                paramName: \"entry.request\"\n            });\n        }\n        await this._addRequest(entry, \"unshift\");\n    }\n    async popRequest() {\n        return this._removeRequest(\"pop\");\n    }\n    async shiftRequest() {\n        return this._removeRequest(\"shift\");\n    }\n    async getAll() {\n        const allEntries = await this._queueStore.getAll();\n        const now = Date.now();\n        const unexpiredEntries = [];\n        for (const entry of allEntries){\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        return unexpiredEntries;\n    }\n    async size() {\n        return await this._queueStore.size();\n    }\n    async _addRequest({ request, metadata, timestamp = Date.now() }, operation) {\n        const storableRequest = await StorableRequest.fromRequest(request.clone());\n        const entry = {\n            requestData: storableRequest.toObject(),\n            timestamp\n        };\n        if (metadata) {\n            entry.metadata = metadata;\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        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        if (this._syncInProgress) {\n            this._requestsAddedDuringSync = true;\n        } else {\n            await this.registerSync();\n        }\n    }\n    async _removeRequest(operation) {\n        const now = Date.now();\n        let entry;\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        if (entry) {\n            const maxRetentionTimeInMs = this._maxRetentionTime * 60 * 1000;\n            if (now - entry.timestamp > maxRetentionTimeInMs) {\n                return this._removeRequest(operation);\n            }\n            return convertEntry(entry);\n        }\n        return undefined;\n    }\n    async replayRequests() {\n        let entry;\n        while(entry = await this.shiftRequest()){\n            try {\n                await fetch(entry.request.clone());\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                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\", {\n                    name: this._name\n                });\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    async registerSync() {\n        if (\"sync\" in self.registration && !this._forceSyncFallback) {\n            try {\n                await self.registration.sync.register(`${TAG_PREFIX}:${this._name}`);\n            } catch (err) {\n                if (process.env.NODE_ENV !== \"production\") {\n                    logger.warn(`Unable to register sync event for '${this._name}'.`, err);\n                }\n            }\n        }\n    }\n    _addSyncListener() {\n        if (\"sync\" in self.registration && !this._forceSyncFallback) {\n            self.addEventListener(\"sync\", (event)=>{\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                    const syncComplete = async ()=>{\n                        this._syncInProgress = true;\n                        let syncError;\n                        try {\n                            await this._onSync({\n                                queue: this\n                            });\n                        } catch (error) {\n                            if (error instanceof Error) {\n                                syncError = error;\n                                throw syncError;\n                            }\n                        } finally{\n                            if (this._requestsAddedDuringSync && !(syncError && !event.lastChance)) {\n                                await this.registerSync();\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            void this._onSync({\n                queue: this\n            });\n        }\n    }\n    static get _queueNames() {\n        return queueNames;\n    }\n}\n\nclass BackgroundSyncPlugin {\n    _queue;\n    constructor(name, options){\n        this._queue = new BackgroundSyncQueue(name, options);\n    }\n    async fetchDidFail({ request }) {\n        await this._queue.pushRequest({\n            request\n        });\n    }\n}\n\nconst copyResponse = async (response, modifier)=>{\n    let origin = null;\n    if (response.url) {\n        const responseURL = new URL(response.url);\n        origin = responseURL.origin;\n    }\n    if (origin !== self.location.origin) {\n        throw new SerwistError(\"cross-origin-copy-response\", {\n            origin\n        });\n    }\n    const clonedResponse = response.clone();\n    const responseInit = {\n        headers: new Headers(clonedResponse.headers),\n        status: clonedResponse.status,\n        statusText: clonedResponse.statusText\n    };\n    const modifiedResponseInit = modifier ? modifier(responseInit) : responseInit;\n    const body = canConstructResponseFromBodyStream() ? clonedResponse.body : await clonedResponse.blob();\n    return new Response(body, modifiedResponseInit);\n};\n\nclass PrecacheStrategy extends Strategy {\n    _fallbackToNetwork;\n    static defaultPrecacheCacheabilityPlugin = {\n        async cacheWillUpdate ({ response }) {\n            if (!response || response.status >= 400) {\n                return null;\n            }\n            return response;\n        }\n    };\n    static copyRedirectedCacheableResponsesPlugin = {\n        async cacheWillUpdate ({ response }) {\n            return response.redirected ? await copyResponse(response) : response;\n        }\n    };\n    constructor(options = {}){\n        options.cacheName = cacheNames.getPrecacheName(options.cacheName);\n        super(options);\n        this._fallbackToNetwork = options.fallbackToNetwork !== false;\n        this.plugins.push(PrecacheStrategy.copyRedirectedCacheableResponsesPlugin);\n    }\n    async _handle(request, handler) {\n        const preloadResponse = await handler.getPreloadResponse();\n        if (preloadResponse) {\n            return preloadResponse;\n        }\n        const response = await handler.cacheMatch(request);\n        if (response) {\n            return response;\n        }\n        if (handler.event && handler.event.type === \"install\") {\n            return await this._handleInstall(request, handler);\n        }\n        return await this._handleFetch(request, handler);\n    }\n    async _handleFetch(request, handler) {\n        let response;\n        const params = handler.params || {};\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            const integrityInManifest = params.integrity;\n            const integrityInRequest = request.integrity;\n            const noIntegrityConflict = !integrityInRequest || integrityInRequest === integrityInManifest;\n            response = await handler.fetch(new Request(request, {\n                integrity: request.mode !== \"no-cors\" ? integrityInRequest || integrityInManifest : undefined\n            }));\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            throw new SerwistError(\"missing-precache-entry\", {\n                cacheName: this.cacheName,\n                url: request.url\n            });\n        }\n        if (process.env.NODE_ENV !== \"production\") {\n            const cacheKey = params.cacheKey || await handler.getCacheKey(request, \"read\");\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            logger.groupCollapsed(\"View request details here.\");\n            logger.log(request);\n            logger.groupEnd();\n            logger.groupCollapsed(\"View response details here.\");\n            logger.log(response);\n            logger.groupEnd();\n            logger.groupEnd();\n        }\n        return response;\n    }\n    async _handleInstall(request, handler) {\n        this._useDefaultCacheabilityPluginIfNeeded();\n        const response = await handler.fetch(request);\n        const wasCached = await handler.cachePut(request, response.clone());\n        if (!wasCached) {\n            throw new SerwistError(\"bad-precaching-response\", {\n                url: request.url,\n                status: response.status\n            });\n        }\n        return response;\n    }\n    _useDefaultCacheabilityPluginIfNeeded() {\n        let defaultPluginIndex = null;\n        let cacheWillUpdatePluginCount = 0;\n        for (const [index, plugin] of this.plugins.entries()){\n            if (plugin === PrecacheStrategy.copyRedirectedCacheableResponsesPlugin) {\n                continue;\n            }\n            if (plugin === PrecacheStrategy.defaultPrecacheCacheabilityPlugin) {\n                defaultPluginIndex = index;\n            }\n            if (plugin.cacheWillUpdate) {\n                cacheWillUpdatePluginCount++;\n            }\n        }\n        if (cacheWillUpdatePluginCount === 0) {\n            this.plugins.push(PrecacheStrategy.defaultPrecacheCacheabilityPlugin);\n        } else if (cacheWillUpdatePluginCount > 1 && defaultPluginIndex !== null) {\n            this.plugins.splice(defaultPluginIndex, 1);\n        }\n    }\n}\n\nconst isNavigationPreloadSupported = ()=>{\n    return Boolean(self.registration?.navigationPreload);\n};\nconst enableNavigationPreload = (headerValue)=>{\n    if (isNavigationPreloadSupported()) {\n        self.addEventListener(\"activate\", (event)=>{\n            event.waitUntil(self.registration.navigationPreload.enable().then(()=>{\n                if (headerValue) {\n                    void self.registration.navigationPreload.setHeaderValue(headerValue);\n                }\n                if (process.env.NODE_ENV !== \"production\") {\n                    logger.log(\"Navigation preloading is enabled.\");\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};\nconst disableNavigationPreload = ()=>{\n    if (isNavigationPreloadSupported()) {\n        self.addEventListener(\"activate\", (event)=>{\n            event.waitUntil(self.registration.navigationPreload.disable().then(()=>{\n                if (process.env.NODE_ENV !== \"production\") {\n                    logger.log(\"Navigation preloading is disabled.\");\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\nconst setCacheNameDetails = (details)=>{\n    if (process.env.NODE_ENV !== \"production\") {\n        for (const key of Object.keys(details)){\n            finalAssertExports.isType(details[key], \"string\", {\n                moduleName: \"@serwist/core\",\n                funcName: \"setCacheNameDetails\",\n                paramName: `details.${key}`\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        if (details.runtime?.length === 0) {\n            throw new SerwistError(\"invalid-cache-name\", {\n                cacheNameId: \"runtime\",\n                value: details.runtime\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    cacheNames.updateDetails(details);\n};\n\nclass PrecacheInstallReportPlugin {\n    updatedURLs = [];\n    notUpdatedURLs = [];\n    handlerWillStart = async ({ request, state })=>{\n        if (state) {\n            state.originalRequest = request;\n        }\n    };\n    cachedResponseWillBeUsed = async ({ event, state, cachedResponse })=>{\n        if (event.type === \"install\") {\n            if (state?.originalRequest && state.originalRequest instanceof Request) {\n                const url = state.originalRequest.url;\n                if (cachedResponse) {\n                    this.notUpdatedURLs.push(url);\n                } else {\n                    this.updatedURLs.push(url);\n                }\n            }\n        }\n        return cachedResponse;\n    };\n}\n\nconst REVISION_SEARCH_PARAM = \"__WB_REVISION__\";\nconst createCacheKey = (entry)=>{\n    if (!entry) {\n        throw new SerwistError(\"add-to-cache-list-unexpected-type\", {\n            entry\n        });\n    }\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    const { revision, url } = entry;\n    if (!url) {\n        throw new SerwistError(\"add-to-cache-list-unexpected-type\", {\n            entry\n        });\n    }\n    if (!revision) {\n        const urlObject = new URL(url, location.href);\n        return {\n            cacheKey: urlObject.href,\n            url: urlObject.href\n        };\n    }\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\nconst parseRoute = (capture, handler, method)=>{\n    if (typeof capture === \"string\") {\n        const captureUrl = new URL(capture, location.href);\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            const valueToCheck = capture.startsWith(\"http\") ? captureUrl.pathname : capture;\n            const wildcards = \"[*:?+]\";\n            if (new RegExp(`${wildcards}`).exec(valueToCheck)) {\n                logger.debug(`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        const matchCallback = ({ url })=>{\n            if (process.env.NODE_ENV !== \"production\") {\n                if (url.pathname === captureUrl.pathname && url.origin !== captureUrl.origin) {\n                    logger.debug(`${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            return url.href === captureUrl.href;\n        };\n        return new Route(matchCallback, handler, method);\n    }\n    if (capture instanceof RegExp) {\n        return new RegExpRoute(capture, handler, method);\n    }\n    if (typeof capture === \"function\") {\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\nconst logGroup = (groupTitle, deletedURLs)=>{\n    logger.groupCollapsed(groupTitle);\n    for (const url of deletedURLs){\n        logger.log(url);\n    }\n    logger.groupEnd();\n};\nconst printCleanupDetails = (deletedURLs)=>{\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\nfunction _nestedGroup(groupTitle, urls) {\n    if (urls.length === 0) {\n        return;\n    }\n    logger.groupCollapsed(groupTitle);\n    for (const url of urls){\n        logger.log(url);\n    }\n    logger.groupEnd();\n}\nconst printInstallDetails = (urlsToPrecache, urlsAlreadyPrecached)=>{\n    const precachedCount = urlsToPrecache.length;\n    const alreadyPrecachedCount = urlsAlreadyPrecached.length;\n    if (precachedCount || alreadyPrecachedCount) {\n        let message = `Precaching ${precachedCount} file${precachedCount === 1 ? \"\" : \"s\"}.`;\n        if (alreadyPrecachedCount > 0) {\n            message += ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? \" is\" : \"s are\"} already cached.`;\n        }\n        logger.groupCollapsed(message);\n        _nestedGroup(\"View newly precached URLs.\", urlsToPrecache);\n        _nestedGroup(\"View previously precached URLs.\", urlsAlreadyPrecached);\n        logger.groupEnd();\n    }\n};\n\nexport { BackgroundSyncPlugin as B, NetworkFirst as N, PrecacheStrategy as P, Route as R, Strategy as S, NetworkOnly as a, NavigationRoute as b, createCacheKey as c, disableDevLogs as d, enableNavigationPreload as e, defaultMethod as f, generateURLVariations as g, PrecacheInstallReportPlugin as h, parallel as i, printInstallDetails as j, printCleanupDetails as k, cacheOkAndOpaquePlugin as l, messages as m, normalizeHandler as n, copyResponse as o, parseRoute as p, disableNavigationPreload as q, isNavigationPreloadSupported as r, setCacheNameDetails as s, StrategyHandler as t, RegExpRoute as u, BackgroundSyncQueue as v, BackgroundSyncQueueStore as w, StorableRequest as x };\n", "import { R as Route, g as generateURLVariations, B as BackgroundSyncPlugin, N as NetworkFirst, a as NetworkOnly, P as PrecacheStrategy, e as enableNavigationPreload, s as setCacheNameDetails, b as NavigationRoute, S as Strategy, d as disableDevLogs, c as createCacheKey, f as defaultMethod, n as normalizeHandler, p as parseRoute, h as PrecacheInstallReportPlugin, i as parallel, j as printInstallDetails, k as printCleanupDetails, m as messages, l as cacheOkAndOpaquePlugin } from './chunks/printInstallDetails.js';\nexport { v as BackgroundSyncQueue, w as BackgroundSyncQueueStore, u as RegExpRoute, x as StorableRequest, t as StrategyHandler, o as copyResponse, q as disableNavigationPreload, r as isNavigationPreloadSupported } from './chunks/printInstallDetails.js';\nimport { l as logger, g as getFriendlyURL, c as cacheNames$1, a as clientsClaim, b as cleanupOutdatedCaches, f as finalAssertExports, S as SerwistError, w as waitUntil, t as timeout, q as quotaErrorCallbacks } from './chunks/waitUntil.js';\nimport { r as resultingClientExists } from './chunks/resultingClientExists.js';\nimport { deleteDB, openDB } from 'idb';\n\nclass PrecacheRoute extends Route {\n    constructor(serwist, options){\n        const match = ({ request })=>{\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 {\n                        cacheKey,\n                        integrity\n                    };\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        super(match, serwist.precacheStrategy);\n    }\n}\n\nconst QUEUE_NAME = \"serwist-google-analytics\";\nconst MAX_RETENTION_TIME = 60 * 48;\nconst GOOGLE_ANALYTICS_HOST = \"www.google-analytics.com\";\nconst GTM_HOST = \"www.googletagmanager.com\";\nconst ANALYTICS_JS_PATH = \"/analytics.js\";\nconst GTAG_JS_PATH = \"/gtag/js\";\nconst GTM_JS_PATH = \"/gtm.js\";\nconst COLLECT_PATHS_REGEX = /^\\/(\\w+\\/)?collect/;\n\nconst createOnSyncCallback = (config)=>{\n    return async ({ queue })=>{\n        let entry;\n        while(entry = await queue.shiftRequest()){\n            const { request, timestamp } = entry;\n            const url = new URL(request.url);\n            try {\n                const params = request.method === \"POST\" ? new URLSearchParams(await request.clone().text()) : url.searchParams;\n                const originalHitTime = timestamp - (Number(params.get(\"qt\")) || 0);\n                const queueTime = Date.now() - originalHitTime;\n                params.set(\"qt\", String(queueTime));\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                if (typeof config.hitFilter === \"function\") {\n                    config.hitFilter.call(null, params);\n                }\n                await fetch(new Request(url.origin + url.pathname, {\n                    body: params.toString(),\n                    method: \"POST\",\n                    mode: \"cors\",\n                    credentials: \"omit\",\n                    headers: {\n                        \"Content-Type\": \"text/plain\"\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                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};\nconst createCollectRoutes = (bgSyncPlugin)=>{\n    const match = ({ url })=>url.hostname === GOOGLE_ANALYTICS_HOST && COLLECT_PATHS_REGEX.test(url.pathname);\n    const handler = new NetworkOnly({\n        plugins: [\n            bgSyncPlugin\n        ]\n    });\n    return [\n        new Route(match, handler, \"GET\"),\n        new Route(match, handler, \"POST\")\n    ];\n};\nconst createAnalyticsJsRoute = (cacheName)=>{\n    const match = ({ url })=>url.hostname === GOOGLE_ANALYTICS_HOST && url.pathname === ANALYTICS_JS_PATH;\n    const handler = new NetworkFirst({\n        cacheName\n    });\n    return new Route(match, handler, \"GET\");\n};\nconst createGtagJsRoute = (cacheName)=>{\n    const match = ({ url })=>url.hostname === GTM_HOST && url.pathname === GTAG_JS_PATH;\n    const handler = new NetworkFirst({\n        cacheName\n    });\n    return new Route(match, handler, \"GET\");\n};\nconst createGtmJsRoute = (cacheName)=>{\n    const match = ({ url })=>url.hostname === GTM_HOST && url.pathname === GTM_JS_PATH;\n    const handler = new NetworkFirst({\n        cacheName\n    });\n    return new Route(match, handler, \"GET\");\n};\nconst initializeGoogleAnalytics = ({ serwist, cacheName, ...options })=>{\n    const resolvedCacheName = cacheNames$1.getGoogleAnalyticsName(cacheName);\n    const bgSyncPlugin = new BackgroundSyncPlugin(QUEUE_NAME, {\n        maxRetentionTime: MAX_RETENTION_TIME,\n        onSync: createOnSyncCallback(options)\n    });\n    const routes = [\n        createGtmJsRoute(resolvedCacheName),\n        createAnalyticsJsRoute(resolvedCacheName),\n        createGtagJsRoute(resolvedCacheName),\n        ...createCollectRoutes(bgSyncPlugin)\n    ];\n    for (const route of routes){\n        serwist.registerRoute(route);\n    }\n};\n\nclass PrecacheFallbackPlugin {\n    _fallbackUrls;\n    _serwist;\n    constructor({ fallbackUrls, serwist }){\n        this._fallbackUrls = fallbackUrls;\n        this._serwist = serwist;\n    }\n    async handlerDidError(param) {\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\nclass PrecacheCacheKeyPlugin {\n    _precacheController;\n    constructor({ precacheController }){\n        this._precacheController = precacheController;\n    }\n    cacheKeyWillBeUsed = async ({ request, params })=>{\n        const cacheKey = params?.cacheKey || this._precacheController.getPrecacheKeyForUrl(request.url);\n        return cacheKey ? new Request(cacheKey, {\n            headers: request.headers\n        }) : request;\n    };\n}\n\nconst parsePrecacheOptions = (serwist, precacheOptions = {})=>{\n    const { cacheName: precacheCacheName, plugins: precachePlugins = [], fetchOptions: precacheFetchOptions, matchOptions: precacheMatchOptions, fallbackToNetwork: precacheFallbackToNetwork, directoryIndex: precacheDirectoryIndex, ignoreURLParametersMatching: precacheIgnoreUrls, cleanURLs: precacheCleanUrls, urlManipulation: precacheUrlManipulation, cleanupOutdatedCaches, concurrency = 10, navigateFallback, navigateFallbackAllowlist, navigateFallbackDenylist } = precacheOptions ?? {};\n    return {\n        precacheStrategyOptions: {\n            cacheName: cacheNames$1.getPrecacheName(precacheCacheName),\n            plugins: [\n                ...precachePlugins,\n                new PrecacheCacheKeyPlugin({\n                    precacheController: serwist\n                })\n            ],\n            fetchOptions: precacheFetchOptions,\n            matchOptions: precacheMatchOptions,\n            fallbackToNetwork: precacheFallbackToNetwork\n        },\n        precacheRouteOptions: {\n            directoryIndex: precacheDirectoryIndex,\n            ignoreURLParametersMatching: precacheIgnoreUrls,\n            cleanURLs: precacheCleanUrls,\n            urlManipulation: precacheUrlManipulation\n        },\n        precacheMiscOptions: {\n            cleanupOutdatedCaches,\n            concurrency,\n            navigateFallback,\n            navigateFallbackAllowlist,\n            navigateFallbackDenylist\n        }\n    };\n};\n\nclass Serwist {\n    _urlsToCacheKeys = new Map();\n    _urlsToCacheModes = new Map();\n    _cacheKeysToIntegrities = new Map();\n    _concurrentPrecaching;\n    _precacheStrategy;\n    _routes;\n    _defaultHandlerMap;\n    _catchHandler;\n    _requestRules;\n    constructor({ precacheEntries, precacheOptions, skipWaiting = false, importScripts, navigationPreload = false, cacheId, clientsClaim: clientsClaim$1 = false, runtimeCaching, offlineAnalyticsConfig, disableDevLogs: disableDevLogs$1 = false, fallbacks, requestRules } = {}){\n        const { precacheStrategyOptions, precacheRouteOptions, precacheMiscOptions } = parsePrecacheOptions(this, precacheOptions);\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        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        if (!!importScripts && importScripts.length > 0) self.importScripts(...importScripts);\n        if (navigationPreload) enableNavigationPreload();\n        if (cacheId !== undefined) {\n            setCacheNameDetails({\n                prefix: cacheId\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        if (clientsClaim$1) clientsClaim();\n        if (!!precacheEntries && precacheEntries.length > 0) {\n            this.addToPrecacheList(precacheEntries);\n        }\n        if (precacheMiscOptions.cleanupOutdatedCaches) {\n            cleanupOutdatedCaches(precacheStrategyOptions.cacheName);\n        }\n        this.registerRoute(new PrecacheRoute(this, precacheRouteOptions));\n        if (precacheMiscOptions.navigateFallback) {\n            this.registerRoute(new NavigationRoute(this.createHandlerBoundToUrl(precacheMiscOptions.navigateFallback), {\n                allowlist: precacheMiscOptions.navigateFallbackAllowlist,\n                denylist: precacheMiscOptions.navigateFallbackDenylist\n            }));\n        }\n        if (offlineAnalyticsConfig !== undefined) {\n            if (typeof offlineAnalyticsConfig === \"boolean\") {\n                offlineAnalyticsConfig && initializeGoogleAnalytics({\n                    serwist: this\n                });\n            } else {\n                initializeGoogleAnalytics({\n                    ...offlineAnalyticsConfig,\n                    serwist: this\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                runtimeCaching.forEach((cacheEntry)=>{\n                    if (cacheEntry.handler instanceof Strategy && !cacheEntry.handler.plugins.some((plugin)=>\"handlerDidError\" in plugin)) {\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        if (disableDevLogs$1) disableDevLogs();\n    }\n    get precacheStrategy() {\n        return this._precacheStrategy;\n    }\n    get routes() {\n        return this._routes;\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    addToPrecacheList(entries) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isArray(entries, {\n                moduleName: \"serwist\",\n                className: \"Serwist\",\n                funcName: \"addToCacheList\",\n                paramName: \"entries\"\n            });\n        }\n        const urlsToWarnAbout = [];\n        for (const entry of entries){\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            const { cacheKey, url } = createCacheKey(entry);\n            const cacheMode = typeof entry !== \"string\" && entry.revision ? \"reload\" : \"default\";\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            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            this._urlsToCacheKeys.set(url, cacheKey);\n            this._urlsToCacheModes.set(url, cacheMode);\n            if (urlsToWarnAbout.length > 0) {\n                const warningMessage = `Serwist is precaching URLs without revision info: ${urlsToWarnAbout.join(\", \")}\\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;\n                if (process.env.NODE_ENV === \"production\") {\n                    console.warn(warningMessage);\n                } else {\n                    logger.warn(warningMessage);\n                }\n            }\n        }\n    }\n    handleInstall(event) {\n        void this.registerRequestRules(event);\n        return waitUntil(event, async ()=>{\n            const installReportPlugin = new PrecacheInstallReportPlugin();\n            this.precacheStrategy.plugins.push(installReportPlugin);\n            await parallel(this._concurrentPrecaching, Array.from(this._urlsToCacheKeys.entries()), async ([url, cacheKey])=>{\n                const integrity = this._cacheKeysToIntegrities.get(cacheKey);\n                const cacheMode = this._urlsToCacheModes.get(url);\n                const request = new Request(url, {\n                    integrity,\n                    cache: cacheMode,\n                    credentials: \"same-origin\"\n                });\n                await Promise.all(this.precacheStrategy.handleAll({\n                    event,\n                    request,\n                    url: new URL(request.url),\n                    params: {\n                        cacheKey\n                    }\n                }));\n            });\n            const { updatedURLs, notUpdatedURLs } = installReportPlugin;\n            if (process.env.NODE_ENV !== \"production\") {\n                printInstallDetails(updatedURLs, notUpdatedURLs);\n            }\n            return {\n                updatedURLs,\n                notUpdatedURLs\n            };\n        });\n    }\n    async registerRequestRules(event) {\n        if (!this._requestRules) {\n            return;\n        }\n        if (!event?.addRoutes) {\n            if (process.env.NODE_ENV !== \"production\") {\n                logger.warn(\"Request rules ignored as the Static Routing API is not supported in this browser. \" + \"See https://caniuse.com/mdn-api_installevent_addroutes for more information.\");\n            }\n            return;\n        }\n        try {\n            if (process.env.NODE_ENV !== \"production\") {\n                logger.warn(\"Request rules may not be supported in all browsers as the Static Routing API is experimental. \" + \"This feature allows bypassing the service worker for specific requests to improve performance. \" + \"See https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent/addRoutes for more information.\");\n            }\n            await event.addRoutes(this._requestRules);\n            this._requestRules = undefined;\n        } catch (error) {\n            if (process.env.NODE_ENV !== \"production\") {\n                logger.error(`Failed to register request rules: ${error instanceof Error ? error.message : String(error)}. ` + \"This may occur if the browser doesn't support the Static Routing API or if the request rules are invalid.\");\n            }\n            throw error;\n        }\n    }\n    handleActivate(event) {\n        return waitUntil(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            const deletedCacheRequests = [];\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            if (process.env.NODE_ENV !== \"production\") {\n                printCleanupDetails(deletedCacheRequests);\n            }\n            return {\n                deletedCacheRequests\n            };\n        });\n    }\n    handleFetch(event) {\n        const { request } = event;\n        const responsePromise = this.handleRequest({\n            request,\n            event\n        });\n        if (responsePromise) {\n            event.respondWith(responsePromise);\n        }\n    }\n    handleCache(event) {\n        if (event.data && event.data.type === \"CACHE_URLS\") {\n            const { payload } = event.data;\n            if (process.env.NODE_ENV !== \"production\") {\n                logger.debug(\"Caching URLs from the window\", payload.urlsToCache);\n            }\n            const requestPromises = Promise.all(payload.urlsToCache.map((entry)=>{\n                let request;\n                if (typeof entry === \"string\") {\n                    request = new Request(entry);\n                } else {\n                    request = new Request(...entry);\n                }\n                return this.handleRequest({\n                    request,\n                    event\n                });\n            }));\n            event.waitUntil(requestPromises);\n            if (event.ports?.[0]) {\n                void requestPromises.then(()=>event.ports[0].postMessage(true));\n            }\n        }\n    }\n    setDefaultHandler(handler, method = defaultMethod) {\n        this._defaultHandlerMap.set(method, normalizeHandler(handler));\n    }\n    setCatchHandler(handler) {\n        this._catchHandler = normalizeHandler(handler);\n    }\n    registerCapture(capture, handler, method) {\n        const route = parseRoute(capture, handler, method);\n        this.registerRoute(route);\n        return route;\n    }\n    registerRoute(route) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(route, \"object\", {\n                moduleName: \"serwist\",\n                className: \"Serwist\",\n                funcName: \"registerRoute\",\n                paramName: \"route\"\n            });\n            finalAssertExports.hasMethod(route, \"match\", {\n                moduleName: \"serwist\",\n                className: \"Serwist\",\n                funcName: \"registerRoute\",\n                paramName: \"route\"\n            });\n            finalAssertExports.isType(route.handler, \"object\", {\n                moduleName: \"serwist\",\n                className: \"Serwist\",\n                funcName: \"registerRoute\",\n                paramName: \"route\"\n            });\n            finalAssertExports.hasMethod(route.handler, \"handle\", {\n                moduleName: \"serwist\",\n                className: \"Serwist\",\n                funcName: \"registerRoute\",\n                paramName: \"route.handler\"\n            });\n            finalAssertExports.isType(route.method, \"string\", {\n                moduleName: \"serwist\",\n                className: \"Serwist\",\n                funcName: \"registerRoute\",\n                paramName: \"route.method\"\n            });\n        }\n        if (!this._routes.has(route.method)) {\n            this._routes.set(route.method, []);\n        }\n        this._routes.get(route.method).push(route);\n    }\n    unregisterRoute(route) {\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        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    getUrlsToPrecacheKeys() {\n        return this._urlsToCacheKeys;\n    }\n    getPrecachedUrls() {\n        return [\n            ...this._urlsToCacheKeys.keys()\n        ];\n    }\n    getPrecacheKeyForUrl(url) {\n        const urlObject = new URL(url, location.href);\n        return this._urlsToCacheKeys.get(urlObject.href);\n    }\n    getIntegrityForPrecacheKey(cacheKey) {\n        return this._cacheKeysToIntegrities.get(cacheKey);\n    }\n    async matchPrecache(request) {\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    createHandlerBoundToUrl(url) {\n        const cacheKey = this.getPrecacheKeyForUrl(url);\n        if (!cacheKey) {\n            throw new SerwistError(\"non-precached-url\", {\n                url\n            });\n        }\n        return (options)=>{\n            options.request = new Request(url);\n            options.params = {\n                cacheKey,\n                ...options.params\n            };\n            return this.precacheStrategy.handle(options);\n        };\n    }\n    handleRequest({ request, event }) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(request, Request, {\n                moduleName: \"serwist\",\n                className: \"Serwist\",\n                funcName: \"handleRequest\",\n                paramName: \"options.request\"\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        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        const debugMessages = [];\n        if (process.env.NODE_ENV !== \"production\") {\n            if (handler) {\n                debugMessages.push([\n                    \"Found a route to handle this request:\",\n                    route\n                ]);\n                if (params) {\n                    debugMessages.push([\n                        `Passing the following params to the route's handler:`,\n                        params\n                    ]);\n                }\n            }\n        }\n        const method = request.method;\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        if (!handler) {\n            if (process.env.NODE_ENV !== \"production\") {\n                logger.debug(`No route found for: ${getFriendlyURL(url)}`);\n            }\n            return;\n        }\n        if (process.env.NODE_ENV !== \"production\") {\n            logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`);\n            for (const msg of debugMessages){\n                if (Array.isArray(msg)) {\n                    logger.log(...msg);\n                } else {\n                    logger.log(msg);\n                }\n            }\n            logger.groupEnd();\n        }\n        let responsePromise;\n        try {\n            responsePromise = handler.handle({\n                url,\n                request,\n                event,\n                params\n            });\n        } catch (err) {\n            responsePromise = Promise.reject(err);\n        }\n        const catchHandler = route?.catchHandler;\n        if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) {\n            responsePromise = responsePromise.catch(async (err)=>{\n                if (catchHandler) {\n                    if (process.env.NODE_ENV !== \"production\") {\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                    try {\n                        return await catchHandler.handle({\n                            url,\n                            request,\n                            event,\n                            params\n                        });\n                    } catch (catchErr) {\n                        if (catchErr instanceof Error) {\n                            err = catchErr;\n                        }\n                    }\n                }\n                if (this._catchHandler) {\n                    if (process.env.NODE_ENV !== \"production\") {\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({\n                        url,\n                        request,\n                        event\n                    });\n                }\n                throw err;\n            });\n        }\n        return responsePromise;\n    }\n    findMatchingRoute({ url, sameOrigin, request, event }) {\n        const routes = this._routes.get(request.method) || [];\n        for (const route of routes){\n            let params;\n            const matchResult = route.match({\n                url,\n                sameOrigin,\n                request,\n                event\n            });\n            if (matchResult) {\n                if (process.env.NODE_ENV !== \"production\") {\n                    if (matchResult instanceof Promise) {\n                        logger.warn(`While routing ${getFriendlyURL(url)}, an async matchCallback function was used. Please convert the following route to use a synchronous matchCallback function:`, route);\n                    }\n                }\n                params = matchResult;\n                if (Array.isArray(params) && params.length === 0) {\n                    params = undefined;\n                } else if (matchResult.constructor === Object && Object.keys(matchResult).length === 0) {\n                    params = undefined;\n                } else if (typeof matchResult === \"boolean\") {\n                    params = undefined;\n                }\n                return {\n                    route,\n                    params\n                };\n            }\n        }\n        return {};\n    }\n}\n\nconst cacheNames = {\n    get googleAnalytics () {\n        return cacheNames$1.getGoogleAnalyticsName();\n    },\n    get precache () {\n        return cacheNames$1.getPrecacheName();\n    },\n    get prefix () {\n        return cacheNames$1.getPrefix();\n    },\n    get runtime () {\n        return cacheNames$1.getRuntimeName();\n    },\n    get suffix () {\n        return cacheNames$1.getSuffix();\n    }\n};\n\nconst BROADCAST_UPDATE_MESSAGE_TYPE = \"CACHE_UPDATED\";\nconst BROADCAST_UPDATE_MESSAGE_META = \"serwist-broadcast-update\";\nconst BROADCAST_UPDATE_DEFAULT_NOTIFY = true;\nconst BROADCAST_UPDATE_DEFAULT_HEADERS = [\n    \"content-length\",\n    \"etag\",\n    \"last-modified\"\n];\n\nconst responsesAreSame = (firstResponse, secondResponse, headersToCheck)=>{\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    const atLeastOneHeaderAvailable = headersToCheck.some((header)=>{\n        return firstResponse.headers.has(header) && secondResponse.headers.has(header);\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        return true;\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        return headerStateComparison && headerValueComparison;\n    });\n};\n\nconst isSafari = typeof navigator !== \"undefined\" && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\nconst defaultPayloadGenerator = (data)=>{\n    return {\n        cacheName: data.cacheName,\n        updatedURL: data.request.url\n    };\n};\nclass BroadcastCacheUpdate {\n    _headersToCheck;\n    _generatePayload;\n    _notifyAllClients;\n    constructor({ generatePayload, headersToCheck, notifyAllClients } = {}){\n        this._headersToCheck = headersToCheck || BROADCAST_UPDATE_DEFAULT_HEADERS;\n        this._generatePayload = generatePayload || defaultPayloadGenerator;\n        this._notifyAllClients = notifyAllClients ?? BROADCAST_UPDATE_DEFAULT_NOTIFY;\n    }\n    async notifyIfUpdated(options) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(options.cacheName, \"string\", {\n                moduleName: \"serwist\",\n                className: \"BroadcastCacheUpdate\",\n                funcName: \"notifyIfUpdated\",\n                paramName: \"cacheName\"\n            });\n            finalAssertExports.isInstance(options.newResponse, Response, {\n                moduleName: \"serwist\",\n                className: \"BroadcastCacheUpdate\",\n                funcName: \"notifyIfUpdated\",\n                paramName: \"newResponse\"\n            });\n            finalAssertExports.isInstance(options.request, Request, {\n                moduleName: \"serwist\",\n                className: \"BroadcastCacheUpdate\",\n                funcName: \"notifyIfUpdated\",\n                paramName: \"request\"\n            });\n        }\n        if (!options.oldResponse) {\n            return;\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            const messageData = {\n                type: BROADCAST_UPDATE_MESSAGE_TYPE,\n                meta: BROADCAST_UPDATE_MESSAGE_META,\n                payload: this._generatePayload(options)\n            };\n            if (options.request.mode === \"navigate\") {\n                let resultingClientId;\n                if (options.event instanceof FetchEvent) {\n                    resultingClientId = options.event.resultingClientId;\n                }\n                const resultingWin = await resultingClientExists(resultingClientId);\n                if (!resultingWin || isSafari) {\n                    await timeout(3500);\n                }\n            }\n            if (this._notifyAllClients) {\n                const windows = await self.clients.matchAll({\n                    type: \"window\"\n                });\n                for (const win of windows){\n                    win.postMessage(messageData);\n                }\n            } else {\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\nclass BroadcastUpdatePlugin {\n    _broadcastUpdate;\n    constructor(options){\n        this._broadcastUpdate = new BroadcastCacheUpdate(options);\n    }\n    cacheDidUpdate(options) {\n        void this._broadcastUpdate.notifyIfUpdated(options);\n    }\n}\n\nclass CacheableResponse {\n    _statuses;\n    _headers;\n    constructor(config = {}){\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            if (config.statuses) {\n                finalAssertExports.isArray(config.statuses, {\n                    moduleName: \"serwist\",\n                    className: \"CacheableResponse\",\n                    funcName: \"constructor\",\n                    paramName: \"config.statuses\"\n                });\n            }\n            if (config.headers) {\n                finalAssertExports.isType(config.headers, \"object\", {\n                    moduleName: \"serwist\",\n                    className: \"CacheableResponse\",\n                    funcName: \"constructor\",\n                    paramName: \"config.headers\"\n                });\n            }\n        }\n        this._statuses = config.statuses;\n        if (config.headers) {\n            this._headers = new Headers(config.headers);\n        }\n    }\n    isResponseCacheable(response) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(response, Response, {\n                moduleName: \"serwist\",\n                className: \"CacheableResponse\",\n                funcName: \"isResponseCacheable\",\n                paramName: \"response\"\n            });\n        }\n        let cacheable = true;\n        if (this._statuses) {\n            cacheable = this._statuses.includes(response.status);\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        if (process.env.NODE_ENV !== \"production\") {\n            if (!cacheable) {\n                logger.groupCollapsed(`The request for '${getFriendlyURL(response.url)}' returned a response that does not meet the criteria for being cached.`);\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                const logFriendlyHeaders = {};\n                response.headers.forEach((value, key)=>{\n                    logFriendlyHeaders[key] = value;\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                logger.groupCollapsed(\"View full response details here.\");\n                logger.log(response.headers);\n                logger.log(response);\n                logger.groupEnd();\n                logger.groupEnd();\n            }\n        }\n        return cacheable;\n    }\n}\n\nclass CacheableResponsePlugin {\n    _cacheableResponse;\n    constructor(config){\n        this._cacheableResponse = new CacheableResponse(config);\n    }\n    cacheWillUpdate = async ({ response })=>{\n        if (this._cacheableResponse.isResponseCacheable(response)) {\n            return response;\n        }\n        return null;\n    };\n}\n\nconst DB_NAME = \"serwist-expiration\";\nconst CACHE_OBJECT_STORE = \"cache-entries\";\nconst normalizeURL = (unNormalizedUrl)=>{\n    const url = new URL(unNormalizedUrl, location.href);\n    url.hash = \"\";\n    return url.href;\n};\nclass CacheTimestampsModel {\n    _cacheName;\n    _db = null;\n    constructor(cacheName){\n        this._cacheName = cacheName;\n    }\n    _getId(url) {\n        return `${this._cacheName}|${normalizeURL(url)}`;\n    }\n    _upgradeDb(db) {\n        const objStore = db.createObjectStore(CACHE_OBJECT_STORE, {\n            keyPath: \"id\"\n        });\n        objStore.createIndex(\"cacheName\", \"cacheName\", {\n            unique: false\n        });\n        objStore.createIndex(\"timestamp\", \"timestamp\", {\n            unique: false\n        });\n    }\n    _upgradeDbAndDeleteOldDbs(db) {\n        this._upgradeDb(db);\n        if (this._cacheName) {\n            void deleteDB(this._cacheName);\n        }\n    }\n    async setTimestamp(url, timestamp) {\n        url = normalizeURL(url);\n        const entry = {\n            id: this._getId(url),\n            cacheName: this._cacheName,\n            url,\n            timestamp\n        };\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    async getTimestamp(url) {\n        const db = await this.getDb();\n        const entry = await db.get(CACHE_OBJECT_STORE, this._getId(url));\n        return entry?.timestamp;\n    }\n    async expireEntries(minTimestamp, maxCount) {\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 = [];\n        let entriesNotDeletedCount = 0;\n        while(cursor){\n            const result = cursor.value;\n            if (result.cacheName === this._cacheName) {\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        return urlsDeleted;\n    }\n    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\nclass CacheExpiration {\n    _isRunning = false;\n    _rerunRequested = false;\n    _maxEntries;\n    _maxAgeSeconds;\n    _matchOptions;\n    _cacheName;\n    _timestampModel;\n    constructor(cacheName, config = {}){\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(cacheName, \"string\", {\n                moduleName: \"serwist\",\n                className: \"CacheExpiration\",\n                funcName: \"constructor\",\n                paramName: \"cacheName\"\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            if (config.maxEntries) {\n                finalAssertExports.isType(config.maxEntries, \"number\", {\n                    moduleName: \"serwist\",\n                    className: \"CacheExpiration\",\n                    funcName: \"constructor\",\n                    paramName: \"config.maxEntries\"\n                });\n            }\n            if (config.maxAgeSeconds) {\n                finalAssertExports.isType(config.maxAgeSeconds, \"number\", {\n                    moduleName: \"serwist\",\n                    className: \"CacheExpiration\",\n                    funcName: \"constructor\",\n                    paramName: \"config.maxAgeSeconds\"\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    async expireEntries() {\n        if (this._isRunning) {\n            this._rerunRequested = true;\n            return;\n        }\n        this._isRunning = true;\n        const minTimestamp = this._maxAgeSeconds ? Date.now() - this._maxAgeSeconds * 1000 : 0;\n        const urlsExpired = await this._timestampModel.expireEntries(minTimestamp, this._maxEntries);\n        const cache = await self.caches.open(this._cacheName);\n        for (const url of urlsExpired){\n            await cache.delete(url, this._matchOptions);\n        }\n        if (process.env.NODE_ENV !== \"production\") {\n            if (urlsExpired.length > 0) {\n                logger.groupCollapsed(`Expired ${urlsExpired.length} ` + `${urlsExpired.length === 1 ? \"entry\" : \"entries\"} and removed ` + `${urlsExpired.length === 1 ? \"it\" : \"them\"} from the ` + `'${this._cacheName}' cache.`);\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        this._isRunning = false;\n        if (this._rerunRequested) {\n            this._rerunRequested = false;\n            void this.expireEntries();\n        }\n    }\n    async updateTimestamp(url) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(url, \"string\", {\n                moduleName: \"serwist\",\n                className: \"CacheExpiration\",\n                funcName: \"updateTimestamp\",\n                paramName: \"url\"\n            });\n        }\n        await this._timestampModel.setTimestamp(url, Date.now());\n    }\n    async isURLExpired(url) {\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    async delete() {\n        this._rerunRequested = false;\n        await this._timestampModel.expireEntries(Number.POSITIVE_INFINITY);\n    }\n}\n\nconst registerQuotaErrorCallback = (callback)=>{\n    if (process.env.NODE_ENV !== \"production\") {\n        finalAssertExports.isType(callback, \"function\", {\n            moduleName: \"@serwist/core\",\n            funcName: \"register\",\n            paramName: \"callback\"\n        });\n    }\n    quotaErrorCallbacks.add(callback);\n    if (process.env.NODE_ENV !== \"production\") {\n        logger.log(\"Registered a callback to respond to quota errors.\", callback);\n    }\n};\n\nclass ExpirationPlugin {\n    _config;\n    _cacheExpirations;\n    constructor(config = {}){\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            if (config.maxEntries) {\n                finalAssertExports.isType(config.maxEntries, \"number\", {\n                    moduleName: \"serwist\",\n                    className: \"ExpirationPlugin\",\n                    funcName: \"constructor\",\n                    paramName: \"config.maxEntries\"\n                });\n            }\n            if (config.maxAgeSeconds) {\n                finalAssertExports.isType(config.maxAgeSeconds, \"number\", {\n                    moduleName: \"serwist\",\n                    className: \"ExpirationPlugin\",\n                    funcName: \"constructor\",\n                    paramName: \"config.maxAgeSeconds\"\n                });\n            }\n            if (config.maxAgeFrom) {\n                finalAssertExports.isType(config.maxAgeFrom, \"string\", {\n                    moduleName: \"serwist\",\n                    className: \"ExpirationPlugin\",\n                    funcName: \"constructor\",\n                    paramName: \"config.maxAgeFrom\"\n                });\n            }\n        }\n        this._config = config;\n        this._cacheExpirations = new Map();\n        if (!this._config.maxAgeFrom) {\n            this._config.maxAgeFrom = \"last-fetched\";\n        }\n        if (this._config.purgeOnQuotaError) {\n            registerQuotaErrorCallback(()=>this.deleteCacheAndMetadata());\n        }\n    }\n    _getCacheExpiration(cacheName) {\n        if (cacheName === cacheNames$1.getRuntimeName()) {\n            throw new SerwistError(\"expire-custom-caches-only\");\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    cachedResponseWillBeUsed({ event, cacheName, request, cachedResponse }) {\n        if (!cachedResponse) {\n            return null;\n        }\n        const isFresh = this._isResponseDateFresh(cachedResponse);\n        const cacheExpiration = this._getCacheExpiration(cacheName);\n        const isMaxAgeFromLastUsed = this._config.maxAgeFrom === \"last-used\";\n        const done = (async ()=>{\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        return isFresh ? cachedResponse : null;\n    }\n    _isResponseDateFresh(cachedResponse) {\n        const isMaxAgeFromLastUsed = this._config.maxAgeFrom === \"last-used\";\n        if (isMaxAgeFromLastUsed) {\n            return true;\n        }\n        const now = Date.now();\n        if (!this._config.maxAgeSeconds) {\n            return true;\n        }\n        const dateHeaderTimestamp = this._getDateHeaderTimestamp(cachedResponse);\n        if (dateHeaderTimestamp === null) {\n            return true;\n        }\n        return dateHeaderTimestamp >= now - this._config.maxAgeSeconds * 1000;\n    }\n    _getDateHeaderTimestamp(cachedResponse) {\n        if (!cachedResponse.headers.has(\"date\")) {\n            return null;\n        }\n        const dateHeader = cachedResponse.headers.get(\"date\");\n        const parsedDate = new Date(dateHeader);\n        const headerTime = parsedDate.getTime();\n        if (Number.isNaN(headerTime)) {\n            return null;\n        }\n        return headerTime;\n    }\n    async cacheDidUpdate({ cacheName, request }) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isType(cacheName, \"string\", {\n                moduleName: \"serwist\",\n                className: \"Plugin\",\n                funcName: \"cacheDidUpdate\",\n                paramName: \"cacheName\"\n            });\n            finalAssertExports.isInstance(request, Request, {\n                moduleName: \"serwist\",\n                className: \"Plugin\",\n                funcName: \"cacheDidUpdate\",\n                paramName: \"request\"\n            });\n        }\n        const cacheExpiration = this._getCacheExpiration(cacheName);\n        await cacheExpiration.updateTimestamp(request.url);\n        await cacheExpiration.expireEntries();\n    }\n    async deleteCacheAndMetadata() {\n        for (const [cacheName, cacheExpiration] of this._cacheExpirations){\n            await self.caches.delete(cacheName);\n            await cacheExpiration.delete();\n        }\n        this._cacheExpirations = new Map();\n    }\n}\n\nconst calculateEffectiveBoundaries = (blob, start, end)=>{\n    if (process.env.NODE_ENV !== \"production\") {\n        finalAssertExports.isInstance(blob, Blob, {\n            moduleName: \"@serwist/range-requests\",\n            funcName: \"calculateEffectiveBoundaries\",\n            paramName: \"blob\"\n        });\n    }\n    const blobSize = blob.size;\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    let effectiveStart;\n    let effectiveEnd;\n    if (start !== undefined && end !== undefined) {\n        effectiveStart = start;\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    return {\n        start: effectiveStart,\n        end: effectiveEnd\n    };\n};\n\nconst parseRangeHeader = (rangeHeader)=>{\n    if (process.env.NODE_ENV !== \"production\") {\n        finalAssertExports.isType(rangeHeader, \"string\", {\n            moduleName: \"@serwist/range-requests\",\n            funcName: \"parseRangeHeader\",\n            paramName: \"rangeHeader\"\n        });\n    }\n    const normalizedRangeHeader = rangeHeader.trim().toLowerCase();\n    if (!normalizedRangeHeader.startsWith(\"bytes=\")) {\n        throw new SerwistError(\"unit-must-be-bytes\", {\n            normalizedRangeHeader\n        });\n    }\n    if (normalizedRangeHeader.includes(\",\")) {\n        throw new SerwistError(\"single-range-only\", {\n            normalizedRangeHeader\n        });\n    }\n    const rangeParts = /(\\d*)-(\\d*)/.exec(normalizedRangeHeader);\n    if (!rangeParts || !(rangeParts[1] || rangeParts[2])) {\n        throw new SerwistError(\"invalid-range-values\", {\n            normalizedRangeHeader\n        });\n    }\n    return {\n        start: rangeParts[1] === \"\" ? undefined : Number(rangeParts[1]),\n        end: rangeParts[2] === \"\" ? undefined : Number(rangeParts[2])\n    };\n};\n\nconst createPartialResponse = async (request, originalResponse)=>{\n    try {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(request, Request, {\n                moduleName: \"@serwist/range-requests\",\n                funcName: \"createPartialResponse\",\n                paramName: \"request\"\n            });\n            finalAssertExports.isInstance(originalResponse, Response, {\n                moduleName: \"@serwist/range-requests\",\n                funcName: \"createPartialResponse\",\n                paramName: \"originalResponse\"\n            });\n        }\n        if (originalResponse.status === 206) {\n            return originalResponse;\n        }\n        const rangeHeader = request.headers.get(\"range\");\n        if (!rangeHeader) {\n            throw new SerwistError(\"no-range-header\");\n        }\n        const boundaries = parseRangeHeader(rangeHeader);\n        const originalBlob = await originalResponse.blob();\n        const effectiveBoundaries = calculateEffectiveBoundaries(originalBlob, boundaries.start, boundaries.end);\n        const slicedBlob = originalBlob.slice(effectiveBoundaries.start, effectiveBoundaries.end);\n        const slicedBlobSize = slicedBlob.size;\n        const slicedResponse = new Response(slicedBlob, {\n            status: 206,\n            statusText: \"Partial Content\",\n            headers: originalResponse.headers\n        });\n        slicedResponse.headers.set(\"Content-Length\", String(slicedBlobSize));\n        slicedResponse.headers.set(\"Content-Range\", `bytes ${effectiveBoundaries.start}-${effectiveBoundaries.end - 1}/` + `${originalBlob.size}`);\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        return new Response(\"\", {\n            status: 416,\n            statusText: \"Range Not Satisfiable\"\n        });\n    }\n};\n\nclass RangeRequestsPlugin {\n    cachedResponseWillBeUsed = async ({ request, cachedResponse })=>{\n        if (cachedResponse && request.headers.has(\"range\")) {\n            return await createPartialResponse(request, cachedResponse);\n        }\n        return cachedResponse;\n    };\n}\n\nclass CacheFirst extends Strategy {\n    async _handle(request, handler) {\n        const logs = [];\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(request, Request, {\n                moduleName: \"serwist\",\n                className: this.constructor.name,\n                funcName: \"makeRequest\",\n                paramName: \"request\"\n            });\n        }\n        let response = await handler.cacheMatch(request);\n        let error;\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            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        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        if (!response) {\n            throw new SerwistError(\"no-response\", {\n                url: request.url,\n                error\n            });\n        }\n        return response;\n    }\n}\n\nclass CacheOnly extends Strategy {\n    async _handle(request, handler) {\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(request, Request, {\n                moduleName: \"serwist\",\n                className: this.constructor.name,\n                funcName: \"makeRequest\",\n                paramName: \"request\"\n            });\n        }\n        const response = await handler.cacheMatch(request);\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        if (!response) {\n            throw new SerwistError(\"no-response\", {\n                url: request.url\n            });\n        }\n        return response;\n    }\n}\n\nclass StaleWhileRevalidate extends Strategy {\n    constructor(options = {}){\n        super(options);\n        if (!this.plugins.some((p)=>\"cacheWillUpdate\" in p)) {\n            this.plugins.unshift(cacheOkAndOpaquePlugin);\n        }\n    }\n    async _handle(request, handler) {\n        const logs = [];\n        if (process.env.NODE_ENV !== \"production\") {\n            finalAssertExports.isInstance(request, Request, {\n                moduleName: \"serwist\",\n                className: this.constructor.name,\n                funcName: \"handle\",\n                paramName: \"request\"\n            });\n        }\n        const fetchAndCachePromise = handler.fetchAndCachePut(request).catch(()=>{});\n        void handler.waitUntil(fetchAndCachePromise);\n        let response = await handler.cacheMatch(request);\n        let error;\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                response = await fetchAndCachePromise;\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            for (const log of logs){\n                logger.log(log);\n            }\n            messages.printFinalResponse(response);\n            logger.groupEnd();\n        }\n        if (!response) {\n            throw new SerwistError(\"no-response\", {\n                url: request.url,\n                error\n            });\n        }\n        return response;\n    }\n}\n\nexport { BROADCAST_UPDATE_DEFAULT_HEADERS, BackgroundSyncPlugin, BroadcastCacheUpdate, BroadcastUpdatePlugin, CacheExpiration, CacheFirst, CacheOnly, CacheableResponse, CacheableResponsePlugin, ExpirationPlugin, NavigationRoute, NetworkFirst, NetworkOnly, PrecacheFallbackPlugin, PrecacheRoute, PrecacheStrategy, RangeRequestsPlugin, Route, Serwist, StaleWhileRevalidate, Strategy, cacheNames, createPartialResponse, disableDevLogs, enableNavigationPreload, initializeGoogleAnalytics, registerQuotaErrorCallback, responsesAreSame, setCacheNameDetails };\n", "export const isViewerRoute = (pathname: string) =>\n  /^\\/0x[a-fA-F0-9]/.test(pathname);\n\nexport const isCompactViewerRoute = (pathname: string) =>\n  /^\\/d\\/(?:o\\/)?[a-fA-F0-9]+$/.test(pathname);\n\nconst isDdocCollaborationRoute = (pathname: string) =>\n  /^\\/(?:u\\/\\d+\\/w\\/[^/]+\\/)?document\\/[^/]+\\/share\\/?$/.test(pathname);\n\nexport const shouldSkipPageCache = (pathname: string) =>\n  isDdocCollaborationRoute(pathname) ||\n  isViewerRoute(pathname) ||\n  isCompactViewerRoute(pathname);\n\nexport const DEPLOYMENT_ID_HEADER = 'x-deployment-id';\n\n/**\n * Cache key for an RSC / prefetch payload. The `_rsc` token is unique per\n * request and dropped; the requesting page's deployment id (sent by Next on\n * every RSC fetch when `deploymentId` is configured) is added, so a page can\n * only ever match payloads cached by its own build. Payloads reference that\n * build's chunk graph, and Flight preloads those chunks while decoding, before\n * Next's build-id guard can reject a foreign payload.\n */\nexport const buildRscCacheKey = (\n  requestUrl: string,\n  deploymentId: string | null\n): string => {\n  const url = new URL(requestUrl);\n  url.searchParams.delete('_rsc');\n  if (deploymentId) url.searchParams.set('dpl', deploymentId);\n  return url.search\n    ? url.origin + url.pathname + url.search\n    : url.origin + url.pathname;\n};\n\nconst NEXT_STATIC_SCRIPT_PATTERN = /\\/_next\\/static\\/[^\"'\\\\<>\\s?]+\\.js/g;\n\n/**\n * Every /_next/static script a cached shell references. Serving HTML whose\n * scripts are no longer cached is unsafe (blank page beats offline.html), so\n * the offline handler verifies each of these against CacheStorage before\n * serving the shell. Replaces the webpack-runtime build fingerprint, which\n * has no Turbopack equivalent (no webpack-*.js chunk exists to compare).\n */\nexport const getNextStaticScriptPaths = (html: string): string[] => [\n  ...new Set(html.match(NEXT_STATIC_SCRIPT_PATTERN) ?? []),\n];\n\n/**\n * A Next router prefetch is not proof that the user opened a file or that its\n * local content exists. Only an actual RSC navigation should seed the matching\n * offline HTML entry.\n */\nexport const shouldShadowCacheRouteHtml = (\n  rscHeader: string | null,\n  routerPrefetchHeader: string | null\n): boolean => rscHeader === '1' && routerPrefetchHeader !== '1';\n", "// Workspace file kinds. A plain `as const` object (not a `const enum`):\n// const enums are inlined by tsc but not preserved by SWC/isolatedModules\n// transpilation, so they can break at runtime depending on the build path.\nexport const FILE_KIND = {\n  DDOC: 'ddoc',\n  DSHEET: 'dsheet',\n} as const;\n\nexport type FileKind = (typeof FILE_KIND)[keyof typeof FILE_KIND];\n", "import type { WorkspaceFileRef } from '@/types';\nimport { FILE_KIND } from '@/constants/file-kind';\n\nexport type WorkspaceFilePageRouteMatch =\n  | {\n      kind: 'bare';\n      file: WorkspaceFileRef;\n    }\n  | {\n      kind: 'workspace';\n      file: WorkspaceFileRef;\n      identityIndex: number;\n      workspaceUrlKey: string;\n    };\n\nexport type DocumentPageRouteMatch =\n  | {\n      kind: 'bare';\n      ddocId: string;\n    }\n  | {\n      kind: 'workspace';\n      ddocId: string;\n      identityIndex: number;\n      workspaceUrlKey: string;\n    };\n\nexport type HomePageRouteMatch =\n  | { kind: 'bare' }\n  | {\n      kind: 'workspace';\n      identityIndex: number;\n      workspaceUrlKey: string;\n    };\n\nconst BARE_WORKSPACE_FILE_PAGE = /^\\/(document|sheet)\\/([^/]+)\\/?$/;\nconst WORKSPACE_FILE_PAGE =\n  /^\\/u\\/(\\d+)\\/w\\/([^/]+)\\/(document|sheet)\\/([^/]+)\\/?$/;\nconst BARE_HOME_PAGE = /^\\/home\\/?$/;\nconst WORKSPACE_HOME_PAGE = /^\\/u\\/(\\d+)\\/w\\/([^/]+)\\/home\\/?$/;\nconst isReservedWorkspaceFileId = (routeSegment: string, id: string) =>\n  id === 'create' || (routeSegment === 'document' && id === 'share');\n\nconst toWorkspaceFileRef = (\n  routeSegment: string,\n  id: string\n): WorkspaceFileRef => ({\n  kind: routeSegment === 'sheet' ? FILE_KIND.DSHEET : FILE_KIND.DDOC,\n  id,\n});\n\n/**\n * Matches only bare or workspace-slotted ddoc/dSheet capability leaves. Create\n * routes, the dDoc collaboration leaf, and nested routes do not qualify for\n * offline HTML caching or local-first capability handling.\n */\nexport function matchWorkspaceFilePagePath(\n  pathname: string\n): WorkspaceFilePageRouteMatch | null {\n  const bare = BARE_WORKSPACE_FILE_PAGE.exec(pathname);\n  if (bare) {\n    const id = bare[2];\n    if (isReservedWorkspaceFileId(bare[1], id)) return null;\n    return {\n      kind: 'bare',\n      file: toWorkspaceFileRef(bare[1], id),\n    };\n  }\n\n  const workspace = WORKSPACE_FILE_PAGE.exec(pathname);\n  if (!workspace) return null;\n\n  const id = workspace[4];\n  if (isReservedWorkspaceFileId(workspace[3], id)) return null;\n\n  return {\n    kind: 'workspace',\n    identityIndex: Number(workspace[1]),\n    workspaceUrlKey: workspace[2],\n    file: toWorkspaceFileRef(workspace[3], id),\n  };\n}\n\n/**\n * Compatibility projection for ddoc-only callers. New route code should use\n * matchWorkspaceFilePagePath so ddocs and dSheets cannot drift.\n */\nexport function matchDocumentPagePath(\n  pathname: string\n): DocumentPageRouteMatch | null {\n  const match = matchWorkspaceFilePagePath(pathname);\n  if (!match || match.file.kind !== FILE_KIND.DDOC) return null;\n\n  return match.kind === 'bare'\n    ? { kind: 'bare', ddocId: match.file.id }\n    : {\n        kind: 'workspace',\n        identityIndex: match.identityIndex,\n        workspaceUrlKey: match.workspaceUrlKey,\n        ddocId: match.file.id,\n      };\n}\n\n/** Matches only the home page itself, never a nested workspace route. */\nexport function matchHomePagePath(pathname: string): HomePageRouteMatch | null {\n  if (BARE_HOME_PAGE.test(pathname)) return { kind: 'bare' };\n\n  const workspace = WORKSPACE_HOME_PAGE.exec(pathname);\n  if (!workspace) return null;\n\n  return {\n    kind: 'workspace',\n    identityIndex: Number(workspace[1]),\n    workspaceUrlKey: workspace[2],\n  };\n}\n", "import { defaultCache } from '@serwist/turbopack/worker';\n\nimport {\n  ExpirationPlugin,\n  ExpirationPluginOptions,\n  PrecacheEntry,\n  SerwistGlobalConfig,\n  StrategyHandler,\n  CacheWillUpdateCallbackParam,\n  StaleWhileRevalidate,\n  NetworkFirst,\n  RuntimeCaching,\n} from 'serwist';\nimport { Serwist, Strategy, CacheableResponse, disableDevLogs } from 'serwist';\nimport {\n  DEPLOYMENT_ID_HEADER,\n  buildRscCacheKey,\n  getNextStaticScriptPaths,\n  shouldShadowCacheRouteHtml,\n  shouldSkipPageCache,\n} from '@/utils/service-worker-route-utils';\nimport {\n  matchHomePagePath,\n  matchWorkspaceFilePagePath,\n} from '@/utils/offline-routes';\n\ndeclare global {\n  interface WorkerGlobalScope extends SerwistGlobalConfig {\n    __SW_MANIFEST: (PrecacheEntry | string)[] | undefined;\n  }\n}\n\ndeclare const self: ServiceWorkerGlobalScope;\n\nconst cacheable = new CacheableResponse({\n  statuses: [0, 200],\n});\n\ndisableDevLogs();\n\n// =============================================================================\n// DIAGNOSTIC LOGGING - Set to true to debug offline issues\n// =============================================================================\nconst DEBUG_OFFLINE = false;\n\nfunction debugLog(category: string, message: string, data?: any) {\n  if (!DEBUG_OFFLINE) return;\n  const timestamp = new Date().toISOString().split('T')[1].slice(0, -1);\n  if (data) {\n    console.log(`[SW:${timestamp}] [${category}] ${message}`, data);\n  } else {\n    console.log(`[SW:${timestamp}] [${category}] ${message}`);\n  }\n}\n\n/**\n * Cache key for RSC / prefetch payloads: drops the per-request `_rsc` token and\n * scopes the entry to the requesting page's deployment id (see\n * buildRscCacheKey). Without the scope, a slow network (>3s) after a deploy\n * would hand a new-build page an old-build payload from this cache.\n */\nclass NormalizeCacheKeyPlugin {\n  cacheKeyWillBeUsed({\n    request,\n    mode,\n  }: {\n    request: Request;\n    mode?: string;\n  }): Promise<string> {\n    const url = new URL(request.url);\n    const hadRsc = url.searchParams.has('_rsc');\n    const normalizedUrl = buildRscCacheKey(\n      request.url,\n      request.headers.get(DEPLOYMENT_ID_HEADER)\n    );\n\n    // Log when normalizing exact workspace-file editor leaves.\n    if (hadRsc && matchWorkspaceFilePagePath(url.pathname)) {\n      debugLog(\n        'CACHE-KEY',\n        `Normalizing (${mode || 'unknown'}): ${request.url} \u2192 ${normalizedUrl}`\n      );\n    }\n\n    return Promise.resolve(normalizedUrl);\n  }\n}\n\nclass IPFSExpirationPlugin extends ExpirationPlugin {\n  cacheName = 'ipfs-cache';\n  constructor(config: ExpirationPluginOptions) {\n    super(config);\n  }\n\n  // Runs before the response is added to the cache\n  async cacheWillUpdate({ response, request }: CacheWillUpdateCallbackParam) {\n    try {\n      if (!cacheable.isResponseCacheable(response)) {\n        return null;\n      }\n      const cache = await caches.open(this.cacheName);\n      const cacheItems = await cache.keys();\n\n      const url = new URL(request.url);\n      const currentHash = url.pathname.split('/').pop();\n\n      for (const item of cacheItems) {\n        const itemUrl = new URL(item.url);\n        const existingHash = itemUrl.pathname.split('/').pop();\n        // Check if the current hash is already cached\n        if (existingHash === currentHash) {\n          // Don't add it to the cache\n          return null;\n        }\n      }\n\n      return response;\n    } catch (error) {\n      console.error('[SW] Error in cacheWillUpdate:', error);\n      // Return response anyway to allow caching to continue\n      return response;\n    }\n  }\n}\n\nclass IPFSStrategyHandler extends Strategy {\n  cacheName = 'ipfs-cache';\n  plugins = [\n    new IPFSExpirationPlugin({\n      // Increased from 20 to support more heavy documents with multiple assets\n      // This reduces repeated fetch/cache cycles that can cause memory buildup\n      maxEntries: 100,\n\n      // Extended from 24 hours to 7 days for better persistence\n      // Heavy documents with many assets benefit from longer cache retention\n      maxAgeSeconds: 60 * 60 * 24 * 7, // 7 days\n\n      // Keep entries based on last-used time (LRU strategy)\n      maxAgeFrom: 'last-used',\n\n      // Automatically purge cache when storage quota is exceeded\n      // This prevents browser crashes from quota errors\n      purgeOnQuotaError: true,\n    }),\n  ];\n\n  async _handle(request: Request, handler: StrategyHandler) {\n    const cacheMatch = await handler.cacheMatch(request);\n\n    if (cacheMatch) return cacheMatch;\n\n    const fetchAndPutCache = await handler.fetchAndCachePut(request);\n    return fetchAndPutCache;\n  }\n}\n\n// Offline fallback page URL\nconst OFFLINE_PAGE_URL = '/offline.html';\n\n// Critical pages that must work offline - these are precached\nconst OFFLINE_CRITICAL_PAGES = ['/'];\n\n// The home route is almost always reached via a client-side redirect\n// (/ \u2192 /u/N/w/personal/home, /home \u2192 /u/N/w/personal/home), so its HTML is\n// never fetched as a navigation and never lands in any cache \u2014 an offline\n// reload of home then falls through to offline.html. Give it the same\n// navigation + shadow-cache treatment as document pages so the HTML is cached\n// when its RSC succeeds online and served on an offline reload.\nconst cacheStrategies: RuntimeCaching[] = [\n  // Critical pages - HTML navigation (must work offline)\n  {\n    matcher: ({ request, url: { pathname }, sameOrigin }) => {\n      const isNavigation =\n        request.mode === 'navigate' ||\n        (request.method === 'GET' &&\n          request.headers.get('accept')?.includes('text/html'));\n      return (\n        isNavigation &&\n        sameOrigin &&\n        !request.headers.get('RSC') &&\n        OFFLINE_CRITICAL_PAGES.includes(pathname)\n      );\n    },\n    handler: new NetworkFirst({\n      cacheName: 'critical-pages',\n      networkTimeoutSeconds: 3,\n      plugins: [\n        new ExpirationPlugin({\n          maxEntries: 10,\n          maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n          maxAgeFrom: 'last-used',\n        }),\n      ],\n    }),\n  },\n  // Critical pages - RSC requests (must work offline)\n  {\n    matcher: ({ request, url: { pathname }, sameOrigin }) =>\n      request.headers.get('RSC') === '1' &&\n      sameOrigin &&\n      OFFLINE_CRITICAL_PAGES.includes(pathname),\n    handler: new NetworkFirst({\n      cacheName: 'critical-pages-rsc',\n      networkTimeoutSeconds: 3,\n      plugins: [\n        new ExpirationPlugin({\n          maxEntries: 20,\n          maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n          maxAgeFrom: 'last-used',\n        }),\n      ],\n    }),\n  },\n  {\n    matcher: ({ request, url: { pathname }, sameOrigin }) =>\n      request.headers.get('RSC') === '1' &&\n      request.headers.get('Next-Router-Prefetch') === '1' &&\n      sameOrigin &&\n      !pathname.startsWith('/api/') &&\n      !shouldSkipPageCache(pathname),\n    handler: new NetworkFirst({\n      cacheName: 'pages-rsc-prefetch',\n      networkTimeoutSeconds: 3,\n      plugins: [\n        new NormalizeCacheKeyPlugin(),\n        new ExpirationPlugin({\n          maxEntries: 200,\n          maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n          maxAgeFrom: 'last-used',\n        }),\n      ],\n    }),\n  },\n  {\n    matcher: ({ request, url: { pathname }, sameOrigin }) =>\n      request.headers.get('RSC') === '1' &&\n      sameOrigin &&\n      !pathname.startsWith('/api/') &&\n      !shouldSkipPageCache(pathname),\n    handler: new NetworkFirst({\n      cacheName: 'pages-rsc',\n      networkTimeoutSeconds: 3,\n      plugins: [\n        new NormalizeCacheKeyPlugin(),\n        new ExpirationPlugin({\n          maxEntries: 200,\n          maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n          maxAgeFrom: 'last-used',\n        }),\n      ],\n    }),\n  },\n  {\n    matcher: ({ request, url: { pathname }, sameOrigin }) => {\n      const isNavigation =\n        request.mode === 'navigate' ||\n        (request.method === 'GET' &&\n          request.headers.get('accept')?.includes('text/html'));\n      return (\n        isNavigation &&\n        sameOrigin &&\n        !pathname.startsWith('/api/') &&\n        !request.headers.get('RSC') &&\n        !shouldSkipPageCache(pathname) &&\n        !OFFLINE_CRITICAL_PAGES.includes(pathname) // Critical pages handled by dedicated strategy\n      );\n    },\n    handler: new NetworkFirst({\n      cacheName: 'pages',\n      networkTimeoutSeconds: 3,\n      plugins: [\n        new NormalizeCacheKeyPlugin(),\n        new ExpirationPlugin({\n          maxEntries: 200,\n          maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n          maxAgeFrom: 'last-used',\n        }),\n      ],\n    }),\n  },\n  {\n    matcher: ({ request, sameOrigin }) =>\n      sameOrigin && request.url.includes('/ipfs/'),\n    handler: new IPFSStrategyHandler(),\n  },\n];\n\n// Custom runtime caching for offline-first - replaces defaultCache NetworkOnly strategies\nconst offlineFirstRuntimeCaching: RuntimeCaching[] = [\n  // Next.js static chunks - cache first for offline support\n  {\n    matcher: ({ url, sameOrigin }) =>\n      sameOrigin && url.pathname.startsWith('/_next/static/'),\n    handler: new StaleWhileRevalidate({\n      cacheName: 'next-static',\n      plugins: [\n        new ExpirationPlugin({\n          maxEntries: 200,\n          maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n          maxAgeFrom: 'last-used',\n        }),\n      ],\n    }),\n  },\n  // Static assets (images, fonts, etc.)\n  {\n    matcher: ({ url, sameOrigin }) =>\n      sameOrigin &&\n      (url.pathname.startsWith('/assets/') ||\n        url.pathname.startsWith('/images/') ||\n        url.pathname.endsWith('.svg') ||\n        url.pathname.endsWith('.png') ||\n        url.pathname.endsWith('.ico') ||\n        url.pathname.endsWith('.webmanifest')),\n    handler: new StaleWhileRevalidate({\n      cacheName: 'static-assets',\n      plugins: [\n        new ExpirationPlugin({\n          maxEntries: 100,\n          maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n          maxAgeFrom: 'last-used',\n        }),\n      ],\n    }),\n  },\n  // JS scripts (like analytics)\n  {\n    matcher: ({ url, sameOrigin }) =>\n      sameOrigin && url.pathname.startsWith('/js/'),\n    handler: new NetworkFirst({\n      cacheName: 'js-scripts',\n      networkTimeoutSeconds: 3,\n      plugins: [\n        new ExpirationPlugin({\n          maxEntries: 20,\n          maxAgeSeconds: 24 * 60 * 60, // 24 hours\n        }),\n      ],\n    }),\n  },\n];\n\nconst serwist = new Serwist({\n  precacheEntries: self.__SW_MANIFEST,\n  skipWaiting: true, // Enable immediate activation so users get SW updates without closing all tabs\n  clientsClaim: false, // Disabled: clientsClaim hijacks the page mid-load on first visit, causing CSS chunks to go through the SW before caches are populated \u2014 resulting in broken styles. SW updates still propagate via skipWaiting; the browser auto-transfers control from old to new SW.\n  navigationPreload: false, // Disabled for better offline-first control\n  // Fallback to offline page only when no cache exists\n  fallbacks: {\n    entries: [\n      {\n        url: OFFLINE_PAGE_URL,\n        matcher: ({ request }) => {\n          const isNav = request.mode === 'navigate';\n          if (isNav) {\n            const reqUrl = new URL(request.url);\n            debugLog(\n              'FALLBACK',\n              `Offline fallback triggered for: ${reqUrl.pathname}`,\n              {\n                mode: request.mode,\n                isRSC: request.headers.get('RSC'),\n              }\n            );\n          }\n          return isNav;\n        },\n      },\n    ],\n  },\n  runtimeCaching: [\n    ...cacheStrategies,\n    ...offlineFirstRuntimeCaching,\n    // Filter out NetworkOnly strategies from defaultCache - they break offline\n    ...defaultCache\n      .filter((strategy) => {\n        // Skip strategies that would use NetworkOnly (development mode)\n        const handlerName = strategy.handler?.constructor?.name;\n        return handlerName !== 'NetworkOnly';\n      })\n      .map((strategy) => {\n        if (typeof strategy.matcher === 'function') {\n          const originalMatcher = strategy.matcher;\n          return {\n            ...strategy,\n            matcher: (options: any) => {\n              const { request, url, sameOrigin } = options;\n              const isNavigation =\n                request.mode === 'navigate' ||\n                (request.method === 'GET' &&\n                  request.headers.get('accept')?.includes('text/html'));\n              if (\n                isNavigation &&\n                sameOrigin &&\n                !url.pathname.startsWith('/api/')\n              ) {\n                return false;\n              }\n              return originalMatcher(options);\n            },\n          };\n        }\n        return strategy;\n      }),\n  ],\n\n  precacheOptions: {\n    fallbackToNetwork: true, // Allow network fallback if precache fails\n    cleanupOutdatedCaches: true,\n  },\n});\n\n// Add install and activate event listeners\nself.addEventListener('install', (event) => {\n  console.log('[SW] Install event triggered');\n\n  // Pre-cache critical pages for offline-first experience\n  // These need to be in the same cache as our runtime strategy uses\n  const preCacheCriticalPages = async () => {\n    const htmlCache = await caches.open('critical-pages');\n    const rscCache = await caches.open('critical-pages-rsc');\n\n    // Cache HTML and RSC for critical pages\n    for (const pageUrl of OFFLINE_CRITICAL_PAGES) {\n      // Cache HTML version (for direct navigation/refresh)\n      try {\n        const htmlResponse = await fetch(pageUrl, {\n          credentials: 'same-origin',\n        });\n        if (htmlResponse.ok) {\n          await htmlCache.put(pageUrl, htmlResponse);\n          console.log(`[SW] Pre-cached HTML: ${pageUrl}`);\n        }\n      } catch (error) {\n        console.warn(`[SW] Failed to pre-cache HTML ${pageUrl}:`, error);\n      }\n\n      // Cache RSC version (for client-side navigation)\n      try {\n        const rscResponse = await fetch(pageUrl, {\n          credentials: 'same-origin',\n          headers: {\n            RSC: '1',\n            'Next-Router-State-Tree': encodeURIComponent(JSON.stringify([])),\n          },\n        });\n        if (rscResponse.ok) {\n          // Create a request with RSC header for cache key matching\n          const rscRequest = new Request(pageUrl, {\n            headers: { RSC: '1' },\n          });\n          await rscCache.put(rscRequest, rscResponse);\n          console.log(`[SW] Pre-cached RSC: ${pageUrl}`);\n        }\n      } catch (error) {\n        console.warn(`[SW] Failed to pre-cache RSC ${pageUrl}:`, error);\n      }\n    }\n\n    // Note: offline.html is precached via additionalPrecacheEntries in next.config.mjs\n  };\n\n  event.waitUntil(\n    Promise.all([preCacheCriticalPages(), serwist.handleInstall(event)])\n  );\n});\n\n// A new worker activates on every deploy (its precache manifest changes), so\n// activation is the moment to drop page and RSC entries cached by earlier\n// builds. Chunk caches are content-addressed and stay. The critical-page\n// caches are rewritten during install and are not purged here.\nconst PREVIOUS_BUILD_PAGE_CACHES = ['pages', 'pages-rsc', 'pages-rsc-prefetch'];\n\nself.addEventListener('activate', (event) => {\n  console.log('[SW] Activate event triggered');\n  event.waitUntil(\n    Promise.all(\n      PREVIOUS_BUILD_PAGE_CACHES.map((name) => caches.delete(name))\n    ).catch((error) => {\n      console.error('[SW] Failed to purge previous-build page caches:', error);\n    })\n  );\n  try {\n    serwist.handleActivate(event);\n  } catch (error) {\n    console.error('[SW] Error during activate:', error);\n  }\n});\n\n// Global error handler for service worker\nself.addEventListener('error', (event) => {\n  console.error('[SW] Global error:', event.error);\n});\n\n// Unhandled rejection handler - CRITICAL: Prevent SW termination\nself.addEventListener('unhandledrejection', (event) => {\n  const reason = event.reason as\n    | { name?: string; message?: string }\n    | undefined;\n  // Workbox's ExpirationPlugin sometimes writes timestamps to its IDB after the\n  // connection has been closed (during SW activate/idle-shutdown). The cache\n  // write itself succeeded \u2014 only the LRU bookkeeping was dropped \u2014 so swallow\n  // it silently instead of polluting the console.\n  const isClosingIdb =\n    reason?.name === 'InvalidStateError' &&\n    typeof reason.message === 'string' &&\n    /database connection is closing/i.test(reason.message);\n\n  if (!isClosingIdb) {\n    console.error('[SW] Unhandled promise rejection:', event.reason);\n  }\n  // Prevent the service worker from being terminated due to unhandled rejections\n  // This is critical for idle tabs where async operations may fail\n  event.preventDefault();\n});\n\n/**\n * Handles offline page requests (workspace files and home) by checking the pages\n * cache for the EXACT URL's HTML (populated via shadow caching). Returns it if\n * present, otherwise null, which triggers the offline.html fallback.\n *\n * Note: We intentionally match on the exact origin+pathname and do NOT serve a\n * different page's HTML as a \"shell\" \u2014 Next.js embeds route params in the HTML,\n * so serving another URL's HTML would make useParams() return wrong values\n * (e.g. the wrong /u/N identity or document id).\n */\nasync function handleWorkspaceFilePageOffline(\n  request: Request,\n  url: URL\n): Promise<Response | null> {\n  // Only handle navigation requests (not RSC)\n  if (request.mode !== 'navigate') return null;\n\n  debugLog('OFFLINE-HANDLER', `Checking offline fallback for: ${url.pathname}`);\n\n  // Try the pages cache for the exact workspace file URL\n  const pagesCache = await caches.open('pages');\n  const normalizedUrl = url.origin + url.pathname; // Strip query params\n  const cachedResponse = await pagesCache.match(normalizedUrl);\n\n  if (cachedResponse) {\n    const html = await cachedResponse\n      .clone()\n      .text()\n      .catch(() => '');\n    const scriptPaths = getNextStaticScriptPaths(html);\n\n    // The shell is only servable offline if every script it references can\n    // itself be served from cache (precache or the next-static runtime\n    // cache \u2014 caches.match spans both). A shell that would request a\n    // non-cached chunk renders a blank page, which is worse than\n    // offline.html. An empty script list means unparseable HTML \u2014 stale.\n    const scriptMatches = await Promise.all(\n      scriptPaths.map((path) => caches.match(path))\n    );\n    if (scriptPaths.length > 0 && scriptMatches.every(Boolean)) {\n      debugLog('OFFLINE-HANDLER', `Found in pages cache: ${url.pathname}`);\n      return cachedResponse;\n    }\n\n    // Remove the stale shell and use offline.html instead of leaving the\n    // user on a blank page.\n    await pagesCache.delete(normalizedUrl);\n    debugLog(\n      'OFFLINE-HANDLER',\n      `Discarded stale cached page: ${url.pathname}`,\n      scriptPaths.filter((_, i) => !scriptMatches[i])\n    );\n    return null;\n  }\n\n  // File not in cache - return null to trigger offline.html fallback\n  debugLog('OFFLINE-HANDLER', `Workspace file not cached: ${url.pathname}`);\n  return null;\n}\n\n// Let Serwist handle all fetch events - our cacheStrategies define the behavior\nself.addEventListener('fetch', (event: FetchEvent) => {\n  const url = new URL(event.request.url);\n  const request = event.request;\n\n  // Turbopack passes worker bootstrap config in the URL hash (#params=...),\n  // which never reaches the network layer. Any SW-generated response rebuilds\n  // the worker's location from the response URL, dropping the hash \u2014 the\n  // worker then dies with \"Missing worker bootstrap config\"\n  // (FILEVERSE-DDOC-710/711). Never intercept worker scripts; offline startup\n  // is covered by the browser HTTP cache (immutable /_next/static assets).\n  if (\n    request.destination === 'worker' ||\n    request.destination === 'sharedworker'\n  ) {\n    return;\n  }\n\n  // Skip caching for proxy URLs - let them go directly to network\n  if (url.href.includes('ipfs-proxy')) return;\n\n  // Only handle same-origin requests and IPFS requests\n  // Let external resources bypass the SW entirely\n  const shouldHandle =\n    url.origin === self.location.origin || url.pathname.includes('/ipfs/');\n\n  if (!shouldHandle) return;\n\n  const workspaceFileRoute = matchWorkspaceFilePagePath(url.pathname);\n  const homeRoute = matchHomePagePath(url.pathname);\n\n  // =============================================================================\n  // WORKSPACE FILE / HOME PAGE OFFLINE HANDLING\n  // Exact editor leaves for both file kinds and home navigations use the same\n  // network-first response with an exact-path HTML fallback.\n  // =============================================================================\n  if ((workspaceFileRoute || homeRoute) && request.mode === 'navigate') {\n    debugLog('FETCH', `Page navigation: ${url.pathname}`);\n\n    event.respondWith(\n      (async () => {\n        // Try network first (normal online behavior)\n        try {\n          const response = await fetch(request);\n          if (response.ok) {\n            // Cache independently from the response path: cache quota/open/\n            // write failures must never turn a valid navigation into an\n            // offline fallback.\n            const normalizedUrl = url.origin + url.pathname;\n            const responseForCache = response.clone();\n            const cacheWrite = caches\n              .open('pages')\n              .then((cache) => cache.put(normalizedUrl, responseForCache))\n              .then(() => {\n                debugLog('FETCH', `Cached page: ${url.pathname}`);\n              })\n              .catch((error) => {\n                debugLog('FETCH', `Failed to cache page: ${String(error)}`);\n              });\n            event.waitUntil(cacheWrite);\n          }\n          return response;\n        } catch (networkError) {\n          // Network failed - we're offline\n          debugLog(\n            'FETCH',\n            `Network failed for: ${url.pathname}, trying offline fallback`\n          );\n\n          const offlineResponse = await handleWorkspaceFilePageOffline(\n            request,\n            url\n          );\n          if (offlineResponse) {\n            return offlineResponse;\n          }\n\n          // Last resort - offline.html from precache\n          debugLog('FALLBACK', `Serving offline.html for: ${url.pathname}`);\n          const offlinePage = await serwist.matchPrecache('/offline.html');\n          if (offlinePage) {\n            return offlinePage;\n          }\n\n          // Fallback if precache lookup fails\n          debugLog(\n            'FALLBACK',\n            'offline.html not in precache, trying caches.match'\n          );\n          const offlinePageFallback = await caches.match('/offline.html');\n          if (offlinePageFallback) {\n            return offlinePageFallback;\n          }\n\n          return new Response('Offline', { status: 503 });\n        }\n      })()\n    );\n    return;\n  }\n\n  // =============================================================================\n  // SHADOW CACHE: When RSC request succeeds, also cache HTML version\n  // This ensures offline full-page navigation works even if the page\n  // was only visited via client-side (RSC) navigation \u2014 which is the norm for\n  // the home route (reached via redirect) and common for workspace files.\n  // =============================================================================\n  if (\n    (workspaceFileRoute || homeRoute) &&\n    shouldShadowCacheRouteHtml(\n      request.headers.get('RSC'),\n      request.headers.get('Next-Router-Prefetch')\n    )\n  ) {\n    debugLog('FETCH', `RSC request: ${url.pathname}`);\n\n    // Let Serwist handle the RSC request normally\n    // But also trigger a background HTML fetch for the pages cache\n    const normalizedUrl = url.origin + url.pathname;\n\n    // Check if we already have this in pages cache\n    const shadowCachePromise = caches\n      .open('pages')\n      .then(async (cache) => {\n        const existing = await cache.match(normalizedUrl);\n        if (!existing) {\n          // Not in pages cache - fetch HTML version in background\n          debugLog('SHADOW-CACHE', `Fetching HTML for: ${url.pathname}`);\n          try {\n            const htmlResponse = await fetch(normalizedUrl, {\n              credentials: 'same-origin',\n              headers: {\n                Accept: 'text/html',\n              },\n            });\n            if (htmlResponse.ok) {\n              await cache.put(normalizedUrl, htmlResponse);\n              debugLog('SHADOW-CACHE', `Cached HTML for: ${url.pathname}`);\n            }\n          } catch (e) {\n            // Silently fail - this is just an optimization\n            debugLog('SHADOW-CACHE', `Failed to cache HTML: ${e}`);\n          }\n        }\n      })\n      .catch((error) => {\n        debugLog('SHADOW-CACHE', `Failed to open pages cache: ${error}`);\n      });\n    event.waitUntil(shadowCachePromise);\n  }\n\n  serwist.handleFetch(event);\n});\n"],
  "mappings": "AAAA,IAAAA,EAAA,CACE,CACE,IAAO,0EACP,SAAY,IACd,EACA,CACE,IAAO,2DACP,SAAY,IACd,EACA,CACE,IAAO,0DACP,SAAY,IACd,EACA,CACE,IAAO,gEACP,SAAY,IACd,EACA,CACE,IAAO,2DACP,SAAY,IACd,EACA,CACE,IAAO,2DACP,SAAY,IACd,EACA,CACE,IAAO,+DACP,SAAY,IACd,EACA,CACE,IAAO,uDACP,SAAY,IACd,EACA,CACE,IAAO,iEACP,SAAY,IACd,EACA,CACE,IAAO,kEACP,SAAY,IACd,EACA,CACE,IAAO,kEACP,SAAY,IACd,EACA,CACE,IAAO,2DACP,SAAY,IACd,EACA,CACE,IAAO,4DACP,SAAY,IACd,EACA,CACE,IAAO,wDACP,SAAY,IACd,EACA,CACE,IAAO,gEACP,SAAY,IACd,EACA,CACE,IAAO,oFACP,SAAY,IACd,EACA,CACE,IAAO,oFACP,SAAY,IACd,EACA,CACE,IAAO,wEACP,SAAY,IACd,EACA,CACE,IAAO,2EACP,SAAY,IACd,EACA,CACE,IAAO,yDACP,SAAY,IACd,EACA,CACE,IAAO,yDACP,SAAY,IACd,EACA,CACE,IAAO,+EACP,SAAY,IACd,EACA,CACE,IAAO,uEACP,SAAY,IACd,EACA,CACE,IAAO,2DACP,SAAY,IACd,EACA,CACE,IAAO,0DACP,SAAY,IACd,EACA,CACE,IAAO,sDACP,SAAY,IACd,EACA,CACE,IAAO,2DACP,SAAY,IACd,EACA,CACE,IAAO,kEACP,SAAY,IACd,EACA,CACE,IAAO,kEACP,SAAY,IACd,EACA,CACE,IAAO,4DACP,SAAY,IACd,EACA,CACE,IAAO,wDACP,SAAY,IACd,EACA,CACE,IAAO,6DACP,SAAY,IACd,EACA,CACE,IAAO,6DACP,SAAY,IACd,EACA,CACE,IAAO,uDACP,SAAY,IACd,EACA,CACE,IAAO,6DACP,SAAY,IACd,EACA,CACE,IAAO,mEACP,SAAY,IACd,EACA,CACE,IAAO,4DACP,SAAY,IACd,EACA,CACE,IAAO,4DACP,SAAY,IACd,EACA,CACE,IAAO,4DACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,mDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,mDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,mDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,mDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,mDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,mDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,mDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,mDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,qDACP,SAAY,IACd,EACA,CACE,IAAO,kEACP,SAAY,IACd,EACA,CACE,IAAO,uDACP,SAAY,IACd,EACA,CACE,IAAO,gBACP,SAAY,kCACd,EACA,CACE,IAAO,cACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,sBACP,SAAY,kCACd,EACA,CACE,IAAO,kBACP,SAAY,kCACd,EACA,CACE,IAAO,mBACP,SAAY,kCACd,EACA,CACE,IAAO,aACP,SAAY,kCACd,EACA,CACE,IAAO,cACP,SAAY,kCACd,EACA,CACE,IAAO,wBACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,gBACP,SAAY,kCACd,EACA,CACE,IAAO,YACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,sBACP,SAAY,kCACd,EACA,CACE,IAAO,kCACP,SAAY,kCACd,EACA,CACE,IAAO,sCACP,SAAY,kCACd,EACA,CACE,IAAO,iCACP,SAAY,kCACd,EACA,CACE,IAAO,gCACP,SAAY,kCACd,EACA,CACE,IAAO,2BACP,SAAY,kCACd,EACA,CACE,IAAO,WACP,SAAY,kCACd,EACA,CACE,IAAO,cACP,SAAY,kCACd,EACA,CACE,IAAO,wBACP,SAAY,kCACd,EACA,CACE,IAAO,wBACP,SAAY,kCACd,EACA,CACE,IAAO,2BACP,SAAY,kCACd,EACA,CACE,IAAO,0BACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,8BACP,SAAY,kCACd,EACA,CACE,IAAO,4BACP,SAAY,kCACd,EACA,CACE,IAAO,mBACP,SAAY,kCACd,EACA,CACE,IAAO,sBACP,SAAY,kCACd,EACA,CACE,IAAO,sBACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,2BACP,SAAY,kCACd,EACA,CACE,IAAO,mBACP,SAAY,kCACd,EACA,CACE,IAAO,6BACP,SAAY,kCACd,EACA,CACE,IAAO,sBACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,8BACP,SAAY,kCACd,EACA,CACE,IAAO,wBACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,wBACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,oBACP,SAAY,kCACd,EACA,CACE,IAAO,wBACP,SAAY,kCACd,EACA,CACE,IAAO,kBACP,SAAY,kCACd,EACA,CACE,IAAO,4BACP,SAAY,kCACd,EACA,CACE,IAAO,gDACP,SAAY,kCACd,EACA,CACE,IAAO,+CACP,SAAY,kCACd,EACA,CACE,IAAO,iDACP,SAAY,kCACd,EACA,CACE,IAAO,gDACP,SAAY,kCACd,EACA,CACE,IAAO,oCACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,oBACP,SAAY,kCACd,EACA,CACE,IAAO,2CACP,SAAY,kCACd,EACA,CACE,IAAO,mCACP,SAAY,kCACd,EACA,CACE,IAAO,mCACP,SAAY,kCACd,EACA,CACE,IAAO,mCACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,wBACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,yBACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,2BACP,SAAY,kCACd,EACA,CACE,IAAO,sBACP,SAAY,kCACd,EACA,CACE,IAAO,8BACP,SAAY,kCACd,EACA,CACE,IAAO,wBACP,SAAY,kCACd,EACA,CACE,IAAO,0BACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,oBACP,SAAY,kCACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,yBACP,SAAY,kCACd,EACA,CACE,IAAO,mBACP,SAAY,kCACd,EACA,CACE,IAAO,8BACP,SAAY,kCACd,EACA,CACE,IAAO,yBACP,SAAY,kCACd,EACA,CACE,IAAO,mBACP,SAAY,kCACd,EACA,CACE,IAAO,gCACP,SAAY,kCACd,EACA,CACE,IAAO,6BACP,SAAY,kCACd,EACA,CACE,IAAO,uCACP,SAAY,kCACd,EACA,CACE,IAAO,mCACP,SAAY,kCACd,EACA,CACE,IAAO,iCACP,SAAY,kCACd,EACA,CACE,IAAO,0CACP,SAAY,kCACd,EACA,CACE,IAAO,mCACP,SAAY,kCACd,EACA,CACE,IAAO,mCACP,SAAY,kCACd,EACA,CACE,IAAO,kCACP,SAAY,kCACd,EACA,CACE,IAAO,mCACP,SAAY,kCACd,EACA,CACE,IAAO,kCACP,SAAY,kCACd,EACA,CACE,IAAO,mCACP,SAAY,kCACd,EACA,CACE,IAAO,kCACP,SAAY,kCACd,EACA,CACE,IAAO,mCACP,SAAY,kCACd,EACA,CACE,IAAO,kCACP,SAAY,kCACd,EACA,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",
  "names": ["define_self_SW_MANIFEST_default", "_cacheNameDetails", "_createCacheName", "cacheName", "value", "eachCacheNameDetail", "fn", "key", "cacheNames", "details", "detail", "userCacheName", "fallback", "code", "args", "msg", "messageGenerator", "fallback", "SerwistError", "errorCode", "details", "message", "getFriendlyURL", "url", "timeout", "ms", "resolve", "quotaErrorCallbacks", "stripParams", "fullURL", "ignoreParams", "strippedURL", "param", "cacheMatchIgnoreParams", "cache", "request", "matchOptions", "strippedRequestURL", "keysOptions", "cacheKeys", "cacheKey", "Deferred", "reject", "executeQuotaErrorCallbacks", "callback", "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", "MAX_RETENTION_TIME", "cacheOkAndOpaquePlugin", "response", "toRequest", "input", "StrategyHandler", "strategy", "options", "Deferred", "plugin", "event", "request", "preloadResponse", "originalRequest", "cb", "err", "SerwistError", "pluginFilteredRequest", "fetchResponse", "callback", "error", "responseClone", "key", "cachedResponse", "cacheName", "matchOptions", "effectiveRequest", "multiMatchOptions", "timeout", "getFriendlyURL", "responseToCache", "cache", "hasCacheUpdateCallback", "oldResponse", "cacheMatchIgnoreParams", "executeQuotaErrorCallbacks", "mode", "name", "param", "state", "statefulParam", "promise", "possiblePreloadResponse", "pluginsUsed", "Strategy", "privateCacheNames", "responseDone", "handler", "waitUntilError", "NetworkFirst", "Strategy", "options", "p", "cacheOkAndOpaquePlugin", "request", "handler", "logs", "promises", "timeoutId", "id", "promise", "networkPromise", "response", "SerwistError", "resolve", "error", "fetchError", "NetworkOnly", "timeoutPromise", "timeout", "err", "isSafari", "DB_NAME", "CACHE_OBJECT_STORE", "normalizeURL", "unNormalizedUrl", "url", "CacheTimestampsModel", "cacheName", "db", "objStore", "deleteDB", "timestamp", "entry", "tx", "minTimestamp", "maxCount", "cursor", "urlsDeleted", "entriesNotDeletedCount", "result", "openDB", "CacheExpiration", "config", "urlsExpired", "cache", "expireOlderThan", "registerQuotaErrorCallback", "callback", "quotaErrorCallbacks", "ExpirationPlugin", "privateCacheNames", "SerwistError", "cacheExpiration", "event", "request", "cachedResponse", "isFresh", "isMaxAgeFromLastUsed", "done", "now", "dateHeaderTimestamp", "dateHeader", "headerTime", "calculateEffectiveBoundaries", "blob", "start", "end", "blobSize", "SerwistError", "effectiveStart", "effectiveEnd", "parseRangeHeader", "rangeHeader", "normalizedRangeHeader", "rangeParts", "createPartialResponse", "request", "originalResponse", "boundaries", "originalBlob", "effectiveBoundaries", "slicedBlob", "slicedBlobSize", "slicedResponse", "RangeRequestsPlugin", "cachedResponse", "CacheFirst", "Strategy", "handler", "logs", "response", "error", "err", "StaleWhileRevalidate", "Strategy", "options", "p", "cacheOkAndOpaquePlugin", "request", "handler", "logs", "fetchAndCachePromise", "response", "error", "err", "SerwistError", "PAGES_CACHE_NAME", "rscPrefetch", "rsc", "html", "defaultCache", "matcher", "handler", "CacheFirst", "cacheName", "plugins", "ExpirationPlugin", "maxEntries", "maxAgeSeconds", "maxAgeFrom", "StaleWhileRevalidate", "RangeRequestsPlugin", "NetworkFirst", "NetworkOnly", "networkTimeoutSeconds", "sameOrigin", "url", "pathname", "startsWith", "method", "request", "headers", "get", "includes", "fallback", "code", "args", "msg", "messageGenerator", "fallback", "SerwistError", "errorCode", "details", "message", "getFriendlyURL", "url", "_cacheNameDetails", "_createCacheName", "cacheName", "value", "eachCacheNameDetail", "fn", "key", "cacheNames", "details", "detail", "userCacheName", "Deferred", "resolve", "reject", "stripParams", "fullURL", "ignoreParams", "strippedURL", "param", "cacheMatchIgnoreParams", "cache", "request", "matchOptions", "strippedRequestURL", "keysOptions", "cacheKeys", "cacheKey", "strippedCacheKeyURL", "quotaErrorCallbacks", "executeQuotaErrorCallbacks", "callback", "timeout", "ms", "supportStatus", "canConstructResponseFromBodyStream", "testResponse", "SUBSTRING_TO_FIND", "deleteOutdatedCaches", "currentPrecacheName", "substringToFind", "cacheNamesToDelete", "cleanupOutdatedCaches", "event", "cachesDeleted", "clientsClaim", "waitUntil", "asyncFn", "returnPromise", "defaultMethod", "normalizeHandler", "handler", "Route", "match", "method", "defaultMethod", "NavigationRoute", "allowlist", "denylist", "options", "url", "request", "pathnameAndSearch", "regExp", "removeIgnoredSearchParams", "urlObject", "ignoreURLParametersMatching", "paramName", "generateURLVariations", "directoryIndex", "cleanURLs", "urlManipulation", "urlWithoutIgnoredParams", "directoryURL", "cleanURL", "additionalURLs", "urlToAttempt", "RegExpRoute", "result", "parallel", "limit", "array", "func", "work", "item", "index", "processor", "res", "results", "next", "queues", "a", "b", "disableDevLogs", "toRequest", "input", "StrategyHandler", "strategy", "Deferred", "plugin", "event", "preloadResponse", "originalRequest", "cb", "err", "SerwistError", "pluginFilteredRequest", "fetchResponse", "callback", "error", "response", "responseClone", "key", "cachedResponse", "cacheName", "matchOptions", "effectiveRequest", "multiMatchOptions", "timeout", "getFriendlyURL", "responseToCache", "cache", "hasCacheUpdateCallback", "oldResponse", "cacheMatchIgnoreParams", "executeQuotaErrorCallbacks", "mode", "name", "param", "state", "statefulParam", "promise", "possiblePreloadResponse", "pluginsUsed", "Strategy", "cacheNames", "responseDone", "handlerDone", "waitUntilError", "cacheOkAndOpaquePlugin", "NetworkFirst", "Strategy", "options", "p", "cacheOkAndOpaquePlugin", "request", "handler", "logs", "promises", "timeoutId", "id", "promise", "networkPromise", "response", "SerwistError", "resolve", "error", "fetchError", "NetworkOnly", "timeoutPromise", "timeout", "err", "BACKGROUND_SYNC_DB_VERSION", "BACKGROUND_SYNC_DB_NAME", "REQUEST_OBJECT_STORE_NAME", "QUEUE_NAME_INDEX", "BackgroundSyncQueueDb", "entry", "tx", "queueName", "results", "query", "direction", "openDB", "db", "oldVersion", "BackgroundSyncQueueStore", "firstId", "serializableProperties", "StorableRequest", "_StorableRequest", "requestData", "value", "key", "prop", "TAG_PREFIX", "MAX_RETENTION_TIME", "queueNames", "convertEntry", "queueStoreEntry", "queueEntry", "BackgroundSyncQueue", "name", "forceSyncFallback", "onSync", "maxRetentionTime", "allEntries", "now", "unexpiredEntries", "maxRetentionTimeInMs", "metadata", "timestamp", "operation", "event", "syncComplete", "syncError", "BackgroundSyncPlugin", "copyResponse", "modifier", "origin", "clonedResponse", "responseInit", "modifiedResponseInit", "body", "canConstructResponseFromBodyStream", "PrecacheStrategy", "_PrecacheStrategy", "cacheNames", "preloadResponse", "params", "integrityInManifest", "integrityInRequest", "noIntegrityConflict", "wasCached", "defaultPluginIndex", "cacheWillUpdatePluginCount", "index", "plugin", "isNavigationPreloadSupported", "enableNavigationPreload", "headerValue", "setCacheNameDetails", "details", "cacheNames", "PrecacheInstallReportPlugin", "request", "state", "event", "cachedResponse", "url", "REVISION_SEARCH_PARAM", "createCacheKey", "entry", "SerwistError", "urlObject", "revision", "cacheKeyURL", "originalURL", "parseRoute", "capture", "handler", "method", "captureUrl", "matchCallback", "Route", "RegExpRoute", "PrecacheRoute", "Route", "serwist", "options", "match", "request", "urlsToCacheKeys", "possibleURL", "generateURLVariations", "cacheKey", "integrity", "QUEUE_NAME", "MAX_RETENTION_TIME", "GOOGLE_ANALYTICS_HOST", "GTM_HOST", "ANALYTICS_JS_PATH", "GTAG_JS_PATH", "GTM_JS_PATH", "COLLECT_PATHS_REGEX", "createOnSyncCallback", "config", "queue", "entry", "timestamp", "url", "params", "originalHitTime", "queueTime", "param", "value", "err", "createCollectRoutes", "bgSyncPlugin", "handler", "NetworkOnly", "createAnalyticsJsRoute", "cacheName", "NetworkFirst", "createGtagJsRoute", "createGtmJsRoute", "initializeGoogleAnalytics", "resolvedCacheName", "cacheNames", "BackgroundSyncPlugin", "routes", "route", "PrecacheFallbackPlugin", "fallbackUrls", "fallback", "fallbackResponse", "PrecacheCacheKeyPlugin", "precacheController", "parsePrecacheOptions", "precacheOptions", "precacheCacheName", "precachePlugins", "precacheFetchOptions", "precacheMatchOptions", "precacheFallbackToNetwork", "precacheDirectoryIndex", "precacheIgnoreUrls", "precacheCleanUrls", "precacheUrlManipulation", "cleanupOutdatedCaches", "concurrency", "navigateFallback", "navigateFallbackAllowlist", "navigateFallbackDenylist", "Serwist", "precacheEntries", "skipWaiting", "importScripts", "navigationPreload", "cacheId", "clientsClaim$1", "runtimeCaching", "offlineAnalyticsConfig", "disableDevLogs$1", "fallbacks", "requestRules", "precacheStrategyOptions", "precacheRouteOptions", "precacheMiscOptions", "PrecacheStrategy", "enableNavigationPreload", "setCacheNameDetails", "event", "clientsClaim", "NavigationRoute", "fallbackPlugin", "cacheEntry", "Strategy", "plugin", "disableDevLogs", "entries", "urlsToWarnAbout", "createCacheKey", "cacheMode", "SerwistError", "warningMessage", "waitUntil", "installReportPlugin", "PrecacheInstallReportPlugin", "parallel", "updatedURLs", "notUpdatedURLs", "error", "cache", "currentlyCachedRequests", "expectedCacheKeys", "deletedCacheRequests", "responsePromise", "payload", "requestPromises", "method", "defaultMethod", "normalizeHandler", "capture", "parseRoute", "routeIndex", "urlObject", "sameOrigin", "debugMessages", "catchHandler", "catchErr", "matchResult", "isSafari", "CacheableResponse", "config", "response", "cacheable", "headerName", "headerValue", "DB_NAME", "CACHE_OBJECT_STORE", "normalizeURL", "unNormalizedUrl", "url", "CacheTimestampsModel", "cacheName", "db", "objStore", "deleteDB", "timestamp", "entry", "tx", "minTimestamp", "maxCount", "cursor", "urlsDeleted", "entriesNotDeletedCount", "result", "openDB", "CacheExpiration", "config", "urlsExpired", "cache", "expireOlderThan", "registerQuotaErrorCallback", "callback", "quotaErrorCallbacks", "ExpirationPlugin", "cacheNames", "SerwistError", "cacheExpiration", "event", "request", "cachedResponse", "isFresh", "isMaxAgeFromLastUsed", "done", "now", "dateHeaderTimestamp", "dateHeader", "headerTime", "StaleWhileRevalidate", "Strategy", "options", "p", "cacheOkAndOpaquePlugin", "request", "handler", "logs", "fetchAndCachePromise", "response", "error", "err", "SerwistError", "isViewerRoute", "pathname", "isCompactViewerRoute", "isDdocCollaborationRoute", "shouldSkipPageCache", "DEPLOYMENT_ID_HEADER", "buildRscCacheKey", "requestUrl", "deploymentId", "url", "NEXT_STATIC_SCRIPT_PATTERN", "getNextStaticScriptPaths", "html", "shouldShadowCacheRouteHtml", "rscHeader", "routerPrefetchHeader", "FILE_KIND", "BARE_WORKSPACE_FILE_PAGE", "WORKSPACE_FILE_PAGE", "BARE_HOME_PAGE", "WORKSPACE_HOME_PAGE", "isReservedWorkspaceFileId", "routeSegment", "id", "toWorkspaceFileRef", "FILE_KIND", "matchWorkspaceFilePagePath", "pathname", "bare", "workspace", "matchHomePagePath", "pathname", "BARE_HOME_PAGE", "workspace", "WORKSPACE_HOME_PAGE", "cacheable", "CacheableResponse", "disableDevLogs", "DEBUG_OFFLINE", "debugLog", "category", "message", "data", "timestamp", "NormalizeCacheKeyPlugin", "request", "mode", "url", "hadRsc", "normalizedUrl", "buildRscCacheKey", "DEPLOYMENT_ID_HEADER", "matchWorkspaceFilePagePath", "IPFSExpirationPlugin", "ExpirationPlugin", "config", "response", "cacheItems", "currentHash", "item", "error", "IPFSStrategyHandler", "Strategy", "handler", "cacheMatch", "OFFLINE_PAGE_URL", "OFFLINE_CRITICAL_PAGES", "cacheStrategies", "pathname", "sameOrigin", "NetworkFirst", "shouldSkipPageCache", "offlineFirstRuntimeCaching", "StaleWhileRevalidate", "serwist", "Serwist", "define_self_SW_MANIFEST_default", "isNav", "reqUrl", "defaultCache", "strategy", "originalMatcher", "options", "event", "preCacheCriticalPages", "htmlCache", "rscCache", "pageUrl", "htmlResponse", "rscResponse", "rscRequest", "PREVIOUS_BUILD_PAGE_CACHES", "name", "reason", "handleWorkspaceFilePageOffline", "pagesCache", "cachedResponse", "html", "scriptPaths", "getNextStaticScriptPaths", "scriptMatches", "path", "_", "i", "workspaceFileRoute", "homeRoute", "matchHomePagePath", "responseForCache", "cacheWrite", "cache", "offlineResponse", "offlinePage", "offlinePageFallback", "shouldShadowCacheRouteHtml", "shadowCachePromise", "e"]
}
