@swoff/cli 0.3.3 → 0.3.5

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 (67) hide show
  1. package/README.md +23 -15
  2. package/dist/__tests__/assemble-sw.test.js +26 -11
  3. package/dist/__tests__/assemble-sw.test.js.map +1 -1
  4. package/dist/__tests__/cli-integration.test.js +11 -14
  5. package/dist/__tests__/cli-integration.test.js.map +1 -1
  6. package/dist/__tests__/config-types.test.js +19 -22
  7. package/dist/__tests__/config-types.test.js.map +1 -1
  8. package/dist/__tests__/file-generators.test.js +9 -97
  9. package/dist/__tests__/file-generators.test.js.map +1 -1
  10. package/dist/__tests__/loader.test.js +6 -6
  11. package/dist/__tests__/loader.test.js.map +1 -1
  12. package/dist/__tests__/validator.test.js +47 -38
  13. package/dist/__tests__/validator.test.js.map +1 -1
  14. package/dist/index.js +2 -2
  15. package/dist/index.js.map +1 -1
  16. package/dist/lib/cli/help.js +3 -3
  17. package/dist/lib/cli/help.js.map +1 -1
  18. package/dist/lib/commands/add.js +14 -5
  19. package/dist/lib/commands/add.js.map +1 -1
  20. package/dist/lib/commands/generate-guide.js +122 -0
  21. package/dist/lib/commands/generate-guide.js.map +1 -0
  22. package/dist/lib/commands/generate.js +7 -10
  23. package/dist/lib/commands/generate.js.map +1 -1
  24. package/dist/lib/commands/info.js +10 -4
  25. package/dist/lib/commands/info.js.map +1 -1
  26. package/dist/lib/commands/init.js +6 -12
  27. package/dist/lib/commands/init.js.map +1 -1
  28. package/dist/lib/commands/validate.js +8 -2
  29. package/dist/lib/commands/validate.js.map +1 -1
  30. package/dist/lib/config/validator.js +52 -51
  31. package/dist/lib/config/validator.js.map +1 -1
  32. package/dist/lib/generators/file-generators/auth-fetch.js +156 -0
  33. package/dist/lib/generators/file-generators/auth-fetch.js.map +1 -0
  34. package/dist/lib/generators/file-generators/auth-state.js +38 -0
  35. package/dist/lib/generators/file-generators/auth-state.js.map +1 -0
  36. package/dist/lib/generators/file-generators/auth-store.js +127 -0
  37. package/dist/lib/generators/file-generators/auth-store.js.map +1 -0
  38. package/dist/lib/generators/file-generators/auth-user.js +95 -0
  39. package/dist/lib/generators/file-generators/auth-user.js.map +1 -0
  40. package/dist/lib/generators/file-generators/context.js.map +1 -1
  41. package/dist/lib/generators/file-generators/generate-hooks.js +167 -0
  42. package/dist/lib/generators/file-generators/generate-hooks.js.map +1 -0
  43. package/dist/lib/generators/file-generators/mutation-queue.js +27 -5
  44. package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
  45. package/dist/lib/generators/file-generators/store.js +1 -1
  46. package/dist/lib/generators/file-generators/store.js.map +1 -1
  47. package/dist/lib/generators/file-generators/sw-generator-build.js +1 -1
  48. package/dist/lib/generators/file-generators/sw-injector.js +5 -2
  49. package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
  50. package/dist/lib/generators/file-generators/type-definitions.js +4 -1
  51. package/dist/lib/generators/file-generators/type-definitions.js.map +1 -1
  52. package/dist/lib/generators/sw-sections/assemble-sw.js +6 -4
  53. package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
  54. package/dist/lib/generators/sw-sections/background-sync-handler.js +9 -6
  55. package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -1
  56. package/dist/lib/generators/sw-sections/config-header.js +2 -2
  57. package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
  58. package/dist/lib/generators/sw-sections/message-handler.js +12 -2
  59. package/dist/lib/generators/sw-sections/message-handler.js.map +1 -1
  60. package/dist/lib/generators/swoff-files-generator.js +11 -2
  61. package/dist/lib/generators/swoff-files-generator.js.map +1 -1
  62. package/dist/lib/shared/config-types.js +34 -24
  63. package/dist/lib/shared/config-types.js.map +1 -1
  64. package/dist/lib/utils/detect-framework.js +33 -0
  65. package/dist/lib/utils/detect-framework.js.map +1 -0
  66. package/package.json +2 -3
  67. package/src/lib/templates/sw-template.js +0 -61
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Generates auth-user.ts/js — fetch, cache, and invalidate current user.
3
+ */
4
+ import { writeFile } from "./context.js";
5
+ export function generateAuthUser(ctx) {
6
+ const ext = ctx.ext;
7
+ const userEndpoint = ctx.config.features.auth.userEndpoint;
8
+ const code = `/**
9
+ * Current User — fetch, cache, and invalidate the current user for offline access.
10
+ *
11
+ * Usage:
12
+ * import { fetchCurrentUser, cacheUser, getCachedUser, clearCachedUser } from "./auth-user.${ext}";
13
+ *
14
+ * await fetchCurrentUser(); // Fetch from server & cache
15
+ * const user = await getCachedUser(); // Get cached (offline-capable)
16
+ * await clearCachedUser(); // Clear on logout
17
+ */
18
+
19
+ import { authenticatedFetch } from "./auth-fetch.${ext}";
20
+
21
+ const DB_NAME = "swoff-auth-user";
22
+ const STORE_NAME = "current-user";
23
+
24
+ function openAuthDB() {
25
+ return new Promise((resolve, reject) => {
26
+ const request = indexedDB.open(DB_NAME, 1);
27
+ request.onupgradeneeded = (e) => {
28
+ const db = e.target.result;
29
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
30
+ db.createObjectStore(STORE_NAME, { keyPath: "key" });
31
+ }
32
+ };
33
+ request.onsuccess = (e) => resolve(e.target.result);
34
+ request.onerror = (e) => reject(e.target.error);
35
+ });
36
+ }
37
+
38
+ /**
39
+ * Fetch current user from your backend and cache locally.
40
+ * Uses userEndpoint from swoff.config.json.
41
+ */
42
+ export async function fetchCurrentUser() {
43
+ const response = await authenticatedFetch("${userEndpoint}");
44
+ if (!response.ok) throw new Error("Failed to fetch user");
45
+
46
+ const user = await response.json();
47
+ await cacheUser(user);
48
+ return user;
49
+ }
50
+
51
+ /**
52
+ * Store user in IndexedDB for offline access.
53
+ */
54
+ export async function cacheUser(user) {
55
+ const db = await openAuthDB();
56
+ return new Promise((resolve, reject) => {
57
+ const tx = db.transaction(STORE_NAME, "readwrite");
58
+ const store = tx.objectStore(STORE_NAME);
59
+ store.put({ key: "user", value: user });
60
+ tx.oncomplete = () => resolve();
61
+ tx.onerror = () => reject(tx.error);
62
+ });
63
+ }
64
+
65
+ /**
66
+ * Get cached user — works offline.
67
+ */
68
+ export async function getCachedUser() {
69
+ const db = await openAuthDB();
70
+ return new Promise((resolve, reject) => {
71
+ const tx = db.transaction(STORE_NAME, "readonly");
72
+ const store = tx.objectStore(STORE_NAME);
73
+ const request = store.get("user");
74
+ request.onsuccess = () => resolve(request.result?.value || null);
75
+ request.onerror = () => reject(request.error);
76
+ });
77
+ }
78
+
79
+ /**
80
+ * Clear cached user on logout.
81
+ */
82
+ export async function clearCachedUser() {
83
+ const db = await openAuthDB();
84
+ return new Promise((resolve, reject) => {
85
+ const tx = db.transaction(STORE_NAME, "readwrite");
86
+ const store = tx.objectStore(STORE_NAME);
87
+ store.delete("user");
88
+ tx.oncomplete = () => resolve();
89
+ tx.onerror = () => reject(tx.error);
90
+ });
91
+ }
92
+ `;
93
+ writeFile(ctx, `auth-user.${ext}`, code);
94
+ }
95
+ //# sourceMappingURL=auth-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-user.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/auth-user.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,gBAAgB,CAAC,GAAqB;IACpD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC;IAE3D,MAAM,IAAI,GAAG;;;;gGAIiF,GAAG;;;;;;;mDAOhD,GAAG;;;;;;;;;;;;;;;;;;;;;;;;+CAwBP,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiD1D,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAC3C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAW5B,MAAM,UAAU,cAAc,CAAC,GAAqB;IAClD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAqB,EAAE,QAAgB,EAAE,IAAY;IAC7E,cAAc,CAAC,GAAG,CAAC,CAAC;IACpB,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;IAClD,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC;AAC/C,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAY5B,MAAM,UAAU,cAAc,CAAC,GAAqB;IAClD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAqB,EAAE,QAAgB,EAAE,IAAY;IAC7E,cAAc,CAAC,GAAG,CAAC,CAAC;IACpB,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;IAClD,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,167 @@
1
+ import { writeFileSync, existsSync, mkdirSync } from "fs";
2
+ import { join } from "path";
3
+ export function generateHooks(ctx) {
4
+ const { config, swoffDir, ext, frameworkName } = ctx;
5
+ if (frameworkName !== "react")
6
+ return;
7
+ const hooksDir = join(swoffDir, "hooks");
8
+ if (!existsSync(hooksDir)) {
9
+ mkdirSync(hooksDir, { recursive: true });
10
+ }
11
+ if (config.features.pwa.enabled) {
12
+ writePWAHooks(hooksDir, ext);
13
+ }
14
+ if (config.features.auth.enabled) {
15
+ writeAuthHook(hooksDir, ext);
16
+ }
17
+ if (config.features.mutationQueue) {
18
+ writeMutationQueueHook(hooksDir, ext);
19
+ }
20
+ }
21
+ function writePWAHooks(dir, ext) {
22
+ writeFileSync(join(dir, `usePWAUpdate.${ext}x`), `import { useState, useEffect, useCallback } from "react";
23
+
24
+ export function usePWAUpdate() {
25
+ const [state, setState] = useState({
26
+ updateStatus: "idle",
27
+ currentVersion: null as string | null,
28
+ availableVersion: null as string | null,
29
+ progress: 0,
30
+ forceUpdate: false,
31
+ error: null as string | null,
32
+ });
33
+
34
+ useEffect(() => {
35
+ setState((s) => ({ ...s, currentVersion: (window as any).currentSWVersion || null }));
36
+
37
+ const onAvailable = (e: CustomEvent) => setState((s) => ({
38
+ ...s,
39
+ updateStatus: "available" as const,
40
+ availableVersion: e.detail.version,
41
+ forceUpdate: (window as any).swUpdateRequired || false,
42
+ }));
43
+ const onProgress = (e: CustomEvent) => setState((s) => ({
44
+ ...s,
45
+ updateStatus: "downloading" as const,
46
+ progress: e.detail.percent,
47
+ }));
48
+ const onReady = () => setState((s) => ({ ...s, updateStatus: "idle" as const, progress: 0 }));
49
+ const onError = () => setState((s) => ({ ...s, error: "SW registration failed" }));
50
+
51
+ window.addEventListener("sw-update-available", onAvailable as EventListener);
52
+ window.addEventListener("sw-progress", onProgress as EventListener);
53
+ window.addEventListener("sw-ready", onReady);
54
+ window.addEventListener("sw-error", onError);
55
+ return () => {
56
+ window.removeEventListener("sw-update-available", onAvailable as EventListener);
57
+ window.removeEventListener("sw-progress", onProgress as EventListener);
58
+ window.removeEventListener("sw-ready", onReady);
59
+ window.removeEventListener("sw-error", onError);
60
+ };
61
+ }, []);
62
+
63
+ const acceptUpdate = useCallback(async () => {
64
+ if (!state.availableVersion) return;
65
+ const { handleUpdateApproved } = await import("../sw-injector.${ext}");
66
+ await handleUpdateApproved(state.availableVersion);
67
+ }, [state.availableVersion]);
68
+
69
+ const dismissUpdate = useCallback(() => {
70
+ sessionStorage.setItem("sw-dismissed-update", "true");
71
+ setState((s) => ({ ...s, updateStatus: "idle" }));
72
+ }, []);
73
+
74
+ return { ...state, acceptUpdate, dismissUpdate };
75
+ }
76
+
77
+ export function useSWProgress() {
78
+ const [state, setState] = useState({
79
+ status: "idle" as "idle" | "installing",
80
+ progress: 0,
81
+ });
82
+
83
+ useEffect(() => {
84
+ const onProgress = (e: CustomEvent) => setState({
85
+ status: "installing",
86
+ progress: e.detail.percent,
87
+ });
88
+ const onReady = () => setState({ status: "idle", progress: 0 });
89
+
90
+ window.addEventListener("sw-progress", onProgress as EventListener);
91
+ window.addEventListener("sw-ready", onReady);
92
+ return () => {
93
+ window.removeEventListener("sw-progress", onProgress as EventListener);
94
+ window.removeEventListener("sw-ready", onReady);
95
+ };
96
+ }, []);
97
+
98
+ return state;
99
+ }
100
+ `);
101
+ // useSWProgress is included in the same file
102
+ }
103
+ function writeAuthHook(dir, ext) {
104
+ writeFileSync(join(dir, `useAuth.${ext}x`), `import { useState, useEffect } from "react";
105
+ import { getAuthState } from "../auth-state.${ext}";
106
+
107
+ export function useAuth() {
108
+ const [state, setState] = useState({
109
+ authenticated: false,
110
+ user: null as Record<string, unknown> | null,
111
+ online: navigator.onLine,
112
+ });
113
+
114
+ useEffect(() => {
115
+ getAuthState().then(setState);
116
+
117
+ const onOnline = () => setState((s) => ({ ...s, online: true }));
118
+ const onOffline = () => setState((s) => ({ ...s, online: false }));
119
+ const onAuthChange = () => getAuthState().then(setState);
120
+
121
+ window.addEventListener("online", onOnline);
122
+ window.addEventListener("offline", onOffline);
123
+ window.addEventListener("sw-auth-state-change", onAuthChange);
124
+
125
+ return () => {
126
+ window.removeEventListener("online", onOnline);
127
+ window.removeEventListener("offline", onOffline);
128
+ window.removeEventListener("sw-auth-state-change", onAuthChange);
129
+ };
130
+ }, []);
131
+
132
+ return state;
133
+ }
134
+ `);
135
+ }
136
+ function writeMutationQueueHook(dir, ext) {
137
+ writeFileSync(join(dir, `useMutationQueue.${ext}x`), `import { useState, useEffect } from "react";
138
+ import { getPendingCount } from "../mutation-queue.${ext}";
139
+
140
+ export function useMutationQueue() {
141
+ const [state, setState] = useState<{
142
+ pending: number;
143
+ lastSync: { succeeded: number; failed: number } | null;
144
+ }>({ pending: 0, lastSync: null });
145
+
146
+ useEffect(() => {
147
+ getPendingCount().then((count: number) => setState((s) => ({ ...s, pending: count })));
148
+
149
+ const onSync = (e: CustomEvent) => setState({
150
+ pending: 0,
151
+ lastSync: { succeeded: e.detail.succeeded, failed: e.detail.failed },
152
+ });
153
+ const onChange = async () => setState((s) => ({ ...s, pending: await getPendingCount() }));
154
+
155
+ window.addEventListener("mutation-sync-complete", onSync as EventListener);
156
+ window.addEventListener("mutation-queue-changed", onChange);
157
+ return () => {
158
+ window.removeEventListener("mutation-sync-complete", onSync as EventListener);
159
+ window.removeEventListener("mutation-queue-changed", onChange);
160
+ };
161
+ }, []);
162
+
163
+ return state;
164
+ }
165
+ `);
166
+ }
167
+ //# sourceMappingURL=generate-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-hooks.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/generate-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,MAAM,UAAU,aAAa,CAAC,GAAqB;IACjD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC;IACrD,IAAI,aAAa,KAAK,OAAO;QAAE,OAAO;IAEtC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAChC,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAClC,sBAAsB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,GAAW;IAC7C,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,gBAAgB,GAAG,GAAG,CAAC,EACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oEA2CgE,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCtE,CACE,CAAC;IAEF,6CAA6C;AAC/C,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,GAAW;IAC7C,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,WAAW,GAAG,GAAG,CAAC,EAC5B;8CAC0C,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BhD,CACE,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,GAAW,EAAE,GAAW;IACtD,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,oBAAoB,GAAG,GAAG,CAAC,EACrC;qDACiD,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BvD,CACE,CAAC;AACJ,CAAC"}
@@ -4,12 +4,25 @@
4
4
  import { writeFile } from "./context.js";
