@swoff/cli 0.3.13 → 0.3.14

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 (224) hide show
  1. package/README.md +28 -32
  2. package/dist/index.js +2 -13
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/cli/help.js +3 -8
  5. package/dist/lib/cli/help.js.map +1 -1
  6. package/dist/lib/commands/add.js +29 -87
  7. package/dist/lib/commands/add.js.map +1 -1
  8. package/dist/lib/commands/generate-guide.js +16 -30
  9. package/dist/lib/commands/generate-guide.js.map +1 -1
  10. package/dist/lib/commands/generate.js +31 -6
  11. package/dist/lib/commands/generate.js.map +1 -1
  12. package/dist/lib/commands/init.js +188 -11
  13. package/dist/lib/commands/init.js.map +1 -1
  14. package/dist/lib/commands/validate.js +2 -4
  15. package/dist/lib/commands/validate.js.map +1 -1
  16. package/dist/lib/config/loader.js +34 -25
  17. package/dist/lib/config/loader.js.map +1 -1
  18. package/dist/lib/config/validator.js +202 -96
  19. package/dist/lib/config/validator.js.map +1 -1
  20. package/dist/lib/generators/file-generators/api-config.js +1 -1
  21. package/dist/lib/generators/file-generators/api-config.js.map +1 -1
  22. package/dist/lib/generators/file-generators/auth-adapter.js +13 -0
  23. package/dist/lib/generators/file-generators/auth-adapter.js.map +1 -0
  24. package/dist/lib/generators/file-generators/auth-check.js +40 -0
  25. package/dist/lib/generators/file-generators/auth-check.js.map +1 -0
  26. package/dist/lib/generators/file-generators/auth-store.js +2 -5
  27. package/dist/lib/generators/file-generators/auth-store.js.map +1 -1
  28. package/dist/lib/generators/file-generators/background-sync.js +1 -1
  29. package/dist/lib/generators/file-generators/background-sync.js.map +1 -1
  30. package/dist/lib/generators/file-generators/cache.js +2 -1
  31. package/dist/lib/generators/file-generators/cache.js.map +1 -1
  32. package/dist/lib/generators/file-generators/client-injector-bundle.js +15 -0
  33. package/dist/lib/generators/file-generators/client-injector-bundle.js.map +1 -0
  34. package/dist/lib/generators/file-generators/client-injector.js +2 -1
  35. package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
  36. package/dist/lib/generators/file-generators/connectivity-manager.js +12 -0
  37. package/dist/lib/generators/file-generators/connectivity-manager.js.map +1 -0
  38. package/dist/lib/generators/file-generators/connectivity.js +12 -0
  39. package/dist/lib/generators/file-generators/connectivity.js.map +1 -0
  40. package/dist/lib/generators/file-generators/context.js +7 -0
  41. package/dist/lib/generators/file-generators/context.js.map +1 -1
  42. package/dist/lib/generators/file-generators/fetch-wrapper.js +1 -1
  43. package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
  44. package/dist/lib/generators/file-generators/generate-framework-adapters.js +29 -20
  45. package/dist/lib/generators/file-generators/generate-framework-adapters.js.map +1 -1
  46. package/dist/lib/generators/file-generators/gql-wrapper.js +2 -2
  47. package/dist/lib/generators/file-generators/gql-wrapper.js.map +1 -1
  48. package/dist/lib/generators/file-generators/guide-generator.js +51 -1
  49. package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
  50. package/dist/lib/generators/file-generators/invalidation-tags.js +2 -3
  51. package/dist/lib/generators/file-generators/invalidation-tags.js.map +1 -1
  52. package/dist/lib/generators/file-generators/mutation-queue.js +2 -2
  53. package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
  54. package/dist/lib/generators/file-generators/mutation-state.js +1 -1
  55. package/dist/lib/generators/file-generators/mutation-state.js.map +1 -1
  56. package/dist/lib/generators/file-generators/notification-generator.js +6 -0
  57. package/dist/lib/generators/file-generators/notification-generator.js.map +1 -0
  58. package/dist/lib/generators/file-generators/open-db.js +6 -0
  59. package/dist/lib/generators/file-generators/open-db.js.map +1 -0
  60. package/dist/lib/generators/file-generators/push.js +1 -2
  61. package/dist/lib/generators/file-generators/push.js.map +1 -1
  62. package/dist/lib/generators/file-generators/pwa-install.js +2 -6
  63. package/dist/lib/generators/file-generators/pwa-install.js.map +1 -1
  64. package/dist/lib/generators/file-generators/server-push.js +1 -1
  65. package/dist/lib/generators/file-generators/server-push.js.map +1 -1
  66. package/dist/lib/generators/file-generators/storage-generator.js +6 -0
  67. package/dist/lib/generators/file-generators/storage-generator.js.map +1 -0
  68. package/dist/lib/generators/file-generators/storage-notify.js +6 -0
  69. package/dist/lib/generators/file-generators/storage-notify.js.map +1 -0
  70. package/dist/lib/generators/file-generators/storage.js +6 -0
  71. package/dist/lib/generators/file-generators/storage.js.map +1 -0
  72. package/dist/lib/generators/file-generators/sw-generator-build.js +96 -45
  73. package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -1
  74. package/dist/lib/generators/file-generators/sw-injector.js +0 -4
  75. package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
  76. package/dist/lib/generators/file-generators/sw-template.js +8 -9
  77. package/dist/lib/generators/file-generators/sw-template.js.map +1 -1
  78. package/dist/lib/generators/file-generators/sw-version-gen.js +32 -0
  79. package/dist/lib/generators/file-generators/sw-version-gen.js.map +1 -0
  80. package/dist/lib/generators/file-generators/swoff-api-bundle.js +51 -0
  81. package/dist/lib/generators/file-generators/swoff-api-bundle.js.map +1 -0
  82. package/dist/lib/generators/sw-build-utils.js +69 -0
  83. package/dist/lib/generators/sw-build-utils.js.map +1 -0
  84. package/dist/lib/generators/sw-generator.js +23 -34
  85. package/dist/lib/generators/sw-generator.js.map +1 -1
  86. package/dist/lib/generators/sw-sections/activate-handler.js +74 -23
  87. package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
  88. package/dist/lib/generators/sw-sections/assemble-sw.js +15 -94
  89. package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
  90. package/dist/lib/generators/sw-sections/background-sync-handler.js +74 -72
  91. package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -1
  92. package/dist/lib/generators/sw-sections/batch-refresh-queue.js +102 -0
  93. package/dist/lib/generators/sw-sections/batch-refresh-queue.js.map +1 -0
  94. package/dist/lib/generators/sw-sections/config-header.js +2 -3
  95. package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
  96. package/dist/lib/generators/sw-sections/default-template.js +59 -6
  97. package/dist/lib/generators/sw-sections/default-template.js.map +1 -1
  98. package/dist/lib/generators/sw-sections/fetch-handler.js +621 -495
  99. package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
  100. package/dist/lib/generators/sw-sections/install-handler.js +40 -23
  101. package/dist/lib/generators/sw-sections/install-handler.js.map +1 -1
  102. package/dist/lib/generators/sw-sections/message-handler.js +25 -8
  103. package/dist/lib/generators/sw-sections/message-handler.js.map +1 -1
  104. package/dist/lib/generators/sw-sections/server-push-handler.js +10 -14
  105. package/dist/lib/generators/sw-sections/server-push-handler.js.map +1 -1
  106. package/dist/lib/generators/sw-sections/shared.js +68 -0
  107. package/dist/lib/generators/sw-sections/shared.js.map +1 -0
  108. package/dist/lib/generators/sw-sections/sw-push.js +2 -6
  109. package/dist/lib/generators/sw-sections/sw-push.js.map +1 -1
  110. package/dist/lib/generators/sw-sections/tag-management.js +55 -86
  111. package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
  112. package/dist/lib/generators/swoff-files-generator.js +183 -59
  113. package/dist/lib/generators/swoff-files-generator.js.map +1 -1
  114. package/dist/lib/shared/config-types.js +67 -63
  115. package/dist/lib/shared/config-types.js.map +1 -1
  116. package/dist/lib/shared/feature-registry.js +198 -0
  117. package/dist/lib/shared/feature-registry.js.map +1 -0
  118. package/dist/lib/utils/detect-framework.js +52 -9
  119. package/dist/lib/utils/detect-framework.js.map +1 -1
  120. package/dist/runtime/api-config.js +2 -2
  121. package/dist/runtime/api-config.js.map +1 -1
  122. package/dist/runtime/auth-adapter.js +179 -0
  123. package/dist/runtime/auth-adapter.js.map +1 -0
  124. package/dist/runtime/auth-state.js +16 -6
  125. package/dist/runtime/auth-state.js.map +1 -1
  126. package/dist/runtime/auth-store.js +219 -213
  127. package/dist/runtime/auth-store.js.map +1 -1
  128. package/dist/runtime/auth-user.js +5 -19
  129. package/dist/runtime/auth-user.js.map +1 -1
  130. package/dist/runtime/background-sync.js +5 -2
  131. package/dist/runtime/background-sync.js.map +1 -1
  132. package/dist/runtime/cache.js +91 -3
  133. package/dist/runtime/cache.js.map +1 -1
  134. package/dist/runtime/client-injector-bundle.js +314 -0
  135. package/dist/runtime/client-injector-bundle.js.map +1 -0
  136. package/dist/runtime/client-injector.js +173 -30
  137. package/dist/runtime/client-injector.js.map +1 -1
  138. package/dist/runtime/connectivity-manager.js +83 -0
  139. package/dist/runtime/connectivity-manager.js.map +1 -0
  140. package/dist/runtime/connectivity.js +83 -0
  141. package/dist/runtime/connectivity.js.map +1 -0
  142. package/dist/runtime/fetch-wrapper.js +26 -59
  143. package/dist/runtime/fetch-wrapper.js.map +1 -1
  144. package/dist/runtime/gql-wrapper.js +15 -9
  145. package/dist/runtime/gql-wrapper.js.map +1 -1
  146. package/dist/runtime/invalidation-tags.js +12 -89
  147. package/dist/runtime/invalidation-tags.js.map +1 -1
  148. package/dist/runtime/mutation-queue.js +83 -31
  149. package/dist/runtime/mutation-queue.js.map +1 -1
  150. package/dist/runtime/mutation-state.js +3 -3
  151. package/dist/runtime/mutation-state.js.map +1 -1
  152. package/dist/runtime/notification.js +65 -0
  153. package/dist/runtime/notification.js.map +1 -0
  154. package/dist/runtime/open-db.js +41 -0
  155. package/dist/runtime/open-db.js.map +1 -0
  156. package/dist/runtime/push.js +15 -27
  157. package/dist/runtime/push.js.map +1 -1
  158. package/dist/runtime/pwa-injector.js +3 -32
  159. package/dist/runtime/pwa-injector.js.map +1 -1
  160. package/dist/runtime/pwa-prompt.js +35 -3
  161. package/dist/runtime/pwa-prompt.js.map +1 -1
  162. package/dist/runtime/reset.js +39 -42
  163. package/dist/runtime/reset.js.map +1 -1
  164. package/dist/runtime/server-push.js +23 -13
  165. package/dist/runtime/server-push.js.map +1 -1
  166. package/dist/runtime/storage.js +32 -0
  167. package/dist/runtime/storage.js.map +1 -0
  168. package/dist/runtime/sw-injector.js +19 -178
  169. package/dist/runtime/sw-injector.js.map +1 -1
  170. package/dist/runtime/sw-version.js +13 -0
  171. package/dist/runtime/sw-version.js.map +1 -0
  172. package/dist/runtime/swoff-api-bundle.js +1491 -0
  173. package/dist/runtime/swoff-api-bundle.js.map +1 -0
  174. package/dist/runtime/type-definitions.js +8 -7
  175. package/dist/runtime/type-definitions.js.map +1 -1
  176. package/dist/runtime/utils.js +4 -0
  177. package/dist/runtime/utils.js.map +1 -1
  178. package/dist/swoff-nkdhhmw8. +18 -0
  179. package/dist/swoff.js +5 -0
  180. package/package.json +1 -1
  181. package/templates/react/useAuth.jsx +7 -4
  182. package/templates/react/useAuth.tsx +14 -14
  183. package/templates/react/useBackgroundSync.jsx +5 -4
  184. package/templates/react/useBackgroundSync.tsx +5 -4
  185. package/templates/react/useCachedFetch.jsx +8 -0
  186. package/templates/react/useCachedFetch.tsx +8 -0
  187. package/templates/react/useMutation.jsx +60 -56
  188. package/templates/react/useMutation.tsx +65 -64
  189. package/templates/react/useMutationQueue.jsx +5 -1
  190. package/templates/react/useMutationQueue.tsx +8 -2
  191. package/templates/react/useMutationState.jsx +3 -4
  192. package/templates/react/useMutationState.tsx +4 -8
  193. package/templates/react/useNetworkStatus.jsx +57 -17
  194. package/templates/react/useNetworkStatus.tsx +42 -20
  195. package/templates/react/useOfflineAnalytics.jsx +42 -0
  196. package/templates/react/useOfflineAnalytics.tsx +50 -0
  197. package/templates/react/usePwaInstall.jsx +26 -0
  198. package/templates/react/usePwaInstall.tsx +26 -0
  199. package/templates/react/useSWUpdate.jsx +7 -52
  200. package/templates/react/useSWUpdate.tsx +12 -51
  201. package/templates/react/useStorageEstimate.jsx +56 -0
  202. package/templates/react/useStorageEstimate.tsx +67 -0
  203. package/dist/__tests__/assemble-sw.test.js +0 -145
  204. package/dist/__tests__/assemble-sw.test.js.map +0 -1
  205. package/dist/__tests__/cli-integration.test.js +0 -231
  206. package/dist/__tests__/cli-integration.test.js.map +0 -1
  207. package/dist/__tests__/config-types.test.js +0 -124
  208. package/dist/__tests__/config-types.test.js.map +0 -1
  209. package/dist/__tests__/detect-language.test.js +0 -51
  210. package/dist/__tests__/detect-language.test.js.map +0 -1
  211. package/dist/__tests__/file-generators.test.js +0 -228
  212. package/dist/__tests__/file-generators.test.js.map +0 -1
  213. package/dist/__tests__/glob-matcher.test.js +0 -86
  214. package/dist/__tests__/glob-matcher.test.js.map +0 -1
  215. package/dist/__tests__/invalidation-tags.test.js +0 -283
  216. package/dist/__tests__/invalidation-tags.test.js.map +0 -1
  217. package/dist/__tests__/loader.test.js +0 -77
  218. package/dist/__tests__/loader.test.js.map +0 -1
  219. package/dist/__tests__/validator.test.js +0 -340
  220. package/dist/__tests__/validator.test.js.map +0 -1
  221. package/templates/react/useCacheInvalidation.jsx +0 -19
  222. package/templates/react/useCacheInvalidation.tsx +0 -52
  223. package/templates/react/useIsFetching.jsx +0 -32
  224. package/templates/react/useIsFetching.tsx +0 -32
