serwist 9.0.0-preview.24

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