@swoff/cli 0.3.8 → 0.3.9
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.
- package/README.md +47 -33
- package/dist/__tests__/assemble-sw.test.js +8 -38
- package/dist/__tests__/assemble-sw.test.js.map +1 -1
- package/dist/__tests__/cli-integration.test.js +119 -11
- package/dist/__tests__/cli-integration.test.js.map +1 -1
- package/dist/__tests__/config-types.test.js +32 -15
- package/dist/__tests__/config-types.test.js.map +1 -1
- package/dist/__tests__/file-generators.test.js +2 -2
- package/dist/__tests__/file-generators.test.js.map +1 -1
- package/dist/__tests__/glob-matcher.test.js +86 -0
- package/dist/__tests__/glob-matcher.test.js.map +1 -0
- package/dist/__tests__/invalidation-tags.test.js +207 -23
- package/dist/__tests__/invalidation-tags.test.js.map +1 -1
- package/dist/__tests__/loader.test.js +12 -12
- package/dist/__tests__/loader.test.js.map +1 -1
- package/dist/__tests__/validator.test.js +144 -97
- package/dist/__tests__/validator.test.js.map +1 -1
- package/dist/index.js +11 -10
- package/dist/index.js.map +1 -1
- package/dist/lib/cli/help.js +0 -5
- package/dist/lib/cli/help.js.map +1 -1
- package/dist/lib/commands/add.js +50 -32
- package/dist/lib/commands/add.js.map +1 -1
- package/dist/lib/commands/clean.js +1 -15
- package/dist/lib/commands/clean.js.map +1 -1
- package/dist/lib/commands/generate-guide.js +2 -2
- package/dist/lib/commands/generate-guide.js.map +1 -1
- package/dist/lib/commands/generate.js +7 -21
- package/dist/lib/commands/generate.js.map +1 -1
- package/dist/lib/commands/info.js +8 -6
- package/dist/lib/commands/info.js.map +1 -1
- package/dist/lib/commands/init.js +2 -10
- package/dist/lib/commands/init.js.map +1 -1
- package/dist/lib/commands/validate.js +3 -3
- package/dist/lib/commands/validate.js.map +1 -1
- package/dist/lib/config/loader.js +3 -6
- package/dist/lib/config/loader.js.map +1 -1
- package/dist/lib/config/validator.js +157 -88
- package/dist/lib/config/validator.js.map +1 -1
- package/dist/lib/generators/file-generators/cache.js +2 -10
- package/dist/lib/generators/file-generators/cache.js.map +1 -1
- package/dist/lib/generators/file-generators/client-injector.js +50 -11
- package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/fetch-wrapper.js +92 -64
- package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/generate-hooks.js +1 -1
- package/dist/lib/generators/file-generators/generate-hooks.js.map +1 -1
- package/dist/lib/generators/file-generators/gql-wrapper.js +1 -14
- package/dist/lib/generators/file-generators/gql-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/guide-generator.js +6 -640
- package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
- package/dist/lib/generators/file-generators/invalidation-tags.js +206 -19
- package/dist/lib/generators/file-generators/invalidation-tags.js.map +1 -1
- package/dist/lib/generators/file-generators/manifest.js +2 -2
- package/dist/lib/generators/file-generators/manifest.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-queue.js +29 -9
- package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
- package/dist/lib/generators/file-generators/push.js +6 -7
- package/dist/lib/generators/file-generators/push.js.map +1 -1
- package/dist/lib/generators/file-generators/quick-readme.js +8 -125
- package/dist/lib/generators/file-generators/quick-readme.js.map +1 -1
- package/dist/lib/generators/file-generators/server-push.js +11 -1
- package/dist/lib/generators/file-generators/server-push.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-generator-build.js +8 -9
- package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-injector.js +2 -1
- package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/type-definitions.js +0 -3
- package/dist/lib/generators/file-generators/type-definitions.js.map +1 -1
- package/dist/lib/generators/sw-generator.js +8 -18
- package/dist/lib/generators/sw-generator.js.map +1 -1
- package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js +14 -11
- package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
- package/dist/lib/generators/sw-sections/background-sync-handler.js +59 -17
- package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/config-header.js +2 -2
- package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
- package/dist/lib/generators/sw-sections/fetch-handler.js +437 -136
- package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/message-handler.js +55 -15
- package/dist/lib/generators/sw-sections/message-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/sw-push.js +67 -0
- package/dist/lib/generators/sw-sections/sw-push.js.map +1 -0
- package/dist/lib/generators/sw-sections/tag-management.js +60 -20
- package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
- package/dist/lib/generators/swoff-files-generator.js +5 -15
- package/dist/lib/generators/swoff-files-generator.js.map +1 -1
- package/dist/lib/shared/config-types.js +121 -71
- package/dist/lib/shared/config-types.js.map +1 -1
- package/dist/lib/shared/glob-matcher.js +77 -0
- package/dist/lib/shared/glob-matcher.js.map +1 -0
- package/dist/lib/utils/tty-status.js +21 -0
- package/dist/lib/utils/tty-status.js.map +1 -0
- package/docs/API.md +565 -0
- package/docs/ARCHITECTURE.md +374 -0
- package/docs/CLI.md +148 -0
- package/docs/COMPARISON.md +192 -0
- package/docs/CONFIG.md +277 -0
- package/docs/ECOSYSTEM.md +33 -0
- package/package.json +2 -1
- package/templates/hooks/useAuth.jsx +2 -2
- package/templates/hooks/useAuth.tsx +2 -2
- package/templates/hooks/useCachedFetch.jsx +3 -28
- package/templates/hooks/useCachedFetch.tsx +2 -33
- package/templates/hooks/useMutation.tsx +13 -1
- package/templates/hooks/useMutationQueue.jsx +2 -1
- package/templates/hooks/useMutationQueue.tsx +2 -1
- package/templates/hooks/useMutationState.jsx +8 -22
- package/templates/hooks/useMutationState.tsx +8 -24
- package/templates/hooks/usePushSubscription.jsx +3 -3
- package/templates/hooks/usePushSubscription.tsx +3 -3
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
useState,
|
|
3
3
|
useEffect,
|
|
4
4
|
useCallback,
|
|
5
|
-
useRef,
|
|
6
5
|
startTransition,
|
|
7
6
|
} from "react";
|
|
8
7
|
import { fetchWithCache } from "../fetch-wrapper.ts";
|
|
@@ -12,9 +11,6 @@ import type { FetchWithCacheOptions } from "../fetch-wrapper.ts";
|
|
|
12
11
|
export function useCachedFetch<T>(
|
|
13
12
|
url: string | null,
|
|
14
13
|
options: FetchWithCacheOptions & {
|
|
15
|
-
refetchOnWindowFocus?: boolean;
|
|
16
|
-
refetchOnReconnect?: boolean;
|
|
17
|
-
refetchInterval?: number;
|
|
18
14
|
enabled?: boolean;
|
|
19
15
|
} = {},
|
|
20
16
|
) {
|
|
@@ -22,10 +18,6 @@ export function useCachedFetch<T>(
|
|
|
22
18
|
const [error, setError] = useState<Error | null>(null);
|
|
23
19
|
const [loading, setLoading] = useState(true);
|
|
24
20
|
const [refetchCount, setRefetchCount] = useState(0);
|
|
25
|
-
const optionsRef = useRef(options);
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
optionsRef.current = options;
|
|
28
|
-
}, [options]);
|
|
29
21
|
|
|
30
22
|
const refetch = useCallback(() => setRefetchCount((c) => c + 1), []);
|
|
31
23
|
|
|
@@ -33,7 +25,7 @@ export function useCachedFetch<T>(
|
|
|
33
25
|
|
|
34
26
|
useEffect(() => {
|
|
35
27
|
if (!isEnabled) {
|
|
36
|
-
setLoading(false);
|
|
28
|
+
startTransition(() => setLoading(false));
|
|
37
29
|
return;
|
|
38
30
|
}
|
|
39
31
|
let cancelled = false;
|
|
@@ -43,7 +35,7 @@ export function useCachedFetch<T>(
|
|
|
43
35
|
const doFetch = async () => {
|
|
44
36
|
try {
|
|
45
37
|
const { response } = await fetchWithCache(url, {
|
|
46
|
-
...
|
|
38
|
+
...options,
|
|
47
39
|
signal: controller.signal,
|
|
48
40
|
});
|
|
49
41
|
if (cancelled) return;
|
|
@@ -85,28 +77,5 @@ export function useCachedFetch<T>(
|
|
|
85
77
|
return () => window.removeEventListener("cache-invalidated", onInvalidated);
|
|
86
78
|
}, [url, isEnabled]);
|
|
87
79
|
|
|
88
|
-
// Auto-refetch on window focus
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
if (!options.refetchOnWindowFocus || !isEnabled) return;
|
|
91
|
-
const onFocus = () => refetch();
|
|
92
|
-
window.addEventListener("focus", onFocus);
|
|
93
|
-
return () => window.removeEventListener("focus", onFocus);
|
|
94
|
-
}, [options.refetchOnWindowFocus, refetch, isEnabled]);
|
|
95
|
-
|
|
96
|
-
// Auto-refetch on reconnect
|
|
97
|
-
useEffect(() => {
|
|
98
|
-
if (!options.refetchOnReconnect || !isEnabled) return;
|
|
99
|
-
const onOnline = () => refetch();
|
|
100
|
-
window.addEventListener("online", onOnline);
|
|
101
|
-
return () => window.removeEventListener("online", onOnline);
|
|
102
|
-
}, [options.refetchOnReconnect, refetch, isEnabled]);
|
|
103
|
-
|
|
104
|
-
// Auto-refetch on interval
|
|
105
|
-
useEffect(() => {
|
|
106
|
-
if (!options.refetchInterval || options.refetchInterval <= 0 || !isEnabled) return;
|
|
107
|
-
const id = setInterval(refetch, options.refetchInterval * 1000);
|
|
108
|
-
return () => clearInterval(id);
|
|
109
|
-
}, [options.refetchInterval, refetch, isEnabled]);
|
|
110
|
-
|
|
111
80
|
return { data, error, loading, refetch };
|
|
112
81
|
}
|
|
@@ -52,7 +52,19 @@ export function useMutation<TData = unknown>(
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
try {
|
|
55
|
-
const { response } = await fetchWithCache<TData>(url, fetchOptions);
|
|
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
|
+
}
|
|
56
68
|
const data: TData = await response.json();
|
|
57
69
|
resolveMutation(mutationId, data);
|
|
58
70
|
setState({
|
|
@@ -1,27 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
2
|
import { getMutationState, onMutationStateChange } from "../mutation-state.js";
|
|
3
3
|
|
|
4
|
+
function subscribeToMutations(cb) {
|
|
5
|
+
return onMutationStateChange(() => cb());
|
|
6
|
+
}
|
|
7
|
+
|
|
4
8
|
export function useMutationState(id) {
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
return useSyncExternalStore(
|
|
10
|
+
subscribeToMutations,
|
|
11
|
+
() => (id ? getMutationState(id) ?? null : null),
|
|
7
12
|
);
|
|
8
|
-
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
if (!id) {
|
|
11
|
-
setState(null);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
setState(getMutationState(id) ?? null);
|
|
16
|
-
|
|
17
|
-
const unsub = onMutationStateChange((updated) => {
|
|
18
|
-
if (updated.id === id) {
|
|
19
|
-
setState(updated);
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return unsub;
|
|
24
|
-
}, [id]);
|
|
25
|
-
|
|
26
|
-
return state;
|
|
27
13
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
2
|
import {
|
|
3
3
|
getMutationState,
|
|
4
4
|
onMutationStateChange,
|
|
5
5
|
} from "../mutation-state.ts";
|
|
6
6
|
import type { MutationState } from "../mutation-state.ts";
|
|
7
7
|
|
|
8
|
+
function subscribeToMutations(cb: () => void) {
|
|
9
|
+
return onMutationStateChange(() => cb());
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
/**
|
|
9
13
|
* Hook that subscribes to a specific mutation's state changes.
|
|
10
14
|
* Useful for showing per-mutation loading spinners, error states, etc.
|
|
@@ -14,28 +18,8 @@ import type { MutationState } from "../mutation-state.ts";
|
|
|
14
18
|
* if (mutation?.status === "error") { ... }
|
|
15
19
|
*/
|
|
16
20
|
export function useMutationState(id: string | null): MutationState | null {
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
return useSyncExternalStore(
|
|
22
|
+
subscribeToMutations,
|
|
23
|
+
() => (id ? getMutationState(id) ?? null : null),
|
|
19
24
|
);
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
if (!id) {
|
|
23
|
-
setState(null);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Initial state
|
|
28
|
-
setState(getMutationState(id) ?? null);
|
|
29
|
-
|
|
30
|
-
// Subscribe to changes
|
|
31
|
-
const unsub = onMutationStateChange((updated) => {
|
|
32
|
-
if (updated.id === id) {
|
|
33
|
-
setState(updated);
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
return unsub;
|
|
38
|
-
}, [id]);
|
|
39
|
-
|
|
40
|
-
return state;
|
|
41
25
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getPushSubscription,
|
|
7
7
|
} from "../push.js";
|
|
8
8
|
|
|
9
|
-
export function usePushSubscription(
|
|
9
|
+
export function usePushSubscription() {
|
|
10
10
|
const [state, setState] = useState({
|
|
11
11
|
subscribed: false,
|
|
12
12
|
subscription: null,
|
|
@@ -55,9 +55,9 @@ export function usePushSubscription(vapidPublicKey) {
|
|
|
55
55
|
}, []);
|
|
56
56
|
|
|
57
57
|
const subscribe = useCallback(async () => {
|
|
58
|
-
const sub = await subscribeToPush(
|
|
58
|
+
const sub = await subscribeToPush();
|
|
59
59
|
return sub !== null;
|
|
60
|
-
}, [
|
|
60
|
+
}, []);
|
|
61
61
|
|
|
62
62
|
const unsubscribe = useCallback(async () => {
|
|
63
63
|
await unsubscribeFromPush();
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getPushSubscription,
|
|
7
7
|
} from "../push.ts";
|
|
8
8
|
|
|
9
|
-
export function usePushSubscription(
|
|
9
|
+
export function usePushSubscription() {
|
|
10
10
|
const [state, setState] = useState({
|
|
11
11
|
subscribed: false,
|
|
12
12
|
subscription: null as PushSubscription | null,
|
|
@@ -55,9 +55,9 @@ export function usePushSubscription(vapidPublicKey: string) {
|
|
|
55
55
|
}, []);
|
|
56
56
|
|
|
57
57
|
const subscribe = useCallback(async () => {
|
|
58
|
-
const sub = await subscribeToPush(
|
|
58
|
+
const sub = await subscribeToPush();
|
|
59
59
|
return sub !== null;
|
|
60
|
-
}, [
|
|
60
|
+
}, []);
|
|
61
61
|
|
|
62
62
|
const unsubscribe = useCallback(async () => {
|
|
63
63
|
await unsubscribeFromPush();
|