@swoff/cli 0.3.7 → 0.3.8

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 (66) hide show
  1. package/README.md +43 -610
  2. package/dist/__tests__/assemble-sw.test.js +4 -4
  3. package/dist/__tests__/assemble-sw.test.js.map +1 -1
  4. package/dist/__tests__/config-types.test.js +7 -4
  5. package/dist/__tests__/config-types.test.js.map +1 -1
  6. package/dist/__tests__/validator.test.js +50 -1
  7. package/dist/__tests__/validator.test.js.map +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/lib/commands/add.js +5 -4
  11. package/dist/lib/commands/add.js.map +1 -1
  12. package/dist/lib/commands/generate-guide.js +3 -3
  13. package/dist/lib/commands/generate-guide.js.map +1 -1
  14. package/dist/lib/commands/info.js +29 -6
  15. package/dist/lib/commands/info.js.map +1 -1
  16. package/dist/lib/config/validator.js +85 -4
  17. package/dist/lib/config/validator.js.map +1 -1
  18. package/dist/lib/generators/file-generators/client-injector.js +1 -1
  19. package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
  20. package/dist/lib/generators/file-generators/fetch-wrapper.js +55 -14
  21. package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
  22. package/dist/lib/generators/file-generators/generate-hooks.js +5 -1
  23. package/dist/lib/generators/file-generators/generate-hooks.js.map +1 -1
  24. package/dist/lib/generators/file-generators/gql-wrapper.js +152 -0
  25. package/dist/lib/generators/file-generators/gql-wrapper.js.map +1 -0
  26. package/dist/lib/generators/file-generators/guide-generator.js +214 -10
  27. package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
  28. package/dist/lib/generators/file-generators/mutation-queue.js +117 -49
  29. package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
  30. package/dist/lib/generators/file-generators/mutation-state.js +126 -0
  31. package/dist/lib/generators/file-generators/mutation-state.js.map +1 -0
  32. package/dist/lib/generators/file-generators/quick-readme.js +59 -9
  33. package/dist/lib/generators/file-generators/quick-readme.js.map +1 -1
  34. package/dist/lib/generators/file-generators/server-push.js +136 -0
  35. package/dist/lib/generators/file-generators/server-push.js.map +1 -0
  36. package/dist/lib/generators/file-generators/type-definitions.js +28 -0
  37. package/dist/lib/generators/file-generators/type-definitions.js.map +1 -1
  38. package/dist/lib/generators/sw-sections/assemble-sw.js +6 -1
  39. package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
  40. package/dist/lib/generators/sw-sections/background-sync-handler.js +22 -8
  41. package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -1
  42. package/dist/lib/generators/sw-sections/config-header.js +1 -1
  43. package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
  44. package/dist/lib/generators/sw-sections/default-template.js +2 -1
  45. package/dist/lib/generators/sw-sections/default-template.js.map +1 -1
  46. package/dist/lib/generators/sw-sections/fetch-handler.js +137 -98
  47. package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
  48. package/dist/lib/generators/sw-sections/server-push-handler.js +114 -0
  49. package/dist/lib/generators/sw-sections/server-push-handler.js.map +1 -0
  50. package/dist/lib/generators/sw-sections/tag-management.js +6 -5
  51. package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
  52. package/dist/lib/generators/swoff-files-generator.js +7 -1
  53. package/dist/lib/generators/swoff-files-generator.js.map +1 -1
  54. package/dist/lib/shared/config-types.js +40 -2
  55. package/dist/lib/shared/config-types.js.map +1 -1
  56. package/package.json +1 -1
  57. package/templates/hooks/useCachedFetch.jsx +43 -4
  58. package/templates/hooks/useCachedFetch.tsx +49 -6
  59. package/templates/hooks/useMutation.jsx +76 -0
  60. package/templates/hooks/useMutation.tsx +97 -0
  61. package/templates/hooks/useMutationQueue.jsx +19 -11
  62. package/templates/hooks/useMutationQueue.tsx +30 -15
  63. package/templates/hooks/useMutationState.jsx +27 -0
  64. package/templates/hooks/useMutationState.tsx +41 -0
  65. package/templates/hooks/usePrefetch.jsx +10 -0
  66. package/templates/hooks/usePrefetch.tsx +25 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Generates mutation-state.ts/js — per-mutation state tracking.
