@swoff/cli 0.3.9 → 0.3.11

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 (216) hide show
  1. package/dist/__tests__/assemble-sw.test.js +8 -17
  2. package/dist/__tests__/assemble-sw.test.js.map +1 -1
  3. package/dist/__tests__/cli-integration.test.js +2 -2
  4. package/dist/__tests__/cli-integration.test.js.map +1 -1
  5. package/dist/__tests__/config-types.test.js +18 -8
  6. package/dist/__tests__/config-types.test.js.map +1 -1
  7. package/dist/__tests__/file-generators.test.js +3 -3
  8. package/dist/__tests__/file-generators.test.js.map +1 -1
  9. package/dist/__tests__/loader.test.js +5 -1
  10. package/dist/__tests__/loader.test.js.map +1 -1
  11. package/dist/__tests__/validator.test.js +6 -13
  12. package/dist/__tests__/validator.test.js.map +1 -1
  13. package/dist/index.js +41 -35
  14. package/dist/index.js.map +1 -1
  15. package/dist/lib/cli/help.js +13 -8
  16. package/dist/lib/cli/help.js.map +1 -1
  17. package/dist/lib/commands/add.js +38 -8
  18. package/dist/lib/commands/add.js.map +1 -1
  19. package/dist/lib/commands/assets.js +38 -0
  20. package/dist/lib/commands/assets.js.map +1 -0
  21. package/dist/lib/commands/clean.js +33 -17
  22. package/dist/lib/commands/clean.js.map +1 -1
  23. package/dist/lib/commands/generate-assets.js +44 -0
  24. package/dist/lib/commands/generate-assets.js.map +1 -0
  25. package/dist/lib/commands/generate-guide.js +22 -29
  26. package/dist/lib/commands/generate-guide.js.map +1 -1
  27. package/dist/lib/commands/generate.js +16 -9
  28. package/dist/lib/commands/generate.js.map +1 -1
  29. package/dist/lib/commands/info.js +36 -45
  30. package/dist/lib/commands/info.js.map +1 -1
  31. package/dist/lib/commands/init.js +25 -3
  32. package/dist/lib/commands/init.js.map +1 -1
  33. package/dist/lib/commands/validate.js +1 -1
  34. package/dist/lib/commands/validate.js.map +1 -1
  35. package/dist/lib/config/loader.js +25 -20
  36. package/dist/lib/config/loader.js.map +1 -1
  37. package/dist/lib/config/validator.js +20 -11
  38. package/dist/lib/config/validator.js.map +1 -1
  39. package/dist/lib/generators/asset-generator/dependency-resolver.js +76 -0
  40. package/dist/lib/generators/asset-generator/dependency-resolver.js.map +1 -0
  41. package/dist/lib/generators/asset-generator/generate.js +111 -0
  42. package/dist/lib/generators/asset-generator/generate.js.map +1 -0
  43. package/dist/lib/generators/asset-generator/guide.js +43 -0
  44. package/dist/lib/generators/asset-generator/guide.js.map +1 -0
  45. package/dist/lib/generators/asset-generator/html-patcher.js +65 -0
  46. package/dist/lib/generators/asset-generator/html-patcher.js.map +1 -0
  47. package/dist/lib/generators/asset-generator/ico-encoder.js +29 -0
  48. package/dist/lib/generators/asset-generator/ico-encoder.js.map +1 -0
  49. package/dist/lib/generators/asset-generator/manifest-patcher.js +23 -0
  50. package/dist/lib/generators/asset-generator/manifest-patcher.js.map +1 -0
  51. package/dist/lib/generators/asset-generator/maskable.js +15 -0
  52. package/dist/lib/generators/asset-generator/maskable.js.map +1 -0
  53. package/dist/lib/generators/asset-generator/rasterize.js +32 -0
  54. package/dist/lib/generators/asset-generator/rasterize.js.map +1 -0
  55. package/dist/lib/generators/asset-generator/sizes.js +25 -0
  56. package/dist/lib/generators/asset-generator/sizes.js.map +1 -0
  57. package/dist/lib/generators/file-generators/api-config.js +6 -0
  58. package/dist/lib/generators/file-generators/api-config.js.map +1 -0
  59. package/dist/lib/generators/file-generators/auth-state.js +2 -34
  60. package/dist/lib/generators/file-generators/auth-state.js.map +1 -1
  61. package/dist/lib/generators/file-generators/auth-store.js +2 -250
  62. package/dist/lib/generators/file-generators/auth-store.js.map +1 -1
  63. package/dist/lib/generators/file-generators/auth-user.js +3 -81
  64. package/dist/lib/generators/file-generators/auth-user.js.map +1 -1
  65. package/dist/lib/generators/file-generators/background-sync.js +2 -57
  66. package/dist/lib/generators/file-generators/background-sync.js.map +1 -1
  67. package/dist/lib/generators/file-generators/cache.js +2 -30
  68. package/dist/lib/generators/file-generators/cache.js.map +1 -1
  69. package/dist/lib/generators/file-generators/client-injector.js +2 -130
  70. package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
  71. package/dist/lib/generators/file-generators/fetch-state.js +6 -0
  72. package/dist/lib/generators/file-generators/fetch-state.js.map +1 -0
  73. package/dist/lib/generators/file-generators/fetch-wrapper.js +3 -295
  74. package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
  75. package/dist/lib/generators/file-generators/generate-framework-adapters.js +56 -0
  76. package/dist/lib/generators/file-generators/generate-framework-adapters.js.map +1 -0
  77. package/dist/lib/generators/file-generators/generate-hooks.js +4 -3
  78. package/dist/lib/generators/file-generators/generate-hooks.js.map +1 -1
  79. package/dist/lib/generators/file-generators/gql-wrapper.js +3 -132
  80. package/dist/lib/generators/file-generators/gql-wrapper.js.map +1 -1
  81. package/dist/lib/generators/file-generators/guide-generator.js +29 -1
  82. package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
  83. package/dist/lib/generators/file-generators/invalidation-tags.js +3 -258
  84. package/dist/lib/generators/file-generators/invalidation-tags.js.map +1 -1
  85. package/dist/lib/generators/file-generators/manifest.js +13 -3
  86. package/dist/lib/generators/file-generators/manifest.js.map +1 -1
  87. package/dist/lib/generators/file-generators/mutation-queue.js +3 -305
  88. package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
  89. package/dist/lib/generators/file-generators/mutation-state.js +2 -117
  90. package/dist/lib/generators/file-generators/mutation-state.js.map +1 -1
  91. package/dist/lib/generators/file-generators/push.js +6 -138
  92. package/dist/lib/generators/file-generators/push.js.map +1 -1
  93. package/dist/lib/generators/file-generators/pwa-install.js +11 -84
  94. package/dist/lib/generators/file-generators/pwa-install.js.map +1 -1
  95. package/dist/lib/generators/file-generators/reset.js +6 -0
  96. package/dist/lib/generators/file-generators/reset.js.map +1 -0
  97. package/dist/lib/generators/file-generators/server-push.js +3 -134
  98. package/dist/lib/generators/file-generators/server-push.js.map +1 -1
  99. package/dist/lib/generators/file-generators/sw-generator-build.js +4 -4
  100. package/dist/lib/generators/file-generators/sw-injector.js +9 -230
  101. package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
  102. package/dist/lib/generators/file-generators/type-definitions.js +2 -111
  103. package/dist/lib/generators/file-generators/type-definitions.js.map +1 -1
  104. package/dist/lib/generators/sw-generator.js +5 -5
  105. package/dist/lib/generators/sw-generator.js.map +1 -1
  106. package/dist/lib/generators/sw-sections/activate-handler.js +25 -3
  107. package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
  108. package/dist/lib/generators/sw-sections/assemble-sw.js +13 -12
  109. package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
  110. package/dist/lib/generators/sw-sections/background-sync-handler.js +14 -7
  111. package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -1
  112. package/dist/lib/generators/sw-sections/config-header.js +1 -1
  113. package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
  114. package/dist/lib/generators/sw-sections/fetch-handler.js +165 -104
  115. package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
  116. package/dist/lib/generators/sw-sections/glob-matcher-code.js.map +1 -0
  117. package/dist/lib/generators/sw-sections/server-push-handler.js +12 -0
  118. package/dist/lib/generators/sw-sections/server-push-handler.js.map +1 -1
  119. package/dist/lib/generators/sw-sections/tag-management.js +6 -4
  120. package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
  121. package/dist/lib/generators/swoff-files-generator.js +66 -35
  122. package/dist/lib/generators/swoff-files-generator.js.map +1 -1
  123. package/dist/lib/shared/config-types.js +89 -28
  124. package/dist/lib/shared/config-types.js.map +1 -1
  125. package/dist/runtime/api-config.js +18 -0
  126. package/dist/runtime/api-config.js.map +1 -0
  127. package/dist/runtime/auth-state.js +35 -0
  128. package/dist/runtime/auth-state.js.map +1 -0
  129. package/dist/runtime/auth-store.js +273 -0
  130. package/dist/runtime/auth-store.js.map +1 -0
  131. package/dist/runtime/auth-user.js +168 -0
  132. package/dist/runtime/auth-user.js.map +1 -0
  133. package/dist/runtime/background-sync.js +59 -0
  134. package/dist/runtime/background-sync.js.map +1 -0
  135. package/dist/runtime/cache.js +30 -0
  136. package/dist/runtime/cache.js.map +1 -0
  137. package/dist/runtime/client-injector.js +136 -0
  138. package/dist/runtime/client-injector.js.map +1 -0
  139. package/dist/runtime/fetch-state.js +42 -0
  140. package/dist/runtime/fetch-state.js.map +1 -0
  141. package/dist/runtime/fetch-wrapper.js +355 -0
  142. package/dist/runtime/fetch-wrapper.js.map +1 -0
  143. package/dist/runtime/gql-wrapper.js +135 -0
  144. package/dist/runtime/gql-wrapper.js.map +1 -0
  145. package/dist/runtime/invalidation-tags.js +260 -0
  146. package/dist/runtime/invalidation-tags.js.map +1 -0
  147. package/dist/runtime/mutation-queue.js +304 -0
  148. package/dist/runtime/mutation-queue.js.map +1 -0
  149. package/dist/runtime/mutation-state.js +117 -0
  150. package/dist/runtime/mutation-state.js.map +1 -0
  151. package/dist/runtime/push.js +138 -0
  152. package/dist/runtime/push.js.map +1 -0
  153. package/dist/runtime/pwa-index.js +11 -0
  154. package/dist/runtime/pwa-index.js.map +1 -0
  155. package/dist/runtime/pwa-injector.js +44 -0
  156. package/dist/runtime/pwa-injector.js.map +1 -0
  157. package/dist/runtime/pwa-install.js +83 -0
  158. package/dist/runtime/pwa-install.js.map +1 -0
  159. package/dist/runtime/pwa-prompt.js +54 -0
  160. package/dist/runtime/pwa-prompt.js.map +1 -0
  161. package/dist/runtime/reset.js +148 -0
  162. package/dist/runtime/reset.js.map +1 -0
  163. package/dist/runtime/server-push.js +148 -0
  164. package/dist/runtime/server-push.js.map +1 -0
  165. package/dist/runtime/sw-injector.js +236 -0
  166. package/dist/runtime/sw-injector.js.map +1 -0
  167. package/dist/runtime/type-definitions.js +138 -0
  168. package/dist/runtime/type-definitions.js.map +1 -0
  169. package/dist/runtime/utils.js +27 -0
  170. package/dist/runtime/utils.js.map +1 -0
  171. package/package.json +3 -2
  172. package/templates/react/useAuth.jsx +106 -0
  173. package/templates/react/useAuth.tsx +118 -0
  174. package/templates/{hooks → react}/useBackgroundSync.jsx +6 -4
  175. package/templates/{hooks → react}/useBackgroundSync.tsx +6 -4
  176. package/templates/{hooks → react}/useCacheInvalidation.jsx +2 -2
  177. package/templates/react/useCacheInvalidation.tsx +52 -0
  178. package/templates/react/useCachedFetch.jsx +140 -0
  179. package/templates/react/useCachedFetch.tsx +160 -0
  180. package/templates/react/useIsFetching.jsx +32 -0
  181. package/templates/react/useIsFetching.tsx +32 -0
  182. package/templates/react/useMutation.jsx +141 -0
  183. package/templates/react/useMutation.tsx +180 -0
  184. package/templates/react/useMutationQueue.jsx +69 -0
  185. package/templates/react/useMutationQueue.tsx +83 -0
  186. package/templates/react/useNetworkStatus.jsx +61 -0
  187. package/templates/react/useNetworkStatus.tsx +76 -0
  188. package/templates/react/usePrefetch.jsx +32 -0
  189. package/templates/react/usePrefetch.tsx +42 -0
  190. package/templates/{hooks → react}/usePushSubscription.jsx +4 -4
  191. package/templates/{hooks → react}/usePushSubscription.tsx +4 -4
  192. package/templates/{hooks → react}/useSWUpdate.jsx +3 -3
  193. package/templates/{hooks → react}/useSWUpdate.tsx +4 -4
  194. package/templates/react/useSwoffReset.jsx +32 -0
  195. package/templates/react/useSwoffReset.tsx +39 -0
  196. package/docs/API.md +0 -565
  197. package/docs/ARCHITECTURE.md +0 -374
  198. package/docs/CLI.md +0 -148
  199. package/docs/COMPARISON.md +0 -192
  200. package/docs/CONFIG.md +0 -277
  201. package/docs/ECOSYSTEM.md +0 -33
  202. package/templates/hooks/useAuth.jsx +0 -30
  203. package/templates/hooks/useAuth.tsx +0 -30
  204. package/templates/hooks/useCacheInvalidation.tsx +0 -19
  205. package/templates/hooks/useCachedFetch.jsx +0 -69
  206. package/templates/hooks/useCachedFetch.tsx +0 -81
  207. package/templates/hooks/useMutation.jsx +0 -76
  208. package/templates/hooks/useMutation.tsx +0 -109
  209. package/templates/hooks/useMutationQueue.jsx +0 -43
  210. package/templates/hooks/useMutationQueue.tsx +0 -50
  211. package/templates/hooks/useNetworkStatus.jsx +0 -19
  212. package/templates/hooks/useNetworkStatus.tsx +0 -19
  213. package/templates/hooks/usePrefetch.jsx +0 -10
  214. package/templates/hooks/usePrefetch.tsx +0 -25
  215. /package/templates/{hooks → react}/useMutationState.jsx +0 -0
  216. /package/templates/{hooks → react}/useMutationState.tsx +0 -0
