serwist 9.0.0-preview.24 → 9.0.0-preview.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/dist/NavigationRoute.d.ts +6 -7
  2. package/dist/NavigationRoute.d.ts.map +1 -1
  3. package/dist/PrecacheRoute.d.ts +2 -2
  4. package/dist/PrecacheRoute.d.ts.map +1 -1
  5. package/dist/RegExpRoute.d.ts +4 -4
  6. package/dist/RegExpRoute.d.ts.map +1 -1
  7. package/dist/Route.d.ts +10 -10
  8. package/dist/Route.d.ts.map +1 -1
  9. package/dist/Serwist.d.ts +39 -44
  10. package/dist/Serwist.d.ts.map +1 -1
  11. package/dist/chunks/printInstallDetails.js +1587 -0
  12. package/dist/chunks/resultingClientExists.js +1 -1
  13. package/dist/chunks/waitUntil.js +426 -1
  14. package/dist/copyResponse.d.ts +8 -10
  15. package/dist/copyResponse.d.ts.map +1 -1
  16. package/dist/disableDevLogs.d.ts +1 -1
  17. package/dist/index.d.ts +41 -12
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.internal.d.ts +3 -1
  20. package/dist/index.internal.d.ts.map +1 -1
  21. package/dist/index.internal.js +1 -2
  22. package/dist/index.js +1464 -8
  23. package/dist/index.legacy.d.ts +4 -8
  24. package/dist/index.legacy.d.ts.map +1 -1
  25. package/dist/index.legacy.js +166 -16
  26. package/dist/legacy/PrecacheController.d.ts +1 -1
  27. package/dist/legacy/PrecacheController.d.ts.map +1 -1
  28. package/dist/legacy/PrecacheRoute.d.ts.map +1 -1
  29. package/dist/legacy/Router.d.ts +1 -1
  30. package/dist/legacy/Router.d.ts.map +1 -1
  31. package/dist/legacy/constants.d.ts.map +1 -0
  32. package/dist/legacy/fallbacks.d.ts +1 -1
  33. package/dist/legacy/fallbacks.d.ts.map +1 -1
  34. package/dist/legacy/handlePrecaching.d.ts.map +1 -1
  35. package/dist/legacy/initializeGoogleAnalytics.d.ts +38 -0
  36. package/dist/legacy/initializeGoogleAnalytics.d.ts.map +1 -0
  37. package/dist/legacy/installSerwist.d.ts +69 -3
  38. package/dist/legacy/installSerwist.d.ts.map +1 -1
  39. package/dist/legacy/registerRoute.d.ts +1 -1
  40. package/dist/legacy/registerRoute.d.ts.map +1 -1
  41. package/dist/{plugins → lib}/backgroundSync/BackgroundSyncPlugin.d.ts +3 -3
  42. package/dist/lib/backgroundSync/BackgroundSyncPlugin.d.ts.map +1 -0
  43. package/dist/{plugins/backgroundSync/Queue.d.ts → lib/backgroundSync/BackgroundSyncQueue.d.ts} +29 -13
  44. package/dist/lib/backgroundSync/BackgroundSyncQueue.d.ts.map +1 -0
  45. package/dist/{plugins/backgroundSync/QueueDb.d.ts → lib/backgroundSync/BackgroundSyncQueueDb.d.ts} +7 -7
  46. package/dist/lib/backgroundSync/BackgroundSyncQueueDb.d.ts.map +1 -0
  47. package/dist/{plugins/backgroundSync/QueueStore.d.ts → lib/backgroundSync/BackgroundSyncQueueStore.d.ts} +7 -7
  48. package/dist/lib/backgroundSync/BackgroundSyncQueueStore.d.ts.map +1 -0
  49. package/dist/lib/backgroundSync/StorableRequest.d.ts.map +1 -0
  50. package/dist/lib/broadcastUpdate/BroadcastCacheUpdate.d.ts.map +1 -0
  51. package/dist/{plugins → lib}/broadcastUpdate/BroadcastUpdatePlugin.d.ts +1 -1
  52. package/dist/lib/broadcastUpdate/BroadcastUpdatePlugin.d.ts.map +1 -0
  53. package/dist/lib/broadcastUpdate/constants.d.ts +5 -0
  54. package/dist/lib/broadcastUpdate/constants.d.ts.map +1 -0
  55. package/dist/lib/broadcastUpdate/responsesAreSame.d.ts.map +1 -0
  56. package/dist/{plugins → lib}/broadcastUpdate/types.d.ts +3 -3
  57. package/dist/lib/broadcastUpdate/types.d.ts.map +1 -0
  58. package/dist/lib/cacheableResponse/CacheableResponse.d.ts.map +1 -0
  59. package/dist/lib/cacheableResponse/CacheableResponsePlugin.d.ts.map +1 -0
  60. package/dist/{plugins → lib}/expiration/CacheExpiration.d.ts +1 -1
  61. package/dist/lib/expiration/CacheExpiration.d.ts.map +1 -0
  62. package/dist/{plugins → lib}/expiration/ExpirationPlugin.d.ts +1 -1
  63. package/dist/lib/expiration/ExpirationPlugin.d.ts.map +1 -0
  64. package/dist/lib/expiration/models/CacheTimestampsModel.d.ts.map +1 -0
  65. package/dist/lib/googleAnalytics/constants.d.ts +10 -0
  66. package/dist/lib/googleAnalytics/constants.d.ts.map +1 -0
  67. package/dist/{plugins/googleAnalytics/initialize.d.ts → lib/googleAnalytics/initializeGoogleAnalytics.d.ts} +2 -2
  68. package/dist/lib/googleAnalytics/initializeGoogleAnalytics.d.ts.map +1 -0
  69. package/dist/{plugins → lib}/precaching/PrecacheFallbackPlugin.d.ts +1 -1
  70. package/dist/lib/precaching/PrecacheFallbackPlugin.d.ts.map +1 -0
  71. package/dist/lib/rangeRequests/RangeRequestsPlugin.d.ts.map +1 -0
  72. package/dist/lib/rangeRequests/createPartialResponse.d.ts.map +1 -0
  73. package/dist/lib/rangeRequests/utils/calculateEffectiveBoundaries.d.ts.map +1 -0
  74. package/dist/lib/rangeRequests/utils/parseRangeHeader.d.ts.map +1 -0
  75. package/dist/{strategies → lib/strategies}/CacheFirst.d.ts +1 -1
  76. package/dist/lib/strategies/CacheFirst.d.ts.map +1 -0
  77. package/dist/{strategies → lib/strategies}/CacheOnly.d.ts +2 -2
  78. package/dist/lib/strategies/CacheOnly.d.ts.map +1 -0
  79. package/dist/{strategies → lib/strategies}/NetworkFirst.d.ts +2 -2
  80. package/dist/lib/strategies/NetworkFirst.d.ts.map +1 -0
  81. package/dist/{strategies → lib/strategies}/NetworkOnly.d.ts +2 -2
  82. package/dist/lib/strategies/NetworkOnly.d.ts.map +1 -0
  83. package/dist/{PrecacheStrategy.d.ts → lib/strategies/PrecacheStrategy.d.ts} +5 -5
  84. package/dist/lib/strategies/PrecacheStrategy.d.ts.map +1 -0
  85. package/dist/{strategies → lib/strategies}/StaleWhileRevalidate.d.ts +1 -1
  86. package/dist/lib/strategies/StaleWhileRevalidate.d.ts.map +1 -0
  87. package/dist/{strategies → lib/strategies}/Strategy.d.ts +15 -17
  88. package/dist/lib/strategies/Strategy.d.ts.map +1 -0
  89. package/dist/{strategies → lib/strategies}/StrategyHandler.d.ts +35 -41
  90. package/dist/lib/strategies/StrategyHandler.d.ts.map +1 -0
  91. package/dist/lib/strategies/plugins/cacheOkAndOpaquePlugin.d.ts +3 -0
  92. package/dist/lib/strategies/plugins/cacheOkAndOpaquePlugin.d.ts.map +1 -0
  93. package/dist/lib/strategies/utils/messages.d.ts.map +1 -0
  94. package/dist/navigationPreload.d.ts +3 -3
  95. package/dist/types.d.ts +12 -7
  96. package/dist/types.d.ts.map +1 -1
  97. package/dist/utils/PrecacheCacheKeyPlugin.d.ts +1 -1
  98. package/dist/utils/PrecacheCacheKeyPlugin.d.ts.map +1 -1
  99. package/dist/utils/assert.d.ts.map +1 -1
  100. package/dist/utils/cleanupOutdatedCaches.d.ts.map +1 -0
  101. package/dist/utils/clientsClaim.d.ts.map +1 -0
  102. package/dist/{parseRoute.d.ts → utils/parseRoute.d.ts} +3 -3
  103. package/dist/utils/parseRoute.d.ts.map +1 -0
  104. package/package.json +7 -21
  105. package/src/NavigationRoute.ts +6 -7
  106. package/src/PrecacheRoute.ts +5 -5
  107. package/src/RegExpRoute.ts +5 -5
  108. package/src/Route.ts +11 -11
  109. package/src/Serwist.ts +73 -80
  110. package/src/copyResponse.ts +7 -9
  111. package/src/disableDevLogs.ts +1 -1
  112. package/src/index.internal.ts +4 -0
  113. package/src/index.legacy.ts +14 -18
  114. package/src/index.ts +105 -19
  115. package/src/legacy/PrecacheController.ts +8 -8
  116. package/src/legacy/PrecacheFallbackPlugin.ts +1 -1
  117. package/src/legacy/PrecacheRoute.ts +3 -3
  118. package/src/legacy/Router.ts +5 -5
  119. package/src/legacy/fallbacks.ts +3 -3
  120. package/src/legacy/handlePrecaching.ts +1 -1
  121. package/src/legacy/initializeGoogleAnalytics.ts +218 -0
  122. package/src/legacy/installSerwist.ts +156 -5
  123. package/src/legacy/registerRoute.ts +1 -1
  124. package/src/{plugins → lib}/backgroundSync/BackgroundSyncPlugin.ts +6 -6
  125. package/src/{plugins/backgroundSync/Queue.ts → lib/backgroundSync/BackgroundSyncQueue.ts} +47 -26
  126. package/src/{plugins/backgroundSync/QueueDb.ts → lib/backgroundSync/BackgroundSyncQueueDb.ts} +16 -16
  127. package/src/{plugins/backgroundSync/QueueStore.ts → lib/backgroundSync/BackgroundSyncQueueStore.ts} +13 -13
  128. package/src/{plugins → lib}/backgroundSync/StorableRequest.ts +2 -2
  129. package/src/{plugins → lib}/broadcastUpdate/BroadcastCacheUpdate.ts +14 -9
  130. package/src/{plugins → lib}/broadcastUpdate/BroadcastUpdatePlugin.ts +1 -1
  131. package/src/lib/broadcastUpdate/constants.ts +12 -0
  132. package/src/{plugins → lib}/broadcastUpdate/types.ts +3 -3
  133. package/src/{plugins → lib}/cacheableResponse/CacheableResponse.ts +5 -5
  134. package/src/{plugins → lib}/expiration/CacheExpiration.ts +7 -7
  135. package/src/{plugins → lib}/expiration/ExpirationPlugin.ts +10 -10
  136. package/src/lib/googleAnalytics/constants.ts +22 -0
  137. package/src/{plugins/googleAnalytics/initialize.ts → lib/googleAnalytics/initializeGoogleAnalytics.ts} +9 -9
  138. package/src/{strategies → lib/strategies}/CacheFirst.ts +5 -5
  139. package/src/{strategies → lib/strategies}/CacheOnly.ts +6 -6
  140. package/src/{strategies → lib/strategies}/NetworkFirst.ts +7 -7
  141. package/src/{strategies → lib/strategies}/NetworkOnly.ts +7 -7
  142. package/src/{PrecacheStrategy.ts → lib/strategies/PrecacheStrategy.ts} +14 -10
  143. package/src/{strategies → lib/strategies}/StaleWhileRevalidate.ts +5 -5
  144. package/src/{strategies → lib/strategies}/Strategy.ts +19 -21
  145. package/src/{strategies → lib/strategies}/StrategyHandler.ts +45 -51
  146. package/src/{strategies → lib/strategies}/plugins/cacheOkAndOpaquePlugin.ts +1 -1
  147. package/src/{strategies → lib/strategies}/utils/messages.ts +2 -2
  148. package/src/models/messages/messages.ts +1 -1
  149. package/src/navigationPreload.ts +3 -3
  150. package/src/registerQuotaErrorCallback.ts +1 -1
  151. package/src/types.ts +12 -7
  152. package/src/utils/PrecacheCacheKeyPlugin.ts +1 -1
  153. package/src/utils/assert.ts +1 -1
  154. package/src/{cleanupOutdatedCaches.ts → utils/cleanupOutdatedCaches.ts} +3 -4
  155. package/src/utils/executeQuotaErrorCallbacks.ts +1 -1
  156. package/src/{parseRoute.ts → utils/parseRoute.ts} +21 -23
  157. package/src/utils/welcome.ts +1 -1
  158. package/dist/PrecacheStrategy.d.ts.map +0 -1
  159. package/dist/chunks/NetworkOnly.js +0 -599
  160. package/dist/chunks/PrecacheFallbackPlugin.js +0 -634
  161. package/dist/chunks/Serwist.js +0 -1034
  162. package/dist/chunks/registerQuotaErrorCallback.js +0 -17
  163. package/dist/chunks/timeout.js +0 -400
  164. package/dist/cleanupOutdatedCaches.d.ts.map +0 -1
  165. package/dist/clientsClaim.d.ts.map +0 -1
  166. package/dist/index.plugins.d.ts +0 -41
  167. package/dist/index.plugins.d.ts.map +0 -1
  168. package/dist/index.plugins.js +0 -669
  169. package/dist/index.strategies.d.ts +0 -22
  170. package/dist/index.strategies.d.ts.map +0 -1
  171. package/dist/index.strategies.js +0 -144
  172. package/dist/parseRoute.d.ts.map +0 -1
  173. package/dist/plugins/backgroundSync/BackgroundSyncPlugin.d.ts.map +0 -1
  174. package/dist/plugins/backgroundSync/Queue.d.ts.map +0 -1
  175. package/dist/plugins/backgroundSync/QueueDb.d.ts.map +0 -1
  176. package/dist/plugins/backgroundSync/QueueStore.d.ts.map +0 -1
  177. package/dist/plugins/backgroundSync/StorableRequest.d.ts.map +0 -1
  178. package/dist/plugins/broadcastUpdate/BroadcastCacheUpdate.d.ts.map +0 -1
  179. package/dist/plugins/broadcastUpdate/BroadcastUpdatePlugin.d.ts.map +0 -1
  180. package/dist/plugins/broadcastUpdate/constants.d.ts +0 -5
  181. package/dist/plugins/broadcastUpdate/constants.d.ts.map +0 -1
  182. package/dist/plugins/broadcastUpdate/responsesAreSame.d.ts.map +0 -1
  183. package/dist/plugins/broadcastUpdate/types.d.ts.map +0 -1
  184. package/dist/plugins/cacheableResponse/CacheableResponse.d.ts.map +0 -1
  185. package/dist/plugins/cacheableResponse/CacheableResponsePlugin.d.ts.map +0 -1
  186. package/dist/plugins/expiration/CacheExpiration.d.ts.map +0 -1
  187. package/dist/plugins/expiration/ExpirationPlugin.d.ts.map +0 -1
  188. package/dist/plugins/expiration/models/CacheTimestampsModel.d.ts.map +0 -1
  189. package/dist/plugins/googleAnalytics/constants.d.ts.map +0 -1
  190. package/dist/plugins/googleAnalytics/initialize.d.ts.map +0 -1
  191. package/dist/plugins/precaching/PrecacheFallbackPlugin.d.ts.map +0 -1
  192. package/dist/plugins/rangeRequests/RangeRequestsPlugin.d.ts.map +0 -1
  193. package/dist/plugins/rangeRequests/createPartialResponse.d.ts.map +0 -1
  194. package/dist/plugins/rangeRequests/utils/calculateEffectiveBoundaries.d.ts.map +0 -1
  195. package/dist/plugins/rangeRequests/utils/parseRangeHeader.d.ts.map +0 -1
  196. package/dist/strategies/CacheFirst.d.ts.map +0 -1
  197. package/dist/strategies/CacheOnly.d.ts.map +0 -1
  198. package/dist/strategies/NetworkFirst.d.ts.map +0 -1
  199. package/dist/strategies/NetworkOnly.d.ts.map +0 -1
  200. package/dist/strategies/StaleWhileRevalidate.d.ts.map +0 -1
  201. package/dist/strategies/Strategy.d.ts.map +0 -1
  202. package/dist/strategies/StrategyHandler.d.ts.map +0 -1
  203. package/dist/strategies/plugins/cacheOkAndOpaquePlugin.d.ts +0 -3
  204. package/dist/strategies/plugins/cacheOkAndOpaquePlugin.d.ts.map +0 -1
  205. package/dist/strategies/utils/messages.d.ts.map +0 -1
  206. package/src/index.plugins.ts +0 -95
  207. package/src/index.strategies.ts +0 -26
  208. package/src/plugins/broadcastUpdate/constants.ts +0 -12
  209. package/dist/{plugins/googleAnalytics → legacy}/constants.d.ts +0 -0
  210. package/dist/{plugins → lib}/backgroundSync/StorableRequest.d.ts +0 -0
  211. package/dist/{plugins → lib}/broadcastUpdate/BroadcastCacheUpdate.d.ts +0 -0
  212. package/dist/{plugins → lib}/broadcastUpdate/responsesAreSame.d.ts +0 -0
  213. package/dist/{plugins → lib}/cacheableResponse/CacheableResponse.d.ts +0 -0
  214. package/dist/{plugins → lib}/cacheableResponse/CacheableResponsePlugin.d.ts +0 -0
  215. package/dist/{plugins → lib}/expiration/models/CacheTimestampsModel.d.ts +0 -0
  216. package/dist/{plugins → lib}/rangeRequests/RangeRequestsPlugin.d.ts +0 -0
  217. package/dist/{plugins → lib}/rangeRequests/createPartialResponse.d.ts +0 -0
  218. package/dist/{plugins → lib}/rangeRequests/utils/calculateEffectiveBoundaries.d.ts +0 -0
  219. package/dist/{plugins → lib}/rangeRequests/utils/parseRangeHeader.d.ts +0 -0
  220. package/dist/{strategies → lib/strategies}/utils/messages.d.ts +0 -0
  221. package/dist/{cleanupOutdatedCaches.d.ts → utils/cleanupOutdatedCaches.d.ts} +0 -0
  222. package/dist/{clientsClaim.d.ts → utils/clientsClaim.d.ts} +0 -0
  223. package/src/{plugins/googleAnalytics → legacy}/constants.ts +0 -0
  224. package/src/{plugins → lib}/broadcastUpdate/responsesAreSame.ts +0 -0
  225. package/src/{plugins → lib}/cacheableResponse/CacheableResponsePlugin.ts +0 -0
  226. package/src/{plugins → lib}/expiration/models/CacheTimestampsModel.ts +0 -0
  227. package/src/{plugins → lib}/precaching/PrecacheFallbackPlugin.ts +1 -1
  228. package/src/{plugins → lib}/rangeRequests/RangeRequestsPlugin.ts +0 -0
  229. package/src/{plugins → lib}/rangeRequests/createPartialResponse.ts +1 -1
  230. package/src/{plugins → lib}/rangeRequests/utils/calculateEffectiveBoundaries.ts +1 -1
  231. package/src/{plugins → lib}/rangeRequests/utils/parseRangeHeader.ts +1 -1
  232. /package/src/{clientsClaim.ts → utils/clientsClaim.ts} +0 -0
