@swoff/cli 0.3.6 → 0.3.7
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 +375 -91
- package/bin/swoff +8 -14
- package/dist/__tests__/assemble-sw.test.js +2 -2
- package/dist/__tests__/assemble-sw.test.js.map +1 -1
- package/dist/__tests__/cli-integration.test.js +0 -1
- package/dist/__tests__/cli-integration.test.js.map +1 -1
- package/dist/__tests__/config-types.test.js +4 -3
- package/dist/__tests__/config-types.test.js.map +1 -1
- package/dist/__tests__/file-generators.test.js +12 -23
- package/dist/__tests__/file-generators.test.js.map +1 -1
- package/dist/__tests__/loader.test.js +0 -1
- package/dist/__tests__/loader.test.js.map +1 -1
- package/dist/__tests__/validator.test.js +0 -1
- package/dist/__tests__/validator.test.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/commands/add.js +4 -4
- package/dist/lib/commands/add.js.map +1 -1
- package/dist/lib/commands/generate-guide.js +33 -6
- package/dist/lib/commands/generate-guide.js.map +1 -1
- package/dist/lib/commands/info.js +18 -4
- package/dist/lib/commands/info.js.map +1 -1
- package/dist/lib/commands/init.js +6 -2
- package/dist/lib/commands/init.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-fetch.js +3 -3
- package/dist/lib/generators/file-generators/auth-fetch.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-store.js +114 -5
- package/dist/lib/generators/file-generators/auth-store.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-user.js +2 -2
- package/dist/lib/generators/file-generators/auth-user.js.map +1 -1
- package/dist/lib/generators/file-generators/cache.js +1 -3
- package/dist/lib/generators/file-generators/cache.js.map +1 -1
- package/dist/lib/generators/file-generators/client-injector.js +4 -16
- package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/fetch-wrapper.js +40 -15
- package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/generate-hooks.js +23 -209
- package/dist/lib/generators/file-generators/generate-hooks.js.map +1 -1
- package/dist/lib/generators/file-generators/guide-generator.js +153 -36
- package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-queue.js +31 -3
- package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
- package/dist/lib/generators/file-generators/push.js +143 -0
- package/dist/lib/generators/file-generators/push.js.map +1 -0
- package/dist/lib/generators/file-generators/quick-readme.js +13 -3
- package/dist/lib/generators/file-generators/quick-readme.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-generator-build.js +1 -1
- package/dist/lib/generators/file-generators/sw-injector.js +1 -1
- package/dist/lib/generators/file-generators/sw-push.js +67 -0
- package/dist/lib/generators/file-generators/sw-push.js.map +1 -0
- package/dist/lib/generators/file-generators/sw-template.js +2 -0
- package/dist/lib/generators/file-generators/sw-template.js.map +1 -1
- package/dist/lib/generators/file-generators/type-definitions.js +13 -13
- package/dist/lib/generators/sw-generator.js +8 -9
- package/dist/lib/generators/sw-generator.js.map +1 -1
- package/dist/lib/generators/sw-sections/activate-handler.js +6 -2
- package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js +5 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
- package/dist/lib/generators/sw-sections/default-template.js +1 -30
- package/dist/lib/generators/sw-sections/default-template.js.map +1 -1
- package/dist/lib/generators/sw-sections/fetch-handler.js +157 -86
- package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/install-handler.js +12 -10
- package/dist/lib/generators/sw-sections/install-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/tag-management.js +11 -0
- package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
- package/dist/lib/generators/swoff-files-generator.js +9 -9
- package/dist/lib/generators/swoff-files-generator.js.map +1 -1
- package/dist/lib/shared/config-types.js +5 -3
- package/dist/lib/shared/config-types.js.map +1 -1
- package/package.json +3 -2
- package/templates/hooks/useAuth.jsx +30 -0
- package/templates/hooks/useAuth.tsx +30 -0
- package/templates/hooks/useBackgroundSync.jsx +31 -0
- package/templates/hooks/useBackgroundSync.tsx +31 -0
- package/templates/hooks/useCacheInvalidation.jsx +19 -0
- package/templates/hooks/useCacheInvalidation.tsx +19 -0
- package/templates/hooks/useCachedFetch.jsx +55 -0
- package/templates/hooks/useCachedFetch.tsx +69 -0
- package/templates/hooks/useMutationQueue.jsx +34 -0
- package/templates/hooks/useMutationQueue.tsx +34 -0
- package/templates/hooks/useNetworkStatus.jsx +19 -0
- package/templates/hooks/useNetworkStatus.tsx +19 -0
- package/templates/hooks/usePushSubscription.jsx +67 -0
- package/templates/hooks/usePushSubscription.tsx +67 -0
- package/templates/hooks/useSWUpdate.jsx +76 -0
- package/templates/hooks/useSWUpdate.tsx +76 -0
|
@@ -1,36 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Generates the SW fetch event handler with all caching strategies.
|
|
3
|
+
*
|
|
4
|
+
* Strategy dispatch tiers (highest to lowest priority):
|
|
5
|
+
* 1. X-SW-Strategy header — per-request override from fetchWithCache({ strategy })
|
|
6
|
+
* 2. URL pattern match — from features.serviceWorker.strategies in swoff.config.json
|
|
7
|
+
* 3. defaultStrategy — fallback from features.serviceWorker.defaultStrategy
|
|
8
|
+
*
|
|
9
|
+
* Cache strategy mode (features.serviceWorker.cacheStrategy):
|
|
10
|
+
* "all" — all GET/HEAD requests go through the strategy system (default)
|
|
11
|
+
* "explicit-only" — only requests with X-SW-Cache-Strategy header go through strategy;
|
|
12
|
+
* plain fetch() calls pass through the SW unmodified
|
|
13
|
+
*
|
|
14
|
+
* Request dispatch flow:
|
|
15
|
+
* navigation (SPA fallback) → precache → strategy (if applicable) → pass-through
|
|
3
16
|
*/
|
|
4
17
|
export function generateFetchHandler(swConfig, tagInvalidation) {
|
|
5
|
-
const { defaultStrategy, strategies, maxCacheEntries, maxCacheAge, navigationMode, spaEntry } = swConfig;
|
|
6
|
-
const
|
|
18
|
+
const { defaultStrategy, strategies, cacheStrategy = "all", maxCacheEntries, maxCacheAge, navigationPreload, navigationMode, spaEntry } = swConfig;
|
|
19
|
+
const hasPerRouteLimits = Object.values(strategies || {}).some((s) => typeof s === "object" && (s.maxCacheEntries || s.maxCacheAge));
|
|
20
|
+
const hasTrim = (maxCacheEntries ?? 0) > 0 || (maxCacheAge ?? 0) > 0 || hasPerRouteLimits;
|
|
7
21
|
const navMode = navigationMode ?? "spa";
|
|
8
22
|
const spaPath = spaEntry ?? "/index.html";
|
|
9
|
-
const navCode = navMode === "spa" ? `
|
|
10
|
-
if (request.mode === "navigate") {
|
|
11
|
-
const precache = await caches.open(CACHE_NAME);
|
|
12
|
-
const entry = await precache.match("${spaPath}");
|
|
13
|
-
if (entry) return entry;
|
|
14
|
-
}` : "";
|
|
15
|
-
const tagInvalidationCode = tagInvalidation ? `
|
|
16
|
-
const tagsHeader = event.request.headers.get("X-SW-Cache-Tags");
|
|
17
|
-
if (tagsHeader) {
|
|
18
|
-
const url = new URL(event.request.url).href;
|
|
19
|
-
const tags = tagsHeader.split(",").map((t) => t.trim());
|
|
20
|
-
await cacheTagUrl(url, tags);
|
|
21
|
-
}` : "";
|
|
22
23
|
const staleVersionCode = tagInvalidation ? `
|
|
24
|
+
cleanStaleVersions();
|
|
23
25
|
if (staleVersions.has(request.url)) {
|
|
24
|
-
event.waitUntil(refreshCache(
|
|
26
|
+
event.waitUntil(refreshCache(request).then(() => staleVersions.delete(request.url)));
|
|
25
27
|
}` : "";
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const trimCode = hasTrim ? `
|
|
28
|
+
const tagCode = tagInvalidation ? `
|
|
29
|
+
const tagsHeader = request.headers.get("X-SW-Cache-Tags");
|
|
30
|
+
if (tagsHeader) {
|
|
31
|
+
const url = new URL(request.url).href;
|
|
32
|
+
const tags = tagsHeader.split(",").map((t) => t.trim());
|
|
33
|
+
await cacheTagUrl(url, tags);
|
|
34
|
+
}` : "";
|
|
35
|
+
const trimCode = hasTrim ? ` await trimRuntimeCache(CACHE_NAME_RUNTIME);\n` : "";
|
|
34
36
|
const trimFunction = hasTrim ? `
|
|
35
37
|
const MAX_CACHE_ENTRIES = ${maxCacheEntries ?? 0};
|
|
36
38
|
const MAX_CACHE_AGE = ${maxCacheAge ?? 0};
|
|
@@ -63,11 +65,36 @@ async function trimRuntimeCache(cacheName) {
|
|
|
63
65
|
}
|
|
64
66
|
` : "";
|
|
65
67
|
return `${trimFunction}
|
|
68
|
+
// --- Cache Helpers ---
|
|
69
|
+
|
|
66
70
|
async function fromPrecache(request) {
|
|
67
71
|
const cache = await caches.open(CACHE_NAME);
|
|
68
|
-
return cache.match(request);
|
|
72
|
+
return cache.match(new URL(request.url).pathname);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function fromRuntime(request) {
|
|
76
|
+
const cache = await caches.open(CACHE_NAME_RUNTIME);
|
|
77
|
+
return cache.match(new URL(request.url).href);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function storeRuntime(request, response) {
|
|
81
|
+
const cache = await caches.open(CACHE_NAME_RUNTIME);
|
|
82
|
+
await cache.put(new URL(request.url).href, response.clone());
|
|
69
83
|
}
|
|
70
84
|
|
|
85
|
+
async function cacheResponse(request, response) {
|
|
86
|
+
await storeRuntime(request, response);${tagCode}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function fromSpaFallback(request) {
|
|
90
|
+
if (request.mode === "navigate") {
|
|
91
|
+
const cache = await caches.open(CACHE_NAME);
|
|
92
|
+
return cache.match("${spaPath}");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// --- Response Helpers ---
|
|
97
|
+
|
|
71
98
|
function markFromCache(response) {
|
|
72
99
|
const headers = new Headers(response.headers);
|
|
73
100
|
headers.set("X-SW-From-Cache", "true");
|
|
@@ -78,134 +105,178 @@ function markFromCache(response) {
|
|
|
78
105
|
});
|
|
79
106
|
}
|
|
80
107
|
|
|
81
|
-
|
|
82
|
-
|
|
108
|
+
// --- Strategy Selection ---
|
|
109
|
+
|
|
110
|
+
function resolveStrategyEntry(entry) {
|
|
111
|
+
return typeof entry === "string" ? { strategy: entry } : entry;
|
|
83
112
|
}
|
|
84
113
|
|
|
85
114
|
function determineCacheStrategy(request, customStrategies, defaultStrategy) {
|
|
115
|
+
const override = request.headers.get("X-SW-Strategy");
|
|
116
|
+
if (override) return { strategy: override };
|
|
86
117
|
const path = new URL(request.url).pathname;
|
|
87
|
-
for (const [pattern,
|
|
88
|
-
if (path.startsWith(pattern.replace("*", ""))) return
|
|
118
|
+
for (const [pattern, entry] of Object.entries(customStrategies)) {
|
|
119
|
+
if (path.startsWith(pattern.replace("*", ""))) return resolveStrategyEntry(entry);
|
|
120
|
+
}
|
|
121
|
+
return { strategy: defaultStrategy };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function applyStrategy(event, request, config) {
|
|
125
|
+
const { strategy, maxCacheEntries, maxCacheAge } = config;
|
|
126
|
+
if (strategy === "stale-while-revalidate") {
|
|
127
|
+
event.respondWith(staleWhileRevalidate(event, request, maxCacheEntries, maxCacheAge));
|
|
128
|
+
} else if (strategy === "network-first") {
|
|
129
|
+
event.respondWith(networkFirst(event, request, maxCacheEntries, maxCacheAge));
|
|
130
|
+
} else if (strategy === "cache-only") {
|
|
131
|
+
event.respondWith(cacheOnly(event, request, maxCacheEntries, maxCacheAge));
|
|
132
|
+
} else if (strategy === "network-only") {
|
|
133
|
+
event.respondWith(networkOnly(event, request));
|
|
134
|
+
} else {
|
|
135
|
+
event.respondWith(cacheFirst(event, request, maxCacheEntries, maxCacheAge));
|
|
89
136
|
}
|
|
90
|
-
return defaultStrategy;
|
|
91
137
|
}
|
|
92
138
|
|
|
93
139
|
self.addEventListener("fetch", (event) => {
|
|
94
|
-
|
|
140
|
+
const { request } = event;
|
|
141
|
+
if (request.method !== "GET" && request.method !== "HEAD") return;
|
|
142
|
+
${cacheStrategy === "explicit-only" ? `if (!request.headers.get("X-SW-Cache-Strategy")) return;` : ""}
|
|
143
|
+
applyStrategy(event, request, determineCacheStrategy(event.request, ${JSON.stringify(strategies)}, "${defaultStrategy}"));
|
|
144
|
+
});
|
|
95
145
|
|
|
96
|
-
|
|
146
|
+
// --- Strategies ---
|
|
97
147
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
148
|
+
${navigationPreload ? `
|
|
149
|
+
async function fetchWithPreload(event, request) {
|
|
150
|
+
try {
|
|
151
|
+
const preload = await event.preloadResponse;
|
|
152
|
+
if (preload) return preload;
|
|
153
|
+
} catch {}
|
|
154
|
+
return fetch(request);
|
|
155
|
+
}
|
|
156
|
+
` : ""}const _fetch = ${navigationPreload ? "fetchWithPreload" : `(event, request) => fetch(request)`};
|
|
102
157
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
158
|
+
const GLOBAL_MAX_ENTRIES = ${maxCacheEntries ?? 0};
|
|
159
|
+
const GLOBAL_MAX_AGE = ${maxCacheAge ?? 0};
|
|
107
160
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
161
|
+
${hasTrim ? `
|
|
162
|
+
async function trimRuntimeCache(cacheName, maxEntries, maxAge) {
|
|
163
|
+
const _maxEntries = maxEntries ?? GLOBAL_MAX_ENTRIES;
|
|
164
|
+
const _maxAge = maxAge ?? GLOBAL_MAX_AGE;
|
|
165
|
+
const cache = await caches.open(cacheName);
|
|
112
166
|
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
167
|
+
if (_maxEntries > 0) {
|
|
168
|
+
const keys = await cache.keys();
|
|
169
|
+
if (keys.length >= _maxEntries) {
|
|
170
|
+
const toDelete = keys.slice(0, keys.length - _maxEntries + 1);
|
|
171
|
+
await Promise.all(toDelete.map((key) => cache.delete(key)));
|
|
172
|
+
}
|
|
116
173
|
}
|
|
117
174
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
175
|
+
if (_maxAge > 0) {
|
|
176
|
+
const keys = await cache.keys();
|
|
177
|
+
const now = Date.now();
|
|
178
|
+
for (const request of keys) {
|
|
179
|
+
const response = await cache.match(request);
|
|
180
|
+
const dateHeader = response?.headers.get("date");
|
|
181
|
+
if (dateHeader) {
|
|
182
|
+
const age = now - new Date(dateHeader).getTime();
|
|
183
|
+
if (age > _maxAge) {
|
|
184
|
+
await cache.delete(request);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
` : ""}function _trim(cacheName, maxEntries, maxAge) {
|
|
191
|
+
${hasTrim ? ` trimRuntimeCache(cacheName, maxEntries, maxAge);` : ""}
|
|
192
|
+
}
|
|
124
193
|
|
|
125
|
-
|
|
194
|
+
async function cacheFirst(event, request, maxEntries, maxAge) {
|
|
195
|
+
const cached = await fromRuntime(request);
|
|
126
196
|
if (cached) {${staleVersionCode}
|
|
127
197
|
return markFromCache(cached);
|
|
128
198
|
}
|
|
129
199
|
|
|
130
200
|
const precached = await fromPrecache(request);
|
|
131
201
|
if (precached) return markFromCache(precached);
|
|
132
|
-
|
|
133
|
-
const
|
|
202
|
+
|
|
203
|
+
const fallback = await fromSpaFallback(request);
|
|
204
|
+
if (fallback) return fallback;
|
|
205
|
+
|
|
206
|
+
const response = await _fetch(event, request);
|
|
134
207
|
if (response.ok) {
|
|
135
|
-
const cloned = response.clone();
|
|
136
208
|
event.waitUntil(
|
|
137
209
|
(async () => {
|
|
138
|
-
await
|
|
139
|
-
|
|
210
|
+
await cacheResponse(request, response);
|
|
211
|
+
_trim(CACHE_NAME_RUNTIME, maxEntries, maxAge);
|
|
212
|
+
})(),
|
|
140
213
|
);
|
|
141
214
|
}
|
|
142
215
|
return response;
|
|
143
216
|
}
|
|
144
217
|
|
|
145
|
-
async function networkFirst(event, request) {
|
|
146
|
-
const runtimeCache = await caches.open(CACHE_NAME_RUNTIME);
|
|
147
|
-
|
|
218
|
+
async function networkFirst(event, request, maxEntries, maxAge) {
|
|
148
219
|
try {
|
|
149
|
-
const response = await
|
|
220
|
+
const response = await _fetch(event, request);
|
|
150
221
|
if (response.ok) {
|
|
151
|
-
const cloned = response.clone();
|
|
152
222
|
event.waitUntil(
|
|
153
223
|
(async () => {
|
|
154
|
-
await
|
|
155
|
-
|
|
224
|
+
await cacheResponse(request, response);
|
|
225
|
+
_trim(CACHE_NAME_RUNTIME, maxEntries, maxAge);
|
|
226
|
+
})(),
|
|
156
227
|
);
|
|
157
228
|
}
|
|
158
229
|
return response;
|
|
159
230
|
} catch {
|
|
160
|
-
const cached = await
|
|
231
|
+
const cached = await fromRuntime(request);
|
|
161
232
|
if (cached) return cached;
|
|
162
233
|
|
|
163
234
|
const precached = await fromPrecache(request);
|
|
164
235
|
if (precached) return precached;
|
|
165
|
-
|
|
236
|
+
|
|
237
|
+
const fallback = await fromSpaFallback(request);
|
|
238
|
+
if (fallback) return fallback;
|
|
239
|
+
|
|
166
240
|
throw new Error("Request failed and no cached response available");
|
|
167
241
|
}
|
|
168
242
|
}
|
|
169
243
|
|
|
170
|
-
async function staleWhileRevalidate(event, request) {
|
|
171
|
-
const
|
|
172
|
-
const cached = await runtimeCache.match(request);
|
|
173
|
-
|
|
244
|
+
async function staleWhileRevalidate(event, request, maxEntries, maxAge) {
|
|
245
|
+
const cached = await fromRuntime(request);
|
|
174
246
|
if (cached) {
|
|
175
|
-
event.waitUntil(refreshCache(
|
|
247
|
+
event.waitUntil(refreshCache(request));
|
|
176
248
|
return markFromCache(cached);
|
|
177
249
|
}
|
|
178
250
|
|
|
179
251
|
const precached = await fromPrecache(request);
|
|
180
252
|
if (precached) {
|
|
181
|
-
event.waitUntil(refreshCache(
|
|
253
|
+
event.waitUntil(refreshCache(request));
|
|
182
254
|
return markFromCache(precached);
|
|
183
255
|
}
|
|
184
256
|
|
|
185
|
-
const response = await
|
|
257
|
+
const response = await _fetch(event, request);
|
|
186
258
|
if (response.ok) {
|
|
187
|
-
await
|
|
188
|
-
|
|
259
|
+
await cacheResponse(request, response);
|
|
260
|
+
_trim(CACHE_NAME_RUNTIME, maxEntries, maxAge);
|
|
261
|
+
}
|
|
189
262
|
return response;
|
|
190
263
|
}
|
|
191
264
|
|
|
192
|
-
async function refreshCache(
|
|
265
|
+
async function refreshCache(request) {
|
|
193
266
|
try {
|
|
194
267
|
const response = await fetch(request);
|
|
195
268
|
if (response.ok) {
|
|
196
|
-
await
|
|
269
|
+
await storeRuntime(request, response);
|
|
197
270
|
}
|
|
198
271
|
} catch {
|
|
199
272
|
// Background refresh failed - stale cache remains usable
|
|
200
273
|
}
|
|
201
274
|
}
|
|
202
275
|
|
|
203
|
-
async function cacheOnly(event, request) {
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (byRequest) {${staleVersionCode}
|
|
208
|
-
return markFromCache(byRequest);
|
|
276
|
+
async function cacheOnly(event, request, maxEntries, maxAge) {
|
|
277
|
+
const cached = await fromRuntime(request);
|
|
278
|
+
if (cached) {${staleVersionCode}
|
|
279
|
+
return markFromCache(cached);
|
|
209
280
|
}
|
|
210
281
|
|
|
211
282
|
const precached = await fromPrecache(request);
|
|
@@ -215,7 +286,7 @@ async function cacheOnly(event, request) {
|
|
|
215
286
|
}
|
|
216
287
|
|
|
217
288
|
async function networkOnly(event, request) {
|
|
218
|
-
return
|
|
289
|
+
return _fetch(event, request);
|
|
219
290
|
}`;
|
|
220
291
|
}
|
|
221
292
|
//# sourceMappingURL=fetch-handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/fetch-handler.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fetch-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/fetch-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,UAAU,oBAAoB,CAClC,QAAkT,EAClT,eAAwB;IAExB,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,GAAG,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC;IAEnJ,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,CAC5D,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAE,CAAkC,CAAC,eAAe,IAAK,CAA8B,CAAC,WAAW,CAAC,CACrI,CAAC;IACF,MAAM,OAAO,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC;IAC1F,MAAM,OAAO,GAAG,cAAc,IAAI,KAAK,CAAC;IACxC,MAAM,OAAO,GAAG,QAAQ,IAAI,aAAa,CAAC;IAE1C,MAAM,gBAAgB,GAAG,eAAe,CAAC,CAAC,CAAC;;;;MAIvC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEV,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC;;;;;;IAMhC,CAAC,CAAC,CAAC,EAAE,CAAC;IAER,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,iDAAiD,CAAC,CAAC,CAAC,EAAE,CAAC;IAElF,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC;4BACL,eAAe,IAAI,CAAC;wBACxB,WAAW,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BvC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,GAAG,YAAY;;;;;;;;;;;;;;;;;;;0CAmBkB,OAAO;;;;;;0BAMvB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAkD7B,aAAa,KAAK,eAAe,CAAC,CAAC,CAAC,0DAA0D,CAAC,CAAC,CAAC,EAAE;wEAC/B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,eAAe;;;;;EAKrH,iBAAiB,CAAC,CAAC,CAAC;;;;;;;;CAQrB,CAAC,CAAC,CAAC,EAAE,kBAAkB,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,oCAAoC;;6BAExE,eAAe,IAAI,CAAC;yBACxB,WAAW,IAAI,CAAC;;EAEvC,OAAO,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BX,CAAC,CAAC,CAAC,EAAE;EACJ,OAAO,CAAC,CAAC,CAAC,oDAAoD,CAAC,CAAC,CAAC,EAAE;;;;;iBAKpD,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkFhB,gBAAgB;;;;;;;;;;;;EAY/B,CAAC;AACH,CAAC"}
|
|
@@ -8,24 +8,26 @@ self.addEventListener("install", (event) => {
|
|
|
8
8
|
(async () => {
|
|
9
9
|
const cache = await caches.open(CACHE_NAME);
|
|
10
10
|
let downloaded = 0;
|
|
11
|
+
let attempted = 0;
|
|
11
12
|
for (const asset of ASSETS_TO_CACHE) {
|
|
13
|
+
attempted++;
|
|
12
14
|
try {
|
|
13
15
|
const request = new Request(asset.url, asset.options);
|
|
14
16
|
await cache.add(request);
|
|
15
17
|
downloaded++;
|
|
16
|
-
const percent = Math.round((downloaded / ASSETS_TO_CACHE.length) * 100);
|
|
17
|
-
const clients = await self.clients.matchAll({ includeUncontrolled: true });
|
|
18
|
-
clients.forEach((client) => {
|
|
19
|
-
client.postMessage({
|
|
20
|
-
type: "SW_PROGRESS",
|
|
21
|
-
percent,
|
|
22
|
-
downloaded,
|
|
23
|
-
total: ASSETS_TO_CACHE.length,
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
18
|
} catch (err) {
|
|
27
19
|
console.error(\`Failed to cache \${asset.url}:\`, err);
|
|
28
20
|
}
|
|
21
|
+
const percent = Math.round((attempted / ASSETS_TO_CACHE.length) * 100);
|
|
22
|
+
const clients = await self.clients.matchAll({ includeUncontrolled: true });
|
|
23
|
+
clients.forEach((client) => {
|
|
24
|
+
client.postMessage({
|
|
25
|
+
type: "SW_PROGRESS",
|
|
26
|
+
percent,
|
|
27
|
+
downloaded,
|
|
28
|
+
total: ASSETS_TO_CACHE.length,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
29
31
|
}
|
|
30
32
|
if (AUTO_SKIP_WAITING) self.skipWaiting();
|
|
31
33
|
})(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/install-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,sBAAsB;IACpC,OAAO
|
|
1
|
+
{"version":3,"file":"install-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/install-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8BL,CAAC;AACL,CAAC"}
|
|
@@ -6,9 +6,20 @@
|
|
|
6
6
|
export function generateTagManagement() {
|
|
7
7
|
return `
|
|
8
8
|
const staleVersions = new Map();
|
|
9
|
+
const STALE_VERSIONS_MAX = 100;
|
|
10
|
+
const STALE_VERSION_TTL = 30 * 60 * 1000;
|
|
9
11
|
const TAG_DB_NAME = "swoff-cache-tags";
|
|
10
12
|
const TAG_STORE_NAME = "tags";
|
|
11
13
|
|
|
14
|
+
function cleanStaleVersions() {
|
|
15
|
+
const now = Date.now();
|
|
16
|
+
for (const [url, ts] of staleVersions) {
|
|
17
|
+
if (staleVersions.size > STALE_VERSIONS_MAX || now - ts > STALE_VERSION_TTL) {
|
|
18
|
+
staleVersions.delete(url);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
12
23
|
function openTagDB() {
|
|
13
24
|
return new Promise((resolve, reject) => {
|
|
14
25
|
const request = indexedDB.open(TAG_DB_NAME, 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tag-management.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/tag-management.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,qBAAqB;IACnC,OAAO
|
|
1
|
+
{"version":3,"file":"tag-management.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/tag-management.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2FP,CAAC;AACH,CAAC"}
|
|
@@ -24,8 +24,8 @@ import { generateBackgroundSync } from "./file-generators/background-sync.js";
|
|
|
24
24
|
import { generatePwaInstall } from "./file-generators/pwa-install.js";
|
|
25
25
|
import { generateManifest } from "./file-generators/manifest.js";
|
|
26
26
|
import { generateInvalidationTags } from "./file-generators/invalidation-tags.js";
|
|
27
|
+
import { generatePush } from "./file-generators/push.js";
|
|
27
28
|
import { generateAuthStore } from "./file-generators/auth-store.js";
|
|
28
|
-
import { generateAuthFetch } from "./file-generators/auth-fetch.js";
|
|
29
29
|
import { generateAuthUser } from "./file-generators/auth-user.js";
|
|
30
30
|
import { generateAuthState } from "./file-generators/auth-state.js";
|
|
31
31
|
import { generateSwGeneratorBuild } from "./file-generators/sw-generator-build.js";
|
|
@@ -36,14 +36,13 @@ import { generateReadme } from "./file-generators/quick-readme.js";
|
|
|
36
36
|
export function generateFiles(ctx, onFile) {
|
|
37
37
|
const steps = [
|
|
38
38
|
{ name: "sw-template", gen: () => generateSwTemplate(ctx), enabled: true },
|
|
39
|
-
{ name: "sw-injector", gen: () => generateSwInjector(ctx), enabled:
|
|
40
|
-
{ name: "client-injector", gen: () => generateClientInjector(ctx), enabled:
|
|
39
|
+
{ name: "sw-injector", gen: () => generateSwInjector(ctx), enabled: true },
|
|
40
|
+
{ name: "client-injector", gen: () => generateClientInjector(ctx), enabled: true },
|
|
41
41
|
{ name: "fetch-wrapper", gen: () => generateFetchWrapper(ctx), enabled: true },
|
|
42
42
|
{ name: "cache", gen: () => generateCache(ctx), enabled: ctx.config.features.tagInvalidation },
|
|
43
43
|
{ name: "mutation-queue", gen: () => generateMutationQueue(ctx), enabled: ctx.config.features.mutationQueue },
|
|
44
44
|
{ name: "background-sync", gen: () => generateBackgroundSync(ctx), enabled: ctx.config.features.backgroundSync },
|
|
45
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
46
|
{ name: "auth-user", gen: () => generateAuthUser(ctx), enabled: ctx.config.features.auth.enabled },
|
|
48
47
|
{ name: "auth-state", gen: () => generateAuthState(ctx), enabled: ctx.config.features.auth.enabled },
|
|
49
48
|
{ name: "sw-generator", gen: () => generateSwGeneratorBuild(ctx), enabled: true },
|
|
@@ -51,6 +50,7 @@ export function generateFiles(ctx, onFile) {
|
|
|
51
50
|
{ name: "pwa-install", gen: () => generatePwaInstall(ctx), enabled: ctx.config.features.pwa.enabled },
|
|
52
51
|
{ name: "manifest.json", gen: () => generateManifest(ctx), enabled: ctx.config.features.pwa.enabled },
|
|
53
52
|
{ name: "invalidation-tags", gen: () => generateInvalidationTags(ctx), enabled: ctx.config.features.tagInvalidation },
|
|
53
|
+
{ name: "push", gen: () => generatePush(ctx), enabled: ctx.config.features.pushNotifications?.enabled ?? false },
|
|
54
54
|
{ name: "hooks", gen: () => generateHooks(ctx), enabled: ctx.config.framework === "react" },
|
|
55
55
|
{ name: "GUIDE.md", gen: () => generateGuide(ctx), enabled: true },
|
|
56
56
|
{ name: "README.md", gen: () => generateReadme(ctx), enabled: true },
|
|
@@ -64,12 +64,12 @@ export function generateFiles(ctx, onFile) {
|
|
|
64
64
|
return ctx.generatedFiles;
|
|
65
65
|
}
|
|
66
66
|
// --- CLI entry point ---
|
|
67
|
-
const args = process.argv.slice(2);
|
|
68
|
-
function getArg(name) {
|
|
69
|
-
const idx = args.findIndex((arg) => arg === `--${name}`);
|
|
70
|
-
return idx !== -1 ? args[idx + 1] : null;
|
|
71
|
-
}
|
|
72
67
|
if (fileURLToPath(import.meta.url) === fileURLToPath(new URL(process.argv[1], "file:"))) {
|
|
68
|
+
const args = process.argv.slice(2);
|
|
69
|
+
const getArg = (name) => {
|
|
70
|
+
const idx = args.indexOf(`--${name}`);
|
|
71
|
+
return idx !== -1 ? args[idx + 1] : null;
|
|
72
|
+
};
|
|
73
73
|
const projectRoot = getArg("project-root") || process.cwd();
|
|
74
74
|
const language = getArg("language") || "ts";
|
|
75
75
|
const configPath = getArg("config-path") || join(projectRoot, "swoff.config.json");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"swoff-files-generator.js","sourceRoot":"","sources":["../../../src/lib/generators/swoff-files-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAG5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AAClF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"swoff-files-generator.js","sourceRoot":"","sources":["../../../src/lib/generators/swoff-files-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,9 +4,9 @@ export const KNOWN_FEATURES = [
|
|
|
4
4
|
"auth",
|
|
5
5
|
"crossTabSync",
|
|
6
6
|
"tagInvalidation",
|
|
7
|
-
"
|
|
7
|
+
"pushNotifications",
|
|
8
8
|
];
|
|
9
|
-
export const OBJECT_FEATURES = ["pwa", "serviceWorker", "auth"];
|
|
9
|
+
export const OBJECT_FEATURES = ["pwa", "serviceWorker", "auth", "pushNotifications"];
|
|
10
10
|
export const VALID_STRATEGIES = [
|
|
11
11
|
"cache-first",
|
|
12
12
|
"network-first",
|
|
@@ -69,7 +69,9 @@ export const defaultConfig = {
|
|
|
69
69
|
autoActivate: false,
|
|
70
70
|
defaultStrategy: "cache-first",
|
|
71
71
|
strategies: {},
|
|
72
|
+
cacheStrategy: "all",
|
|
72
73
|
clearRuntimeOnUpdate: false,
|
|
74
|
+
navigationPreload: true,
|
|
73
75
|
navigationMode: "spa",
|
|
74
76
|
spaEntry: "/index.html",
|
|
75
77
|
},
|
|
@@ -78,7 +80,7 @@ export const defaultConfig = {
|
|
|
78
80
|
auth: { ...defaultAuth },
|
|
79
81
|
crossTabSync: true,
|
|
80
82
|
tagInvalidation: true,
|
|
81
|
-
|
|
83
|
+
pushNotifications: { enabled: false },
|
|
82
84
|
},
|
|
83
85
|
build: {
|
|
84
86
|
outputDir: "dist",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-types.js","sourceRoot":"","sources":["../../../src/lib/shared/config-types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config-types.js","sourceRoot":"","sources":["../../../src/lib/shared/config-types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swoff/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for Swoff - Offline-first web apps made easy",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"bin/",
|
|
21
|
-
"dist/"
|
|
21
|
+
"dist/",
|
|
22
|
+
"templates/"
|
|
22
23
|
],
|
|
23
24
|
"keywords": [
|
|
24
25
|
"service-worker",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import { getAuthState } from "../auth/state.js";
|
|
3
|
+
|
|
4
|
+
export function useAuth() {
|
|
5
|
+
const [state, setState] = useState({
|
|
6
|
+
authenticated: false,
|
|
7
|
+
user: null,
|
|
8
|
+
online: navigator.onLine,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
getAuthState().then(setState);
|
|
13
|
+
|
|
14
|
+
const onOnline = () => setState((s) => ({ ...s, online: true }));
|
|
15
|
+
const onOffline = () => setState((s) => ({ ...s, online: false }));
|
|
16
|
+
const onAuthChange = () => getAuthState().then(setState);
|
|
17
|
+
|
|
18
|
+
window.addEventListener("online", onOnline);
|
|
19
|
+
window.addEventListener("offline", onOffline);
|
|
20
|
+
window.addEventListener("sw-auth-state-change", onAuthChange);
|
|
21
|
+
|
|
22
|
+
return () => {
|
|
23
|
+
window.removeEventListener("online", onOnline);
|
|
24
|
+
window.removeEventListener("offline", onOffline);
|
|
25
|
+
window.removeEventListener("sw-auth-state-change", onAuthChange);
|
|
26
|
+
};
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
return state;
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import { getAuthState } from "../auth/state.ts";
|
|
3
|
+
|
|
4
|
+
export function useAuth() {
|
|
5
|
+
const [state, setState] = useState({
|
|
6
|
+
authenticated: false,
|
|
7
|
+
user: null as Record<string, unknown> | null,
|
|
8
|
+
online: navigator.onLine,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
getAuthState().then(setState);
|
|
13
|
+
|
|
14
|
+
const onOnline = () => setState((s) => ({ ...s, online: true }));
|
|
15
|
+
const onOffline = () => setState((s) => ({ ...s, online: false }));
|
|
16
|
+
const onAuthChange = () => getAuthState().then(setState);
|
|
17
|
+
|
|
18
|
+
window.addEventListener("online", onOnline);
|
|
19
|
+
window.addEventListener("offline", onOffline);
|
|
20
|
+
window.addEventListener("sw-auth-state-change", onAuthChange);
|
|
21
|
+
|
|
22
|
+
return () => {
|
|
23
|
+
window.removeEventListener("online", onOnline);
|
|
24
|
+
window.removeEventListener("offline", onOffline);
|
|
25
|
+
window.removeEventListener("sw-auth-state-change", onAuthChange);
|
|
26
|
+
};
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
return state;
|
|
30
|
+
}
|