@@ -22,21 +22,25 @@
22
22
  * On successful refresh, CACHE_UPDATED is posted to all clients.
23
23
  */
24
24
  export function generateFetchHandler(swConfig, tagInvalidation, mutationQueueEnabled) {
25
- const { strategy: { default: defaultStrategy, patterns: strategies, mode: cacheStrategy = "all", normalizeKey: normalizeCacheKey, ignoreQueryParams }, navigation: { mode: navMode = "spa", preload: navigationPreload, fallback: spaPath = "/index.html" }, refetchQueue: { batchSize: refetchBatchSize = 5, batchDelayMs: refetchBatchDelayMs = 1000, maxRetries: refetchMaxRetries = 3, retryDelayMs: refetchRetryDelayMs = 1000 } } = swConfig;
26
- const { staleTime: globalStaleTime, refetchInterval: globalRefetchInterval, refetchOnReconnect: globalRefetchOnReconnect, refetchOnFocus: globalRefetchOnFocus } = swConfig.strategy.reactive?.defaults || {};
27
- const staleVersionCode = tagInvalidation ? `
25
+ const { strategy: { default: defaultStrategy, patterns: strategies, mode: cacheStrategy = "all", normalizeKey: normalizeCacheKey, ignoreQueryParams, }, navigation: { mode: navMode = "spa", preload: navigationPreload, fallback: spaPath = "/index.html", }, refetchQueue: { batchSize: refetchBatchSize = 5, batchDelayMs: refetchBatchDelayMs = 1000, maxRetries: refetchMaxRetries = 3, retryDelayMs: refetchRetryDelayMs = 1000, }, } = swConfig;
26
+ const { staleTime: globalStaleTime, refetchInterval: globalRefetchInterval, refetchOnReconnect: globalRefetchOnReconnect, refetchOnFocus: globalRefetchOnFocus, } = swConfig.strategy.reactive?.defaults || {};
27
+ const staleVersionCode = tagInvalidation
28
+ ? `
28
29
  cleanStaleVersions();
29
30
  if (staleVersions.has(cacheKey(request))) {
30
31
  queueRefresh(cacheKey(request), new URL(request.url).href);
31
- }` : "";
32
- const tagCode = tagInvalidation ? `
32
+ }`
33
+ : "";
34
+ const tagCode = tagInvalidation
35
+ ? `
33
36
  const tagsHeader = request.headers.get("X-SW-Cache-Tags");