package/dist/index.js CHANGED
@@ -1,10 +1,652 @@
1
- import { c as cacheNames$1 } from './chunks/timeout.js';
2
- export { N as NavigationRoute, P as PrecacheRoute, g as PrecacheStrategy, R as RegExpRoute, S as Serwist, c as cleanupOutdatedCaches, a as clientsClaim, b as copyResponse, d as disableDevLogs, e as disableNavigationPreload, f as enableNavigationPreload, i as isNavigationPreloadSupported, p as parseRoute, s as setCacheNameDetails } from './chunks/Serwist.js';
3
- export { r as registerQuotaErrorCallback } from './chunks/registerQuotaErrorCallback.js';
4
- export { R as Route } from './chunks/PrecacheFallbackPlugin.js';
5
- import './chunks/waitUntil.js';
6
- import './chunks/NetworkOnly.js';
7
- import 'idb';
1
+ import { R as Route, g as generateURLVariations, B as BackgroundSyncPlugin, N as NetworkOnly, a as NetworkFirst, P as PrecacheStrategy, e as enableNavigationPreload, s as setCacheNameDetails, b as NavigationRoute, S as Strategy, d as disableDevLogs, c as createCacheKey, p as parallel, f as printInstallDetails, h as printCleanupDetails, n as normalizeHandler, i as defaultMethod, j as parseRoute, k as PrecacheInstallReportPlugin, m as messages, l as cacheOkAndOpaquePlugin } from './chunks/printInstallDetails.js';
2
+ export { 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';
3
+ import { 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';
4
+ import { r as resultingClientExists } from './chunks/resultingClientExists.js';
5
+ import { deleteDB, openDB } from 'idb';
6
+
7
+ class PrecacheRoute extends Route {
8
+ constructor(serwist, options){
9
+ const match = ({ request })=>{
10
+ const urlsToCacheKeys = serwist.getUrlsToPrecacheKeys();
11
+ for (const possibleURL of generateURLVariations(request.url, options)){
12
+ const cacheKey = urlsToCacheKeys.get(possibleURL);
13
+ if (cacheKey) {
14
+ const integrity = serwist.getIntegrityForPrecacheKey(cacheKey);
15
+ return {
16
+ cacheKey,
17
+ integrity
18
+ };
19
+ }
20
+ }
21
+ if (process.env.NODE_ENV !== "production") {
22
+ logger.debug(`Precaching did not find a match for ${getFriendlyURL(request.url)}.`);
23
+ }
24
+ return;
25
+ };
26
+ super(match, serwist.precacheStrategy);
27
+ }
28
+ }
29
+
30
+ const QUEUE_NAME = "serwist-google-analytics";
31
+ const MAX_RETENTION_TIME = 60 * 48;
32
+ const GOOGLE_ANALYTICS_HOST = "www.google-analytics.com";
33
+ const GTM_HOST = "www.googletagmanager.com";
34
+ const ANALYTICS_JS_PATH = "/analytics.js";
35
+ const GTAG_JS_PATH = "/gtag/js";
36
+ const GTM_JS_PATH = "/gtm.js";
37
+ const COLLECT_PATHS_REGEX = /^\/(\w+\/)?collect/;
38
+
39
+ const createOnSyncCallback = (config)=>{
40
+ return async ({ queue })=>{
41
+ let entry = undefined;
42
+ while(entry = await queue.shiftRequest()){
43
+ const { request, timestamp } = entry;
44
+ const url = new URL(request.url);
45
+ try {
46
+ const params = request.method === "POST" ? new URLSearchParams(await request.clone().text()) : url.searchParams;
47
+ const originalHitTime = timestamp - (Number(params.get("qt")) || 0);
48
+ const queueTime = Date.now() - originalHitTime;
49
+ params.set("qt", String(queueTime));
50
+ if (config.parameterOverrides) {
51
+ for (const param of Object.keys(config.parameterOverrides)){
52
+ const value = config.parameterOverrides[param];
53
+ params.set(param, value);
54
+ }
55
+ }
56
+ if (typeof config.hitFilter === "function") {
57
+ config.hitFilter.call(null, params);
58
+ }
59
+ await fetch(new Request(url.origin + url.pathname, {
60
+ body: params.toString(),
61
+ method: "POST",
62
+ mode: "cors",
63
+ credentials: "omit",
64
+ headers: {
65
+ "Content-Type": "text/plain"
66
+ }
67
+ }));
68
+ if (process.env.NODE_ENV !== "production") {
69
+ logger.log(`Request for '${getFriendlyURL(url.href)}' has been replayed`);
70
+ }
71
+ } catch (err) {
72
+ await queue.unshiftRequest(entry);
73
+ if (process.env.NODE_ENV !== "production") {
74
+ logger.log(`Request for '${getFriendlyURL(url.href)}' failed to replay, putting it back in the queue.`);
75
+ }
76
+ throw err;
77
+ }
78
+ }
79
+ if (process.env.NODE_ENV !== "production") {
80
+ logger.log("All Google Analytics request successfully replayed; " + "the queue is now empty!");
81
+ }
82
+ };
83
+ };
84
+ const createCollectRoutes = (bgSyncPlugin)=>{
85
+ const match = ({ url })=>url.hostname === GOOGLE_ANALYTICS_HOST && COLLECT_PATHS_REGEX.test(url.pathname);
86
+ const handler = new NetworkOnly({
87
+ plugins: [
88
+ bgSyncPlugin
89
+ ]
90
+ });
91
+ return [
92
+ new Route(match, handler, "GET"),
93
+ new Route(match, handler, "POST")
94
+ ];
95
+ };
96
+ const createAnalyticsJsRoute = (cacheName)=>{
97
+ const match = ({ url })=>url.hostname === GOOGLE_ANALYTICS_HOST && url.pathname === ANALYTICS_JS_PATH;
98
+ const handler = new NetworkFirst({
99
+ cacheName
100
+ });
101
+ return new Route(match, handler, "GET");
102
+ };
103
+ const createGtagJsRoute = (cacheName)=>{
104
+ const match = ({ url })=>url.hostname === GTM_HOST && url.pathname === GTAG_JS_PATH;
105
+ const handler = new NetworkFirst({
106
+ cacheName
107
+ });
108
+ return new Route(match, handler, "GET");
109
+ };
110
+ const createGtmJsRoute = (cacheName)=>{
111
+ const match = ({ url })=>url.hostname === GTM_HOST && url.pathname === GTM_JS_PATH;
112
+ const handler = new NetworkFirst({
113
+ cacheName
114
+ });
115
+ return new Route(match, handler, "GET");
116
+ };
117
+ const initializeGoogleAnalytics = ({ serwist, cacheName, ...options })=>{
118
+ const resolvedCacheName = cacheNames$1.getGoogleAnalyticsName(cacheName);
119
+ const bgSyncPlugin = new BackgroundSyncPlugin(QUEUE_NAME, {
120
+ maxRetentionTime: MAX_RETENTION_TIME,
121
+ onSync: createOnSyncCallback(options)
122
+ });
123
+ const routes = [
124
+ createGtmJsRoute(resolvedCacheName),
125
+ createAnalyticsJsRoute(resolvedCacheName),
126
+ createGtagJsRoute(resolvedCacheName),
127
+ ...createCollectRoutes(bgSyncPlugin)
128
+ ];
129
+ for (const route of routes){
130
+ serwist.registerRoute(route);
131
+ }
132
+ };
133
+
134
+ class PrecacheFallbackPlugin {
135
+ _fallbackUrls;
136
+ _serwist;
137
+ constructor({ fallbackUrls, serwist }){
138
+ this._fallbackUrls = fallbackUrls;
139
+ this._serwist = serwist;
140
+ }
141
+ async handlerDidError(param) {
142
+ for (const fallback of this._fallbackUrls){
143
+ if (typeof fallback === "string") {
144
+ const fallbackResponse = await this._serwist.matchPrecache(fallback);
145
+ if (fallbackResponse !== undefined) {
146
+ return fallbackResponse;
147
+ }
148
+ } else if (fallback.matcher(param)) {
149
+ const fallbackResponse = await this._serwist.matchPrecache(fallback.url);
150
+ if (fallbackResponse !== undefined) {
151
+ return fallbackResponse;
152
+ }
153
+ }
154
+ }
155
+ return undefined;
156
+ }
157
+ }
158
+
159
+ class PrecacheCacheKeyPlugin {
160
+ _precacheController;
161
+ constructor({ precacheController }){
162
+ this._precacheController = precacheController;
163
+ }
164
+ cacheKeyWillBeUsed = async ({ request, params })=>{
165
+ const cacheKey = params?.cacheKey || this._precacheController.getPrecacheKeyForUrl(request.url);
166
+ return cacheKey ? new Request(cacheKey, {
167
+ headers: request.headers
168
+ }) : request;
169
+ };
170
+ }
171
+
172
+ class Serwist {
173
+ _urlsToCacheKeys = new Map();
174
+ _urlsToCacheModes = new Map();
175
+ _cacheKeysToIntegrities = new Map();
176
+ _concurrentPrecaching;
177
+ _precacheStrategy;
178
+ _routes;
179
+ _defaultHandlerMap;
180
+ _catchHandler;
181
+ constructor({ precacheEntries, precacheOptions, skipWaiting = false, importScripts, navigationPreload = false, cacheId, clientsClaim: clientsClaim$1 = false, runtimeCaching, offlineAnalyticsConfig, disableDevLogs: disableDevLogs$1 = false, fallbacks } = {}){
182
+ this._concurrentPrecaching = precacheOptions?.concurrency ?? 10;
183
+ this._precacheStrategy = new PrecacheStrategy({
184
+ cacheName: cacheNames$1.getPrecacheName(precacheOptions?.cacheName),
185
+ plugins: [
186
+ ...precacheOptions?.plugins ?? [],
187
+ new PrecacheCacheKeyPlugin({
188
+ precacheController: this
189
+ })
190
+ ],
191
+ fallbackToNetwork: precacheOptions?.fallbackToNetwork
192
+ });
193
+ this._routes = new Map();
194
+ this._defaultHandlerMap = new Map();
195
+ this.handleInstall = this.handleInstall.bind(this);
196
+ this.handleActivate = this.handleActivate.bind(this);
197
+ this.handleFetch = this.handleFetch.bind(this);
198
+ this.handleCache = this.handleCache.bind(this);
199
+ if (!!importScripts && importScripts.length > 0) self.importScripts(...importScripts);
200
+ if (navigationPreload) enableNavigationPreload();
201
+ if (cacheId !== undefined) {
202
+ setCacheNameDetails({
203
+ prefix: cacheId
204
+ });
205
+ }
206
+ if (skipWaiting) {
207
+ self.skipWaiting();
208
+ } else {
209
+ self.addEventListener("message", (event)=>{
210
+ if (event.data && event.data.type === "SKIP_WAITING") {
211
+ self.skipWaiting();
212
+ }
213
+ });
214
+ }
215
+ if (clientsClaim$1) clientsClaim();
216
+ if (!!precacheEntries && precacheEntries.length > 0) {
217
+ this.addToPrecacheList(precacheEntries);
218
+ }
219
+ if (precacheOptions?.cleanupOutdatedCaches) {
220
+ cleanupOutdatedCaches(precacheOptions?.cacheName);
221
+ }
222
+ this.registerRoute(new PrecacheRoute(this, precacheOptions));
223
+ if (precacheOptions?.navigateFallback) {
224
+ this.registerRoute(new NavigationRoute(this.createHandlerBoundToUrl(precacheOptions?.navigateFallback), {
225
+ allowlist: precacheOptions?.navigateFallbackAllowlist,
226
+ denylist: precacheOptions?.navigateFallbackDenylist
227
+ }));
228
+ }
229
+ if (offlineAnalyticsConfig !== undefined) {
230
+ if (typeof offlineAnalyticsConfig === "boolean") {
231
+ offlineAnalyticsConfig && initializeGoogleAnalytics({
232
+ serwist: this
233
+ });
234
+ } else {
235
+ initializeGoogleAnalytics({
236
+ ...offlineAnalyticsConfig,
237
+ serwist: this
238
+ });
239
+ }
240
+ }
241
+ if (runtimeCaching !== undefined) {
242
+ if (fallbacks !== undefined) {
243
+ const fallbackPlugin = new PrecacheFallbackPlugin({
244
+ fallbackUrls: fallbacks.entries,
245
+ serwist: this
246
+ });
247
+ runtimeCaching.forEach((cacheEntry)=>{
248
+ if (cacheEntry.handler instanceof Strategy && !cacheEntry.handler.plugins.some((plugin)=>"handlerDidError" in plugin)) {
249
+ cacheEntry.handler.plugins.push(fallbackPlugin);
250
+ }
251
+ });
252
+ }
253
+ for (const entry of runtimeCaching){
254
+ this.registerCapture(entry.matcher, entry.handler, entry.method);
255
+ }
256
+ }
257
+ if (disableDevLogs$1) disableDevLogs();
258
+ }
259
+ get precacheStrategy() {
260
+ return this._precacheStrategy;
261
+ }
262
+ get routes() {
263
+ return this._routes;
264
+ }
265
+ addEventListeners() {
266
+ self.addEventListener("install", this.handleInstall);
267
+ self.addEventListener("activate", this.handleActivate);
268
+ self.addEventListener("fetch", this.handleFetch);
269
+ self.addEventListener("message", this.handleCache);
270
+ }
271
+ addToPrecacheList(entries) {
272
+ if (process.env.NODE_ENV !== "production") {
273
+ finalAssertExports.isArray(entries, {
274
+ moduleName: "serwist",
275
+ className: "Serwist",
276
+ funcName: "addToCacheList",
277
+ paramName: "entries"
278
+ });
279
+ }
280
+ const urlsToWarnAbout = [];
281
+ for (const entry of entries){
282
+ if (typeof entry === "string") {
283
+ urlsToWarnAbout.push(entry);
284
+ } else if (entry && !entry.integrity && entry.revision === undefined) {
285
+ urlsToWarnAbout.push(entry.url);
286
+ }
287
+ const { cacheKey, url } = createCacheKey(entry);
288
+ const cacheMode = typeof entry !== "string" && entry.revision ? "reload" : "default";
289
+ if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) {
290
+ throw new SerwistError("add-to-cache-list-conflicting-entries", {
291
+ firstEntry: this._urlsToCacheKeys.get(url),
292
+ secondEntry: cacheKey
293
+ });
294
+ }
295
+ if (typeof entry !== "string" && entry.integrity) {
296
+ if (this._cacheKeysToIntegrities.has(cacheKey) && this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity) {
297
+ throw new SerwistError("add-to-cache-list-conflicting-integrities", {
298
+ url
299
+ });
300
+ }
301
+ this._cacheKeysToIntegrities.set(cacheKey, entry.integrity);
302
+ }
303
+ this._urlsToCacheKeys.set(url, cacheKey);
304
+ this._urlsToCacheModes.set(url, cacheMode);
305
+ if (urlsToWarnAbout.length > 0) {
306
+ const warningMessage = `Serwist is precaching URLs without revision info: ${urlsToWarnAbout.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;
307
+ if (process.env.NODE_ENV === "production") {
308
+ console.warn(warningMessage);
309
+ } else {
310
+ logger.warn(warningMessage);
311
+ }
312
+ }
313
+ }
314
+ }
315
+ handleInstall(event) {
316
+ return waitUntil(event, async ()=>{
317
+ const installReportPlugin = new PrecacheInstallReportPlugin();
318
+ this.precacheStrategy.plugins.push(installReportPlugin);
319
+ await parallel(this._concurrentPrecaching, Array.from(this._urlsToCacheKeys.entries()), async ([url, cacheKey])=>{
320
+ const integrity = this._cacheKeysToIntegrities.get(cacheKey);
321
+ const cacheMode = this._urlsToCacheModes.get(url);
322
+ const request = new Request(url, {
323
+ integrity,
324
+ cache: cacheMode,
325
+ credentials: "same-origin"
326
+ });
327
+ await Promise.all(this.precacheStrategy.handleAll({
328
+ event,
329
+ request,
330
+ url: new URL(request.url),
331
+ params: {
332
+ cacheKey
333
+ }
334
+ }));
335
+ });
336
+ const { updatedURLs, notUpdatedURLs } = installReportPlugin;
337
+ if (process.env.NODE_ENV !== "production") {
338
+ printInstallDetails(updatedURLs, notUpdatedURLs);
339
+ }
340
+ return {
341
+ updatedURLs,
342
+ notUpdatedURLs
343
+ };
344
+ });
345
+ }
346
+ handleActivate(event) {
347
+ return waitUntil(event, async ()=>{
348
+ const cache = await self.caches.open(this.precacheStrategy.cacheName);
349
+ const currentlyCachedRequests = await cache.keys();
350
+ const expectedCacheKeys = new Set(this._urlsToCacheKeys.values());
351
+ const deletedCacheRequests = [];
352
+ for (const request of currentlyCachedRequests){
353
+ if (!expectedCacheKeys.has(request.url)) {
354
+ await cache.delete(request);
355
+ deletedCacheRequests.push(request.url);
356
+ }
357
+ }
358
+ if (process.env.NODE_ENV !== "production") {
359
+ printCleanupDetails(deletedCacheRequests);
360
+ }
361
+ return {
362
+ deletedCacheRequests
363
+ };
364
+ });
365
+ }
366
+ handleFetch(event) {
367
+ const { request } = event;
368
+ const responsePromise = this.handleRequest({
369
+ request,
370
+ event
371
+ });
372
+ if (responsePromise) {
373
+ event.respondWith(responsePromise);
374
+ }
375
+ }
376
+ handleCache(event) {
377
+ if (event.data && event.data.type === "CACHE_URLS") {
378
+ const { payload } = event.data;
379
+ if (process.env.NODE_ENV !== "production") {
380
+ logger.debug("Caching URLs from the window", payload.urlsToCache);
381
+ }
382
+ const requestPromises = Promise.all(payload.urlsToCache.map((entry)=>{
383
+ let request;
384
+ if (typeof entry === "string") {
385
+ request = new Request(entry);
386
+ } else {
387
+ request = new Request(...entry);
388
+ }
389
+ return this.handleRequest({
390
+ request,
391
+ event
392
+ });
393
+ }));
394
+ event.waitUntil(requestPromises);
395
+ if (event.ports?.[0]) {
396
+ void requestPromises.then(()=>event.ports[0].postMessage(true));
397
+ }
398
+ }
399
+ }
400
+ setDefaultHandler(handler, method = defaultMethod) {
401
+ this._defaultHandlerMap.set(method, normalizeHandler(handler));
402
+ }
403
+ setCatchHandler(handler) {
404
+ this._catchHandler = normalizeHandler(handler);
405
+ }
406
+ registerCapture(capture, handler, method) {
407
+ const route = parseRoute(capture, handler, method);
408
+ this.registerRoute(route);
409
+ return route;
410
+ }
411
+ registerRoute(route) {
412
+ if (process.env.NODE_ENV !== "production") {
413
+ finalAssertExports.isType(route, "object", {
414
+ moduleName: "serwist",
415
+ className: "Serwist",
416
+ funcName: "registerRoute",
417
+ paramName: "route"
418
+ });
419
+ finalAssertExports.hasMethod(route, "match", {
420
+ moduleName: "serwist",
421
+ className: "Serwist",
422
+ funcName: "registerRoute",
423
+ paramName: "route"
424
+ });
425
+ finalAssertExports.isType(route.handler, "object", {
426
+ moduleName: "serwist",
427
+ className: "Serwist",
428
+ funcName: "registerRoute",
429
+ paramName: "route"
430
+ });
431
+ finalAssertExports.hasMethod(route.handler, "handle", {
432
+ moduleName: "serwist",
433
+ className: "Serwist",
434
+ funcName: "registerRoute",
435
+ paramName: "route.handler"
436
+ });
437
+ finalAssertExports.isType(route.method, "string", {
438
+ moduleName: "serwist",
439
+ className: "Serwist",
440
+ funcName: "registerRoute",
441
+ paramName: "route.method"
442
+ });
443
+ }
444
+ if (!this._routes.has(route.method)) {
445
+ this._routes.set(route.method, []);
446
+ }
447
+ this._routes.get(route.method).push(route);
448
+ }
449
+ unregisterRoute(route) {
450
+ if (!this._routes.has(route.method)) {
451
+ throw new SerwistError("unregister-route-but-not-found-with-method", {
452
+ method: route.method
453
+ });
454
+ }
455
+ const routeIndex = this._routes.get(route.method).indexOf(route);
456
+ if (routeIndex > -1) {
457
+ this._routes.get(route.method).splice(routeIndex, 1);
458
+ } else {
459
+ throw new SerwistError("unregister-route-route-not-registered");
460
+ }
461
+ }
462
+ getUrlsToPrecacheKeys() {
463
+ return this._urlsToCacheKeys;
464
+ }
465
+ getPrecachedUrls() {
466
+ return [
467
+ ...this._urlsToCacheKeys.keys()
468
+ ];
469
+ }
470
+ getPrecacheKeyForUrl(url) {
471
+ const urlObject = new URL(url, location.href);
472
+ return this._urlsToCacheKeys.get(urlObject.href);
473
+ }
474
+ getIntegrityForPrecacheKey(cacheKey) {
475
+ return this._cacheKeysToIntegrities.get(cacheKey);
476
+ }
477
+ async matchPrecache(request) {
478
+ const url = request instanceof Request ? request.url : request;
479
+ const cacheKey = this.getPrecacheKeyForUrl(url);
480
+ if (cacheKey) {
481
+ const cache = await self.caches.open(this.precacheStrategy.cacheName);
482
+ return cache.match(cacheKey);
483
+ }
484
+ return undefined;
485
+ }
486
+ createHandlerBoundToUrl(url) {
487
+ const cacheKey = this.getPrecacheKeyForUrl(url);
488
+ if (!cacheKey) {
489
+ throw new SerwistError("non-precached-url", {
490
+ url
491
+ });
492
+ }
493
+ return (options)=>{
494
+ options.request = new Request(url);
495
+ options.params = {
496
+ cacheKey,
497
+ ...options.params
498
+ };
499
+ return this.precacheStrategy.handle(options);
500
+ };
501
+ }
502
+ handleRequest({ request, event }) {
503
+ if (process.env.NODE_ENV !== "production") {
504
+ finalAssertExports.isInstance(request, Request, {
505
+ moduleName: "serwist",
506
+ className: "Serwist",
507
+ funcName: "handleRequest",
508
+ paramName: "options.request"
509
+ });
510
+ }
511
+ const url = new URL(request.url, location.href);
512
+ if (!url.protocol.startsWith("http")) {
513
+ if (process.env.NODE_ENV !== "production") {
514
+ logger.debug("Router only supports URLs that start with 'http'.");
515
+ }
516
+ return;
517
+ }
518
+ const sameOrigin = url.origin === location.origin;
519
+ const { params, route } = this.findMatchingRoute({
520
+ event,
521
+ request,
522
+ sameOrigin,
523
+ url
524
+ });
525
+ let handler = route?.handler;
526
+ const debugMessages = [];
527
+ if (process.env.NODE_ENV !== "production") {
528
+ if (handler) {
529
+ debugMessages.push([
530
+ "Found a route to handle this request:",
531
+ route
532
+ ]);
533
+ if (params) {
534
+ debugMessages.push([
535
+ `Passing the following params to the route's handler:`,
536
+ params
537
+ ]);
538
+ }
539
+ }
540
+ }
541
+ const method = request.method;
542
+ if (!handler && this._defaultHandlerMap.has(method)) {
543
+ if (process.env.NODE_ENV !== "production") {
544
+ debugMessages.push(`Failed to find a matching route. Falling back to the default handler for ${method}.`);
545
+ }
546
+ handler = this._defaultHandlerMap.get(method);
547
+ }
548
+ if (!handler) {
549
+ if (process.env.NODE_ENV !== "production") {
550
+ logger.debug(`No route found for: ${getFriendlyURL(url)}`);
551
+ }
552
+ return;
553
+ }
554
+ if (process.env.NODE_ENV !== "production") {
555
+ logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`);
556
+ for (const msg of debugMessages){
557
+ if (Array.isArray(msg)) {
558
+ logger.log(...msg);
559
+ } else {
560
+ logger.log(msg);
561
+ }
562
+ }
563
+ logger.groupEnd();
564
+ }
565
+ let responsePromise;
566
+ try {
567
+ responsePromise = handler.handle({
568
+ url,
569
+ request,
570
+ event,
571
+ params
572
+ });
573
+ } catch (err) {
574
+ responsePromise = Promise.reject(err);
575
+ }
576
+ const catchHandler = route?.catchHandler;
577
+ if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) {
578
+ responsePromise = responsePromise.catch(async (err)=>{
579
+ if (catchHandler) {
580
+ if (process.env.NODE_ENV !== "production") {
581
+ logger.groupCollapsed(`Error thrown when responding to: ${getFriendlyURL(url)}. Falling back to route's Catch Handler.`);
582
+ logger.error("Error thrown by:", route);
583
+ logger.error(err);
584
+ logger.groupEnd();
585
+ }
586
+ try {
587
+ return await catchHandler.handle({
588
+ url,
589
+ request,
590
+ event,
591
+ params
592
+ });
593
+ } catch (catchErr) {
594
+ if (catchErr instanceof Error) {
595
+ err = catchErr;
596
+ }
597
+ }
598
+ }
599
+ if (this._catchHandler) {
600
+ if (process.env.NODE_ENV !== "production") {
601
+ logger.groupCollapsed(`Error thrown when responding to: ${getFriendlyURL(url)}. Falling back to global Catch Handler.`);
602
+ logger.error("Error thrown by:", route);
603
+ logger.error(err);
604
+ logger.groupEnd();
605
+ }
606
+ return this._catchHandler.handle({
607
+ url,
608
+ request,
609
+ event
610
+ });
611
+ }
612
+ throw err;
613
+ });
614
+ }
615
+ return responsePromise;
616
+ }
617
+ findMatchingRoute({ url, sameOrigin, request, event }) {
618
+ const routes = this._routes.get(request.method) || [];
619
+ for (const route of routes){
620
+ let params;
621
+ const matchResult = route.match({
622
+ url,
623
+ sameOrigin,
624
+ request,
625
+ event
626
+ });
627
+ if (matchResult) {
628
+ if (process.env.NODE_ENV !== "production") {
629
+ if (matchResult instanceof Promise) {
630
+ logger.warn(`While routing ${getFriendlyURL(url)}, an async matchCallback function was used. Please convert the following route to use a synchronous matchCallback function:`, route);
631
+ }
632
+ }
633
+ params = matchResult;
634
+ if (Array.isArray(params) && params.length === 0) {
635
+ params = undefined;
636
+ } else if (matchResult.constructor === Object && Object.keys(matchResult).length === 0) {
637
+ params = undefined;
638
+ } else if (typeof matchResult === "boolean") {
639
+ params = undefined;
640
+ }
641
+ return {
642
+ route,
643
+ params
644
+ };
645
+ }
646
+ }
647
+ return {};
648
+ }
649
+ }
8
650
 