@@ -1,76 +1,31 @@
1
- import { useState, useEffect, useCallback } from "react";
2
- import { handleUpdateApproved } from "../sw/injector.js";
1
+ import { useState, useEffect } from "react";
3
2
 
4
3
  export function useSWUpdate() {
5
4
  const [state, setState] = useState(() => ({
6
- updateStatus: "idle",
7
- currentVersion: typeof window !== "undefined" ? window.currentSWVersion || null : null,
8
- availableVersion: null,
5
+ status: "idle",
9
6
  progress: 0,
10
- forceUpdate: false,
11
7
  error: null,
12
8
  }));
13
9
 
14
10
  useEffect(() => {
15
- if (sessionStorage.getItem("sw-dismissed-update") === "true") return;
16
-
17
- const onAvailable = (e) =>
18
- setState((s) => ({
19
- ...s,
20
- updateStatus: "available",
21
- availableVersion: e.detail.version,
22
- forceUpdate: window.swUpdateRequired || false,
23
- }));
24
11
  const onProgress = (e) =>
25
- setState((s) => ({ ...s, updateStatus: "downloading", progress: e.detail.percent }));
12
+ setState((s) => ({ ...s, status: "installing", progress: e.detail.percent }));
13
+
26
14
  const onReady = () =>
27
- setState((s) => ({ ...s, updateStatus: "idle", progress: 0 }));
15
+ setState({ status: "idle", progress: 0, error: null });
16
+
28
17
  const onError = () =>
29
- setState((s) => ({ ...s, error: "SW registration failed" }));
18
+ setState({ status: "idle", progress: 0, error: "SW registration failed" });
30
19
 
31
- window.addEventListener("sw-update-available", onAvailable);
32
20
  window.addEventListener("sw-progress", onProgress);
33
21
  window.addEventListener("sw-ready", onReady);
34
22
  window.addEventListener("sw-error", onError);
35
23
  return () => {
36
- window.removeEventListener("sw-update-available", onAvailable);
37
24
  window.removeEventListener("sw-progress", onProgress);
38
25
  window.removeEventListener("sw-ready", onReady);
39
26
  window.removeEventListener("sw-error", onError);
40
27
  };
41
28
  }, []);
42
29
 
43
- const acceptUpdate = useCallback(async () => {
44
- if (!state.availableVersion) return;
45
- await handleUpdateApproved(state.availableVersion);
46
- }, [state.availableVersion]);
47
-
48
- const dismissUpdate = useCallback(() => {
49
- sessionStorage.setItem("sw-dismissed-update", "true");
50
- setState((s) => ({ ...s, updateStatus: "idle" }));
51
- }, []);
52
-
53
- return { ...state, acceptUpdate, dismissUpdate };
54
- }
55
-
56
- export function useSWProgress() {
57
- const [state, setState] = useState({
58
- status: "idle",
59
- progress: 0,
60
- });
61
-
62
- useEffect(() => {
63
- const onProgress = (e) =>
64
- setState({ status: "installing", progress: e.detail.percent });
65
- const onReady = () => setState({ status: "idle", progress: 0 });
66
-
67
- window.addEventListener("sw-progress", onProgress);
68
- window.addEventListener("sw-ready", onReady);
69
- return () => {
70
- window.removeEventListener("sw-progress", onProgress);
71
- window.removeEventListener("sw-ready", onReady);
72
- };
73
- }, []);
74
-
75
30
  return state;
76
31
  }