34
37
  if (tagsHeader) {
35
38
  const cacheKeyUrl = cacheKey(request);
36
39
  const actualUrl = new URL(request.url).href;
37
40
  const tags = tagsHeader.split(",").map((t) => t.trim());
38
41
  await cacheTagUrl(cacheKeyUrl, actualUrl, tags);
39
- }` : "";
42
+ }`
43
+ : "";
40
44
  const reactGlobalDefaults = {
41
45
  staleTime: globalStaleTime,
42
46
  refetchInterval: globalRefetchInterval,
@@ -64,44 +68,42 @@ const REFRESH_MAX_RETRIES = ${refetchMaxRetries};
64
68
  const REFRESH_RETRY_DELAY_MS = ${refetchRetryDelayMs};`;
65
69
  const GLOB_CODE = "\n" +
66
70
  "// --- Glob Pattern Matching ---\n" +
67
- "// NOTE: This is an inline copy of the algorithm in shared/glob-matcher.ts.\n" +
68
- "// Keep the two implementations in sync when making changes.\n" +
69
71
  "\n" +
70
72
  "function escapeGlobMeta(s) {\n" +
71
- " return s.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$$&\");\n" +
73
+ ' return s.replace(/[.+^${}()|[\\]\\\\]/g, "\\\\$$&");\n' +
72
74
  "}\n" +
73
75
  "\n" +
74
76
  "function globPartRe(part) {\n" +
75
- " for (var o = \"\", i = 0; i < part.length; i++) {\n" +
77
+ ' for (var o = "", i = 0; i < part.length; i++) {\n' +
76
78
  " var c = part[i];\n" +
77
- " if (c === \"*\") { o += \"[^/]*\"; }\n" +
78
- " else if (c === \"?\") { o += \"[^/]\"; }\n" +
79
- " else if (c === \"{\") {\n" +
80
- " var cl = part.indexOf(\"}\", i);\n" +
81
- " if (cl === -1) { o += \"\\\\\" + c; }\n" +
79
+ ' if (c === "*") { o += "[^/]*"; }\n' +
80
+ ' else if (c === "?") { o += "[^/]"; }\n' +
81
+ ' else if (c === "{") {\n' +
82
+ ' var cl = part.indexOf("}", i);\n' +
83
+ ' if (cl === -1) { o += "\\\\" + c; }\n' +
82
84
  " else {\n" +
83
- " o += \"(?:\" + part.slice(i + 1, cl).split(\",\").map(function(s) { return escapeGlobMeta(s.trim()); }).join(\"|\") + \")\";\n" +
85
+ ' o += "(?:" + part.slice(i + 1, cl).split(",").map(function(s) { return escapeGlobMeta(s.trim()); }).join("|") + ")";\n' +
84
86
  " i = cl;\n" +
85
87
  " }\n" +
86
- " } else { o += \"\\\\\" + c; }\n" +
88
+ ' } else { o += "\\\\" + c; }\n' +
87
89
  " }\n" +
88
90
  " return o;\n" +
89
91
  "}\n" +
90
92
  "\n" +
91
93
  "function matchGlob(path, pattern) {\n" +
92
- " if (pattern.charAt(0) === \"!\") return !matchGlob(path, pattern.slice(1));\n" +
93
- " var parts = pattern.split(\"/\").filter(Boolean);\n" +
94
- " var pps = path.split(\"/\").filter(Boolean);\n" +
94
+ ' if (pattern.charAt(0) === "!") return !matchGlob(path, pattern.slice(1));\n' +
95
+ ' var parts = pattern.split("/").filter(Boolean);\n' +
96
+ ' var pps = path.split("/").filter(Boolean);\n' +
95
97
  " var pi = 0, ppi = 0;\n" +
96
98
  " while (pi < parts.length && ppi < pps.length) {\n" +
97
99
  " var part = parts[pi];\n" +
98
- " if (part === \"**\") {\n" +
100
+ ' if (part === "**") {\n' +
99
101
  " if (pi === parts.length - 1) return true;\n" +
100
102
  " var nxt = parts[pi + 1];\n" +
101
103
  " var found = -1;\n" +
102
104
  " for (var j = ppi; j < pps.length; j++) {\n" +
103
- " if (nxt.indexOf(\"*\") > -1 || nxt.indexOf(\"?\") > -1 || nxt.indexOf(\"{\") > -1) {\n" +
104
- " if (new RegExp(\"^\" + globPartRe(nxt) + \"$\").test(pps[j])) { found = j; break; }\n" +
105
+ ' if (nxt.indexOf("*") > -1 || nxt.indexOf("?") > -1 || nxt.indexOf("{") > -1) {\n' +
106
+ ' if (new RegExp("^" + globPartRe(nxt) + "$").test(pps[j])) { found = j; break; }\n' +
105
107
  " } else if (nxt === pps[j]) { found = j; break; }\n" +
106
108
  " }\n" +
107
109
  " if (found === -1) return false;\n" +
@@ -109,8 +111,8 @@ const REFRESH_RETRY_DELAY_MS = ${refetchRetryDelayMs};`;
109
111
  " pi++;\n" +
110
112
  " continue;\n" +
111
113
  " }\n" +
112
- " if (part.indexOf(\"*\") > -1 || part.indexOf(\"?\") > -1 || part.indexOf(\"{\") > -1) {\n" +
113
- " if (!new RegExp(\"^\" + globPartRe(part) + \"$\").test(pps[ppi])) return false;\n" +
114
+ ' if (part.indexOf("*") > -1 || part.indexOf("?") > -1 || part.indexOf("{") > -1) {\n' +
115
+ ' if (!new RegExp("^" + globPartRe(part) + "$").test(pps[ppi])) return false;\n' +
114
116
  " } else if (part !== pps[ppi]) return false;\n" +
115
117
  " pi++;\n" +
116
118
  " ppi++;\n" +
@@ -122,86 +124,105 @@ const REFRESH_RETRY_DELAY_MS = ${refetchRetryDelayMs};`;
122
124
  // --- Batch Refresh Queue ---
123
125
 
124
126
  const _refreshQueue = new Map();
125
- let _refreshQueueProcessing = false;
126
127
  let _refreshQueuePromise = null;
127
128
 
128
- function queueRefresh(cacheKeyUrl, actualUrl${tagInvalidation ? ", tags" : ""}) {
129
- // Use Map keyed by cacheKey for proper deduplication${tagInvalidation ? `
129
+ function queueRefresh(cacheKeyUrl, actualUrl${tagInvalidation ? ", tags" : ""}${tagInvalidation ? ", method, body, contentType" : ""}) {
130
+ // Use Map keyed by cacheKey for proper deduplication${tagInvalidation
131
+ ? `
130
132
  // Don't let a tagless (SWR/reactive) refresh override an invalidation-triggered entry with tags
131
- if (_refreshQueue.has(cacheKeyUrl) && !tags) return;` : ""}
132
- _refreshQueue.set(cacheKeyUrl, { cacheKey: cacheKeyUrl, actualUrl: actualUrl || cacheKeyUrl, retryCount: 0${tagInvalidation ? ", tags: tags || null" : ""} });
133
+ if (_refreshQueue.has(cacheKeyUrl) && !tags) return;`
134
+ : ""}
135
+ _refreshQueue.set(cacheKeyUrl, { cacheKey: cacheKeyUrl, actualUrl: actualUrl || cacheKeyUrl, retryCount: 0${tagInvalidation ? ", tags: tags || null, method: method || null, body: body || null, contentType: contentType || null" : ""} });
133
136
  if (!_refreshQueuePromise) {
134
- _refreshQueuePromise = _processRefreshQueue().finally(() => {
135
- _refreshQueuePromise = null;
136
- if (_refreshQueue.size > 0) queueRefresh();
137
- });
137
+ _refreshQueuePromise = _processRefreshQueue();
138
138
  }
139
139
  return _refreshQueuePromise;
140
140
  }
141
141
 
142
- function resolveActualUrl(entry) {
143
- const url = entry.actualUrl || entry.cacheKey;
142
+ async function resolveActualUrl(entry) {
143
+ if (entry.actualUrl) return entry.actualUrl;
144
+ const url = entry.cacheKey;
144
145
  if (url.includes("/__swc/")) {
145
- // Virtual cache key — use the stored actual URL from tag registry
146
- return url;
146
+ // Virtual cache key — look up the real URL from tag registry
147
+ try {
148
+ const db = await openTagDB();
149
+ const tx = db.transaction(TAG_STORE_NAME, "readonly");
150
+ const store = tx.objectStore(TAG_STORE_NAME);
151
+ const stored = await new Promise((resolve) => {
152
+ const req = store.get(url);
153
+ req.onsuccess = () => resolve(req.result);
154
+ req.onerror = () => resolve(null);
155
+ });
156
+ db.close();
157
+ if (stored?.actualUrl) return stored.actualUrl;
158
+ } catch {}
147
159
  }
148
160
  return url;
149
161
  }
150
162
 
151
163
  async function _processRefreshQueue() {
152
- while (_refreshQueue.size > 0) {
153
- const batch = [];
154
- for (const [cacheKey, entry] of _refreshQueue) {
155
- if (batch.length >= REFETCH_BATCH_SIZE) break;
156
- batch.push(entry);
157
- _refreshQueue.delete(cacheKey);
158
- }
159
- if (batch.length === 0) break;
160
-
161
- const clients = await self.clients.matchAll();
162
-
163
- await Promise.allSettled(batch.map(async (entry) => {
164
- const fetchUrl = resolveActualUrl(entry);
165
- try {
166
- const response = await fetch(fetchUrl);
167
- if (response.ok) {
168
- const request = new Request(entry.cacheKey);
169
- await storeRuntime(request, response);${tagInvalidation ? `
164
+ try {
165
+ while (_refreshQueue.size > 0) {
166
+ const batch = [];
167
+ for (const [cacheKey, entry] of _refreshQueue) {
168
+ if (batch.length >= REFETCH_BATCH_SIZE) break;
169
+ if (entry.nextRetryAt && entry.nextRetryAt > Date.now()) continue;
170
+ batch.push(entry);
171
+ _refreshQueue.delete(cacheKey);
172
+ }
173
+ if (batch.length === 0) break;
174
+
175
+ const clients = await self.clients.matchAll();
176
+
177
+ await Promise.allSettled(batch.map(async (entry) => {
178
+ const fetchUrl = await resolveActualUrl(entry);
179
+ try {
180
+ const fetchOpts = {};
181
+ if (entry.method && entry.method !== "GET" && entry.method !== "HEAD") {
182
+ fetchOpts.method = entry.method;
183
+ if (entry.body) fetchOpts.body = entry.body;
184
+ if (entry.contentType) fetchOpts.headers = { "Content-Type": entry.contentType };
185
+ }
186
+ const response = await fetch(fetchUrl, fetchOpts);
187
+ if (response.ok) {
188
+ const request = new Request(entry.cacheKey);
189
+ await storeRuntime(request, response);${tagInvalidation
190
+ ? `
170
191
  if (entry.tags && typeof cacheTagUrl !== "undefined") {
171
- await cacheTagUrl(entry.cacheKey, fetchUrl, entry.tags);
172
- }` : ""}
173
- // Clean up stale version tracking on successful refresh
174
- if (typeof staleVersions !== "undefined" && staleVersions.has(entry.cacheKey)) {
175
- staleVersions.delete(entry.cacheKey);
192
+ await cacheTagUrl(entry.cacheKey, fetchUrl, entry.tags, entry.method, entry.body, entry.contentType);
193
+ }`
194
+ : ""}
195
+ // Clean up stale version tracking on successful refresh
196
+ if (typeof staleVersions !== "undefined" && staleVersions.has(entry.cacheKey)) {
197
+ staleVersions.delete(entry.cacheKey);
198
+ }
199
+ for (const client of clients) {
200
+ client.postMessage({ type: "CACHE_UPDATED", url: fetchUrl });
201
+ }
176
202
  }
177
- for (const client of clients) {
178
- client.postMessage({ type: "CACHE_UPDATED", url: fetchUrl });
203
+ } catch {
204
+ // Refresh failed retry with exponential backoff
205
+ if (entry.retryCount < REFRESH_MAX_RETRIES) {
206
+ entry.retryCount++;
207
+ const delay = REFRESH_RETRY_DELAY_MS * Math.pow(2, entry.retryCount - 1);
208
+ entry.nextRetryAt = Date.now() + delay;
209
+ _refreshQueue.set(entry.cacheKey, entry);
210
+ setTimeout(() => {
211
+ if (!_refreshQueuePromise) {
212
+ _refreshQueuePromise = _processRefreshQueue();
213
+ }
214
+ }, delay);
179
215
  }
180
216
  }
181
- } catch {
182
- // Refresh failed — retry with exponential backoff
183
- if (entry.retryCount < REFRESH_MAX_RETRIES) {
184
- entry.retryCount++;
185
- const delay = REFRESH_RETRY_DELAY_MS * Math.pow(2, entry.retryCount - 1);
186
- _refreshQueue.set(entry.cacheKey, entry);
187
- // Schedule re-processing after delay
188
- setTimeout(() => {
189
- if (!_refreshQueuePromise) {
190
- _refreshQueuePromise = _processRefreshQueue().finally(() => {
191
- _refreshQueuePromise = null;
192
- if (_refreshQueue.size > 0) queueRefresh();
193
- });
194
- }
195
- }, delay);
196
- }
197
- }
198
- }));
217
+ }));
199
218
 
200
- if (_refreshQueue.size > 0 && REFETCH_BATCH_DELAY_MS > 0) {
201
- await new Promise(r => setTimeout(r, REFETCH_BATCH_DELAY_MS));
219
+ if (_refreshQueue.size > 0 && REFETCH_BATCH_DELAY_MS > 0) {
220
+ await new Promise(r => setTimeout(r, REFETCH_BATCH_DELAY_MS));
221
+ }
202
222
  }
223
+ } finally {
224
+ _refreshQueuePromise = null;
203
225
  }
204
- _refreshQueueProcessing = false;
205
226
  }
206
227
 
207
228
  // --- Reactive Patterns (extracted for interval/focus/reconnect) ---
@@ -230,7 +251,8 @@ ${(() => {
230
251
  return "";
231
252
  return `// Start intervals for reactive patterns with refetchInterval
232
253
  (async () => {
233
- ${patternsWithInterval.map(p => ` setInterval(async () => {
254
+ ${patternsWithInterval
255
+ .map((p) => ` setInterval(async () => {
234
256
  const cache = await caches.open(CACHE_NAME_RUNTIME);
235
257
  const keys = await cache.keys();
236
258
  for (const request of keys) {
@@ -244,7 +266,8 @@ ${patternsWithInterval.map(p => ` setInterval(async () => {
244
266
  queueRefresh(request.url, url.href);
245
267
  }
246
268
  }
247
- }, ${p.refetchInterval * 1000});`).join("\n")}
269
+ }, ${p.refetchInterval * 1000});`)
270
+ .join("\n")}
248
271
  })();
249
272
  `;
250
273
  })()}
@@ -295,13 +318,15 @@ async function handleOnFocus() {
295
318
  function cacheKey(request) {
296
319
  const key = request.headers.get("X-SW-Cache-Key");
297
320
  if (key) return new URL("/__swc/" + key, self.location.origin).href;
298
- const url = new URL(request.url);${normalizeCacheKey ? `
321
+ const url = new URL(request.url);${normalizeCacheKey
322
+ ? `
299
323
  // Sort query params alphabetically for consistent cache keys
300
324
  if (url.search) {
301
325
  const params = new URLSearchParams(url.search);
302
326
  params.sort();
303
327
  url.search = params.toString();
304
- }` : ""}${ignoreQueryParams && ignoreQueryParams.length > 0
328
+ }`
329
+ : ""}${ignoreQueryParams && ignoreQueryParams.length > 0
305
330
  ? `
306
331
  // Strip configured query params from cache key
307
332
  const ignore = ${JSON.stringify(ignoreQueryParams)};
@@ -339,7 +364,23 @@ async function storeRuntime(request, response) {
339
364
  }
340
365
 
341
366
  async function cacheResponse(request, response) {
342
- await storeRuntime(request, response);${tagCode}
367
+ await storeRuntime(request, response);
368
+ const tagsHeader = request.headers.get("X-SW-Cache-Tags");
369
+ if (tagsHeader) {
370
+ const cacheKeyUrl = cacheKey(request);
371
+ const actualUrl = new URL(request.url).href;
372
+ const tags = tagsHeader.split(",").map((t) => t.trim());
373
+ const method = request.method;
374
+ let body = null;
375
+ let contentType = null;
376
+ if (method !== "GET" && method !== "HEAD") {
377
+ contentType = request.headers.get("Content-Type");
378
+ try {
379
+ body = await request.clone().text();
380
+ } catch {}
381
+ }
382
+ await cacheTagUrl(cacheKeyUrl, actualUrl, tags, method, body, contentType);
383
+ }
343
384
  }
344
385
 
345
386
  async function fromSpaFallback(request) {
@@ -362,7 +403,7 @@ function markFromCache(response) {
362
403
  }
363
404
 
364
405
  function isStale(response, staleTimeSeconds) {
365
- if (!staleTimeSeconds || staleTimeSeconds <= 0) return false;
406
+ if (staleTimeSeconds == null || staleTimeSeconds <= 0) return false;
366
407
  const cachedAt = response.headers.get("X-SW-Cached-At");
367
408
  if (!cachedAt) return false;
368
409
  return Date.now() - Number(cachedAt) > staleTimeSeconds * 1000;
@@ -377,7 +418,14 @@ function resolveStrategyEntry(entry) {
377
418
  function determineCacheStrategy(request, customStrategies, globalDefaults) {
378
419
  const override = request.headers.get("X-SW-Strategy");
379
420
  if (override) {
380
- return { strategy: override };
421
+ const cfg = { strategy: override };
422
+ const hStale = request.headers.get("X-SW-Stale-Time");
423
+ if (hStale !== null) cfg.staleTime = Number(hStale);
424
+ const hFocus = request.headers.get("X-SW-Refetch-On-Focus");
425
+ if (hFocus !== null) cfg.refetchOnFocus = hFocus !== "false";
426
+ const hReconnect = request.headers.get("X-SW-Refetch-On-Reconnect");
427
+ if (hReconnect !== null) cfg.refetchOnReconnect = hReconnect !== "false";
428
+ return cfg;
381
429
  }
382
430
  const path = new URL(request.url).pathname;
383
431
  for (const [pattern, entry] of Object.entries(customStrategies)) {
@@ -404,7 +452,8 @@ function applyStrategy(event, request, config) {
404
452
  const { strategy } = config;
405
453
  if (strategy === "reactive") {
406
454
  const reactiveCfg = findReactiveConfig(new URL(request.url).href);
407
- event.respondWith(reactiveStrategy(event, request, reactiveCfg?.staleTime));
455
+ const staleTime = config.staleTime !== undefined ? config.staleTime : reactiveCfg?.staleTime;
456
+ event.respondWith(reactiveStrategy(event, request, staleTime));
408
457
  } else if (strategy === "stale-while-revalidate") {
409
458
  event.respondWith(staleWhileRevalidate(event, request));
410
459
  } else if (strategy === "network-first") {
@@ -418,14 +467,17 @@ function applyStrategy(event, request, config) {
418
467
  }
419
468
  }
420
469
 
421
- ${mutationQueueEnabled ? `// --- Mutation Queue IDB Helpers ---
470
+ ${mutationQueueEnabled
471
+ ? `// --- Mutation Queue IDB Helpers ---
422
472
 
423
473
  const MUTATION_DB_NAME = "swoff-queue";
424
474
  const MUTATION_STORE_NAME = "mutations";
475
+ // Bump this when adding new indexes/stores for schema migration
476
+ const MUTATION_DB_VERSION = 1;
425
477
 
426
478
  function openMutationQueueDB() {
427
479
  return new Promise((resolve, reject) => {
428
- const request = indexedDB.open(MUTATION_DB_NAME, 1);
480
+ const request = indexedDB.open(MUTATION_DB_NAME, MUTATION_DB_VERSION);
429
481
  request.onupgradeneeded = (e) => {
430
482
  const db = e.target.result;
431
483
  if (!db.objectStoreNames.contains(MUTATION_STORE_NAME)) {
@@ -459,7 +511,7 @@ async function storeMutationInSW(request) {
459
511
  url: new URL(request.url).href,
460
512
  body,
461
513
  bodyType,
462
- headers: {},
514
+ headers: request.headers.get("Content-Type") ? { "Content-Type": request.headers.get("Content-Type") } : {},
463
515
  timestamp: Date.now(),
464
516
  retryCount: 0,
465
517
  nextRetryAt: 0,
@@ -494,15 +546,18 @@ async function handleMutation(event) {
494
546
  }
495
547
  }
496
548
 
497
- ` : ""}self.addEventListener("fetch", (event) => {
498
- const { request } = event;${mutationQueueEnabled ? `
549
+ `
550
+ : ""}self.addEventListener("fetch", (event) => {
551
+ const { request } = event;${mutationQueueEnabled
552
+ ? `
499
553
  if (request.method !== "GET" && request.method !== "HEAD") {
500
554
  if (request.headers.get("X-SW-Cache-Strategy") === "mutation") {
501
555
  event.respondWith(handleMutation(event));
502
556
  return;
503
557
  }
504
558
  if (!request.headers.get("X-SW-Cache-Key")) return;
505
- }` : `
559
+ }`
560
+ : `
506
561
  if (request.method !== "GET" && request.method !== "HEAD") {
507
562
  if (!request.headers.get("X-SW-Cache-Key")) return;
508
563
  }`}
@@ -512,7 +567,8 @@ async function handleMutation(event) {
512
567
 
513
568
  // --- Strategies ---
514
569
 
515
- ${navigationPreload ? `
570
+ ${navigationPreload
571
+ ? `
516
572
  async function fetchWithPreload(event, request) {
517
573
  try {
518
574
  const preload = await event.preloadResponse;
@@ -520,7 +576,8 @@ async function fetchWithPreload(event, request) {
520
576
  } catch {}
521
577
  return fetch(request);
522
578
  }
523
- ` : ""}const _fetch = ${navigationPreload ? "fetchWithPreload" : `(event, request) => fetch(request)`};
579
+ `
580
+ : ""}const _fetch = ${navigationPreload ? "fetchWithPreload" : `(event, request) => fetch(request)`};
524
581
 
525
582
  async function cacheFirst(event, request) {
526
583
  const cached = await fromRuntime(request);
@@ -534,20 +591,22 @@ async function cacheFirst(event, request) {
534
591
  const fallback = await fromSpaFallback(request);
535
592
  if (fallback) return fallback;
536
593
 
594
+ const reqForCache = request.clone();
537
595
  const response = await _fetch(event, request);
538
596
  if (response.ok) {
539
597
  const responseToCache = response.clone();
540
- event.waitUntil(cacheResponse(request, responseToCache));
598
+ event.waitUntil(cacheResponse(reqForCache, responseToCache));
541
599
  }
542
600
  return response;
543
601
  }
544
602
 
545
603
  async function networkFirst(event, request) {
546
604
  try {
605
+ const reqForCache = request.clone();
547
606
  const response = await _fetch(event, request);
548
607
  if (response.ok) {
549
608
  const responseToCache = response.clone();
550
- event.waitUntil(cacheResponse(request, responseToCache));
609
+ event.waitUntil(cacheResponse(reqForCache, responseToCache));
551
610
  }
552
611
  return response;
553
612
  } catch {
@@ -579,10 +638,11 @@ async function staleWhileRevalidate(event, request) {
579
638
  return markFromCache(precached);
580
639
  }
581
640
 
641
+ const reqForCache = request.clone();
582
642
  const response = await _fetch(event, request);
583
643
  if (response.ok) {
584
644
  const responseToCache = response.clone();
585
- await cacheResponse(request, responseToCache);
645
+ await cacheResponse(reqForCache, responseToCache);
586
646
  }
587
647
  return response;
588
648
  }
@@ -605,10 +665,11 @@ async function reactiveStrategy(event, request, staleTime) {
605
665
  const fallback = await fromSpaFallback(request);
606
666
  if (fallback) return fallback;
607
667
 
668
+ const reqForCache = request.clone();
608
669
  const response = await _fetch(event, request);
609
670
  if (response.ok) {
610
671
  const responseToCache = response.clone();
611
- await cacheResponse(request, responseToCache);
672
+ await cacheResponse(reqForCache, responseToCache);
612
673
  }
613
674
  return response;
614
675
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/fetch-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetch-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/fetch-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob-matcher-code.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/glob-matcher-code.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI;IACrC,oCAAoC;IACpC,IAAI;IACJ,gCAAgC;IAChC,0DAA0D;IAC1D,KAAK;IACL,IAAI;IACJ,+BAA+B;IAC/B,qDAAqD;IACrD,wBAAwB;IACxB,wCAAwC;IACxC,4CAA4C;IAC5C,6BAA6B;IAC7B,wCAAwC;IACxC,6CAA6C;IAC7C,gBAAgB;IAChB,gIAAgI;IAChI,mBAAmB;IACnB,WAAW;IACX,mCAAmC;IACnC,OAAO;IACP,eAAe;IACf,KAAK;IACL,IAAI;IACJ,uCAAuC;IACvC,+EAA+E;IAC/E,qDAAqD;IACrD,gDAAgD;IAChD,0BAA0B;IAC1B,qDAAqD;IACrD,6BAA6B;IAC7B,4BAA4B;IAC5B,mDAAmD;IACnD,kCAAkC;IAClC,yBAAyB;IACzB,kDAAkD;IAClD,0FAA0F;IAC1F,6FAA6F;IAC7F,4DAA4D;IAC5D,WAAW;IACX,yCAAyC;IACzC,sBAAsB;IACtB,eAAe;IACf,mBAAmB;IACnB,SAAS;IACT,yFAAyF;IACzF,qFAAqF;IACrF,mDAAmD;IACnD,aAAa;IACb,cAAc;IACd,OAAO;IACP,uDAAuD;IACvD,KAAK;IACL,IAAI,CAAC"}
@@ -48,6 +48,14 @@ self.addEventListener("activate", (event) => {
48
48
  return `
49
49
  // --- Server Push Events (SSE) ---
50
50
 
51
+ function notifyClientsSSE(connected) {
52
+ self.clients.matchAll().then(function(clients) {
53
+ clients.forEach(function(client) {
54
+ client.postMessage({ type: "SSE_STATUS", connected: !!connected });
55
+ });
56
+ });
57
+ }
58
+
51
59
  let pushReconnectTimer = null;
52
60
  let pushAbortController = null;
53
61
 
@@ -56,12 +64,15 @@ async function connectPushEvents() {
56
64
  pushAbortController = new AbortController();
57
65
  const response = await fetch("${endpoint}", {
58
66
  headers: { Accept: "text/event-stream" },
67
+ credentials: "include",
59
68
  signal: pushAbortController.signal,
60
69
  });
61
70
  if (!response.ok || !response.body) {
71
+ notifyClientsSSE(false);
62
72
  scheduleReconnect();
63
73
  return;
64
74
  }
75
+ notifyClientsSSE(true);
65
76
  const reader = response.body.getReader();
66
77
  const decoder = new TextDecoder();
67
78
  let buffer = "";
@@ -98,6 +109,7 @@ async function connectPushEvents() {
98
109
  } catch {
99
110
  // Connection lost or aborted
100
111
  }
112
+ notifyClientsSSE(false);
101
113
  scheduleReconnect();
102
114
  }
103
115
 
@@ -1 +1 @@
1
- {"version":3,"file":"server-push-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/server-push-handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,yBAAyB,CACvC,IAAyB,EACzB,QAAgB,EAChB,gBAAwB;IAExB,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,OAAO;;;;;;;;8BAQmB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;uDAuBiB,gBAAgB;;;;;;CAMtE,CAAC;IACA,CAAC;IAED,qCAAqC;IACrC,OAAO;;;;;;;;;oCAS2B,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uDAiDW,gBAAgB;;;;;;CAMtE,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"server-push-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/server-push-handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,yBAAyB,CACvC,IAAyB,EACzB,QAAgB,EAChB,gBAAwB;IAExB,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,OAAO;;;;;;;;8BAQmB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;uDAuBiB,gBAAgB;;;;;;CAMtE,CAAC;IACA,CAAC;IAED,qCAAqC;IACrC,OAAO;;;;;;;;;;;;;;;;;oCAiB2B,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uDAqDW,gBAAgB;;;;;;CAMtE,CAAC;AACF,CAAC"}
@@ -12,6 +12,8 @@ const STALE_VERSIONS_MAX = 100;
12
12
  const STALE_VERSION_TTL = 30 * 60 * 1000;
13
13
  const TAG_DB_NAME = "swoff-cache-tags";
14
14
  const TAG_STORE_NAME = "tags";
15
+ // Bump this when adding new indexes/stores for schema migration
16
+ const TAG_DB_VERSION = 1;
15
17
 
16
18
  function cleanStaleVersions() {
17
19
  const now = Date.now();
@@ -24,7 +26,7 @@ function cleanStaleVersions() {
24
26
 
25
27
  function openTagDB() {
26
28
  return new Promise((resolve, reject) => {
27
- const request = indexedDB.open(TAG_DB_NAME, 1);
29
+ const request = indexedDB.open(TAG_DB_NAME, TAG_DB_VERSION);
28
30
  request.onupgradeneeded = (e) => {
29
31
  const db = e.target.result;
30
32
  if (!db.objectStoreNames.contains(TAG_STORE_NAME)) {
@@ -37,11 +39,11 @@ function openTagDB() {
37
39
  });
38
40
  }
39
41
 
40
- async function cacheTagUrl(url, actualUrl, tags) {
42
+ async function cacheTagUrl(url, actualUrl, tags, method, body, contentType) {
41
43
  const db = await openTagDB();
42
44
  const tx = db.transaction(TAG_STORE_NAME, "readwrite");
43
45
  const store = tx.objectStore(TAG_STORE_NAME);
44
- store.put({ url, actualUrl, tags });
46
+ store.put({ url, actualUrl, tags, method: method || "GET", body: body || null, contentType: contentType || null });
45
47
  await new Promise((resolve, reject) => {
46
48
  tx.oncomplete = () => resolve();
47
49
  tx.onerror = () => reject(tx.error);
@@ -81,7 +83,7 @@ async function invalidateByTag(tag) {
81
83
  // Enqueue background refetch through batched refresh queue
82
84
  for (const entry of entries) {
83
85
  staleVersions.set(entry.url, Date.now());
84
- queueRefresh(entry.url, entry.actualUrl, entry.tags);
86
+ queueRefresh(entry.url, entry.actualUrl, entry.tags, entry.method, entry.body, entry.contentType);
85
87
  }
86
88
 
87
89
  const clients = await self.clients.matchAll();
@@ -1 +1 @@
1
- {"version":3,"file":"tag-management.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/tag-management.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkIP,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"tag-management.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/tag-management.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoIP,CAAC;AACH,CAAC"}