5
5
  export function generateMutationQueue(ctx) {
6
6
  const ext = ctx.ext;
7
+ const authEnabled = ctx.config.features.auth.enabled;
8
+ const importLines = authEnabled
9
+ ? `import { getAuth } from "./auth-store.${ext}";
10
+ `
11
+ : "";
12
+ const authReplayBlock = authEnabled
13
+ ? ` const auth = await getAuth();
14
+ const authHeader = auth?.token ? { Authorization: \`Bearer \${auth.token}\` } : {};
15
+ `
16
+ : "";
17
+ const authHeadersSpread = authEnabled
18
+ ? ` ...authHeader,`
19
+ : "";
7
20
  const code = `/**
8
21
  * Swoff Mutation Queue
9
22
  * Queue offline writes and sync when connection returns.
10
23
  *
11
24
  * Usage:
12
- * import { queueMutation, processMutationQueue, getPendingCount } from './swoff/mutation-queue.${ext}';
25
+ * import { queueMutation, processMutationQueue, flushMutations, getPendingCount } from './swoff/mutation-queue.${ext}';
13
26
  *
14
27
  * // Queue a mutation
15
28
  * await queueMutation({
@@ -21,10 +34,13 @@ export function generateMutationQueue(ctx) {
21
34
  * tempId: "temp_abc123",
22
35
  * });
23
36
  *
37
+ * // Flush queued mutations (e.g., after login)
38
+ * await flushMutations();
39
+ *
24
40
  * // Auto-processes on online event
25
41
  */
26
42
 
27
- const DB_NAME = "swoff-queue";
43
+ ${importLines}const DB_NAME = "swoff-queue";
28
44
  const STORE_NAME = "mutations";
29
45
  const MAX_RETRIES = 5;
30
46
 
@@ -77,7 +93,7 @@ export async function processMutationQueue() {
77
93
  isSyncing = true;
78
94
 
79
95
  try {
80
- const db = await openQueueDB();
96
+ ${authReplayBlock} const db = await openQueueDB();
81
97
  const tx = db.transaction(STORE_NAME, "readonly");
82
98
  const store = tx.objectStore(STORE_NAME);
83
99
  const index = store.index("by-timestamp");
@@ -103,7 +119,7 @@ export async function processMutationQueue() {
103
119
  method: item.method,
104
120
  headers: {
105
121
  "Content-Type": "application/json",
106
- ...item.headers,
122
+ ${authHeadersSpread} ...item.headers,
107
123
  },
108
124
  body: JSON.stringify(item.body),
109
125
  });
@@ -141,6 +157,12 @@ export async function processMutationQueue() {
141
157
  }
142
158
  }
143
159
 
160
+ export async function flushMutations() {
161
+ await processMutationQueue();
162
+ }
163
+ `;
164
+ // Helper functions (unchanged) are appended outside the template string
165
+ const helpers = `
144
166
  async function removeFromQueue(id) {
145
167
  const db = await openQueueDB();
146
168
  const tx = db.transaction(STORE_NAME, "readwrite");
@@ -220,6 +242,6 @@ export async function getPendingCount() {
220
242
  });
221
243
  }
222
244
  `;
223
- writeFile(ctx, `mutation-queue.${ext}`, code);
245
+ writeFile(ctx, `mutation-queue.${ext}`, code + helpers);
224
246
  }
