@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
@@ -6,65 +6,45 @@
6
6
  * 2. URL pattern match — from features.serviceWorker.strategies in swoff.config.json
7
7
  * 3. defaultStrategy — fallback from features.serviceWorker.defaultStrategy
8
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
9
+ * Each tier also carries: staleTime, maxCacheEntries, maxCacheAge
10
+ * Per-request values override route values, which override globals.
13
11
  *
14
- * Request dispatch flow:
15
- * navigation (SPA fallback) precache strategy (if applicable) → pass-through
12
+ * With staleTime enabled, every strategy gains a "fresh" window:
13
+ * - cache-first: returns cached immediately, background refresh if stale
14
+ * - network-first: skips network if fresh, tries network if stale
15
+ * - stale-while-revalidate: skips refresh if fresh, refreshes if stale
16
+ * - cache-only: background refresh if stale (best effort)
17
+ * - network-only: unaffected (never caches)
16
18
  */
17
19
  export function generateFetchHandler(swConfig, tagInvalidation) {
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;
20
+ const { defaultStrategy, strategies, cacheStrategy = "all", staleTime, maxCacheEntries, maxCacheAge, navigationPreload, navigationMode, spaEntry } = swConfig;
21
21
  const navMode = navigationMode ?? "spa";
22
22
  const spaPath = spaEntry ?? "/index.html";
23
23
  const staleVersionCode = tagInvalidation ? `
24
24
  cleanStaleVersions();
25
- if (staleVersions.has(request.url)) {
26
- event.waitUntil(refreshCache(request).then(() => staleVersions.delete(request.url)));
25
+ if (staleVersions.has(cacheKey(request))) {
26
+ event.waitUntil(refreshCache(request).then(() => staleVersions.delete(cacheKey(request))));
27
27
  }` : "";
28
28
  const tagCode = tagInvalidation ? `
29
29
  const tagsHeader = request.headers.get("X-SW-Cache-Tags");
30
30
  if (tagsHeader) {
31
- const url = new URL(request.url).href;
31
+ const cacheKeyUrl = cacheKey(request);
32
+ const actualUrl = new URL(request.url).href;
32
33
  const tags = tagsHeader.split(",").map((t) => t.trim());
33
- await cacheTagUrl(url, tags);
34
+ await cacheTagUrl(cacheKeyUrl, actualUrl, tags);
34
35
  }` : "";
35
- const trimCode = hasTrim ? ` await trimRuntimeCache(CACHE_NAME_RUNTIME);\n` : "";
36
- const trimFunction = hasTrim ? `
37
- const MAX_CACHE_ENTRIES = ${maxCacheEntries ?? 0};
38
- const MAX_CACHE_AGE = ${maxCacheAge ?? 0};
39
-
40
- async function trimRuntimeCache(cacheName) {
41
- const cache = await caches.open(cacheName);
42
-
43
- if (MAX_CACHE_ENTRIES > 0) {
44
- const keys = await cache.keys();
45
- if (keys.length >= MAX_CACHE_ENTRIES) {
46
- const toDelete = keys.slice(0, keys.length - MAX_CACHE_ENTRIES + 1);
47
- await Promise.all(toDelete.map((key) => cache.delete(key)));
48
- }
49
- }
50
-
51
- if (MAX_CACHE_AGE > 0) {
52
- const keys = await cache.keys();
53
- const now = Date.now();
54
- for (const request of keys) {
55
- const response = await cache.match(request);
56
- const dateHeader = response?.headers.get("date");
57
- if (dateHeader) {
58
- const age = now - new Date(dateHeader).getTime();
59
- if (age > MAX_CACHE_AGE) {
60
- await cache.delete(request);
61
- }
62
- }
63
- }
64
- }
36
+ const trimDecl = `const GLOBAL_MAX_ENTRIES = ${maxCacheEntries ?? 0};
37
+ const GLOBAL_MAX_AGE = ${maxCacheAge ?? 0};
38
+ const GLOBAL_STALE_TIME = ${staleTime ?? 0};`;
39
+ return `${trimDecl}
40
+ // --- Cache Key ---
41
+
42
+ function cacheKey(request) {
43
+ const key = request.headers.get("X-SW-Cache-Key");
44
+ if (key) return new URL("/__swc/" + key, self.location.origin).href;
45
+ return new URL(request.url).href;
65
46
  }
66
- ` : "";
67
- return `${trimFunction}
47
+
68
48
  // --- Cache Helpers ---
69
49
 
70
50
  async function fromPrecache(request) {
@@ -74,12 +54,19 @@ async function fromPrecache(request) {
74
54
 
75
55
  async function fromRuntime(request) {
76
56
  const cache = await caches.open(CACHE_NAME_RUNTIME);
77
- return cache.match(new URL(request.url).href);
57
+ return cache.match(cacheKey(request));
78
58
  }
79
59
 
80
60
  async function storeRuntime(request, response) {
81
61
  const cache = await caches.open(CACHE_NAME_RUNTIME);
82
- await cache.put(new URL(request.url).href, response.clone());
62
+ const headers = new Headers(response.headers);
63
+ headers.set("X-SW-Cached-At", String(Date.now()));
64
+ const cloned = new Response(response.body, {
65
+ status: response.status,
66
+ statusText: response.statusText,
67
+ headers,
68
+ });
69
+ await cache.put(cacheKey(request), cloned);
83
70
  }
84
71
 
85
72
  async function cacheResponse(request, response) {
@@ -105,42 +92,71 @@ function markFromCache(response) {
105
92
  });
106
93
  }
107
94
 
108
- // --- Strategy Selection ---
95
+ function isStale(response, staleTimeSeconds) {
96
+ if (!staleTimeSeconds || staleTimeSeconds <= 0) return false;
97
+ const cachedAt = response.headers.get("X-SW-Cached-At");
98
+ if (!cachedAt) return false;
99
+ return Date.now() - Number(cachedAt) > staleTimeSeconds * 1000;
100
+ }
101
+
102
+ // --- Strategy Selection (3-tier config resolution) ---
109
103
 
110
104
  function resolveStrategyEntry(entry) {
111
105
  return typeof entry === "string" ? { strategy: entry } : entry;
112
106
  }
113
107
 
114
- function determineCacheStrategy(request, customStrategies, defaultStrategy) {
108
+ function determineCacheStrategy(request, customStrategies, globalDefaults) {
115
109
  const override = request.headers.get("X-SW-Strategy");
116
- if (override) return { strategy: override };
110
+ if (override) {
111
+ return {
112
+ strategy: override,
113
+ staleTime: Number(request.headers.get("X-SW-Stale-Time")) || globalDefaults.staleTime,
114
+ maxCacheEntries: Number(request.headers.get("X-SW-Max-Entries")) || globalDefaults.maxCacheEntries,
115
+ maxCacheAge: Number(request.headers.get("X-SW-Max-Age")) || globalDefaults.maxCacheAge,
116
+ };
117
+ }
117
118
  const path = new URL(request.url).pathname;
118
119
  for (const [pattern, entry] of Object.entries(customStrategies)) {
119
- if (path.startsWith(pattern.replace("*", ""))) return resolveStrategyEntry(entry);
120
+ if (path.startsWith(pattern.replace("*", ""))) {
121
+ const resolved = resolveStrategyEntry(entry);
122
+ return {
123
+ strategy: resolved.strategy,
124
+ staleTime: resolved.staleTime ?? globalDefaults.staleTime,
125
+ maxCacheEntries: resolved.maxCacheEntries ?? globalDefaults.maxCacheEntries,
126
+ maxCacheAge: resolved.maxCacheAge ?? globalDefaults.maxCacheAge,
127
+ };
128
+ }
120
129
  }
121
- return { strategy: defaultStrategy };
130
+ return {
131
+ strategy: globalDefaults.defaultStrategy,
132
+ staleTime: globalDefaults.staleTime,
133
+ maxCacheEntries: globalDefaults.maxCacheEntries,
134
+ maxCacheAge: globalDefaults.maxCacheAge,
135
+ };
122
136
  }
123
137
 
124
138
  function applyStrategy(event, request, config) {
125
- const { strategy, maxCacheEntries, maxCacheAge } = config;
139
+ const { strategy, staleTime, maxCacheEntries, maxCacheAge } = config;
126
140
  if (strategy === "stale-while-revalidate") {
127
- event.respondWith(staleWhileRevalidate(event, request, maxCacheEntries, maxCacheAge));
141
+ event.respondWith(staleWhileRevalidate(event, request, staleTime, maxCacheEntries, maxCacheAge));
128
142
  } else if (strategy === "network-first") {
129
- event.respondWith(networkFirst(event, request, maxCacheEntries, maxCacheAge));
143
+ event.respondWith(networkFirst(event, request, staleTime, maxCacheEntries, maxCacheAge));
130
144
  } else if (strategy === "cache-only") {
131
- event.respondWith(cacheOnly(event, request, maxCacheEntries, maxCacheAge));
145
+ event.respondWith(cacheOnly(event, request, staleTime, maxCacheEntries, maxCacheAge));
132
146
  } else if (strategy === "network-only") {
133
147
  event.respondWith(networkOnly(event, request));
134
148
  } else {
135
- event.respondWith(cacheFirst(event, request, maxCacheEntries, maxCacheAge));
149
+ event.respondWith(cacheFirst(event, request, staleTime, maxCacheEntries, maxCacheAge));
136
150
  }
137
151
  }
138
152
 
139
153
  self.addEventListener("fetch", (event) => {
140
154
  const { request } = event;
141
- if (request.method !== "GET" && request.method !== "HEAD") return;
155
+ if (request.method !== "GET" && request.method !== "HEAD") {
156
+ if (!request.headers.get("X-SW-Cache-Key")) return;
157
+ }
142
158
  ${cacheStrategy === "explicit-only" ? `if (!request.headers.get("X-SW-Cache-Strategy")) return;` : ""}
143
- applyStrategy(event, request, determineCacheStrategy(event.request, ${JSON.stringify(strategies)}, "${defaultStrategy}"));
159
+ applyStrategy(event, request, determineCacheStrategy(event.request, ${JSON.stringify(strategies)}, { defaultStrategy: "${defaultStrategy}", staleTime: GLOBAL_STALE_TIME, maxCacheEntries: GLOBAL_MAX_ENTRIES, maxCacheAge: GLOBAL_MAX_AGE }));
144
160
  });
145
161
 
146
162
  // --- Strategies ---
@@ -155,45 +171,17 @@ async function fetchWithPreload(event, request) {
155
171
  }
156
172
  ` : ""}const _fetch = ${navigationPreload ? "fetchWithPreload" : `(event, request) => fetch(request)`};
157
173
 
158
- const GLOBAL_MAX_ENTRIES = ${maxCacheEntries ?? 0};
159
- const GLOBAL_MAX_AGE = ${maxCacheAge ?? 0};
160
-
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);
166
-
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
- }
173
- }
174
-
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);` : ""}
174
+ ${generateTrimCode(maxCacheEntries, maxCacheAge)}
175
+ function _trim(cacheName, maxEntries, maxAge) {
176
+ ${maxCacheEntries || maxCacheAge ? ` trimRuntimeCache(cacheName, maxEntries, maxAge);` : ""}
192
177
  }
193
178
 
194
- async function cacheFirst(event, request, maxEntries, maxAge) {
179
+ async function cacheFirst(event, request, staleTime, maxEntries, maxAge) {
195
180
  const cached = await fromRuntime(request);
196
181
  if (cached) {${staleVersionCode}
182
+ if (isStale(cached, staleTime)) {
183
+ event.waitUntil(refreshCache(request));
184
+ }
197
185
  return markFromCache(cached);
198
186
  }
199
187
 
@@ -215,7 +203,15 @@ async function cacheFirst(event, request, maxEntries, maxAge) {
215
203
  return response;
216
204
  }
217
205
 
218
- async function networkFirst(event, request, maxEntries, maxAge) {
206
+ async function networkFirst(event, request, staleTime, maxEntries, maxAge) {
207
+ // If cached and fresh (within staleTime), skip network entirely
208
+ if (staleTime > 0) {
209
+ const cached = await fromRuntime(request);
210
+ if (cached && !isStale(cached, staleTime)) {
211
+ return markFromCache(cached);
212
+ }
213
+ }
214
+
219
215
  try {
220
216
  const response = await _fetch(event, request);
221
217
  if (response.ok) {
@@ -241,9 +237,13 @@ async function networkFirst(event, request, maxEntries, maxAge) {
241
237
  }
242
238
  }
243
239
 
244
- async function staleWhileRevalidate(event, request, maxEntries, maxAge) {
240
+ async function staleWhileRevalidate(event, request, staleTime, maxEntries, maxAge) {
245
241
  const cached = await fromRuntime(request);
246
242
  if (cached) {
243
+ // Skip background refresh if still fresh
244
+ if (!isStale(cached, staleTime)) {
245
+ return markFromCache(cached);
246
+ }
247
247
  event.waitUntil(refreshCache(request));
248
248
  return markFromCache(cached);
249
249
  }
@@ -264,7 +264,9 @@ async function staleWhileRevalidate(event, request, maxEntries, maxAge) {
264
264
 
265
265
  async function refreshCache(request) {
266
266
  try {
267
- const response = await fetch(request);
267
+ const key = request.headers.get("X-SW-Cache-Key");
268
+ const fetchRequest = key ? new Request(new URL(request.url).href, { method: request.method, headers: request.headers, body: request.method !== "GET" ? request.body : undefined }) : request;
269
+ const response = await fetch(fetchRequest);
268
270
  if (response.ok) {
269
271
  await storeRuntime(request, response);
270
272
  }
@@ -273,9 +275,12 @@ async function refreshCache(request) {
273
275
  }
274
276
  }
275
277
 
276
- async function cacheOnly(event, request, maxEntries, maxAge) {
278
+ async function cacheOnly(event, request, staleTime, maxEntries, maxAge) {
277
279
  const cached = await fromRuntime(request);
278
280
  if (cached) {${staleVersionCode}
281
+ if (isStale(cached, staleTime)) {
282
+ event.waitUntil(refreshCache(request));
283
+ }
279
284
  return markFromCache(cached);
280
285
  }
281
286
 
@@ -289,4 +294,38 @@ async function networkOnly(event, request) {
289
294
  return _fetch(event, request);
290
295
  }`;
291
296
  }
297
+ function generateTrimCode(maxCacheEntries, maxCacheAge) {
298
+ if (!maxCacheEntries && !maxCacheAge)
299
+ return "";
300
+ return `
301
+ async function trimRuntimeCache(cacheName, maxEntries, maxAge) {
302
+ const _maxEntries = maxEntries ?? GLOBAL_MAX_ENTRIES;
303
+ const _maxAge = maxAge ?? GLOBAL_MAX_AGE;
304
+ const cache = await caches.open(cacheName);
305
+
306
+ if (_maxEntries > 0) {
307
+ const keys = await cache.keys();
308
+ if (keys.length >= _maxEntries) {
309
+ const toDelete = keys.slice(0, keys.length - _maxEntries + 1);
310
+ await Promise.all(toDelete.map((key) => cache.delete(key)));
311
+ }
312
+ }
313
+
314
+ if (_maxAge > 0) {
315
+ const keys = await cache.keys();
316
+ const now = Date.now();
317
+ for (const request of keys) {
318
+ const response = await cache.match(request);
319
+ const dateHeader = response?.headers.get("date");
320
+ if (dateHeader) {
321
+ const age = now - new Date(dateHeader).getTime();
322
+ if (age > _maxAge) {
323
+ await cache.delete(request);
324
+ }
325
+ }
326
+ }
327
+ }
328
+ }
329
+ `;
330
+ }
292
331
  //# 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;;;;;;;;;;;;;;;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"}
1
+ {"version":3,"file":"fetch-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/fetch-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,UAAU,oBAAoB,CAClC,QAA0V,EAC1V,eAAwB;IAExB,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,GAAG,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC;IAE9J,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;;;;;;;IAOhC,CAAC,CAAC,CAAC,EAAE,CAAC;IAER,MAAM,QAAQ,GAAG,8BAA8B,eAAe,IAAI,CAAC;yBAC5C,WAAW,IAAI,CAAC;4BACb,SAAS,IAAI,CAAC,GAAG,CAAC;IAE5C,OAAO,GAAG,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0CAkCsB,OAAO;;;;;;0BAMvB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+E7B,aAAa,KAAK,eAAe,CAAC,CAAC,CAAC,0DAA0D,CAAC,CAAC,CAAC,EAAE;wEAC/B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,yBAAyB,eAAe;;;;;EAKxI,iBAAiB,CAAC,CAAC,CAAC;;;;;;;;CAQrB,CAAC,CAAC,CAAC,EAAE,kBAAkB,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,oCAAoC;;EAEnG,gBAAgB,CAAC,eAAe,EAAE,WAAW,CAAC;;EAE9C,eAAe,IAAI,WAAW,CAAC,CAAC,CAAC,oDAAoD,CAAC,CAAC,CAAC,EAAE;;;;;iBAK3E,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmGhB,gBAAgB;;;;;;;;;;;;;;;EAe/B,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,eAAmC,EAAE,WAA+B;IAC5F,IAAI,CAAC,eAAe,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAEhD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BR,CAAC;AACF,CAAC"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Generates the SW push event connection handler.
3
+ * Opens an SSE (fetch+stream) or WebSocket connection from the SW,
4
+ * listens for "invalidate" events, and calls invalidateByTag().
5
+ */
6
+ export function generateServerPushHandler(type, endpoint, reconnectDelayMs) {
7
+ if (type === "websocket") {
8
+ return `
9
+ // --- Server Push Events (WebSocket) ---
10
+
11
+ let pushWs = null;
12
+ let pushReconnectTimer = null;
13
+
14
+ async function connectPushEvents() {
15
+ try {
16
+ pushWs = new WebSocket("${endpoint}");
17
+ pushWs.onmessage = (event) => {
18
+ try {
19
+ const data = JSON.parse(event.data);
20
+ if (data.type === "invalidate" && data.tags) {
21
+ data.tags.forEach((tag) => invalidateByTag(tag));
22
+ }
23
+ } catch {}
24
+ };
25
+ pushWs.onclose = () => {
26
+ pushWs = null;
27
+ scheduleReconnect();
28
+ };
29
+ pushWs.onerror = () => {
30
+ pushWs?.close();
31
+ };
32
+ } catch {
33
+ scheduleReconnect();
34
+ }
35
+ }
36
+
37
+ function scheduleReconnect() {
38
+ if (pushReconnectTimer) clearTimeout(pushReconnectTimer);
39
+ pushReconnectTimer = setTimeout(connectPushEvents, ${reconnectDelayMs});
40
+ }
41
+
42
+ self.addEventListener("activate", (event) => {
43
+ event.waitUntil(connectPushEvents());
44
+ });
45
+ `;
46
+ }
47
+ // SSE: fetch + ReadableStream reader
48
+ return `
49
+ // --- Server Push Events (SSE) ---
50
+
51
+ let pushReconnectTimer = null;
52
+ let pushAbortController = null;
53
+
54
+ async function connectPushEvents() {
55
+ try {
56
+ pushAbortController = new AbortController();
57
+ const response = await fetch("${endpoint}", {
58
+ headers: { Accept: "text/event-stream" },
59
+ signal: pushAbortController.signal,
60
+ });
61
+ if (!response.ok || !response.body) {
62
+ scheduleReconnect();
63
+ return;
64
+ }
65
+ const reader = response.body.getReader();
66
+ const decoder = new TextDecoder();
67
+ let buffer = "";
68
+ let eventType = "";
69
+ let dataStr = "";
70
+
71
+ while (true) {
72
+ const { done, value } = await reader.read();
73
+ if (done) break;
74
+ buffer += decoder.decode(value, { stream: true });
75
+
76
+ const lines = buffer.split("\\n");
77
+ buffer = lines.pop() || "";
78
+
79
+ for (const line of lines) {
80
+ if (line.startsWith("event: ")) {
81
+ eventType = line.slice(7).trim();
82
+ } else if (line.startsWith("data: ")) {
83
+ dataStr = line.slice(6);
84
+ } else if (line === "") {
85
+ if (eventType === "invalidate" && dataStr) {
86
+ try {
87
+ const parsed = JSON.parse(dataStr);
88
+ if (parsed.tags) {
89
+ parsed.tags.forEach((tag) => invalidateByTag(tag));
90
+ }
91
+ } catch {}
92
+ }
93
+ eventType = "";
94
+ dataStr = "";
95
+ }
96
+ }
97
+ }
98
+ } catch {
99
+ // Connection lost or aborted
100
+ }
101
+ scheduleReconnect();
102
+ }
103
+
104
+ function scheduleReconnect() {
105
+ if (pushReconnectTimer) clearTimeout(pushReconnectTimer);
106
+ pushReconnectTimer = setTimeout(connectPushEvents, ${reconnectDelayMs});
107
+ }
108
+
109
+ self.addEventListener("activate", (event) => {
110
+ event.waitUntil(connectPushEvents());
111
+ });
112
+ `;
113
+ }
114
+ //# sourceMappingURL=server-push-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-push-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/server-push-handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,yBAAyB,CACvC,IAAyB,EACzB,QAAgB,EAChB,gBAAwB;IAExB,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,OAAO;;;;;;;;8BAQmB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;uDAuBiB,gBAAgB;;;;;;CAMtE,CAAC;IACA,CAAC;IAED,qCAAqC;IACrC,OAAO;;;;;;;;;oCAS2B,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uDAiDW,gBAAgB;;;;;;CAMtE,CAAC;AACF,CAAC"}
@@ -35,20 +35,21 @@ function openTagDB() {
35
35
  });
36
36
  }
37
37
 
38
- async function cacheTagUrl(url, tags) {
38
+ async function cacheTagUrl(url, actualUrl, tags) {
39
39
  const db = await openTagDB();
40
40
  const tx = db.transaction(TAG_STORE_NAME, "readwrite");
41
41
  const store = tx.objectStore(TAG_STORE_NAME);
42
- store.put({ url, tags });
42
+ store.put({ url, actualUrl, tags });
43
43
  await new Promise((resolve, reject) => {
44
44
  tx.oncomplete = () => resolve();
45
45
  tx.onerror = () => reject(tx.error);
46
46
  });
47
47
  }
48
48
 
49
- async function refetchAfterInvalidation(url) {
49
+ async function refetchAfterInvalidation(url, actualUrl) {
50
+ const fetchUrl = actualUrl || url;
50
51
  try {
51
- const response = await fetch(url);
52
+ const response = await fetch(fetchUrl);
52
53
  if (response.ok) {
53
54
  const runtimeCache = await caches.open(CACHE_NAME_RUNTIME);
54
55
  await runtimeCache.put(url, response);
@@ -88,7 +89,7 @@ async function invalidateByTag(tag) {
88
89
 
89
90
  // Background refetch each deleted URL; keep stale on failure
90
91
  for (const entry of entries) {
91
- refetchAfterInvalidation(entry.url);
92
+ refetchAfterInvalidation(entry.url, entry.actualUrl);
92
93
  }
93
94
 
94
95
  const clients = await self.clients.matchAll();
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2FP,CAAC;AACH,CAAC"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4FP,CAAC;AACH,CAAC"}
@@ -25,10 +25,13 @@ 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
27
  import { generatePush } from "./file-generators/push.js";
28
+ import { generateMutationState } from "./file-generators/mutation-state.js";
29
+ import { generateServerPush } from "./file-generators/server-push.js";
28
30
  import { generateAuthStore } from "./file-generators/auth-store.js";
29
31
  import { generateAuthUser } from "./file-generators/auth-user.js";
30
32
  import { generateAuthState } from "./file-generators/auth-state.js";
31
33
  import { generateSwGeneratorBuild } from "./file-generators/sw-generator-build.js";
34
+ import { generateGqlWrapper } from "./file-generators/gql-wrapper.js";
32
35
  import { generateTypeDefinitions } from "./file-generators/type-definitions.js";
33
36
  import { generateHooks } from "./file-generators/generate-hooks.js";
34
37
  import { generateGuide } from "./file-generators/guide-generator.js";
@@ -40,7 +43,8 @@ export function generateFiles(ctx, onFile) {
40
43
  { name: "client-injector", gen: () => generateClientInjector(ctx), enabled: true },
41
44
  { name: "fetch-wrapper", gen: () => generateFetchWrapper(ctx), enabled: true },
42
45
  { name: "cache", gen: () => generateCache(ctx), enabled: ctx.config.features.tagInvalidation },
43
- { name: "mutation-queue", gen: () => generateMutationQueue(ctx), enabled: ctx.config.features.mutationQueue },
46
+ { name: "mutation-queue", gen: () => generateMutationQueue(ctx), enabled: ctx.config.features.mutationQueue.enabled },
47
+ { name: "mutation-state", gen: () => generateMutationState(ctx), enabled: ctx.config.features.mutationQueue.enabled },
44
48
  { name: "background-sync", gen: () => generateBackgroundSync(ctx), enabled: ctx.config.features.backgroundSync },
45
49
  { name: "auth-store", gen: () => generateAuthStore(ctx), enabled: ctx.config.features.auth.enabled },
46
50
  { name: "auth-user", gen: () => generateAuthUser(ctx), enabled: ctx.config.features.auth.enabled },
@@ -50,7 +54,9 @@ export function generateFiles(ctx, onFile) {
50
54
  { name: "pwa-install", gen: () => generatePwaInstall(ctx), enabled: ctx.config.features.pwa.enabled },
51
55
  { name: "manifest.json", gen: () => generateManifest(ctx), enabled: ctx.config.features.pwa.enabled },
52
56
  { name: "invalidation-tags", gen: () => generateInvalidationTags(ctx), enabled: ctx.config.features.tagInvalidation },
57
+ { name: "gql-wrapper", gen: () => generateGqlWrapper(ctx), enabled: ctx.config.features.graphql.enabled },
53
58
  { name: "push", gen: () => generatePush(ctx), enabled: ctx.config.features.pushNotifications?.enabled ?? false },
59
+ { name: "server-push", gen: () => generateServerPush(ctx), enabled: ctx.config.features.serverPush.enabled },
54
60
  { name: "hooks", gen: () => generateHooks(ctx), enabled: ctx.config.framework === "react" },
55
61
  { name: "GUIDE.md", gen: () => generateGuide(ctx), enabled: true },
56
62
  { name: "README.md", gen: () => generateReadme(ctx), enabled: true },
@@ -1 +1 @@
1
- {"version":3,"file":"swoff-files-generator.js","sourceRoot":"","sources":["../../../src/lib/generators/swoff-files-generator.ts"],"names":[],"mappings":"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"}
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,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAQnE,MAAM,UAAU,aAAa,CAAC,GAAqB,EAAE,MAA+B;IAClF,MAAM,KAAK,GAAW;QACpB,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;QAC1E,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;QAC1E,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,sBAAsB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;QAClF,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9E,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE;QAE9F,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE;QACrH,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE;QACrH,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,sBAAsB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE;QAChH,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE;QACpG,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE;QAClG,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE;QACpG,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;QACjF,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,KAAK,IAAI,EAAE;QAC1F,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE;QACrG,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE;QACrG,EAAE,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE;QACrH,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE;QACzG,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,IAAI,KAAK,EAAE;QAChH,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,EAAE;QAC5G,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,OAAO,EAAE;QAC3F,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;QAClE,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;KACrE,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,SAAS;QAC5B,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,CAAC,GAAG,EAAE,CAAC;IACb,CAAC;IAED,OAAO,GAAG,CAAC,cAAc,CAAC;AAC5B,CAAC;AAED,0BAA0B;AAC1B,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,aAAa,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IACxF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAiB,EAAE;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACtC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3C,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;IAC5C,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAEnF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAEvD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,MAAM,GAAG,GAAqB;QAC5B,MAAM;QACN,WAAW;QACX,QAAQ;QACR,GAAG;QACH,cAAc;QACd,aAAa,EAAE,MAAM,CAAC,SAAS,IAAI,SAAS;KAC7C,CAAC;IAEF,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK;QACpC,CAAC,CAAC,CAAC,GAAW,EAAE,EAAE;YACd,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;YAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QAC9D,CAAC;QACH,CAAC,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAE7C,OAAO,CAAC,GAAG,CAAC,2BAA2B,QAAQ,MAAM,CAAC,CAAC;IAEvD,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC;IAExD,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAChC,cAAc,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,YAAY,cAAc,CAAC,MAAM,QAAQ,CAAC,CAAC;AACzD,CAAC"}
@@ -4,9 +4,11 @@ export const KNOWN_FEATURES = [
4
4
  "auth",
5
5
  "crossTabSync",
6
6
  "tagInvalidation",
7
+ "graphql",
7
8
  "pushNotifications",
9
+ "serverPush",
8
10
  ];
9
- export const OBJECT_FEATURES = ["pwa", "serviceWorker", "auth", "pushNotifications"];
11
+ export const OBJECT_FEATURES = ["pwa", "serviceWorker", "auth", "pushNotifications", "graphql", "serverPush"];
10
12
  export const VALID_STRATEGIES = [
11
13
  "cache-first",
12
14
  "network-first",
@@ -27,6 +29,20 @@ function normalizeSwVersion(ver) {
27
29
  return { ...defaultVersionConfig, ...ver };
28
30
  return defaultVersionConfig;
29
31
  }
32
+ function normalizeGql(val) {
33
+ if (typeof val === "boolean")
34
+ return { ...defaultGql, enabled: val };
35
+ if (val && typeof val === "object")
36
+ return { ...defaultGql, ...val };
37
+ return defaultGql;
38
+ }
39
+ function normalizeMutationQueue(val) {
40
+ if (typeof val === "boolean")
41
+ return { ...defaultMutationQueue, enabled: val };
42
+ if (val && typeof val === "object")
43
+ return { ...defaultMutationQueue, ...val };
44
+ return defaultMutationQueue;
45
+ }
30
46
  export function mergeConfigs(base, override) {
31
47
  return {
32
48
  ...base,
@@ -41,6 +57,9 @@ export function mergeConfigs(base, override) {
41
57
  version: normalizeSwVersion(override.features?.serviceWorker?.version),
42
58
  },
43
59
  auth: normalizeAuth(override.features?.auth),
60
+ mutationQueue: normalizeMutationQueue(override.features?.mutationQueue),
61
+ graphql: normalizeGql(override.features?.graphql),
62
+ serverPush: { ...defaultServerPush, ...override.features?.serverPush },
44
63
  },
45
64
  build: { ...base.build, ...override.build },
46
65
  };
@@ -56,6 +75,23 @@ export const defaultVersionConfig = {
56
75
  source: "from-package",
57
76
  minSupportedVersion: "0.0.0",
58
77
  };
78
+ export const defaultGql = {
79
+ enabled: false,
80
+ endpoint: "/graphql",
81
+ };
82
+ export const defaultMutationQueue = {
83
+ enabled: false,
84
+ batchSize: 1,
85
+ batchDelayMs: 0,
86
+ maxRetries: 5,
87
+ retryBackoffMs: 1000,
88
+ };
89
+ export const defaultServerPush = {
90
+ enabled: false,
91
+ type: "sse",
92
+ endpoint: "/api/events",
93
+ reconnectDelayMs: 5000,
94
+ };
59
95
  export const defaultConfig = {
60
96
  enabled: true,
61
97
  features: {
@@ -75,12 +111,14 @@ export const defaultConfig = {
75
111
  navigationMode: "spa",
76
112
  spaEntry: "/index.html",
77
113
  },
78
- mutationQueue: false,
114
+ mutationQueue: { ...defaultMutationQueue },
79
115
  backgroundSync: false,
80
116
  auth: { ...defaultAuth },
81
117
  crossTabSync: true,
82
118
  tagInvalidation: true,
119
+ graphql: { ...defaultGql },
83
120
  pushNotifications: { enabled: false },
121
+ serverPush: { ...defaultServerPush },
84
122
  },
85
123
  build: {
86
124
  outputDir: "dist",