3
+ * Provides a lightweight store for tracking individual mutation lifecycle states,
4
+ * enabling useMutation-style hooks and fine-grained mutation status UI.
5
+ */
6
+ import { writeFile } from "./context.js";
7
+ export function generateMutationState(ctx) {
8
+ const ext = ctx.ext;
9
+ const ts = ext === "ts";
10
+ const T = (type) => (ts ? `: ${type}` : "");
11
+ const R = (type) => (ts ? `: ${type}` : " ");
12
+ const code = `/**
13
+ * Swoff Mutation State
14
+ * Lightweight in-memory mutation state tracker.
15
+ * Enables per-mutation status UI (loading spinners, error states, success indicators).
16
+ *
17
+ * Usage:
18
+ * import { trackMutation, getMutationState, clearMutationState } from './swoff/mutation-state.${ext}';
19
+ *
20
+ * // After queueing a mutation
21
+ * const id = "mutation-" + crypto.randomUUID();
22
+ * trackMutation(id, "pending");
23
+ *
24
+ * // Check state later
25
+ * const state = getMutationState(id);
26
+ * if (state?.status === "error") { showError(state.error); }
27
+ *
28
+ * // Clear when done
29
+ * clearMutationState(id);
30
+ */
31
+
32
+ export type MutationStatus = "idle" | "pending" | "success" | "error";
33
+
34
+ export interface MutationState {
35
+ id${T("string")};
36
+ status${T("MutationStatus")};
37
+ error${T("Error | null")};
38
+ data${T("unknown")};
39
+ timestamp${T("number")};
40
+ }
41
+
42
+ const mutations = new Map<string, MutationState>();
43
+
44
+ let listenerId = 0;
45
+ const listeners = new Map<number, (state: MutationState) => void>();
46
+
47
+ /** Track a mutation with the given ID and initial status. */
48
+ export function trackMutation(id${T("string")}, status${T("MutationStatus")} = "idle")${R("MutationState")}{
49
+ let state = mutations.get(id);
50
+ if (!state) {
51
+ state = { id, status, error: null, data: null, timestamp: Date.now() };
52
+ mutations.set(id, state);
53
+ } else {
54
+ state.status = status;
55
+ state.timestamp = Date.now();
56
+ }
57
+ notifyListeners(state);
58
+ window.dispatchEvent(new CustomEvent("mutation-state-changed", { detail: state }));
59
+ return state;
60
+ }
61
+
62
+ /** Update an existing mutation's state. */
63
+ export function updateMutationState(id${T("string")}, partial${T("Partial<MutationState>")})${R("MutationState | null")}{
64
+ const state = mutations.get(id);
65
+ if (!state) return null;
66
+ Object.assign(state, partial);
67
+ state.timestamp = Date.now();
68
+ notifyListeners(state);
69
+ window.dispatchEvent(new CustomEvent("mutation-state-changed", { detail: state }));
70
+ return state;
71
+ }
72
+
73
+ /** Mark a mutation as successful with optional data. */
74
+ export function resolveMutation(id${T("string")}, data${T("unknown")} = null)${R("void")}{
75
+ updateMutationState(id, { status: "success", data, error: null });
76
+ }
77
+
78
+ /** Mark a mutation as failed with an error. */
79
+ export function rejectMutation(id${T("string")}, error${T("Error")})${R("void")}{
80
+ updateMutationState(id, { status: "error", error });
81
+ }
82
+
83
+ /** Get the current state of a mutation by ID. */
84
+ export function getMutationState(id${T("string")})${R("MutationState | undefined")}{
85
+ return mutations.get(id);
86
+ }
87
+
88
+ /** Remove a mutation's state from the tracker. */
89
+ export function clearMutationState(id${T("string")})${R("void")}{
90
+ mutations.delete(id);
91
+ }
92
+
93
+ /** Get all tracked mutations. */
94
+ export function getAllMutationStates()${R("MutationState[]")}{
95
+ return Array.from(mutations.values());
96
+ }
97
+
98
+ /** Get the count of mutations in a given status. */
99
+ export function getMutationCount(status${T("MutationStatus")})${R("number")}{
100
+ let count = 0;
101
+ for (const state of mutations.values()) {
102
+ if (state.status === status) count++;
103
+ }
104
+ return count;
105
+ }
106
+
107
+ /** Subscribe to mutation state changes. Returns an unsubscribe function. */
108
+ export function onMutationStateChange(callback${T("(state: MutationState) => void")})${R("() => void")}{
109
+ const id = ++listenerId;
110
+ listeners.set(id, callback);
111
+ return () => { listeners.delete(id); };
112
+ }
113
+
114
+ function notifyListeners(state${T("MutationState")})${R("void")}{
115
+ for (const cb of listeners.values()) {
116
+ try {
117
+ cb(state);
118
+ } catch {
119
+ // Handle listener errors silently
120
+ }
121
+ }
122
+ }
123
+ `;
124
+ writeFile(ctx, `mutation-state.${ext}`, code);
125
+ }
126
+ //# sourceMappingURL=mutation-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutation-state.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/mutation-state.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,qBAAqB,CAAC,GAAqB;IACzD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAErD,MAAM,IAAI,GAAG;;;;;;mGAMoF,GAAG;;;;;;;;;;;;;;;;;MAiBhG,CAAC,CAAC,QAAQ,CAAC;UACP,CAAC,CAAC,gBAAgB,CAAC;SACpB,CAAC,CAAC,cAAc,CAAC;QAClB,CAAC,CAAC,SAAS,CAAC;aACP,CAAC,CAAC,QAAQ,CAAC;;;;;;;;;kCASU,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,eAAe,CAAC;;;;;;;;;;;;;;;wCAelE,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,sBAAsB,CAAC;;;;;;;;;;;oCAWnF,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;;;;;mCAKrD,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;;;;;qCAK1C,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,2BAA2B,CAAC;;;;;uCAK3C,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;;;;;wCAKvB,CAAC,CAAC,iBAAiB,CAAC;;;;;yCAKnB,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;;;;;;;;;gDAS3B,CAAC,CAAC,gCAAgC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC;;;;;;gCAMtE,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;;;;;;;;;CAS9D,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,kBAAkB,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC"}
@@ -36,7 +36,7 @@ export function generateReadme(ctx) {
36
36
  w("```");
37
37
  w("");
38
38
  }