225
247
  //# sourceMappingURL=mutation-queue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mutation-queue.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/mutation-queue.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,qBAAqB,CAAC,GAAqB;IACzD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,IAAI,GAAG;;;;;oGAKqF,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+DA4GxC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDAgDb,GAAG;;;;;;kDAMN,GAAG;;;kDAGH,GAAG;;;;;;;;;;;;;;;;;yEAiBoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4B3E,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,kBAAkB,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"mutation-queue.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/mutation-queue.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,qBAAqB,CAAC,GAAqB;IACzD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;IAErD,MAAM,WAAW,GAAG,WAAW;QAC7B,CAAC,CAAC,yCAAyC,GAAG;CACjD;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,eAAe,GAAG,WAAW;QACjC,CAAC,CAAC;;CAEL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,iBAAiB,GAAG,WAAW;QACnC,CAAC,CAAC,4BAA4B;QAC9B,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,IAAI,GAAG;;;;;oHAKqG,GAAG;;;;;;;;;;;;;;;;;;EAkBrH,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqDX,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;EA0Bf,iBAAiB;;;;;;;;;;;;;;+DAc4C,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BjE,CAAC;IAEA,wEAAwE;IACxE,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;qDAyBmC,GAAG;;;;;;kDAMN,GAAG;;;kDAGH,GAAG;;;;;;;;;;;;;;;;;yEAiBoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4B3E,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,kBAAkB,GAAG,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC;AAC1D,CAAC"}