9
651
  const cacheNames = {
10
652
  get googleAnalytics () {
@@ -24,4 +666,818 @@ const cacheNames = {
24
666
  }
25
667
  };
26
668
 
27
- export { cacheNames };
669
+ const BROADCAST_UPDATE_MESSAGE_TYPE = "CACHE_UPDATED";
670
+ const BROADCAST_UPDATE_MESSAGE_META = "serwist-broadcast-update";
671
+ const BROADCAST_UPDATE_DEFAULT_NOTIFY = true;
672
+ const BROADCAST_UPDATE_DEFAULT_HEADERS = [
673
+ "content-length",
674
+ "etag",
675
+ "last-modified"
676
+ ];
677
+
678
+ const responsesAreSame = (firstResponse, secondResponse, headersToCheck)=>{
679
+ if (process.env.NODE_ENV !== "production") {
680
+ if (!(firstResponse instanceof Response && secondResponse instanceof Response)) {
681
+ throw new SerwistError("invalid-responses-are-same-args");
682
+ }
683
+ }
684
+ const atLeastOneHeaderAvailable = headersToCheck.some((header)=>{
685
+ return firstResponse.headers.has(header) && secondResponse.headers.has(header);
686
+ });
687
+ if (!atLeastOneHeaderAvailable) {
688
+ if (process.env.NODE_ENV !== "production") {
689
+ logger.warn("Unable to determine where the response has been updated because none of the headers that would be checked are present.");
690
+ logger.debug("Attempting to compare the following: ", firstResponse, secondResponse, headersToCheck);
691
+ }
692
+ return true;
693
+ }
694
+ return headersToCheck.every((header)=>{
695
+ const headerStateComparison = firstResponse.headers.has(header) === secondResponse.headers.has(header);
696
+ const headerValueComparison = firstResponse.headers.get(header) === secondResponse.headers.get(header);
697
+ return headerStateComparison && headerValueComparison;
698
+ });
699
+ };
700
+
701
+ const isSafari = typeof navigator !== "undefined" && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
702
+ const defaultPayloadGenerator = (data)=>{
703
+ return {
704
+ cacheName: data.cacheName,
705
+ updatedURL: data.request.url
706
+ };
707
+ };
708
+ class BroadcastCacheUpdate {
709
+ _headersToCheck;
710
+ _generatePayload;
711
+ _notifyAllClients;
712
+ constructor({ generatePayload, headersToCheck, notifyAllClients } = {}){
713
+ this._headersToCheck = headersToCheck || BROADCAST_UPDATE_DEFAULT_HEADERS;
714
+ this._generatePayload = generatePayload || defaultPayloadGenerator;
715
+ this._notifyAllClients = notifyAllClients ?? BROADCAST_UPDATE_DEFAULT_NOTIFY;
716
+ }
717
+ async notifyIfUpdated(options) {
718
+ if (process.env.NODE_ENV !== "production") {
719
+ finalAssertExports.isType(options.cacheName, "string", {
720
+ moduleName: "serwist",
721
+ className: "BroadcastCacheUpdate",
722
+ funcName: "notifyIfUpdated",
723
+ paramName: "cacheName"
724
+ });
725
+ finalAssertExports.isInstance(options.newResponse, Response, {
726
+ moduleName: "serwist",
727
+ className: "BroadcastCacheUpdate",
728
+ funcName: "notifyIfUpdated",
729
+ paramName: "newResponse"
730
+ });
731
+ finalAssertExports.isInstance(options.request, Request, {
732
+ moduleName: "serwist",
733
+ className: "BroadcastCacheUpdate",
734
+ funcName: "notifyIfUpdated",
735
+ paramName: "request"
736
+ });
737
+ }
738
+ if (!options.oldResponse) {
739
+ return;
740
+ }
741
+ if (!responsesAreSame(options.oldResponse, options.newResponse, this._headersToCheck)) {
742
+ if (process.env.NODE_ENV !== "production") {
743
+ logger.log("Newer response found (and cached) for:", options.request.url);
744
+ }
745
+ const messageData = {
746
+ type: BROADCAST_UPDATE_MESSAGE_TYPE,
747
+ meta: BROADCAST_UPDATE_MESSAGE_META,
748
+ payload: this._generatePayload(options)
749
+ };
750
+ if (options.request.mode === "navigate") {
751
+ let resultingClientId;
752
+ if (options.event instanceof FetchEvent) {
753
+ resultingClientId = options.event.resultingClientId;
754
+ }
755
+ const resultingWin = await resultingClientExists(resultingClientId);
756
+ if (!resultingWin || isSafari) {
757
+ await timeout(3500);
758
+ }
759
+ }
760
+ if (this._notifyAllClients) {
761
+ const windows = await self.clients.matchAll({
762
+ type: "window"
763
+ });
764
+ for (const win of windows){
765
+ win.postMessage(messageData);
766
+ }
767
+ } else {
768
+ if (options.event instanceof FetchEvent) {
769
+ const client = await self.clients.get(options.event.clientId);
770
+ client?.postMessage(messageData);
771
+ }
772
+ }
773
+ }
774
+ }
775
+ }
776
+
777
+ class BroadcastUpdatePlugin {
778
+ _broadcastUpdate;
779
+ constructor(options){
780
+ this._broadcastUpdate = new BroadcastCacheUpdate(options);
781
+ }
782
+ cacheDidUpdate(options) {
783
+ void this._broadcastUpdate.notifyIfUpdated(options);
784
+ }
785
+ }
786
+
787
+ class CacheableResponse {
788
+ _statuses;
789
+ _headers;
790
+ constructor(config = {}){
791
+ if (process.env.NODE_ENV !== "production") {
792
+ if (!(config.statuses || config.headers)) {
793
+ throw new SerwistError("statuses-or-headers-required", {
794
+ moduleName: "serwist",
795
+ className: "CacheableResponse",
796
+ funcName: "constructor"
797
+ });
798
+ }
799
+ if (config.statuses) {
800
+ finalAssertExports.isArray(config.statuses, {
801
+ moduleName: "serwist",
802
+ className: "CacheableResponse",
803
+ funcName: "constructor",
804
+ paramName: "config.statuses"
805
+ });
806
+ }
807
+ if (config.headers) {
808
+ finalAssertExports.isType(config.headers, "object", {
809
+ moduleName: "serwist",
810
+ className: "CacheableResponse",
811
+ funcName: "constructor",
812
+ paramName: "config.headers"
813
+ });
814
+ }
815
+ }
816
+ this._statuses = config.statuses;
817
+ if (config.headers) {
818
+ this._headers = new Headers(config.headers);
819
+ }
820
+ }
821
+ isResponseCacheable(response) {
822
+ if (process.env.NODE_ENV !== "production") {
823
+ finalAssertExports.isInstance(response, Response, {
824
+ moduleName: "serwist",
825
+ className: "CacheableResponse",
826
+ funcName: "isResponseCacheable",
827
+ paramName: "response"
828
+ });
829
+ }
830
+ let cacheable = true;
831
+ if (this._statuses) {
832
+ cacheable = this._statuses.includes(response.status);
833
+ }
834
+ if (this._headers && cacheable) {
835
+ for (const [headerName, headerValue] of this._headers.entries()){
836
+ if (response.headers.get(headerName) !== headerValue) {
837
+ cacheable = false;
838
+ break;
839
+ }
840
+ }
841
+ }
842
+ if (process.env.NODE_ENV !== "production") {
843
+ if (!cacheable) {
844
+ logger.groupCollapsed(`The request for '${getFriendlyURL(response.url)}' returned a response that does not meet the criteria for being cached.`);
845
+ logger.groupCollapsed("View cacheability criteria here.");
846
+ logger.log(`Cacheable statuses: ${JSON.stringify(this._statuses)}`);
847
+ logger.log(`Cacheable headers: ${JSON.stringify(this._headers, null, 2)}`);
848
+ logger.groupEnd();
849
+ const logFriendlyHeaders = {};
850
+ response.headers.forEach((value, key)=>{
851
+ logFriendlyHeaders[key] = value;
852
+ });
853
+ logger.groupCollapsed("View response status and headers here.");
854
+ logger.log(`Response status: ${response.status}`);
855
+ logger.log(`Response headers: ${JSON.stringify(logFriendlyHeaders, null, 2)}`);
856
+ logger.groupEnd();
857
+ logger.groupCollapsed("View full response details here.");
858
+ logger.log(response.headers);
859
+ logger.log(response);
860
+ logger.groupEnd();
861
+ logger.groupEnd();
862
+ }
863
+ }
864
+ return cacheable;
865
+ }
866
+ }
867
+
868
+ class CacheableResponsePlugin {
869
+ _cacheableResponse;
870
+ constructor(config){
871
+ this._cacheableResponse = new CacheableResponse(config);
872
+ }
873
+ cacheWillUpdate = async ({ response })=>{
874
+ if (this._cacheableResponse.isResponseCacheable(response)) {
875
+ return response;
876
+ }
877
+ return null;
878
+ };
879
+ }
880
+
881
+ const DB_NAME = "serwist-expiration";
882
+ const CACHE_OBJECT_STORE = "cache-entries";
883
+ const normalizeURL = (unNormalizedUrl)=>{
884
+ const url = new URL(unNormalizedUrl, location.href);
885
+ url.hash = "";
886
+ return url.href;
887
+ };
888
+ class CacheTimestampsModel {
889
+ _cacheName;
890
+ _db = null;
891
+ constructor(cacheName){
892
+ this._cacheName = cacheName;
893
+ }
894
+ _getId(url) {
895
+ return `${this._cacheName}|${normalizeURL(url)}`;
896
+ }
897
+ _upgradeDb(db) {
898
+ const objStore = db.createObjectStore(CACHE_OBJECT_STORE, {
899
+ keyPath: "id"
900
+ });
901
+ objStore.createIndex("cacheName", "cacheName", {
902
+ unique: false
903
+ });
904
+ objStore.createIndex("timestamp", "timestamp", {
905
+ unique: false
906
+ });
907
+ }
908
+ _upgradeDbAndDeleteOldDbs(db) {
909
+ this._upgradeDb(db);
910
+ if (this._cacheName) {
911
+ void deleteDB(this._cacheName);
912
+ }
913
+ }
914
+ async setTimestamp(url, timestamp) {
915
+ url = normalizeURL(url);
916
+ const entry = {
917
+ id: this._getId(url),
918
+ cacheName: this._cacheName,
919
+ url,
920
+ timestamp
921
+ };
922
+ const db = await this.getDb();
923
+ const tx = db.transaction(CACHE_OBJECT_STORE, "readwrite", {
924
+ durability: "relaxed"
925
+ });
926
+ await tx.store.put(entry);
927
+ await tx.done;
928
+ }
929
+ async getTimestamp(url) {
930
+ const db = await this.getDb();
931
+ const entry = await db.get(CACHE_OBJECT_STORE, this._getId(url));
932
+ return entry?.timestamp;
933
+ }
934
+ async expireEntries(minTimestamp, maxCount) {
935
+ const db = await this.getDb();
936
+ let cursor = await db.transaction(CACHE_OBJECT_STORE, "readwrite").store.index("timestamp").openCursor(null, "prev");
937
+ const urlsDeleted = [];
938
+ let entriesNotDeletedCount = 0;
939
+ while(cursor){
940
+ const result = cursor.value;
941
+ if (result.cacheName === this._cacheName) {
942
+ if (minTimestamp && result.timestamp < minTimestamp || maxCount && entriesNotDeletedCount >= maxCount) {
943
+ cursor.delete();
944
+ urlsDeleted.push(result.url);
945
+ } else {
946
+ entriesNotDeletedCount++;
947
+ }
948
+ }
949
+ cursor = await cursor.continue();
950
+ }
951
+ return urlsDeleted;
952
+ }
953
+ async getDb() {
954
+ if (!this._db) {
955
+ this._db = await openDB(DB_NAME, 1, {
956
+ upgrade: this._upgradeDbAndDeleteOldDbs.bind(this)
957
+ });
958
+ }
959
+ return this._db;
960
+ }
961
+ }
962
+
963
+ class CacheExpiration {
964
+ _isRunning = false;
965
+ _rerunRequested = false;
966
+ _maxEntries;
967
+ _maxAgeSeconds;
968
+ _matchOptions;
969
+ _cacheName;
970
+ _timestampModel;
971
+ constructor(cacheName, config = {}){
972
+ if (process.env.NODE_ENV !== "production") {
973
+ finalAssertExports.isType(cacheName, "string", {
974
+ moduleName: "serwist",
975
+ className: "CacheExpiration",
976
+ funcName: "constructor",
977
+ paramName: "cacheName"
978
+ });
979
+ if (!(config.maxEntries || config.maxAgeSeconds)) {
980
+ throw new SerwistError("max-entries-or-age-required", {
981
+ moduleName: "serwist",
982
+ className: "CacheExpiration",
983
+ funcName: "constructor"
984
+ });
985
+ }
986
+ if (config.maxEntries) {
987
+ finalAssertExports.isType(config.maxEntries, "number", {
988
+ moduleName: "serwist",
989
+ className: "CacheExpiration",
990
+ funcName: "constructor",
991
+ paramName: "config.maxEntries"
992
+ });
993
+ }
994
+ if (config.maxAgeSeconds) {
995
+ finalAssertExports.isType(config.maxAgeSeconds, "number", {
996
+ moduleName: "serwist",
997
+ className: "CacheExpiration",
998
+ funcName: "constructor",
999
+ paramName: "config.maxAgeSeconds"
1000
+ });
1001
+ }
1002
+ }
1003
+ this._maxEntries = config.maxEntries;
1004
+ this._maxAgeSeconds = config.maxAgeSeconds;
1005
+ this._matchOptions = config.matchOptions;
1006
+ this._cacheName = cacheName;
1007
+ this._timestampModel = new CacheTimestampsModel(cacheName);
1008
+ }
1009
+ async expireEntries() {
1010
+ if (this._isRunning) {
1011
+ this._rerunRequested = true;
1012
+ return;
1013
+ }
1014
+ this._isRunning = true;
1015
+ const minTimestamp = this._maxAgeSeconds ? Date.now() - this._maxAgeSeconds * 1000 : 0;
1016
+ const urlsExpired = await this._timestampModel.expireEntries(minTimestamp, this._maxEntries);
1017
+ const cache = await self.caches.open(this._cacheName);
1018
+ for (const url of urlsExpired){
1019
+ await cache.delete(url, this._matchOptions);
1020
+ }
1021
+ if (process.env.NODE_ENV !== "production") {
1022
+ if (urlsExpired.length > 0) {
1023
+ logger.groupCollapsed(`Expired ${urlsExpired.length} ` + `${urlsExpired.length === 1 ? "entry" : "entries"} and removed ` + `${urlsExpired.length === 1 ? "it" : "them"} from the ` + `'${this._cacheName}' cache.`);
1024
+ logger.log(`Expired the following ${urlsExpired.length === 1 ? "URL" : "URLs"}:`);
1025
+ for (const url of urlsExpired){
1026
+ logger.log(` ${url}`);
1027
+ }
1028
+ logger.groupEnd();
1029
+ } else {
1030
+ logger.debug("Cache expiration ran and found no entries to remove.");
1031
+ }
1032
+ }
1033
+ this._isRunning = false;
1034
+ if (this._rerunRequested) {
1035
+ this._rerunRequested = false;
1036
+ void this.expireEntries();
1037
+ }
1038
+ }
1039
+ async updateTimestamp(url) {
1040
+ if (process.env.NODE_ENV !== "production") {
1041
+ finalAssertExports.isType(url, "string", {
1042
+ moduleName: "serwist",
1043
+ className: "CacheExpiration",
1044
+ funcName: "updateTimestamp",
1045
+ paramName: "url"
1046
+ });
1047
+ }
1048
+ await this._timestampModel.setTimestamp(url, Date.now());
1049
+ }
1050
+ async isURLExpired(url) {
1051
+ if (!this._maxAgeSeconds) {
1052
+ if (process.env.NODE_ENV !== "production") {
1053
+ throw new SerwistError("expired-test-without-max-age", {
1054
+ methodName: "isURLExpired",
1055
+ paramName: "maxAgeSeconds"
1056
+ });
1057
+ }
1058
+ return false;
1059
+ }
1060
+ const timestamp = await this._timestampModel.getTimestamp(url);
1061
+ const expireOlderThan = Date.now() - this._maxAgeSeconds * 1000;
1062
+ return timestamp !== undefined ? timestamp < expireOlderThan : true;
1063
+ }
1064
+ async delete() {
1065
+ this._rerunRequested = false;
1066
+ await this._timestampModel.expireEntries(Number.POSITIVE_INFINITY);
1067
+ }
1068
+ }
1069
+
1070
+ const registerQuotaErrorCallback = (callback)=>{
1071
+ if (process.env.NODE_ENV !== "production") {
1072
+ finalAssertExports.isType(callback, "function", {
1073
+ moduleName: "@serwist/core",
1074
+ funcName: "register",
1075
+ paramName: "callback"
1076
+ });
1077
+ }
1078
+ quotaErrorCallbacks.add(callback);
1079
+ if (process.env.NODE_ENV !== "production") {
1080
+ logger.log("Registered a callback to respond to quota errors.", callback);
1081
+ }
1082
+ };
1083
+
1084
+ class ExpirationPlugin {
1085
+ _config;
1086
+ _cacheExpirations;
1087
+ constructor(config = {}){
1088
+ if (process.env.NODE_ENV !== "production") {
1089
+ if (!(config.maxEntries || config.maxAgeSeconds)) {
1090
+ throw new SerwistError("max-entries-or-age-required", {
1091
+ moduleName: "serwist",
1092
+ className: "ExpirationPlugin",
1093
+ funcName: "constructor"
1094
+ });
1095
+ }
1096
+ if (config.maxEntries) {
1097
+ finalAssertExports.isType(config.maxEntries, "number", {
1098
+ moduleName: "serwist",
1099
+ className: "ExpirationPlugin",
1100
+ funcName: "constructor",
1101
+ paramName: "config.maxEntries"
1102
+ });
1103
+ }
1104
+ if (config.maxAgeSeconds) {
1105
+ finalAssertExports.isType(config.maxAgeSeconds, "number", {
1106
+ moduleName: "serwist",
1107
+ className: "ExpirationPlugin",
1108
+ funcName: "constructor",
1109
+ paramName: "config.maxAgeSeconds"
1110
+ });
1111
+ }
1112
+ if (config.maxAgeFrom) {
1113
+ finalAssertExports.isType(config.maxAgeFrom, "string", {
1114
+ moduleName: "serwist",
1115
+ className: "ExpirationPlugin",
1116
+ funcName: "constructor",
1117
+ paramName: "config.maxAgeFrom"
1118
+ });
1119
+ }
1120
+ }
1121
+ this._config = config;
1122
+ this._cacheExpirations = new Map();
1123
+ if (!this._config.maxAgeFrom) {
1124
+ this._config.maxAgeFrom = "last-fetched";
1125
+ }
1126
+ if (this._config.purgeOnQuotaError) {
1127
+ registerQuotaErrorCallback(()=>this.deleteCacheAndMetadata());
1128
+ }
1129
+ }
1130
+ _getCacheExpiration(cacheName) {
1131
+ if (cacheName === cacheNames$1.getRuntimeName()) {
1132
+ throw new SerwistError("expire-custom-caches-only");
1133
+ }
1134
+ let cacheExpiration = this._cacheExpirations.get(cacheName);
1135
+ if (!cacheExpiration) {
1136
+ cacheExpiration = new CacheExpiration(cacheName, this._config);
1137
+ this._cacheExpirations.set(cacheName, cacheExpiration);
1138
+ }
1139
+ return cacheExpiration;
1140
+ }
1141
+ cachedResponseWillBeUsed({ event, cacheName, request, cachedResponse }) {
1142
+ if (!cachedResponse) {
1143
+ return null;
1144
+ }
1145
+ const isFresh = this._isResponseDateFresh(cachedResponse);
1146
+ const cacheExpiration = this._getCacheExpiration(cacheName);
1147
+ const isMaxAgeFromLastUsed = this._config.maxAgeFrom === "last-used";
1148
+ const done = (async ()=>{
1149
+ if (isMaxAgeFromLastUsed) {
1150
+ await cacheExpiration.updateTimestamp(request.url);
1151
+ }
1152
+ await cacheExpiration.expireEntries();
1153
+ })();
1154
+ try {
1155
+ event.waitUntil(done);
1156
+ } catch (error) {
1157
+ if (process.env.NODE_ENV !== "production") {
1158
+ if (event instanceof FetchEvent) {
1159
+ logger.warn(`Unable to ensure service worker stays alive when updating cache entry for '${getFriendlyURL(event.request.url)}'.`);
1160
+ }
1161
+ }
1162
+ }
1163
+ return isFresh ? cachedResponse : null;
1164
+ }
1165
+ _isResponseDateFresh(cachedResponse) {
1166
+ const isMaxAgeFromLastUsed = this._config.maxAgeFrom === "last-used";
1167
+ if (isMaxAgeFromLastUsed) {
1168
+ return true;
1169
+ }
1170
+ const now = Date.now();
1171
+ if (!this._config.maxAgeSeconds) {
1172
+ return true;
1173
+ }
1174
+ const dateHeaderTimestamp = this._getDateHeaderTimestamp(cachedResponse);
1175
+ if (dateHeaderTimestamp === null) {
1176
+ return true;
1177
+ }
1178
+ return dateHeaderTimestamp >= now - this._config.maxAgeSeconds * 1000;
1179
+ }
1180
+ _getDateHeaderTimestamp(cachedResponse) {
1181
+ if (!cachedResponse.headers.has("date")) {
1182
+ return null;
1183
+ }
1184
+ const dateHeader = cachedResponse.headers.get("date");
1185
+ const parsedDate = new Date(dateHeader);
1186
+ const headerTime = parsedDate.getTime();
1187
+ if (Number.isNaN(headerTime)) {
1188
+ return null;
1189
+ }
1190
+ return headerTime;
1191
+ }
1192
+ async cacheDidUpdate({ cacheName, request }) {
1193
+ if (process.env.NODE_ENV !== "production") {
1194
+ finalAssertExports.isType(cacheName, "string", {
1195
+ moduleName: "serwist",
1196
+ className: "Plugin",
1197
+ funcName: "cacheDidUpdate",
1198
+ paramName: "cacheName"
1199
+ });
1200
+ finalAssertExports.isInstance(request, Request, {
1201
+ moduleName: "serwist",
1202
+ className: "Plugin",
1203
+ funcName: "cacheDidUpdate",
1204
+ paramName: "request"
1205
+ });
1206
+ }
1207
+ const cacheExpiration = this._getCacheExpiration(cacheName);
1208
+ await cacheExpiration.updateTimestamp(request.url);
1209
+ await cacheExpiration.expireEntries();
1210
+ }
1211
+ async deleteCacheAndMetadata() {
1212
+ for (const [cacheName, cacheExpiration] of this._cacheExpirations){
1213
+ await self.caches.delete(cacheName);
1214
+ await cacheExpiration.delete();
1215
+ }
1216
+ this._cacheExpirations = new Map();
1217
+ }
1218
+ }
1219
+
1220
+ const calculateEffectiveBoundaries = (blob, start, end)=>{
1221
+ if (process.env.NODE_ENV !== "production") {
1222
+ finalAssertExports.isInstance(blob, Blob, {
1223
+ moduleName: "@serwist/range-requests",
1224
+ funcName: "calculateEffectiveBoundaries",
1225
+ paramName: "blob"
1226
+ });
1227
+ }
1228
+ const blobSize = blob.size;
1229
+ if (end && end > blobSize || start && start < 0) {
1230
+ throw new SerwistError("range-not-satisfiable", {
1231
+ size: blobSize,
1232
+ end,
1233
+ start
1234
+ });
1235
+ }
1236
+ let effectiveStart;
1237
+ let effectiveEnd;
1238
+ if (start !== undefined && end !== undefined) {
1239
+ effectiveStart = start;
1240
+ effectiveEnd = end + 1;
1241
+ } else if (start !== undefined && end === undefined) {
1242
+ effectiveStart = start;
1243
+ effectiveEnd = blobSize;
1244
+ } else if (end !== undefined && start === undefined) {
1245
+ effectiveStart = blobSize - end;
1246
+ effectiveEnd = blobSize;
1247
+ }
1248
+ return {
1249
+ start: effectiveStart,
1250
+ end: effectiveEnd
1251
+ };
1252
+ };
1253
+
1254
+ const parseRangeHeader = (rangeHeader)=>{
1255
+ if (process.env.NODE_ENV !== "production") {
1256
+ finalAssertExports.isType(rangeHeader, "string", {
1257
+ moduleName: "@serwist/range-requests",
1258
+ funcName: "parseRangeHeader",
1259
+ paramName: "rangeHeader"
1260
+ });
1261
+ }
1262
+ const normalizedRangeHeader = rangeHeader.trim().toLowerCase();
1263
+ if (!normalizedRangeHeader.startsWith("bytes=")) {
1264
+ throw new SerwistError("unit-must-be-bytes", {
1265
+ normalizedRangeHeader
1266
+ });
1267
+ }
1268
+ if (normalizedRangeHeader.includes(",")) {
1269
+ throw new SerwistError("single-range-only", {
1270
+ normalizedRangeHeader
1271
+ });
1272
+ }
1273
+ const rangeParts = /(\d*)-(\d*)/.exec(normalizedRangeHeader);
1274
+ if (!rangeParts || !(rangeParts[1] || rangeParts[2])) {
1275
+ throw new SerwistError("invalid-range-values", {
1276
+ normalizedRangeHeader
1277
+ });
1278
+ }
1279
+ return {
1280
+ start: rangeParts[1] === "" ? undefined : Number(rangeParts[1]),
1281
+ end: rangeParts[2] === "" ? undefined : Number(rangeParts[2])
1282
+ };
1283
+ };
1284
+
1285
+ const createPartialResponse = async (request, originalResponse)=>{
1286
+ try {
1287
+ if (process.env.NODE_ENV !== "production") {
1288
+ finalAssertExports.isInstance(request, Request, {
1289
+ moduleName: "@serwist/range-requests",
1290
+ funcName: "createPartialResponse",
1291
+ paramName: "request"
1292
+ });
1293
+ finalAssertExports.isInstance(originalResponse, Response, {
1294
+ moduleName: "@serwist/range-requests",
1295
+ funcName: "createPartialResponse",
1296
+ paramName: "originalResponse"
1297
+ });
1298
+ }
1299
+ if (originalResponse.status === 206) {
1300
+ return originalResponse;
1301
+ }
1302
+ const rangeHeader = request.headers.get("range");
1303
+ if (!rangeHeader) {
1304
+ throw new SerwistError("no-range-header");
1305
+ }
1306
+ const boundaries = parseRangeHeader(rangeHeader);
1307
+ const originalBlob = await originalResponse.blob();
1308
+ const effectiveBoundaries = calculateEffectiveBoundaries(originalBlob, boundaries.start, boundaries.end);
1309
+ const slicedBlob = originalBlob.slice(effectiveBoundaries.start, effectiveBoundaries.end);
1310
+ const slicedBlobSize = slicedBlob.size;
1311
+ const slicedResponse = new Response(slicedBlob, {
1312
+ status: 206,
1313
+ statusText: "Partial Content",
1314
+ headers: originalResponse.headers
1315
+ });
1316
+ slicedResponse.headers.set("Content-Length", String(slicedBlobSize));
1317
+ slicedResponse.headers.set("Content-Range", `bytes ${effectiveBoundaries.start}-${effectiveBoundaries.end - 1}/` + `${originalBlob.size}`);
1318
+ return slicedResponse;
1319
+ } catch (error) {
1320
+ if (process.env.NODE_ENV !== "production") {
1321
+ logger.warn("Unable to construct a partial response; returning a " + "416 Range Not Satisfiable response instead.");
1322
+ logger.groupCollapsed("View details here.");
1323
+ logger.log(error);
1324
+ logger.log(request);
1325
+ logger.log(originalResponse);
1326
+ logger.groupEnd();
1327
+ }
1328
+ return new Response("", {
1329
+ status: 416,
1330
+ statusText: "Range Not Satisfiable"
1331
+ });
1332
+ }
1333
+ };
1334
+
1335
+ class RangeRequestsPlugin {
1336
+ cachedResponseWillBeUsed = async ({ request, cachedResponse })=>{
1337
+ if (cachedResponse && request.headers.has("range")) {
1338
+ return await createPartialResponse(request, cachedResponse);
1339
+ }
1340
+ return cachedResponse;
1341
+ };
1342
+ }
1343
+
1344
+ class CacheFirst extends Strategy {
1345
+ async _handle(request, handler) {
1346
+ const logs = [];
1347
+ if (process.env.NODE_ENV !== "production") {
1348
+ finalAssertExports.isInstance(request, Request, {
1349
+ moduleName: "serwist",
1350
+ className: this.constructor.name,
1351
+ funcName: "makeRequest",
1352
+ paramName: "request"
1353
+ });
1354
+ }
1355
+ let response = await handler.cacheMatch(request);
1356
+ let error = undefined;
1357
+ if (!response) {
1358
+ if (process.env.NODE_ENV !== "production") {
1359
+ logs.push(`No response found in the '${this.cacheName}' cache. Will respond with a network request.`);
1360
+ }
1361
+ try {
1362
+ response = await handler.fetchAndCachePut(request);
1363
+ } catch (err) {
1364
+ if (err instanceof Error) {
1365
+ error = err;
1366
+ }
1367
+ }
1368
+ if (process.env.NODE_ENV !== "production") {
1369
+ if (response) {
1370
+ logs.push("Got response from network.");
1371
+ } else {
1372
+ logs.push("Unable to get a response from the network.");
1373
+ }
1374
+ }
1375
+ } else {
1376
+ if (process.env.NODE_ENV !== "production") {
1377
+ logs.push(`Found a cached response in the '${this.cacheName}' cache.`);
1378
+ }
1379
+ }
1380
+ if (process.env.NODE_ENV !== "production") {
1381
+ logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));
1382
+ for (const log of logs){
1383
+ logger.log(log);
1384
+ }
1385
+ messages.printFinalResponse(response);
1386
+ logger.groupEnd();
1387
+ }
1388
+ if (!response) {
1389
+ throw new SerwistError("no-response", {
1390
+ url: request.url,
1391
+ error
1392
+ });
1393
+ }
1394
+ return response;
1395
+ }
1396
+ }
1397
+
1398
+ class CacheOnly extends Strategy {
1399
+ async _handle(request, handler) {
1400
+ if (process.env.NODE_ENV !== "production") {
1401
+ finalAssertExports.isInstance(request, Request, {
1402
+ moduleName: "serwist",
1403
+ className: this.constructor.name,
1404
+ funcName: "makeRequest",
1405
+ paramName: "request"
1406
+ });
1407
+ }
1408
+ const response = await handler.cacheMatch(request);
1409
+ if (process.env.NODE_ENV !== "production") {
1410
+ logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));
1411
+ if (response) {
1412
+ logger.log(`Found a cached response in the '${this.cacheName}' cache.`);
1413
+ messages.printFinalResponse(response);
1414
+ } else {
1415
+ logger.log(`No response found in the '${this.cacheName}' cache.`);
1416
+ }
1417
+ logger.groupEnd();
1418
+ }
1419
+ if (!response) {
1420
+ throw new SerwistError("no-response", {
1421
+ url: request.url
1422
+ });
1423
+ }
1424
+ return response;
1425
+ }
1426
+ }
1427
+
1428
+ class StaleWhileRevalidate extends Strategy {
1429
+ constructor(options = {}){
1430
+ super(options);
1431
+ if (!this.plugins.some((p)=>"cacheWillUpdate" in p)) {
1432
+ this.plugins.unshift(cacheOkAndOpaquePlugin);
1433
+ }
1434
+ }
1435
+ async _handle(request, handler) {
1436
+ const logs = [];
1437
+ if (process.env.NODE_ENV !== "production") {
1438
+ finalAssertExports.isInstance(request, Request, {
1439
+ moduleName: "serwist",
1440
+ className: this.constructor.name,
1441
+ funcName: "handle",
1442
+ paramName: "request"
1443
+ });
1444
+ }
1445
+ const fetchAndCachePromise = handler.fetchAndCachePut(request).catch(()=>{});
1446
+ void handler.waitUntil(fetchAndCachePromise);
1447
+ let response = await handler.cacheMatch(request);
1448
+ let error = undefined;
1449
+ if (response) {
1450
+ if (process.env.NODE_ENV !== "production") {
1451
+ logs.push(`Found a cached response in the '${this.cacheName}' cache. Will update with the network response in the background.`);
1452
+ }
1453
+ } else {
1454
+ if (process.env.NODE_ENV !== "production") {
1455
+ logs.push(`No response found in the '${this.cacheName}' cache. Will wait for the network response.`);
1456
+ }
1457
+ try {
1458
+ response = await fetchAndCachePromise;
1459
+ } catch (err) {
1460
+ if (err instanceof Error) {
1461
+ error = err;
1462
+ }
1463
+ }
1464
+ }
1465
+ if (process.env.NODE_ENV !== "production") {
1466
+ logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));
1467
+ for (const log of logs){
1468
+ logger.log(log);
1469
+ }
1470
+ messages.printFinalResponse(response);
1471
+ logger.groupEnd();
1472
+ }
1473
+ if (!response) {
1474
+ throw new SerwistError("no-response", {
1475
+ url: request.url,
1476
+ error
1477
+ });
1478
+ }
1479
+ return response;
1480
+ }
1481
+ }
1482
+
1483
+ export { 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 };