@@ -1,76 +1,37 @@
1
- import { useState, useEffect, useCallback } from "react";
2
- import { handleUpdateApproved } from "../sw/injector";
1
+ import { useState, useEffect } from "react";
2
+
3
+ type UpdateStatus = "idle" | "installing";
3
4
 
4
5
  export function useSWUpdate() {
5
6
  const [state, setState] = useState(() => ({
6
- updateStatus: "idle" as "idle" | "available" | "downloading" | "ready",
7
- currentVersion: typeof window !== "undefined" ? (window.currentSWVersion as string | undefined) || null : null,
8
- availableVersion: null as string | null,
9
- progress: 0 as number,
10
- forceUpdate: false,
7
+ status: "idle" as UpdateStatus,
8
+ progress: 0,
11
9
  error: null as string | null,
12
10
  }));
13
11
 
14
12
  useEffect(() => {
15
- if (sessionStorage.getItem("sw-dismissed-update") === "true") return;
16
-
17
- const onAvailable = (e: WindowEventMap["sw-update-available"]) =>
13
+ const onProgress = (e: WindowEventMap["sw-progress"]) =>
18
14
  setState((s) => ({
19
15
  ...s,
20
- updateStatus: "available",
21
- availableVersion: e.detail.version,
22
- forceUpdate: window.swUpdateRequired || false,
16
+ status: "installing",
17
+ progress: e.detail.percent,
23
18
  }));
24
- const onProgress = (e: WindowEventMap["sw-progress"]) =>
25
- setState((s) => ({ ...s, updateStatus: "downloading", progress: e.detail.percent }));
19
+
26
20
  const onReady = () =>
27
- setState((s) => ({ ...s, updateStatus: "idle", progress: 0 }));
21
+ setState({ status: "idle", progress: 0, error: null });
22
+
28
23
  const onError = () =>
29
- setState((s) => ({ ...s, error: "SW registration failed" }));
24
+ setState({ status: "idle", progress: 0, error: "SW registration failed" });
30
25
 
31
- window.addEventListener("sw-update-available", onAvailable);
32
26
  window.addEventListener("sw-progress", onProgress);
33
27
  window.addEventListener("sw-ready", onReady);
34
28
  window.addEventListener("sw-error", onError);
35
29
  return () => {
36
- window.removeEventListener("sw-update-available", onAvailable);
37
30
  window.removeEventListener("sw-progress", onProgress);
38
31
  window.removeEventListener("sw-ready", onReady);
39
32
  window.removeEventListener("sw-error", onError);
40
33
  };
41
34
  }, []);
42
35
 
43
- const acceptUpdate = useCallback(async () => {
44
- if (!state.availableVersion) return;
45
- await handleUpdateApproved(state.availableVersion);
46
- }, [state.availableVersion]);
47
-
48
- const dismissUpdate = useCallback(() => {
49
- sessionStorage.setItem("sw-dismissed-update", "true");
50
- setState((s) => ({ ...s, updateStatus: "idle" }));
51
- }, []);
52
-
53
- return { ...state, acceptUpdate, dismissUpdate };
54
- }
55
-
56
- export function useSWProgress() {
57
- const [state, setState] = useState({
58
- status: "idle" as "idle" | "installing",
59
- progress: 0 as number,
60
- });
61
-
62
- useEffect(() => {
63
- const onProgress = (e: WindowEventMap["sw-progress"]) =>
64
- setState({ status: "installing", progress: e.detail.percent });
65
- const onReady = () => setState({ status: "idle", progress: 0 });
66
-
67
- window.addEventListener("sw-progress", onProgress);
68
- window.addEventListener("sw-ready", onReady);
69
- return () => {
70
- window.removeEventListener("sw-progress", onProgress);
71
- window.removeEventListener("sw-ready", onReady);
72
- };
73
- }, []);
74
-
75
36
  return state;
76
37
  }
