@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
@@ -1,69 +0,0 @@
1
- import { useState, useEffect, useCallback, startTransition } from "react";
2
- import { fetchWithCache } from "../fetch-wrapper.js";
3
- import { generateTags } from "../invalidation-tags.js";
4
-
5
- export function useCachedFetch(url, options = {}) {
6
- const [data, setData] = useState(null);
7
- const [error, setError] = useState(null);
8
- const [loading, setLoading] = useState(true);
9
- const [refetchCount, setRefetchCount] = useState(0);
10
-
11
- const refetch = useCallback(() => setRefetchCount((c) => c + 1), []);
12
-
13
- const isEnabled = options.enabled !== false && url != null;
14
-
15
- useEffect(() => {
16
- if (!isEnabled) {
17
- startTransition(() => setLoading(false));
18
- return;
19
- }
20
- let cancelled = false;
21
- const controller = new AbortController();
22
- startTransition(() => setLoading(true));
23
-
24
- const doFetch = async () => {
25
- try {
26
- const { response } = await fetchWithCache(url, {
27
- ...options,
28
- signal: controller.signal,
29
- });
30
- if (cancelled) return;
31
- if (response) {
32
- setData(await response.json());
33
- } else {
34
- setData(null);
35
- }
36
- if (!cancelled) setError(null);
37
- } catch (err) {
38
- if (!cancelled && err instanceof DOMException && err.name === "AbortError") return;
39
- if (!cancelled) setError(err instanceof Error ? err : new Error(String(err)));
40
- } finally {
41
- if (!cancelled) setLoading(false);
42
- }
43
- };
44
-
45
- doFetch();
46
- return () => {
47
- cancelled = true;
48
- controller.abort();
49
- };
50
- }, [url, refetchCount, isEnabled]);
51
-
52
- // Auto-refetch on cache invalidation
53
- useEffect(() => {
54
- if (!isEnabled) return;
55
- const onInvalidated = (e) => {
56
- const detail = e.detail;
57
- const tags = detail?.tags;
58
- if (!tags || !Array.isArray(tags)) return;
59
- const urlTags = generateTags(url);
60
- if (tags.some((t) => urlTags.includes(t))) {
61
- setRefetchCount((c) => c + 1);
62
- }
63
- };
64
- window.addEventListener("cache-invalidated", onInvalidated);
65
- return () => window.removeEventListener("cache-invalidated", onInvalidated);
66
- }, [url, isEnabled]);
67
-
68
- return { data, error, loading, refetch };
69
- }
@@ -1,81 +0,0 @@
1
- import {
2
- useState,
3
- useEffect,
4
- useCallback,
5
- startTransition,
6
- } from "react";
7
- import { fetchWithCache } from "../fetch-wrapper.ts";
8
- import { generateTags } from "../invalidation-tags.ts";
9
- import type { FetchWithCacheOptions } from "../fetch-wrapper.ts";
10
-
11
- export function useCachedFetch<T>(
12
- url: string | null,
13
- options: FetchWithCacheOptions & {
14
- enabled?: boolean;
15
- } = {},
16
- ) {
17
- const [data, setData] = useState<T | null>(null);
18
- const [error, setError] = useState<Error | null>(null);
19
- const [loading, setLoading] = useState(true);
20
- const [refetchCount, setRefetchCount] = useState(0);
21
-
22
- const refetch = useCallback(() => setRefetchCount((c) => c + 1), []);
23
-
24
- const isEnabled = options.enabled !== false && url != null;
25
-
26
- useEffect(() => {
27
- if (!isEnabled) {
28
- startTransition(() => setLoading(false));
29
- return;
30
- }
31
- let cancelled = false;
32
- const controller = new AbortController();
33
- startTransition(() => setLoading(true));
34
-
35
- const doFetch = async () => {
36
- try {
37
- const { response } = await fetchWithCache(url, {
38
- ...options,
39
- signal: controller.signal,
40
- });
41
- if (cancelled) return;
42
- if (response) {
43
- setData(await response.json());
44
- } else {
45
- setData(null);
46
- }
47
- if (!cancelled) setError(null);
48
- } catch (err) {
49
- if (!cancelled && err instanceof DOMException && err.name === "AbortError") return;
50
- if (!cancelled)
51
- setError(err instanceof Error ? err : new Error(String(err)));
52
- } finally {
53
- if (!cancelled) setLoading(false);
54
- }
55
- };
56
-
57
- doFetch();
58
- return () => {
59
- cancelled = true;
60
- controller.abort();
61
- };
62
- }, [url, refetchCount, isEnabled]);
63
-
64
- // Auto-refetch on cache invalidation
65
- useEffect(() => {
66
- if (!isEnabled) return;
67
- const onInvalidated = (e: Event) => {
68
- const detail = (e as CustomEvent).detail;
69
- const tags = detail?.tags;
70
- if (!tags || !Array.isArray(tags)) return;
71
- const urlTags = generateTags(url!);
72
- if (tags.some((t: string) => urlTags.includes(t))) {
73
- setRefetchCount((c) => c + 1);
74
- }
75
- };
76
- window.addEventListener("cache-invalidated", onInvalidated);
77
- return () => window.removeEventListener("cache-invalidated", onInvalidated);
78
- }, [url, isEnabled]);
79
-
80
- return { data, error, loading, refetch };
81
- }
@@ -1,76 +0,0 @@
1
- import { useEffect, useState, useCallback, useRef } from "react";
2
- import { fetchWithCache } from "../fetch-wrapper.js";
3
- import {
4
- trackMutation,
5
- resolveMutation,
6
- rejectMutation,
7
- } from "../mutation-state.js";
8
-
9
- export function useMutation(options = {}) {
10
- const [state, setState] = useState({
11
- data: null,
12
- error: null,
13
- isLoading: false,
14
- isError: false,
15
- isSuccess: false,
16
- });
17
-
18
- const optionsRef = useRef(options);
19
-
20
- useEffect(() => {
21
- optionsRef.current = options;
22
- }, [options]);
23
-
24
- const mutate = useCallback(async (url, fetchOptions = {}) => {
25
- const mutationId = "mut-" + crypto.randomUUID();
26
- trackMutation(mutationId, "pending");
27
- setState({
28
- data: null,
29
- error: null,
30
- isLoading: true,
31
- isError: false,
32
- isSuccess: false,
33
- });
34
-
35
- try {
36
- const { response } = await fetchWithCache(url, fetchOptions);
37
- const data = await response.json();
38
- resolveMutation(mutationId, data);
39
- setState({
40
- data,
41
- error: null,
42
- isLoading: false,
43
- isError: false,
44
- isSuccess: true,
45
- });
46
- optionsRef.current.onSuccess?.(data);
47
- optionsRef.current.onSettled?.();
48
- return data;
49
- } catch (err) {
50
- const error = err instanceof Error ? err : new Error(String(err));
51
- rejectMutation(mutationId, error);
52
- setState({
53
- data: null,
54
- error,
55
- isLoading: false,
56
- isError: true,
57
- isSuccess: false,
58
- });
59
- optionsRef.current.onError?.(error);
60
- optionsRef.current.onSettled?.();
61
- return null;
62
- }
63
- }, []);
64
-
65
- const reset = useCallback(() => {
66
- setState({
67
- data: null,
68
- error: null,
69
- isLoading: false,
70
- isError: false,
71
- isSuccess: false,
72
- });
73
- }, []);
74
-
75
- return { ...state, mutate, reset };
76
- }
@@ -1,109 +0,0 @@
1
- import { useEffect, useState, useCallback, useRef } from "react";
2
- import { fetchWithCache } from "../fetch-wrapper.ts";
3
- import {
4
- trackMutation,
5
- resolveMutation,
6
- rejectMutation,
7
- } from "../mutation-state.ts";
8
- import type { FetchWithCacheOptions } from "../fetch-wrapper.ts";
9
-
10
- export interface UseMutationOptions<TData> {
11
- onSuccess?: (data: TData) => void;
12
- onError?: (error: Error) => void;
13
- onSettled?: () => void;
14
- }
15
-
16
- export function useMutation<TData = unknown>(
17
- options: UseMutationOptions<TData> = {},
18
- ) {
19
- const [state, setState] = useState<{
20
- data: TData | null;
21
- error: Error | null;
22
- isLoading: boolean;
23
- isError: boolean;
24
- isSuccess: boolean;
25
- }>({
26
- data: null,
27
- error: null,
28
- isLoading: false,
29
- isError: false,
30
- isSuccess: false,
31
- });
32
-
33
- const optionsRef = useRef(options);
34
-
35
- useEffect(() => {
36
- optionsRef.current = options;
37
- }, [options]);
38
-
39
- const mutate = useCallback(
40
- async (
41
- url: string,
42
- fetchOptions: FetchWithCacheOptions = {},
43
- ): Promise<TData | null> => {
44
- const mutationId = "mut-" + crypto.randomUUID();
45
- trackMutation(mutationId, "pending");
46
- setState({
47
- data: null,
48
- error: null,
49
- isLoading: true,
50
- isError: false,
51
- isSuccess: false,
52
- });
53
-
54
- try {
55
- const { response, queued } = await fetchWithCache<TData>(url, fetchOptions);
56
- if (queued) {
57
- resolveMutation(mutationId, null);
58
- setState({
59
- data: null,
60
- error: null,
61
- isLoading: false,
62
- isError: false,
63
- isSuccess: false,
64
- });
65
- optionsRef.current.onSettled?.();
66
- return null;
67
- }
68
- const data: TData = await response.json();
69
- resolveMutation(mutationId, data);
70
- setState({
71
- data,
72
- error: null,
73
- isLoading: false,
74
- isError: false,
75
- isSuccess: true,
76
- });
77
- optionsRef.current.onSuccess?.(data);
78
- optionsRef.current.onSettled?.();
79
- return data;
80
- } catch (err) {
81
- const error = err instanceof Error ? err : new Error(String(err));
82
- rejectMutation(mutationId, error);
83
- setState({
84
- data: null,
85
- error,
86
- isLoading: false,
87
- isError: true,
88
- isSuccess: false,
89
- });
90
- optionsRef.current.onError?.(error);
91
- optionsRef.current.onSettled?.();
92
- return null;
93
- }
94
- },
95
- [],
96
- );
97
-
98
- const reset = useCallback(() => {
99
- setState({
100
- data: null,
101
- error: null,
102
- isLoading: false,
103
- isError: false,
104
- isSuccess: false,
105
- });
106
- }, []);
107
-
108
- return { ...state, mutate, reset };
109
- }
@@ -1,43 +0,0 @@
1
- import { useState, useEffect, useCallback } from "react";
2
- import { getPendingCount, getQueueItems } from "../mutation-queue.js";
3
-
4
- export function useMutationQueue() {
5
- const [state, setState] = useState({
6
- pending: 0,
7
- items: [],
8
- lastSync: null,
9
- });
10
-
11
- const refresh = useCallback(async () => {
12
- const [count, items] = await Promise.all([
13
- getPendingCount(),
14
- getQueueItems(),
15
- ]);
16
- setState((s) => ({ ...s, pending: count, items }));
17
- }, []);
18
-
19
- useEffect(() => {
20
- // Defer initial data load to avoid cascading render warning
21
- queueMicrotask(() => refresh());
22
-
23
- const onSync = (e) => {
24
- refresh();
25
- setState((s) => ({
26
- ...s,
27
- lastSync: { succeeded: e.detail.succeeded, failed: e.detail.failed },
28
- }));
29
- };
30
- const onChange = () => {
31
- refresh();
32
- };
33
-
34
- window.addEventListener("mutation-sync-complete", onSync);
35
- window.addEventListener("mutation-queue-changed", onChange);
36
- return () => {
37
- window.removeEventListener("mutation-sync-complete", onSync);
38
- window.removeEventListener("mutation-queue-changed", onChange);
39
- };
40
- }, [refresh]);
41
-
42
- return state;
43
- }
@@ -1,50 +0,0 @@
1
- import { useState, useEffect, useCallback } from "react";
2
- import { getPendingCount, getQueueItems } from "../mutation-queue.ts";
3
- import type { MutationQueueItem } from "../swoff.d.ts";
4
-
5
- export interface MutationQueueState {
6
- pending: number;
7
- items: MutationQueueItem[];
8
- lastSync: { succeeded: number; failed: number } | null;
9
- }
10
-
11
- export function useMutationQueue() {
12
- const [state, setState] = useState<MutationQueueState>({
13
- pending: 0,
14
- items: [],
15
- lastSync: null,
16
- });
17
-
18
- const refresh = useCallback(async () => {
19
- const [count, items] = await Promise.all([
20
- getPendingCount(),
21
- getQueueItems(),
22
- ]);
23
- setState((s) => ({ ...s, pending: count, items }));
24
- }, []);
25
-
26
- useEffect(() => {
27
- // Defer initial data load to avoid cascading render warning
28
- queueMicrotask(() => refresh());
29
-
30
- const onSync = (e: CustomEvent) => {
31
- refresh();
32
- setState((s) => ({
33
- ...s,
34
- lastSync: { succeeded: e.detail.succeeded, failed: e.detail.failed },
35
- }));
36
- };
37
- const onChange = () => {
38
- refresh();
39
- };
40
-
41
- window.addEventListener("mutation-sync-complete", onSync);
42
- window.addEventListener("mutation-queue-changed", onChange);
43
- return () => {
44
- window.removeEventListener("mutation-sync-complete", onSync);
45
- window.removeEventListener("mutation-queue-changed", onChange);
46
- };
47
- }, [refresh]);
48
-
49
- return state;
50
- }
@@ -1,19 +0,0 @@
1
- import { useState, useEffect } from "react";
2
-
3
- export function useNetworkStatus() {
4
- const [online, setOnline] = useState(navigator.onLine);
5
-
6
- useEffect(() => {
7
- const onOnline = () => setOnline(true);
8
- const onOffline = () => setOnline(false);
9
-
10
- window.addEventListener("online", onOnline);
11
- window.addEventListener("offline", onOffline);
12
- return () => {
13
- window.removeEventListener("online", onOnline);
14
- window.removeEventListener("offline", onOffline);
15
- };
16
- }, []);
17
-
18
- return online;
19
- }
@@ -1,19 +0,0 @@
1
- import { useState, useEffect } from "react";
2
-
3
- export function useNetworkStatus() {
4
- const [online, setOnline] = useState(navigator.onLine);
5
-
6
- useEffect(() => {
7
- const onOnline = () => setOnline(true);
8
- const onOffline = () => setOnline(false);
9
-
10
- window.addEventListener("online", onOnline);
11
- window.addEventListener("offline", onOffline);
12
- return () => {
13
- window.removeEventListener("online", onOnline);
14
- window.removeEventListener("offline", onOffline);
15
- };
16
- }, []);
17
-
18
- return online;
19
- }
@@ -1,10 +0,0 @@
1
- import { useCallback } from "react";
2
- import { prefetchCache } from "../fetch-wrapper.js";
3
-
4
- export function usePrefetch() {
5
- const prefetch = useCallback((url, options) => {
6
- prefetchCache(url, options);
7
- }, []);
8
-
9
- return prefetch;
10
- }
@@ -1,25 +0,0 @@
1
- import { useCallback } from "react";
2
- import { prefetchCache } from "../fetch-wrapper.ts";
3
- import type { FetchWithCacheOptions } from "../fetch-wrapper.ts";
4
-
5
- /**
6
- * Hook that returns a stable prefetch callback for warming the SW cache.
7
- * Useful for route-level prefetching, link hover prefetching, etc.
8
- *
9
- * Usage:
10
- * const prefetch = usePrefetch();
11
- * <Link onMouseEnter={() => prefetch("/api/todos")} to="/todos" />
12
- */
13
- export function usePrefetch(): (
14
- url: string,
15
- options?: FetchWithCacheOptions,
16
- ) => void {
17
- const prefetch = useCallback(
18
- (url: string, options?: FetchWithCacheOptions) => {
19
- prefetchCache(url, options);
20
- },
21
- [],
22
- );
23
-
24
- return prefetch;
25
- }
File without changes
File without changes