@@ -4,7 +4,7 @@
4
4
  import { writeFile } from "./context.js";
5
5
  export function generateStore(ctx) {
6
6
  const ext = ctx.ext;
7
- const dbName = ctx.config.features.indexeddb?.name || "app-db";
7
+ const dbName = "app-db";
8
8
  const code = `/**
9
9
  * Swoff IndexedDB Store
10
10
  * Generic CRUD operations for app's IndexedDB database.
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,aAAa,CAAC,GAAqB;IACjD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,IAAI,QAAQ,CAAC;IAE/D,MAAM,IAAI,GAAG;;;;;oFAKqE,GAAG;;;;;;;mBAOpE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDxB,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,aAAa,CAAC,GAAqB;IACjD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,MAAM,GAAG,QAAQ,CAAC;IAExB,MAAM,IAAI,GAAG;;;;;oFAKqE,GAAG;;;;;;;mBAOpE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDxB,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
@@ -72,7 +72,7 @@ const assetsToCache = combined.map(url => ({ url, options: {} }));
72
72
  let sw = template;
73
73
  sw = sw.replace('// [[CACHE_NAME]]', \`CACHE_NAME = 'sw-v\${version}'\`);
74
74
  sw = sw.replace('// [[ASSETS_LIST]]', \`ASSETS_TO_CACHE = \${JSON.stringify(assetsToCache, null, 2)}\`);
75
- sw = sw.replace('// [[AUTO_SKIP_WAITING]]', \`const AUTO_SKIP_WAITING = \${config.serviceWorker?.autoActivate || false};\`);
75
+ sw = sw.replace('// [[AUTO_SKIP_WAITING]]', \`const AUTO_SKIP_WAITING = \${config.features?.serviceWorker?.autoActivate || false};\`);
76
76
 
77
77
  writeFileSync(join(outDir, swFile), sw);
78
78
  writeFileSync(join(outDir, 'version.json'), JSON.stringify({
@@ -3,13 +3,14 @@
3
3
  */
4
4
  import { writeFile } from "./context.js";
5
5
  export function generateSwInjector(ctx) {
6
- const autoRegister = ctx.config.serviceWorker.autoRegister;
7
- const autoActivate = ctx.config.serviceWorker.autoActivate;
6
+ const autoRegister = ctx.config.features.serviceWorker.autoRegister;
7
+ const autoActivate = ctx.config.features.serviceWorker.autoActivate;
8
8
  const pwaEnabled = ctx.config.features.pwa.enabled;
9
9
  const preventDefaultInstall = ctx.config.features.pwa.preventDefaultInstall;
10
10
  const crossTabSync = ctx.config.features.crossTabSync;
11
11
  const ext = ctx.ext;
12
12
  const mutationQueueEnabled = ctx.config.features.mutationQueue;
13
+ const authEnabled = ctx.config.features.auth.enabled;
13
14
  const code = `/**
14
15
  * Swoff SW Injector
15
16
  * Framework-agnostic SW registration, PWA install support, and cross-tab sync.
@@ -32,6 +33,8 @@ export function generateSwInjector(ctx) {
32
33
  * mutation-sync-complete - Queued mutations synced (detail: { succeeded, failed })
33
34
  * mutation-queue-changed - Queue modified
34
35
  * mutation-rollback - Mutation exhausted retries (detail: { method, url, tempId, previousData })
36
+ * sw-auth-unauthorized - 401 response received (token expired or invalid)${authEnabled ? `
37
+ * sw-auth-state-change - Login or logout (detail: { authenticated: boolean })` : ""}
35
38
  *
36
39
  * Window properties:
37
40
  * window.latestSWVersion - Latest version from version.json
@@ -1 +1 @@
1
- {"version":3,"file":"sw-injector.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/sw-injector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,kBAAkB,CAAC,GAAqB;IACtD,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC;IAC3D,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC;IAC3D,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;IACnD,MAAM,qBAAqB,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAC5E,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;IACtD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IAEpB,MAAM,oBAAoB,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;IAE/D,MAAM,IAAI,GAAG;;;;;8DAK+C,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6B/D,oBAAoB,CAAC,CAAC,CAAC,0DAA0D,GAAG;CACrF,CAAC,CAAC,CAAC,EAAE;wBACkB,YAAY;wBACZ,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgJlC,UAAU,CAAC,CAAC,CAAC;;;;;QAKP,qBAAqB;;;;;;;;;;;;;;;;;;;;;CAqB5B,CAAC,CAAC,CAAC,EAAE;EACJ,oBAAoB,CAAC,CAAC,CAAC;;;CAGxB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BJ,YAAY,CAAC,CAAC,CAAC;;;;;;;;CAQhB,CAAC,CAAC,CAAC,EAAE;;CAEL,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC"}
1
+ {"version":3,"file":"sw-injector.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/sw-injector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,kBAAkB,CAAC,GAAqB;IACtD,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC;IACpE,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC;IACpE,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;IACnD,MAAM,qBAAqB,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAC5E,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;IACtD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IAEpB,MAAM,oBAAoB,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;IAE/D,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;IAErD,MAAM,IAAI,GAAG;;;;;8DAK+C,GAAG;;;;;;;;;;;;;;;;;+EAiBc,WAAW,CAAC,CAAC,CAAC;kFACX,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;EAarF,oBAAoB,CAAC,CAAC,CAAC,0DAA0D,GAAG;CACrF,CAAC,CAAC,CAAC,EAAE;wBACkB,YAAY;wBACZ,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgJlC,UAAU,CAAC,CAAC,CAAC;;;;;QAKP,qBAAqB;;;;;;;;;;;;;;;;;;;;;CAqB5B,CAAC,CAAC,CAAC,EAAE;EACJ,oBAAoB,CAAC,CAAC,CAAC;;;CAGxB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BJ,YAAY,CAAC,CAAC,CAAC;;;;;;;;CAQhB,CAAC,CAAC,CAAC,EAAE;;CAEL,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC"}
@@ -5,6 +5,9 @@ import { writeFile } from "./context.js";
5
5
  export function generateTypeDefinitions(ctx) {
6
6
  if (ctx.ext !== "ts")
7
7
  return;
8
+ const authBlock = ctx.config.features.auth.enabled ? `
9
+ swAuthState?: "authenticated" | "unauthenticated" | "loading";
10
+ swCurrentUser?: object | null;` : "";
8
11
  const code = `interface BeforeInstallPromptEvent extends Event {
9
12
  prompt(): Promise<void>;
10
13
  userChoice: Promise<{ outcome: "accepted" | "dismissed" }>;
@@ -20,7 +23,7 @@ declare global {
20
23
  swUpdateRequired?: boolean;
21
24
  swMinSupportedVersion?: string;
22
25
  swReady?: boolean;
23
- swError?: boolean;
26
+ swError?: boolean;${authBlock}
24
27
  }
25
28
  }
26
29
 
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Dd,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,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;;mCAEpB,CAAC,CAAC,CAAC,EAAE,CAAC;IAEvC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;wBAeS,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ChC,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC"}
@@ -29,7 +29,8 @@ function collectAssets(dir, baseDir) {
29
29
  return assets;
30
30
  }
31
31
  export function assembleSW(config, version, projectRoot) {
32
- const { serviceWorker, features } = config;
32
+ const { serviceWorker } = config.features;
33
+ const { features } = config;
33
34
  const outputDir = config.build?.outputDir || "dist";
34
35
  const swFilename = config.build?.swFilename || "sw";
35
36
  const fallback = ["/index.html"];
@@ -49,11 +50,11 @@ export function assembleSW(config, version, projectRoot) {
49
50
  let sw = getDefaultTemplate();
50
51
  sw = sw.replace("// [[CACHE_NAME]]", `CACHE_NAME = 'sw-v${version}'`);
51
52
  sw = sw.replace("// [[ASSETS_LIST]]", `ASSETS_TO_CACHE = ${JSON.stringify(assetsToCache.map((url) => ({ url, options: {} })), null, 2)}`);
52
- sw = sw.replace("// [[AUTO_SKIP_WAITING]]", `const AUTO_SKIP_WAITING = ${config.serviceWorker.autoActivate};`);
53
+ sw = sw.replace("// [[AUTO_SKIP_WAITING]]", `const AUTO_SKIP_WAITING = ${serviceWorker.autoActivate};`);
53
54
  sw = sw.replace("// [[FETCH_HANDLER]]", generateFetchHandler(serviceWorker, features.tagInvalidation));
54
55
  sw = sw.replace("// [[ACTIVATE_HANDLER]]", generateActivateHandler(serviceWorker.clearRuntimeOnUpdate));
55
56
  sw = sw.replace("// [[INSTALL_HANDLER]]", generateInstallHandler());
56
- sw = sw.replace("// [[MESSAGE_HANDLER]]", generateMessageHandler(features.tagInvalidation));
57
+ sw = sw.replace("// [[MESSAGE_HANDLER]]", generateMessageHandler(features.tagInvalidation, features.auth.enabled));
57
58
  if (features.tagInvalidation) {
58
59
  sw = sw.replace("// [[TAG_MANAGEMENT]]", generateTagManagement());
59
60
  }
@@ -62,7 +63,8 @@ export function assembleSW(config, version, projectRoot) {
62
63
  }
63
64
  sw = `${generateConfigHeader(config, version)}\n\n${sw}`;
64
65
  if (features.backgroundSync) {
65
- sw += `\n\n${generateBackgroundSyncHandler()}`;
66
+ const authType = features.auth.enabled ? features.auth.type : undefined;
67
+ sw += `\n\n${generateBackgroundSyncHandler(authType)}`;
66
68
  }
67
69
  return sw;
68
70
  }
@@ -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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"}
@@ -2,7 +2,10 @@
2
2
  * Generates Background Sync event handler for the SW.
3
3
  * Processes mutation queue when browser sync fires.
4
4
  */
5
- export function generateBackgroundSyncHandler() {
5
+ export function generateBackgroundSyncHandler(authType) {
6
+ const credentialsLine = authType === "cookie"
7
+ ? ` credentials: "same-origin",`
8
+ : "";
6
9
  return `
7
10
  self.addEventListener("sync", (event) => {
8
11
  if (event.tag === "sync-mutations") {
@@ -10,11 +13,11 @@ self.addEventListener("sync", (event) => {
10
13
  }
11
14
  });
12
15
 
13
- async function processMutationQueueInSW() {
14
- const SW_DB_NAME = "swoff-queue";
15
- const SW_STORE_NAME = "mutations";
16
- const SW_MAX_RETRIES = 5;
16
+ const SW_DB_NAME = "swoff-queue";
17
+ const SW_STORE_NAME = "mutations";
18
+ const SW_MAX_RETRIES = 5;
17
19
 
20
+ async function processMutationQueueInSW() {
18
21
  let succeeded = 0;
19
22
  let failed = 0;
20
23
  const tagsToInvalidate = new Set();
@@ -53,7 +56,7 @@ async function processMutationQueueInSW() {
53
56
  method: item.method,
54
57
  headers: { "Content-Type": "application/json", ...item.headers },
55
58
  body: JSON.stringify(item.body),
56
- });
59
+ ${credentialsLine} });
57
60
  if (!response.ok) throw new Error(\`HTTP \${response.status}\`);
58
61
 
59
62
  if (item.tags) {
@@ -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;IAC3C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkGP,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;;;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"}
@@ -7,8 +7,8 @@ export function generateConfigHeader(config, resolvedVersion) {
7
7
  * Generated from swoff.config.json
8
8
  * DO NOT EDIT MANUALLY
9
9
  * Version: ${resolvedVersion}
10
- * Features: versionedSw=${config.features.versionedSw}, mutationQueue=${config.features.mutationQueue}, backgroundSync=${config.features.backgroundSync}, tagInvalidation=${config.features.tagInvalidation}
11
- * Default Strategy: ${config.serviceWorker.defaultStrategy}
10
+ * Features: versionedSw=${config.features.serviceWorker.versionedSw}, mutationQueue=${config.features.mutationQueue}, backgroundSync=${config.features.backgroundSync}, tagInvalidation=${config.features.tagInvalidation}
11
+ * Default Strategy: ${config.features.serviceWorker.defaultStrategy}
12
12
  * See: https://swoff.netlify.app/docs
13
13
  */`;
14
14
  }
@@ -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;2BACF,MAAM,CAAC,QAAQ,CAAC,WAAW,mBAAmB,MAAM,CAAC,QAAQ,CAAC,aAAa,oBAAoB,MAAM,CAAC,QAAQ,CAAC,cAAc,qBAAqB,MAAM,CAAC,QAAQ,CAAC,eAAe;uBACrL,MAAM,CAAC,aAAa,CAAC,eAAe;;IAEvD,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;2BACF,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,mBAAmB,MAAM,CAAC,QAAQ,CAAC,aAAa,oBAAoB,MAAM,CAAC,QAAQ,CAAC,cAAc,qBAAqB,MAAM,CAAC,QAAQ,CAAC,eAAe;uBACnM,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,eAAe;;IAEhE,CAAC;AACL,CAAC"}
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Generates the SW message event handler (SKIP_WAITING, INVALIDATE_TAG).
2
+ * Generates the SW message event handler (SKIP_WAITING, INVALIDATE_TAG, CLEAR_RUNTIME_CACHE).
3
3
  */
4
- export function generateMessageHandler(tagInvalidation) {
4
+ export function generateMessageHandler(tagInvalidation, authEnabled) {
5
5
  let code = `
6
6
  self.addEventListener("message", (event) => {
7
7
  if (event.data.type === "SKIP_WAITING") {
@@ -11,6 +11,16 @@ self.addEventListener("message", (event) => {
11
11
  code += `
12
12
  if (event.data.type === "INVALIDATE_TAG" && event.data.tag) {
13
13
  event.waitUntil(invalidateByTag(event.data.tag));
14
+ }`;
15
+ }
16
+ if (authEnabled) {
17
+ code += `
18
+ if (event.data.type === "CLEAR_RUNTIME_CACHE") {
19
+ event.waitUntil(
20
+ caches.delete(CACHE_NAME_RUNTIME).then(() => {
21
+ return caches.open(CACHE_NAME_RUNTIME);
22
+ }),
23
+ );
14
24
  }`;
15
25
  }
16
26
  code += `
@@ -1 +1 @@
1
- {"version":3,"file":"message-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/message-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,sBAAsB,CAAC,eAAwB;IAC7D,IAAI,IAAI,GAAG;;;;IAIT,CAAC;IAEH,IAAI,eAAe,EAAE,CAAC;QACpB,IAAI,IAAI;;;IAGR,CAAC;IACH,CAAC;IAED,IAAI,IAAI;IACN,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"message-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/message-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,sBAAsB,CAAC,eAAwB,EAAE,WAAoB;IACnF,IAAI,IAAI,GAAG;;;;IAIT,CAAC;IAEH,IAAI,eAAe,EAAE,CAAC;QACpB,IAAI,IAAI;;;IAGR,CAAC;IACH,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,IAAI;;;;;;;IAOR,CAAC;IACH,CAAC;IAED,IAAI,IAAI;IACN,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -22,12 +22,16 @@ import { generateMutationQueue } from "./file-generators/mutation-queue.js";
22
22
  import { generateStore } from "./file-generators/store.js";
23
23
  import { generateReconcile } from "./file-generators/reconcile.js";
24
24
  import { generateBackgroundSync } from "./file-generators/background-sync.js";
25
- import { generateIndexedDB } from "./file-generators/indexeddb.js";
26
25
  import { generatePwaInstall } from "./file-generators/pwa-install.js";
27
26
  import { generateManifest } from "./file-generators/manifest.js";
28
27
  import { generateInvalidationTags } from "./file-generators/invalidation-tags.js";
28
+ import { generateAuthStore } from "./file-generators/auth-store.js";
29
+ import { generateAuthFetch } from "./file-generators/auth-fetch.js";
30
+ import { generateAuthUser } from "./file-generators/auth-user.js";
31
+ import { generateAuthState } from "./file-generators/auth-state.js";
29
32
  import { generateSwGeneratorBuild } from "./file-generators/sw-generator-build.js";
30
33
  import { generateTypeDefinitions } from "./file-generators/type-definitions.js";
34
+ import { generateHooks } from "./file-generators/generate-hooks.js";
31
35
  export function generateFiles(ctx, onFile) {
32
36
  const steps = [
33
37
  { name: "sw-template", gen: () => generateSwTemplate(ctx), enabled: true },
@@ -38,12 +42,16 @@ export function generateFiles(ctx, onFile) {
38
42
  { name: "reconcile", gen: () => generateReconcile(ctx), enabled: ctx.config.features.mutationQueue },
39
43
  { name: "mutation-queue", gen: () => generateMutationQueue(ctx), enabled: ctx.config.features.mutationQueue },
40
44
  { name: "background-sync", gen: () => generateBackgroundSync(ctx), enabled: ctx.config.features.backgroundSync },
41
- { name: "indexeddb", gen: () => generateIndexedDB(ctx), enabled: ctx.config.features.indexeddb.enabled },
45
+ { name: "auth-store", gen: () => generateAuthStore(ctx), enabled: ctx.config.features.auth.enabled },
46
+ { name: "auth-fetch", gen: () => generateAuthFetch(ctx), enabled: ctx.config.features.auth.enabled },
47
+ { name: "auth-user", gen: () => generateAuthUser(ctx), enabled: ctx.config.features.auth.enabled },
48
+ { name: "auth-state", gen: () => generateAuthState(ctx), enabled: ctx.config.features.auth.enabled },
42
49
  { name: "sw-generator", gen: () => generateSwGeneratorBuild(ctx), enabled: true },
43
50
  { name: "swoff.d.ts", gen: () => generateTypeDefinitions(ctx), enabled: ctx.ext === "ts" },
44
51
  { name: "pwa-install", gen: () => generatePwaInstall(ctx), enabled: ctx.config.features.pwa.enabled },
45
52
  { name: "manifest.json", gen: () => generateManifest(ctx), enabled: ctx.config.features.pwa.enabled },
46
53
  { name: "invalidation-tags", gen: () => generateInvalidationTags(ctx), enabled: ctx.config.features.tagInvalidation },
54
+ { name: "hooks", gen: () => generateHooks(ctx), enabled: ctx.config.framework === "react" },
47
55
  ];
48
56
  for (const step of steps) {
49
57
  if (!step.enabled)
@@ -77,6 +85,7 @@ if (fileURLToPath(import.meta.url) === fileURLToPath(new URL(process.argv[1], "f
77
85
  swoffDir,
78
86
  ext,
79
87
  generatedFiles,
88
+ frameworkName: config.framework ?? "vanilla",
80
89
  };
81
90
  const ttyStatus = process.stdout.isTTY
82
91
  ? (msg) => {