@@ -0,0 +1,56 @@
1
+ import { useState, useEffect } from "react";
2
+ import { getStorageEstimate, formatBytes } from "../storage";
3
+
4
+ /**
5
+ * Reactive storage estimate. Shows available quota and usage.
6
+ *
7
+ * Usage:
8
+ * const { usage, quota, percentUsed, formattedUsage, formattedQuota, loading } = useStorageEstimate();
9
+ *
10
+ * if (!loading && percentUsed > 80) return <StorageWarning />;
11
+ *
12
+ * @param autoRefresh - Re-check on visibility change (default true)
13
+ */
14
+ export function useStorageEstimate(autoRefresh = true) {
15
+ const [state, setState] = useState({
16
+ usage: 0,
17
+ quota: 0,
18
+ percentUsed: 0,
19
+ formattedUsage: "0 B",
20
+ formattedQuota: "0 B",
21
+ loading: true,
22
+ error: null,
23
+ });
24
+
25
+ const check = async () => {
26
+ try {
27
+ const { usage, quota, percentUsed } = await getStorageEstimate();
28
+ setState({
29
+ usage,
30
+ quota,
31
+ percentUsed,
32
+ formattedUsage: formatBytes(usage),
33
+ formattedQuota: formatBytes(quota),
34
+ loading: false,
35
+ error: null,
36
+ });
37
+ } catch (err) {
38
+ setState((s) => ({ ...s, loading: false, error: String(err) }));
39
+ }
40
+ };
41
+
42
+ useEffect(() => {
43
+ check();
44
+ }, []);
45
+
46
+ useEffect(() => {
47
+ if (!autoRefresh) return;
48
+ const onVisible = () => {
49
+ if (document.visibilityState === "visible") check();
50
+ };
51
+ document.addEventListener("visibilitychange", onVisible);
52
+ return () => document.removeEventListener("visibilitychange", onVisible);
53
+ }, [autoRefresh]);
54
+
55
+ return state;
56
+ }
@@ -0,0 +1,67 @@
1
+ import { useState, useEffect } from "react";
2
+ import { getStorageEstimate, formatBytes } from "../storage";
3
+
4
+ interface StorageEstimateState {
5
+ usage: number;
6
+ quota: number;
7
+ percentUsed: number;
8
+ formattedUsage: string;
9
+ formattedQuota: string;
10
+ loading: boolean;
11
+ error: string | null;
12
+ }
13
+
14
+ /**
15
+ * Reactive storage estimate. Shows available quota and usage.
16
+ *
17
+ * Usage:
18
+ * const { usage, quota, percentUsed, formattedUsage, formattedQuota, loading } = useStorageEstimate();
19
+ *
20
+ * if (!loading && percentUsed > 80) return <StorageWarning />;
21
+ *
22
+ * @param autoRefresh - Re-check on visibility change (default true)
23
+ * @returns {{ usage: number, quota: number, percentUsed: number, formattedUsage: string, formattedQuota: string, loading: boolean, error: string | null }}
24
+ */
25
+ export function useStorageEstimate(autoRefresh = true): StorageEstimateState {
26
+ const [state, setState] = useState<StorageEstimateState>({
27
+ usage: 0,
28
+ quota: 0,
29
+ percentUsed: 0,
30
+ formattedUsage: "0 B",
31
+ formattedQuota: "0 B",
32
+ loading: true,
33
+ error: null,
34
+ });
35
+
36
+ const check = async () => {
37
+ try {
38
+ const { usage, quota, percentUsed } = await getStorageEstimate();
39
+ setState({
40
+ usage,
41
+ quota,
42
+ percentUsed,
43
+ formattedUsage: formatBytes(usage),
44
+ formattedQuota: formatBytes(quota),
45
+ loading: false,
46
+ error: null,
47
+ });
48
+ } catch (err) {
49
+ setState((s) => ({ ...s, loading: false, error: String(err) }));
50
+ }
51
+ };
52
+
53
+ useEffect(() => {
54
+ check();
55
+ }, []);
56
+
57
+ useEffect(() => {
58
+ if (!autoRefresh) return;
59
+ const onVisible = () => {
60
+ if (document.visibilityState === "visible") check();
61
+ };
62
+ document.addEventListener("visibilitychange", onVisible);
63
+ return () => document.removeEventListener("visibilitychange", onVisible);
64
+ }, [autoRefresh]);
65
+
66
+ return state;
67
+ }
@@ -1,145 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { assembleSW } from "../lib/generators/sw-sections/assemble-sw.js";
3
- import { defaultConfig, defaultPwaAssets } from "../lib/shared/config-types.js";
4
- describe("assembleSW", () => {
5
- const config = {
6
- ...defaultConfig,
7
- };
8
- it("generates a service worker string", () => {
9
- const sw = assembleSW(config, "1.0.0");
10
- expect(sw).toContain("CACHE_NAME = 'sw-v1.0.0'");
11
- expect(sw).toContain("self.addEventListener");
12
- expect(sw).toContain("CACHE_NAME_RUNTIME");
13
- });
14
- it("includes config header with resolved version", () => {
15
- const sw = assembleSW(config, "2.5.0");
16
- expect(sw).toContain("Swoff Service Worker - Auto-Generated");
17
- expect(sw).toContain("Version: 2.5.0");
18
- expect(sw).not.toContain("Version: from-package");
19
- });
20
- it("includes install handler", () => {
21
- const sw = assembleSW(config, "1.0.0");
22
- expect(sw).toContain('self.addEventListener("install"');
23
- expect(sw).toContain("SW_PROGRESS");
24
- });
25
- it("includes activate handler with clients.claim()", () => {
26
- const sw = assembleSW(config, "1.0.0");
27
- expect(sw).toContain('self.addEventListener("activate"');
28
- expect(sw).toContain("caches.keys()");
29
- expect(sw).toContain("self.clients.claim()");
30
- });
31
- it("includes fetch handler with strategies", () => {
32
- const sw = assembleSW(config, "1.0.0");
33
- expect(sw).toContain('self.addEventListener("fetch"');
34
- expect(sw).toContain("cacheFirst");
35
- expect(sw).toContain("networkFirst");
36
- expect(sw).toContain("staleWhileRevalidate");
37
- expect(sw).toContain("cacheOnly");
38
- expect(sw).toContain("networkOnly");
39
- expect(sw).toContain("reactiveStrategy");
40
- });
41
- it("checks precache from all strategies", () => {
42
- const sw = assembleSW(config, "1.0.0");
43
- expect(sw).toContain("fromPrecache");
44
- expect(sw).toContain("async function fromPrecache");
45
- expect(sw).toContain("return cache.match(new URL");
46
- expect(sw).toContain("precached = await fromPrecache(request)");
47
- });
48
- it("includes message handler", () => {
49
- const sw = assembleSW(config, "1.0.0");
50
- expect(sw).toContain('self.addEventListener("message"');
51
- expect(sw).toContain("SKIP_WAITING");
52
- });
53
- it("includes tag management", () => {
54
- const sw = assembleSW(config, "1.0.0");
55
- expect(sw).toContain("invalidateByTag");
56
- expect(sw).toContain("INVALIDATE_TAG");
57
- });
58
- it("includes background sync handler when enabled", () => {
59
- const configWithSync = {
60
- ...config,
61
- features: { ...config.features, backgroundSync: true },
62
- };
63
- const sw = assembleSW(configWithSync, "1.0.0");
64
- expect(sw).toContain('self.addEventListener("sync"');
65
- expect(sw).toContain("sync-mutations");
66
- });
67
- it("excludes background sync when disabled", () => {
68
- const sw = assembleSW(config, "1.0.0");
69
- expect(sw).not.toContain('self.addEventListener("sync"');
70
- });
71
- it("sets AUTO_SKIP_WAITING based on autoActivate config", () => {
72
- const configAutoActivate = {
73
- ...config,
74
- features: {
75
- ...config.features,
76
- serviceWorker: { ...config.features.serviceWorker, autoActivate: true },
77
- },
78
- };
79
- const sw = assembleSW(configAutoActivate, "1.0.0");
80
- expect(sw).toContain("const AUTO_SKIP_WAITING = true");
81
- const configNoAutoActivate = {
82
- ...config,
83
- features: {
84
- ...config.features,
85
- serviceWorker: { ...config.features.serviceWorker, autoActivate: false },
86
- },
87
- };
88
- const sw2 = assembleSW(configNoAutoActivate, "1.0.0");
89
- expect(sw2).toContain("const AUTO_SKIP_WAITING = false");
90
- });
91
- it("uses hash-based cache name when version mode is 'hash'", () => {
92
- const configHash = {
93
- ...config,
94
- features: {
95
- ...config.features,
96
- serviceWorker: {
97
- ...config.features.serviceWorker,
98
- version: "hash",
99
- },
100
- },
101
- };
102
- const sw = assembleSW(configHash, "1.0.0");
103
- expect(sw).toContain("CACHE_NAME = 'sw-cache-");
104
- expect(sw).not.toContain("sw-v1.0.0");
105
- });
106
- it("includes PWA assets when pwa feature is enabled", () => {
107
- const configWithPwa = {
108
- ...config,
109
- features: { ...config.features, pwa: { enabled: true, preventDefaultInstall: false, assets: { ...defaultPwaAssets } } },
110
- };
111
- const sw = assembleSW(configWithPwa, "1.0.0");
112
- expect(sw).toContain("/manifest.json");
113
- });
114
- it("excludes PWA assets when pwa feature is disabled", () => {
115
- const configNoPwa = {
116
- ...config,
117
- features: { ...config.features, pwa: { enabled: false, preventDefaultInstall: false, assets: { ...defaultPwaAssets } } },
118
- };
119
- const sw = assembleSW(configNoPwa, "1.0.0");
120
- expect(sw).not.toContain("/manifest.json");
121
- });
122
- it("includes custom strategies in fetch handler", () => {
123
- const configWithStrategies = {
124
- ...config,
125
- features: {
126
- ...config.features,
127
- serviceWorker: {
128
- ...config.features.serviceWorker,
129
- strategy: { ...config.features.serviceWorker.strategy, patterns: { "/api/*": "network-first" } },
130
- },
131
- },
132
- };
133
- const sw = assembleSW(configWithStrategies, "1.0.0");
134
- expect(sw).toContain("/api/*");
135
- expect(sw).toContain("network-first");
136
- expect(sw).toContain("new URL(request.url).pathname");
137
- expect(sw).toContain("matchGlob");
138
- });
139
- it("includes refresh retry constants", () => {
140
- const sw = assembleSW(config, "1.0.0");
141
- expect(sw).toContain("REFRESH_MAX_RETRIES");
142
- expect(sw).toContain("REFRESH_RETRY_DELAY_MS");
143
- });
144
- });
145
- //# sourceMappingURL=assemble-sw.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"assemble-sw.test.js","sourceRoot":"","sources":["../../src/__tests__/assemble-sw.test.ts"],"names":[],"mappings":"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"}