39
- if (config.features.mutationQueue) {
39
+ if (config.features.mutationQueue.enabled) {
40
40
  w("## Offline mutations (queue writes when offline)");
41
41
  w("```ts");
42
42
  w(`import { queueMutation, getPendingCount } from "./swoff/mutation-queue.${ext}";`);
@@ -52,6 +52,26 @@ export function generateReadme(ctx) {
52
52
  w("");
53
53
  }
54
54
  }
55
+ if (config.features.graphql.enabled) {
56
+ w("## GraphQL (cached queries with body-hash)");
57
+ w("```ts");
58
+ w(`import { queryGql, mutateGql } from "./swoff/gql-wrapper.${ext}";`);
59
+ w('const { data } = await queryGql("{ todos { id title } }");');
60
+ w('const { data: created } = await mutateGql(');
61
+ w(' "mutation CreateTodo($t: String!) { createTodo(title: $t) { id } }",');
62
+ w(' { t: "New task" },');
63
+ w(");");
64
+ w("```");
65
+ w("");
66
+ }
67
+ if (config.features.serverPush.enabled) {
68
+ w("## Server push events (real-time cache invalidation)");
69
+ w("```ts");
70
+ w(`import { startPushEvents } from "./swoff/server-push.${ext}";`);
71
+ w("startPushEvents();");
72
+ w("```");
73
+ w("");
74
+ }
55
75
  if (config.features.pushNotifications?.enabled) {
56
76
  w("## Push notifications");
57
77
  w("```ts");
@@ -60,6 +80,44 @@ export function generateReadme(ctx) {
60
80
  w("```");
61
81
  w("");
62
82
  }
83
+ if (ctx.frameworkName === "react") {
84
+ w("## React hooks");
85
+ w("```tsx");
86
+ w(`import { useCachedFetch } from "./swoff/hooks/useCachedFetch.${ext}x";`);
87
+ w(`import { useMutation } from "./swoff/hooks/useMutation.${ext}x";`);
88
+ w(`import { usePrefetch } from "./swoff/hooks/usePrefetch.${ext}x";`);
89
+ w(`import { useMutationState } from "./swoff/hooks/useMutationState.${ext}x";`);
90
+ w("");
91
+ w('const { data, error, loading, refetch } = useCachedFetch("/api/todos", {');
92
+ w(' refetchOnWindowFocus: true,');
93
+ w('});');
94
+ w("");
95
+ w('// Dependent query — skip until user is loaded');
96
+ w('const { data: posts } = useCachedFetch("/api/posts", { enabled: !!user });');
97
+ w("");
98
+ w('const { mutate } = useMutation({ onSuccess: (data) => console.log(data) });');
99
+ w('mutate("/api/todos", { method: "POST", body: JSON.stringify({ title: "New" }) });');
100
+ w("");
101
+ w('const prefetch = usePrefetch();');
102
+ w('prefetch("/api/todos");');
103
+ w("");
104
+ w('// Track a specific mutation by its returned id');
105
+ w('const mutation = useMutationState(mutationId);');
106
+ w("```");
107
+ w("");
108
+ if (config.features.mutationQueue.enabled) {
109
+ w("## Mutation queue hooks");
110
+ w("```tsx");
111
+ w(`import { useMutationQueue } from "./swoff/hooks/useMutationQueue.${ext}x";`);
112
+ w(`import { useMutationState } from "./swoff/hooks/useMutationState.${ext}x";`);
113
+ w("");
114
+ w('const { pending, items, lastSync } = useMutationQueue();');
115
+ w("// items: MutationQueueItem[] — each with id, url, method, status, retryCount");
116
+ w("// lastSync: { succeeded, failed } | null — result of the last sync attempt");
117
+ w("```");
118
+ w("");
119
+ }
120
+ }
63
121
  if (config.features.tagInvalidation) {
64
122
  w("## Cache invalidation");
65
123
  w("```ts");
@@ -69,14 +127,6 @@ export function generateReadme(ctx) {
69
127
  w("```");
70
128
  w("");
71
129
  }
72
- if (ctx.frameworkName === "react") {
73
- w("## React hook — auto-refetch on cache invalidation");
74
- w("```tsx");
75
- w(`import { useCachedFetch } from "./swoff/hooks/useCachedFetch.${ext}x";`);
76
- w('const { data, error, loading, refetch } = useCachedFetch("/api/todos");');
77
- w("```");
78
- w("");
79
- }
80
130
  w("## Build script");
81
131
  w("The SW generator learns your build output to precache assets.");
82
132
  w("Swoff has already added this to your `package.json`:");
@@ -1 +1 @@
1
- {"version":3,"file":"quick-readme.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/quick-readme.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"quick-readme.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/quick-readme.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Generates server-push.ts/js — client-side connection manager for SSE/WebSocket.
3
+ * The SW connects to the push endpoint directly in modern browsers.
4
+ * This client-side helper provides a fallback and status events for the UI.
5
+ */
6
+ import { writeFile } from "./context.js";
7
+ export function generateServerPush(ctx) {
8
+ const ext = ctx.ext;
9
+ const ts = ext === "ts";
10
+ const T = (type) => (ts ? `: ${type}` : "");
11
+ const R = (type) => (ts ? `: ${type}` : " ");
12
+ const sp = ctx.config.features.serverPush;
13
+ const endpoint = sp.endpoint;
14
+ const reconnectDelayMs = sp.reconnectDelayMs;
15
+ const invalidate = `
16
+ // Forward to SW for cache invalidation
17
+ if (navigator.serviceWorker.controller) {
18
+ for (const tag of tags) {
19
+ navigator.serviceWorker.controller.postMessage({ type: "INVALIDATE_TAG", tag });
20
+ }
21
+ }`;
22
+ const sseConnect = `
23
+ return new Promise((resolve) => {
24
+ fetch("${endpoint}", {
25
+ headers: { Accept: "text/event-stream" },
26
+ signal: options.signal,
27
+ }).then(async (response) => {
28
+ if (!response.ok || !response.body) { resolve(); return; }
29
+ notifyStatus(true);
30
+ const reader = response.body.getReader();
31
+ const decoder = new TextDecoder();
32
+ let buffer = "";
33
+ let eventType = "";
34
+ let dataStr = "";
35
+
36
+ while (true) {
37
+ const { done, value } = await reader.read();
38
+ if (done) break;
39
+ buffer += decoder.decode(value, { stream: true });
40
+ const lines = buffer.split("\\n");
41
+ buffer = lines.pop() || "";
42
+ for (const line of lines) {
43
+ if (line.startsWith("event: ")) eventType = line.slice(7).trim();
44
+ else if (line.startsWith("data: ")) dataStr = line.slice(6);
45
+ else if (line === "" && eventType === "invalidate" && dataStr) {
46
+ try {
47
+ const p = JSON.parse(dataStr); if (p.tags) handleInvalidation(p.tags);
48
+ } catch {
49
+ // Handle invalidation data
50
+ }
51
+ eventType = ""; dataStr = "";
52
+ }
53
+ }
54
+ }
55
+ }).catch(() => {}).finally(() => {
56
+ notifyStatus(false);
57
+ resolve();
58
+ });
59
+ });`;
60
+ const wsConnect = `
61
+ return new Promise((resolve) => {
62
+ try {
63
+ const ws = new WebSocket("${endpoint}");
64
+ ws.onopen = () => notifyStatus(true);
65
+ ws.onmessage = (event) => {
66
+ try { const d = JSON.parse(event.data); if (d.type === "invalidate" && d.tags) handleInvalidation(d.tags); } catch {}
67
+ };
68
+ ws.onclose = () => { notifyStatus(false); resolve(); };
69
+ ws.onerror = () => { ws.close(); resolve(); };
70
+ if (options.signal) {
71
+ options.signal.addEventListener("abort", () => ws.close());
72
+ }
73
+ } catch { resolve(); }
74
+ });`;
75
+ const code = `/**
76
+ * Swoff Server Push Events
77
+ *
78
+ * The service worker connects to ${endpoint} and invalidates cache tags
79
+ * when the server sends "invalidate" events — no polling needed.
80
+ * This client-side helper provides status tracking and a manual start/stop API.
81
+ *
82
+ * Usage:
83
+ * import { startPushEvents, stopPushEvents, isPushConnected } from "./server-push.${ext}";
84
+ * startPushEvents();
85
+ *
86
+ * Server sends:
87
+ * event: invalidate
88
+ * data: {"tags": ["todos", "todo:42"]}
89
+ */
90
+
91
+ type PushEventOptions= {
92
+ signal${T("AbortSignal")};
93
+ };
94
+
95
+ let active${T("boolean")} = false;
96
+ let reconnectTimer${T("ReturnType<typeof setTimeout> | null")} = null;
97
+
98
+ function handleInvalidation(tags${T("string[]")})${R("void")}{${invalidate}
99
+ window.dispatchEvent(new CustomEvent("cache-invalidated", { detail: { tags } }));
100
+ }
101
+
102
+ function notifyStatus(connected${T("boolean")})${R("void")}{
103
+ window.dispatchEvent(new CustomEvent("push-events-status", { detail: { connected } }));
104
+ }
105
+
106
+ async function connect(options${T("PushEventOptions")} = {} as PushEventOptions)${R("Promise<void>")}{
107
+ ${sp.type === "sse" ? sseConnect : wsConnect}
108
+ }
109
+
110
+ /** Start listening for server push events. Retries on connection loss with exponential backoff. */
111
+ export async function startPushEvents(){
112
+ if (active) return;
113
+ active = true;
114
+ let delay = ${reconnectDelayMs};
115
+ while (active) {
116
+ await connect();
117
+ if (!active) break;
118
+ await new Promise((r) => { reconnectTimer = setTimeout(r, delay); });
119
+ delay = Math.min(delay * 1.5, 30000); // cap at 30s
120
+ }
121
+ }
122
+
123
+ /** Stop listening for push events. */
124
+ export function stopPushEvents(){
125
+ active = false;
126
+ if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; }
127
+ }
128
+
129
+ /** Check if the push connection is currently established. */
130
+ export function isPushConnected(){
131
+ return active;
132
+ }
133
+ `;
134
+ writeFile(ctx, `server-push.${ext}`, code);
135
+ }
136
+ //# sourceMappingURL=server-push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-push.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/server-push.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,kBAAkB,CAAC,GAAqB;IACtD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC;IAC1C,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC;IAC7B,MAAM,gBAAgB,GAAG,EAAE,CAAC,gBAAgB,CAAC;IAE7C,MAAM,UAAU,GAAG;;;;;;IAMjB,CAAC;IAEH,MAAM,UAAU,GAAG;;aAER,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAmCf,CAAC;IAEL,MAAM,SAAS,GAAG;;;kCAGc,QAAQ;;;;;;;;;;;MAWpC,CAAC;IAEL,MAAM,IAAI,GAAG;;;oCAGqB,QAAQ;;;;;uFAK2C,GAAG;;;;;;;;;UAShF,CAAC,CAAC,aAAa,CAAC;;;YAGd,CAAC,CAAC,SAAS,CAAC;oBACJ,CAAC,CAAC,sCAAsC,CAAC;;kCAE3B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,UAAU;;;;iCAIzC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;;;;gCAI1B,CAAC,CAAC,kBAAkB,CAAC,6BAA6B,CAAC,CAAC,eAAe,CAAC;IAChG,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;;;;;;;gBAO9B,gBAAgB;;;;;;;;;;;;;;;;;;;CAmB/B,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC"}
@@ -38,6 +38,7 @@ declare global {
38
38
  "mutation-sync-complete": CustomEvent<{ succeeded: number; failed: number }>;
39
39
  "mutation-queue-changed": CustomEvent;
40
40
  "cache-invalidated": CustomEvent<{ tags?: string[] }>;
41
+ "mutation-state-changed": CustomEvent<{ id: string; status: string; error?: Error; data?: unknown }>;
41
42
  "background-sync-complete": CustomEvent<{ succeeded: number; failed: number }>;
42
43
  "push-subscription-changed": CustomEvent<{ subscribed: boolean }>;
43
44
  "push-permission-changed": CustomEvent<{ permission: NotificationPermission }>;
@@ -69,6 +70,31 @@ export interface FetchWithCacheOptions extends RequestInit {
69
70
  strategy?: "read" | "mutation";
70
71
  tags?: string[];
71
72
  staleWhileRevalidate?: boolean;
73
+ staleTime?: number;
74
+ }
75
+
76
+ export type MutationStatus = "idle" | "pending" | "success" | "error";
77
+
78
+ export interface MutationState {
79
+ id: string;
80
+ status: MutationStatus;
81
+ error: Error | null;
82
+ data: unknown;
83
+ timestamp: number;
84
+ }
85
+
86
+ export interface GqlOptions {
87
+ variables?: Record<string, unknown>;
88
+ tags?: string[];
89
+ staleWhileRevalidate?: boolean;
90
+ auth?: boolean;
91
+ queueOffline?: boolean;
92
+ invalidate?: 'auto' | string[] | false;
93
+ }
94
+
95
+ export interface GqlResult${"<T>"} {
96
+ data: T;
97
+ fromCache: boolean;
72
98
  }
73
99
 
74
100
  export interface MutationQueueItem {
@@ -80,12 +106,14 @@ export interface MutationQueueItem {
80
106
  headers: Record<string, string>;
81
107
  timestamp: number;
82
108
  retryCount: number;
109
+ nextRetryAt?: number;
83
110
  tags: string[];
84
111
  }
85
112
 
86
113
  export interface MutationQueueResult {
87
114
  succeeded: number;
88
115
  failed: number;
116
+ total?: number;
89
117
  }
90
118
 
91
119
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"type-definitions.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/type-definitions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,uBAAuB,CAAC,GAAqB;IAC3D,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI;QAAE,OAAO;IAE7B,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoFd,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"type-definitions.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/type-definitions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,uBAAuB,CAAC,GAAqB;IAC3D,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI;QAAE,OAAO;IAE7B,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAuFa,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;CAyBhC,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC"}
@@ -14,6 +14,7 @@ import { generateFetchHandler } from "./fetch-handler.js";
14
14
  import { generateTagManagement } from "./tag-management.js";
15
15
  import { generateBackgroundSyncHandler } from "./background-sync-handler.js";
16
16
  import { generateSwPushHandlers } from "../file-generators/sw-push.js";
17
+ import { generateServerPushHandler } from "./server-push-handler.js";
17
18
  function collectAssets(dir, baseDir) {
18
19
  if (!existsSync(dir))
19
20
  return [];
@@ -49,6 +50,9 @@ function applyReplacements(sw, config, assetsToCache) {
49
50
  sw = features.pushNotifications?.enabled
50
51
  ? sw.replace("// [[PUSH_HANDLERS]]", generateSwPushHandlers())
51
52
  : sw.replace("// [[PUSH_HANDLERS]]", "");
53
+ sw = features.serverPush?.enabled
54
+ ? sw.replace("// [[SERVER_PUSH_HANDLER]]", generateServerPushHandler(features.serverPush.type, features.serverPush.endpoint, features.serverPush.reconnectDelayMs))
55
+ : sw.replace("// [[SERVER_PUSH_HANDLER]]", "");
52
56
  return sw;
53
57
  }
54
58
  export function assembleSW(config, version, projectRoot) {
@@ -88,7 +92,8 @@ export function assembleSW(config, version, projectRoot) {
88
92
  }
89
93
  if (features.backgroundSync) {
90
94
  const authType = features.auth.enabled ? features.auth.type : undefined;
91
- sw += `\n\n${generateBackgroundSyncHandler(authType)}`;
95
+ const mq = features.mutationQueue;
96
+ sw += `\n\n${generateBackgroundSyncHandler(authType, mq.batchSize, mq.batchDelayMs, mq.maxRetries, mq.retryBackoffMs)}`;
92
97
  }
93
98
  return sw;
94
99
  }
@@ -1 +1 @@
1
- {"version":3,"file":"assemble-sw.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/assemble-sw.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"assemble-sw.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/assemble-sw.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,4 @@
1
- /**
2
- * Generates Background Sync event handler for the SW.
3
- * Processes mutation queue when browser sync fires.
4
- */
5
- export function generateBackgroundSyncHandler(authType) {
1
+ export function generateBackgroundSyncHandler(authType, batchSize, batchDelayMs, maxRetries, retryBackoffMs) {
6
2
  const credentialsLine = authType === "cookie"
7
3
  ? ` credentials: "same-origin",`
8
4
  : "";
@@ -13,9 +9,14 @@ self.addEventListener("sync", (event) => {
13
9
  }
14
10
  });
15
11
 
16
- const SW_DB_NAME = "swoff-queue";
17
- const SW_STORE_NAME = "mutations";
18
- const SW_MAX_RETRIES = 5;
12
+ const SW_BATCH_SIZE = ${batchSize};
13
+ const SW_BATCH_DELAY_MS = ${batchDelayMs};
14
+ const SW_MAX_RETRIES = ${maxRetries};
15
+ const SW_RETRY_BACKOFF_MS = ${retryBackoffMs};
16
+
17
+ function swSleep(ms) {
18
+ return new Promise((r) => setTimeout(r, ms));
19
+ }
19
20
 
20
21
  async function processMutationQueueInSW() {
21
22
  let succeeded = 0;
@@ -45,12 +46,19 @@ async function processMutationQueueInSW() {
45
46
  request.onerror = () => reject(request.error);
46
47
  });
47
48
 
49
+ const total = queue.length;
48
50
  for (const item of queue) {
49
51
  if (item.retryCount >= SW_MAX_RETRIES) {
50
52
  await removeFromSWQueue(db, item.id);
51
53
  failed++;
52
54
  continue;
53
55
  }
56
+
57
+ // Skip items whose backoff delay hasn't elapsed yet
58
+ if (item.nextRetryAt && Date.now() < item.nextRetryAt) {
59
+ continue;
60
+ }
61
+
54
62
  try {
55
63
  const response = await fetch(item.url, {
56
64
  method: item.method,
@@ -67,9 +75,15 @@ ${credentialsLine} });
67
75
  succeeded++;
68
76
  } catch {
69
77
  item.retryCount++;
78
+ item.nextRetryAt = Date.now() + SW_RETRY_BACKOFF_MS * Math.pow(2, item.retryCount - 1);
70
79
  await updateInSWQueue(db, item);
71
80
  failed++;
72
81
  }
82
+
83
+ // Rate limiting delay between mutations
84
+ if (SW_BATCH_DELAY_MS > 0 && succeeded + failed < total) {
85
+ await swSleep(SW_BATCH_DELAY_MS);
86
+ }
73
87
  }
74
88
  } catch (err) {
75
89
  console.error("Background sync failed:", err);
@@ -1 +1 @@
1
- {"version":3,"file":"background-sync-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/background-sync-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,6BAA6B,CAAC,QAAiB;IAC7D,MAAM,eAAe,GAAG,QAAQ,KAAK,QAAQ;QAC3C,CAAC,CAAC,uCAAuC;QACzC,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkDP,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgDf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"background-sync-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/background-sync-handler.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,6BAA6B,CAAC,QAA4B,EAAE,SAAiB,EAAE,YAAoB,EAAE,UAAkB,EAAE,cAAsB;IAC7J,MAAM,eAAe,GAAG,QAAQ,KAAK,QAAQ;QAC3C,CAAC,CAAC,uCAAuC;QACzC,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;;wBAOe,SAAS;4BACL,YAAY;yBACf,UAAU;8BACL,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoD1C,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDf,CAAC;AACH,CAAC"}
@@ -7,7 +7,7 @@ export function generateConfigHeader(config, resolvedVersion) {
7
7
  * Generated from swoff.config.json
8
8
  * DO NOT EDIT MANUALLY
9
9
  * Version: ${resolvedVersion}
10
- * Features: version.enabled=${config.features.serviceWorker.version.enabled}, mutationQueue=${config.features.mutationQueue}, backgroundSync=${config.features.backgroundSync}, tagInvalidation=${config.features.tagInvalidation}
10
+ * Features: version.enabled=${config.features.serviceWorker.version.enabled}, mutationQueue=${config.features.mutationQueue.enabled}, backgroundSync=${config.features.backgroundSync}, tagInvalidation=${config.features.tagInvalidation}
11
11
  * Default Strategy: ${config.features.serviceWorker.defaultStrategy}
12
12
  * See: https://swoff.netlify.app/docs
13
13
  */`;
@@ -1 +1 @@
1
- {"version":3,"file":"config-header.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/config-header.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,UAAU,oBAAoB,CAAC,MAAmB,EAAE,eAAuB;IAC/E,OAAO;;;;cAIK,eAAe;+BACE,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,mBAAmB,MAAM,CAAC,QAAQ,CAAC,aAAa,oBAAoB,MAAM,CAAC,QAAQ,CAAC,cAAc,qBAAqB,MAAM,CAAC,QAAQ,CAAC,eAAe;uBAC3M,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,eAAe;;IAEhE,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"config-header.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/config-header.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,UAAU,oBAAoB,CAAC,MAAmB,EAAE,eAAuB;IAC/E,OAAO;;;;cAIK,eAAe;+BACE,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,mBAAmB,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,oBAAoB,MAAM,CAAC,QAAQ,CAAC,cAAc,qBAAqB,MAAM,CAAC,QAAQ,CAAC,eAAe;uBACnN,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,eAAe;;IAEhE,CAAC;AACL,CAAC"}
@@ -17,6 +17,7 @@ const CACHE_NAME_RUNTIME = "swoff-runtime";
17
17
  // [[MESSAGE_HANDLER]]
18
18
  // [[FETCH_HANDLER]]
19
19
  // [[TAG_MANAGEMENT]]
20
- // [[PUSH_HANDLERS]]`;
20
+ // [[PUSH_HANDLERS]]
21
+ // [[SERVER_PUSH_HANDLER]]`;
21
22
  }
22
23
  //# sourceMappingURL=default-template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"default-template.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/default-template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,kBAAkB;IAChC,OAAO;;;;;;;;;;;;;;qBAcY,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"default-template.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/default-template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,kBAAkB;IAChC,OAAO;;;;;;;;;;;;;;;2BAekB,CAAC;AAC5B,CAAC"}