offline-page-kit 0.2.1 → 0.3.2

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/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import path3 from "path";
4
+ import path2 from "path";
5
5
 
6
6
  // src/core/utils.ts
7
7
  import fs from "fs";
@@ -23,14 +23,20 @@ function exists(filePath) {
23
23
  }
24
24
  function parseArgs(argv) {
25
25
  const m = /* @__PURE__ */ new Map();
26
+ const norm = (k) => k.replace(/-/g, "").toLowerCase();
26
27
  for (let i = 0; i < argv.length; i++) {
27
28
  const a = argv[i];
28
29
  if (!a.startsWith("--")) continue;
29
- const key = a.slice(2);
30
+ const rawKey = a.slice(2);
31
+ const key = norm(rawKey);
30
32
  const value = argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[++i] : "true";
31
33
  m.set(key, value);
32
34
  }
33
- return m;
35
+ return {
36
+ get(name) {
37
+ return m.get(norm(name));
38
+ }
39
+ };
34
40
  }
35
41
  function splitList(v) {
36
42
  return (v || "").split(",").map((s) => s.trim()).filter(Boolean);
@@ -82,171 +88,23 @@ function offlineSvgTemplate() {
82
88
  }
83
89
 
84
90
  // src/core/swTemplate.ts
85
- var DEFAULT_EXTS = [
86
- "js",
87
- "css",
88
- "map",
89
- "ico",
90
- "png",
91
- "jpg",
92
- "jpeg",
93
- "webp",
94
- "svg",
95
- "gif",
96
- "woff2",
97
- "woff",
98
- "ttf",
99
- "eot",
100
- "json",
101
- "txt",
102
- "xml",
103
- "webmanifest"
104
- ];
105
- function jsString(v) {
106
- return JSON.stringify(v);
107
- }
91
+ var js = (v) => JSON.stringify(v);
108
92
  function buildServiceWorkerJS(options2) {
109
- const {
110
- cacheName,
111
- offlinePage,
112
- offlineImage,
113
- precache,
114
- htmlStrategy,
115
- assetStrategy,
116
- imageStrategy,
117
- assetExtensions,
118
- apiPrefixes
119
- } = options2;
120
- const precacheList = Array.from(
121
- new Set([offlinePage, offlineImage, ...precache ?? []].filter(Boolean))
122
- );
123
- return `/* offline-page-kit service worker */
124
- const CACHE_NAME = ${jsString(cacheName)};
125
- const OFFLINE_PAGE = ${jsString(offlinePage)};
126
- const OFFLINE_IMAGE = ${jsString(offlineImage)};
127
- const PRECACHE = ${jsString(precacheList)};
128
-
129
- const HTML_STRATEGY = ${jsString(htmlStrategy)};
130
- const ASSET_STRATEGY = ${jsString(assetStrategy)};
131
- const IMAGE_STRATEGY = ${jsString(imageStrategy)};
132
-
133
- const ASSET_EXTS = new Set(${jsString(assetExtensions.length ? assetExtensions : DEFAULT_EXTS)});
134
- const API_PREFIXES = ${jsString(apiPrefixes || [])};
135
-
136
- const SAME_ORIGIN_ONLY = true;
137
-
138
- // ---------------------------
139
- // helpers
140
- // ---------------------------
141
- const isSameOrigin = (url) => url.origin === self.location.origin;
142
-
143
- const isApi = (url) => {
144
- if (!API_PREFIXES || API_PREFIXES.length === 0) return false;
145
- return API_PREFIXES.some((p) => {
146
- try {
147
- // allow either absolute prefix or pathname prefix
148
- return url.href.startsWith(p) || url.pathname.startsWith(p);
149
- } catch {
150
- return false;
151
- }
152
- });
153
- };
154
-
155
- const extOf = (pathname) => {
156
- const i = pathname.lastIndexOf(".");
157
- return i === -1 ? "" : pathname.slice(i + 1).toLowerCase();
158
- };
159
-
160
- const isImageExt = (ext) => ["png","jpg","jpeg","webp","gif","svg","ico"].includes(ext);
161
-
162
- // Only cache successful, basic responses (avoid caching errors)
163
- const isCacheableResponse = (res) => res && (res.ok || res.type === "opaque");
164
-
165
- // Cache helpers
166
- async function cacheGet(reqOrUrl) {
167
- const cache = await caches.open(CACHE_NAME);
168
- return cache.match(reqOrUrl);
169
- }
170
-
171
- async function cachePut(req, res) {
172
- try {
173
- if (!isCacheableResponse(res)) return;
174
- const cache = await caches.open(CACHE_NAME);
175
- await cache.put(req, res);
176
- } catch {
177
- // ignore quota / put errors
178
- }
179
- }
180
-
181
- async function cleanOldCaches() {
182
- const keys = await caches.keys();
183
- await Promise.all(keys.map((k) => (k === CACHE_NAME ? null : caches.delete(k))));
184
- }
185
-
186
- // ---------------------------
187
- // strategies
188
- // ---------------------------
189
- async function networkFirst(req, fallbackUrl) {
190
- try {
191
- const res = await fetch(req);
192
- await cachePut(req, res.clone());
193
- return res;
194
- } catch {
195
- const cached = await cacheGet(req);
196
- if (cached) return cached;
197
- if (fallbackUrl) {
198
- const fb = await cacheGet(fallbackUrl);
199
- if (fb) return fb;
200
- }
201
- return new Response("Offline", { status: 503, headers: { "content-type": "text/plain" } });
202
- }
203
- }
93
+ const { cacheName, offlinePage, offlineImage } = options2;
94
+ return `/* offline-page-kit service worker (minimal) */
95
+ const CACHE_NAME = ${js(cacheName)};
96
+ const OFFLINE_PAGE = ${js(offlinePage)};
97
+ const OFFLINE_IMAGE = ${js(offlineImage)};
204
98
 
205
- async function cacheFirst(req, fallbackUrl) {
206
- const cached = await cacheGet(req);
207
- if (cached) return cached;
208
-
209
- try {
210
- const res = await fetch(req);
211
- await cachePut(req, res.clone());
212
- return res;
213
- } catch {
214
- if (fallbackUrl) {
215
- const fb = await cacheGet(fallbackUrl);
216
- if (fb) return fb;
217
- }
218
- return new Response("Offline", { status: 503, headers: { "content-type": "text/plain" } });
219
- }
220
- }
221
-
222
- async function staleWhileRevalidate(req) {
223
- const cached = await cacheGet(req);
224
-
225
- const fetchPromise = fetch(req)
226
- .then(async (res) => {
227
- await cachePut(req, res.clone());
228
- return res;
229
- })
230
- .catch(() => null);
231
-
232
- return cached || (await fetchPromise) || new Response("Offline", { status: 503 });
233
- }
234
-
235
- function pickStrategy(name) {
236
- if (name === "cacheFirst") return cacheFirst;
237
- if (name === "staleWhileRevalidate") return staleWhileRevalidate;
238
- return networkFirst;
239
- }
240
-
241
- // ---------------------------
242
- // lifecycle
243
- // ---------------------------
244
99
  self.addEventListener("install", (event) => {
245
100
  event.waitUntil((async () => {
246
101
  const cache = await caches.open(CACHE_NAME);
247
102
 
248
- // \u2705 fail-safe install (never redundant from a single bad file)
249
- await Promise.allSettled(PRECACHE.map((u) => cache.add(u)));
103
+ // \u2705 Do not let one 404 kill the install
104
+ await Promise.allSettled([
105
+ cache.add(OFFLINE_PAGE),
106
+ cache.add(OFFLINE_IMAGE),
107
+ ]);
250
108
 
251
109
  await self.skipWaiting();
252
110
  })());
@@ -254,130 +112,32 @@ self.addEventListener("install", (event) => {
254
112
 
255
113
  self.addEventListener("activate", (event) => {
256
114
  event.waitUntil((async () => {
257
- await cleanOldCaches();
258
115
  await self.clients.claim();
259
116
  })());
260
117
  });
261
118
 
262
- // Allow app to trigger update instantly:
263
- // navigator.serviceWorker.controller?.postMessage({ type: "SKIP_WAITING" })
264
- self.addEventListener("message", (event) => {
265
- if (event?.data?.type === "SKIP_WAITING") {
266
- self.skipWaiting();
267
- }
268
- });
269
-
270
- // ---------------------------
271
- // fetch routing
272
- // ---------------------------
273
119
  self.addEventListener("fetch", (event) => {
274
120
  const req = event.request;
275
121
 
276
- // Don't touch non-GET requests
277
- if (req.method && req.method !== "GET") return;
278
-
279
- const url = new URL(req.url);
280
-
281
- // Safe default: same-origin only
282
- if (SAME_ORIGIN_ONLY && !isSameOrigin(url)) return;
283
-
284
- const accept = req.headers.get("accept") || "";
285
- const ext = extOf(url.pathname);
286
-
287
- // 1) HTML / navigations -> offline page fallback
288
- const isHtml = req.mode === "navigate" || accept.includes("text/html");
289
- if (isHtml) {
290
- const fn = pickStrategy(HTML_STRATEGY);
291
- event.respondWith(fn(req, OFFLINE_PAGE));
292
- return;
293
- }
294
-
295
- // 2) API calls (network-first by default)
296
- if (isApi(url)) {
297
- event.respondWith(networkFirst(req));
298
- return;
299
- }
300
-
301
- // 3) Images (cache-first default) with OFFLINE_IMAGE fallback
302
- if (isImageExt(ext)) {
303
- const fn = pickStrategy(IMAGE_STRATEGY);
304
- event.respondWith(fn(req, OFFLINE_IMAGE));
305
- return;
306
- }
307
-
308
- // 4) Static assets (js/css/fonts/json/etc.)
309
- if (ASSET_EXTS.has(ext)) {
310
- const fn = pickStrategy(ASSET_STRATEGY);
311
- if (fn === staleWhileRevalidate) {
312
- event.respondWith(staleWhileRevalidate(req));
313
- } else {
314
- event.respondWith(fn(req));
315
- }
316
- return;
317
- }
318
-
319
- // Everything else: do nothing (network as normal)
320
- });
321
- `;
322
- }
323
-
324
- // src/core/precacheScan.ts
325
- import fs2 from "fs";
326
- import path2 from "path";
327
- function normalizeExts(exts) {
328
- return new Set(exts.map((e) => e.replace(/^\./, "").toLowerCase()));
329
- }
330
- function toUrlPath(outDirAbs, fileAbs) {
331
- const rel = path2.relative(outDirAbs, fileAbs).split(path2.sep).join("/");
332
- return "/" + rel.replace(/^\/+/, "");
333
- }
334
- function startsWithAny(urlPath, prefixes) {
335
- return prefixes.some((p) => urlPath.startsWith(p));
336
- }
337
- function scanPrecacheFiles(opts) {
338
- const exts = normalizeExts(opts.extensions);
339
- const results = [];
340
- const walk = (dirAbs) => {
341
- if (results.length >= opts.maxFiles) return;
342
- const entries = fs2.readdirSync(dirAbs, { withFileTypes: true });
343
- for (const ent of entries) {
344
- if (results.length >= opts.maxFiles) break;
345
- const abs = path2.join(dirAbs, ent.name);
346
- if (ent.isDirectory()) {
347
- walk(abs);
348
- continue;
349
- }
350
- if (!ent.isFile()) continue;
122
+ // \u2705 Offline fallback only for page navigations
123
+ if (req.mode === "navigate") {
124
+ event.respondWith((async () => {
351
125
  try {
352
- const st = fs2.statSync(abs);
353
- if (st.size > opts.maxFileSizeKB * 1024) continue;
126
+ return await fetch(req);
354
127
  } catch {
355
- continue;
128
+ const cache = await caches.open(CACHE_NAME);
129
+ return (await cache.match(OFFLINE_PAGE)) || new Response("Offline", { status: 503 });
356
130
  }
357
- const urlPath = toUrlPath(opts.outDir, abs);
358
- if (startsWithAny(urlPath, opts.ignorePrefixes)) continue;
359
- const dot = urlPath.lastIndexOf(".");
360
- const ext = dot === -1 ? "" : urlPath.slice(dot + 1).toLowerCase();
361
- if (!exts.has(ext)) continue;
362
- results.push(urlPath);
363
- }
364
- };
365
- walk(opts.outDir);
366
- return results;
131
+ })());
132
+ }
133
+ });
134
+ `;
367
135
  }
368
136
 
369
137
  // src/cli.ts
370
138
  function normalizePublicPath(p) {
371
- if (!p) return "/";
372
- return p.startsWith("/") ? p : "/" + p;
373
- }
374
- function normalizeIgnorePrefix(p) {
375
- return normalizePublicPath(p.trim());
376
- }
377
- function safeNumber(v, fallback) {
378
- if (!v) return fallback;
379
- const n = Number(v);
380
- return Number.isFinite(n) ? n : fallback;
139
+ if (!p.startsWith("/")) return "/" + p;
140
+ return p;
381
141
  }
382
142
  function withDefaults(o) {
383
143
  return {
@@ -391,69 +151,28 @@ function withDefaults(o) {
391
151
  assetStrategy: o.assetStrategy ?? "staleWhileRevalidate",
392
152
  imageStrategy: o.imageStrategy ?? "cacheFirst",
393
153
  assetExtensions: o.assetExtensions ?? [],
394
- apiPrefixes: o.apiPrefixes ?? [],
395
- autoPrecache: o.autoPrecache ?? true,
396
- precacheExtensions: o.precacheExtensions ?? [
397
- "ico",
398
- "png",
399
- "jpg",
400
- "jpeg",
401
- "webp",
402
- "svg",
403
- "gif",
404
- "css",
405
- "js",
406
- "woff2",
407
- "woff",
408
- "ttf",
409
- "eot",
410
- "json",
411
- "webmanifest",
412
- "txt",
413
- "xml"
414
- ],
415
- precacheIgnore: o.precacheIgnore ?? [
416
- "/sw.js",
417
- "/sw.js.map",
418
- "/_next/",
419
- "/static/"
420
- ],
421
- precacheMaxFiles: o.precacheMaxFiles ?? 200,
422
- precacheMaxFileSizeKB: o.precacheMaxFileSizeKB ?? 512
154
+ apiPrefixes: o.apiPrefixes ?? []
423
155
  };
424
156
  }
425
- function parseCommand(argv) {
426
- const first = argv[0];
427
- if (first === "init" || first === "build") {
428
- return { cmd: first, rest: argv.slice(1) };
429
- }
430
- return { cmd: "init", rest: argv };
431
- }
432
- var rawArgv = process.argv.slice(2);
433
- var { cmd, rest } = parseCommand(rawArgv);
434
- var args = parseArgs(rest);
435
- var outDir = path3.resolve(process.cwd(), args.get("outDir") || "public");
157
+ var args = parseArgs(process.argv.slice(2));
158
+ var cmd = process.argv.slice(2).find((a) => !a.startsWith("--")) || "init";
159
+ var outDir = path2.resolve(process.cwd(), args.get("outDir") || "public");
436
160
  var options = withDefaults({
437
161
  outDir,
438
162
  swFileName: args.get("swFileName") || "sw.js",
439
163
  offlinePage: args.get("offlinePage") || "/offline.html",
440
164
  offlineImage: args.get("offlineImage") || "/offline.svg",
441
165
  cacheName: args.get("cacheName") || "offline-page-kit",
442
- precache: splitList(args.get("precache")).map(normalizePublicPath),
166
+ precache: splitList(args.get("precache")),
443
167
  htmlStrategy: args.get("htmlStrategy") || "networkFirst",
444
168
  assetStrategy: args.get("assetStrategy") || "staleWhileRevalidate",
445
169
  imageStrategy: args.get("imageStrategy") || "cacheFirst",
446
170
  assetExtensions: splitList(args.get("assetExtensions")),
447
- apiPrefixes: splitList(args.get("apiPrefixes")),
448
- autoPrecache: args.get("autoPrecache") !== "false",
449
- precacheExtensions: splitList(args.get("precacheExtensions")),
450
- precacheIgnore: splitList(args.get("precacheIgnore")).map(normalizeIgnorePrefix),
451
- precacheMaxFiles: safeNumber(args.get("precacheMaxFiles"), 200),
452
- precacheMaxFileSizeKB: safeNumber(args.get("precacheMaxFileSizeKB"), 512)
171
+ apiPrefixes: splitList(args.get("apiPrefixes"))
453
172
  });
454
- var swOut = path3.join(outDir, options.swFileName);
455
- var offlineHtmlOut = path3.join(outDir, options.offlinePage.replace(/^\//, ""));
456
- var offlineSvgOut = path3.join(outDir, options.offlineImage.replace(/^\//, ""));
173
+ var swOut = path2.join(outDir, options.swFileName);
174
+ var offlineHtmlOut = path2.join(outDir, options.offlinePage.replace(/^\//, ""));
175
+ var offlineSvgOut = path2.join(outDir, options.offlineImage.replace(/^\//, ""));
457
176
  if (cmd === "init" || cmd === "build") {
458
177
  if (cmd === "build" || !exists(offlineHtmlOut)) {
459
178
  writeFileSafe(offlineHtmlOut, offlineHtmlTemplate());
@@ -461,46 +180,12 @@ if (cmd === "init" || cmd === "build") {
461
180
  if (cmd === "build" || !exists(offlineSvgOut)) {
462
181
  writeFileSafe(offlineSvgOut, offlineSvgTemplate());
463
182
  }
464
- let scanned = [];
465
- if (options.autoPrecache) {
466
- const swUrlPath = normalizePublicPath(options.swFileName);
467
- const swMapUrlPath = swUrlPath + ".map";
468
- const ignorePrefixes = Array.from(/* @__PURE__ */ new Set([
469
- swUrlPath,
470
- swMapUrlPath,
471
- ...options.precacheIgnore.map(normalizeIgnorePrefix)
472
- ]));
473
- scanned = scanPrecacheFiles({
474
- outDir,
475
- // absolute /public
476
- extensions: options.precacheExtensions.length ? options.precacheExtensions : ["ico", "png", "css", "js", "woff2", "json", "webmanifest", "svg"],
477
- ignorePrefixes,
478
- maxFiles: options.precacheMaxFiles,
479
- maxFileSizeKB: options.precacheMaxFileSizeKB
480
- }).map(normalizePublicPath);
481
- }
482
- const allPrecache = Array.from(/* @__PURE__ */ new Set([
483
- normalizePublicPath(options.offlinePage),
484
- normalizePublicPath(options.offlineImage),
485
- ...(options.precache || []).map(normalizePublicPath),
486
- ...scanned.map(normalizePublicPath)
487
- ]));
488
- const sw = buildServiceWorkerJS({
489
- ...options,
490
- precache: allPrecache
491
- });
183
+ const sw = buildServiceWorkerJS(options);
492
184
  writeFileSafe(swOut, sw);
493
- const manualCount = (options.precache || []).length;
494
- const scannedCount = scanned.length;
495
185
  console.log(`[offline-page-kit] Generated:
496
186
  - ${swOut}
497
187
  - ${offlineHtmlOut}
498
188
  - ${offlineSvgOut}
499
-
500
- Precache:
501
- - manual: ${manualCount}
502
- - scanned: ${scannedCount}
503
- - total: ${allPrecache.length}
504
189
  `);
505
190
  } else {
506
191
  console.log(`[offline-page-kit] Unknown command: ${cmd}
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/core/utils.ts","../src/core/offlineHtml.ts","../src/core/offlineSvg.ts","../src/core/swTemplate.ts","../src/core/precacheScan.ts"],"sourcesContent":["#!/usr/bin/env node\r\nimport path from \"node:path\";\r\nimport { parseArgs, splitList, writeFileSafe, exists } from \"./core/utils\";\r\nimport { offlineHtmlTemplate } from \"./core/offlineHtml\";\r\nimport { offlineSvgTemplate } from \"./core/offlineSvg\";\r\nimport { buildServiceWorkerJS } from \"./core/swTemplate\";\r\nimport type { OfflineKitBuildOptions } from \"./types\";\r\nimport { scanPrecacheFiles } from \"./core/precacheScan\";\r\n\r\ntype Cmd = \"init\" | \"build\";\r\n\r\nfunction normalizePublicPath(p: string) {\r\n if (!p) return \"/\";\r\n return p.startsWith(\"/\") ? p : \"/\" + p;\r\n}\r\n\r\nfunction normalizeIgnorePrefix(p: string) {\r\n // ignore prefixes are URL-style and should start with \"/\"\r\n return normalizePublicPath(p.trim());\r\n}\r\n\r\nfunction safeNumber(v: string | undefined, fallback: number) {\r\n if (!v) return fallback;\r\n const n = Number(v);\r\n return Number.isFinite(n) ? n : fallback;\r\n}\r\n\r\nfunction withDefaults(o: OfflineKitBuildOptions): Required<OfflineKitBuildOptions> {\r\n return {\r\n outDir: o.outDir ?? \"public\",\r\n swFileName: o.swFileName ?? \"sw.js\",\r\n\r\n offlinePage: normalizePublicPath(o.offlinePage ?? \"/offline.html\"),\r\n offlineImage: normalizePublicPath(o.offlineImage ?? \"/offline.svg\"),\r\n\r\n cacheName: o.cacheName ?? \"offline-page-kit\",\r\n precache: o.precache ?? [],\r\n\r\n htmlStrategy: o.htmlStrategy ?? \"networkFirst\",\r\n assetStrategy: o.assetStrategy ?? \"staleWhileRevalidate\",\r\n imageStrategy: o.imageStrategy ?? \"cacheFirst\",\r\n\r\n assetExtensions: o.assetExtensions ?? [],\r\n apiPrefixes: o.apiPrefixes ?? [],\r\n\r\n autoPrecache: o.autoPrecache ?? true,\r\n precacheExtensions: o.precacheExtensions ?? [\r\n \"ico\", \"png\", \"jpg\", \"jpeg\", \"webp\", \"svg\", \"gif\",\r\n \"css\", \"js\", \"woff2\", \"woff\", \"ttf\", \"eot\",\r\n \"json\", \"webmanifest\", \"txt\", \"xml\"\r\n ],\r\n precacheIgnore: o.precacheIgnore ?? [\r\n \"/sw.js\",\r\n \"/sw.js.map\",\r\n \"/_next/\",\r\n \"/static/\"\r\n ],\r\n precacheMaxFiles: o.precacheMaxFiles ?? 200,\r\n precacheMaxFileSizeKB: o.precacheMaxFileSizeKB ?? 512,\r\n };\r\n}\r\n\r\n/**\r\n * Command parsing\r\n * Supports:\r\n * offline-page-kit init --outDir public\r\n * offline-page-kit --outDir public (defaults to init)\r\n */\r\nfunction parseCommand(argv: string[]): { cmd: Cmd; rest: string[] } {\r\n const first = argv[0];\r\n if (first === \"init\" || first === \"build\") {\r\n return { cmd: first, rest: argv.slice(1) };\r\n }\r\n return { cmd: \"init\", rest: argv };\r\n}\r\n\r\nconst rawArgv = process.argv.slice(2);\r\nconst { cmd, rest } = parseCommand(rawArgv);\r\nconst args = parseArgs(rest);\r\n\r\nconst outDir = path.resolve(process.cwd(), args.get(\"outDir\") || \"public\");\r\n\r\nconst options = withDefaults({\r\n outDir,\r\n swFileName: args.get(\"swFileName\") || \"sw.js\",\r\n offlinePage: args.get(\"offlinePage\") || \"/offline.html\",\r\n offlineImage: args.get(\"offlineImage\") || \"/offline.svg\",\r\n cacheName: args.get(\"cacheName\") || \"offline-page-kit\",\r\n precache: splitList(args.get(\"precache\")).map(normalizePublicPath),\r\n\r\n htmlStrategy: (args.get(\"htmlStrategy\") as any) || \"networkFirst\",\r\n assetStrategy: (args.get(\"assetStrategy\") as any) || \"staleWhileRevalidate\",\r\n imageStrategy: (args.get(\"imageStrategy\") as any) || \"cacheFirst\",\r\n\r\n assetExtensions: splitList(args.get(\"assetExtensions\")),\r\n apiPrefixes: splitList(args.get(\"apiPrefixes\")),\r\n\r\n autoPrecache: args.get(\"autoPrecache\") !== \"false\",\r\n precacheExtensions: splitList(args.get(\"precacheExtensions\")),\r\n precacheIgnore: splitList(args.get(\"precacheIgnore\")).map(normalizeIgnorePrefix),\r\n\r\n precacheMaxFiles: safeNumber(args.get(\"precacheMaxFiles\"), 200),\r\n precacheMaxFileSizeKB: safeNumber(args.get(\"precacheMaxFileSizeKB\"), 512),\r\n} as OfflineKitBuildOptions);\r\n\r\nconst swOut = path.join(outDir, options.swFileName);\r\nconst offlineHtmlOut = path.join(outDir, options.offlinePage.replace(/^\\//, \"\"));\r\nconst offlineSvgOut = path.join(outDir, options.offlineImage.replace(/^\\//, \"\"));\r\n\r\nif (cmd === \"init\" || cmd === \"build\") {\r\n // 1) Generate offline page + offline svg first (so scanner can find them)\r\n if (cmd === \"build\" || !exists(offlineHtmlOut)) {\r\n writeFileSafe(offlineHtmlOut, offlineHtmlTemplate());\r\n }\r\n if (cmd === \"build\" || !exists(offlineSvgOut)) {\r\n writeFileSafe(offlineSvgOut, offlineSvgTemplate());\r\n }\r\n\r\n // 2) Auto-scan (after offline files exist)\r\n let scanned: string[] = [];\r\n if (options.autoPrecache) {\r\n // ✅ always ignore the actual sw filename (even if user customizes it)\r\n const swUrlPath = normalizePublicPath(options.swFileName);\r\n const swMapUrlPath = swUrlPath + \".map\";\r\n\r\n const ignorePrefixes = Array.from(new Set([\r\n swUrlPath,\r\n swMapUrlPath,\r\n ...options.precacheIgnore.map(normalizeIgnorePrefix),\r\n ]));\r\n\r\n scanned = scanPrecacheFiles({\r\n outDir, // absolute /public\r\n extensions: options.precacheExtensions.length\r\n ? options.precacheExtensions\r\n : [\"ico\", \"png\", \"css\", \"js\", \"woff2\", \"json\", \"webmanifest\", \"svg\"],\r\n ignorePrefixes,\r\n maxFiles: options.precacheMaxFiles,\r\n maxFileSizeKB: options.precacheMaxFileSizeKB,\r\n }).map(normalizePublicPath);\r\n }\r\n\r\n // 3) Merge + de-duplicate (and normalize)\r\n const allPrecache = Array.from(new Set([\r\n normalizePublicPath(options.offlinePage),\r\n normalizePublicPath(options.offlineImage),\r\n ...(options.precache || []).map(normalizePublicPath),\r\n ...scanned.map(normalizePublicPath),\r\n ]));\r\n\r\n // 4) Build SW using merged list\r\n const sw = buildServiceWorkerJS({\r\n ...options,\r\n precache: allPrecache,\r\n });\r\n\r\n writeFileSafe(swOut, sw);\r\n\r\n const manualCount = (options.precache || []).length;\r\n const scannedCount = scanned.length;\r\n\r\n console.log(`[offline-page-kit] Generated:\r\n- ${swOut}\r\n- ${offlineHtmlOut}\r\n- ${offlineSvgOut}\r\n\r\nPrecache:\r\n- manual: ${manualCount}\r\n- scanned: ${scannedCount}\r\n- total: ${allPrecache.length}\r\n`);\r\n} else {\r\n console.log(`[offline-page-kit] Unknown command: ${cmd}\r\nUse:\r\n offline-page-kit init --outDir public\r\n offline-page-kit build --outDir public\r\n`);\r\n}","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\n\r\nexport function ensureDir(p: string) {\r\n fs.mkdirSync(p, { recursive: true });\r\n}\r\n\r\nexport function writeFileSafe(filePath: string, content: string) {\r\n ensureDir(path.dirname(filePath));\r\n fs.writeFileSync(filePath, content, \"utf8\");\r\n}\r\n\r\nexport function exists(filePath: string) {\r\n try { fs.accessSync(filePath); return true; } catch { return false; }\r\n}\r\n\r\nexport function parseArgs(argv: string[]) {\r\n const m = new Map<string, string>();\r\n for (let i = 0; i < argv.length; i++) {\r\n const a = argv[i];\r\n if (!a.startsWith(\"--\")) continue;\r\n const key = a.slice(2);\r\n const value = argv[i + 1] && !argv[i + 1].startsWith(\"--\") ? argv[++i] : \"true\";\r\n m.set(key, value);\r\n }\r\n return m;\r\n}\r\n\r\nexport function splitList(v: string | undefined) {\r\n return (v || \"\")\r\n .split(\",\")\r\n .map(s => s.trim())\r\n .filter(Boolean);\r\n}","export function offlineHtmlTemplate(title = \"You're Offline\") {\r\n return `<!doctype html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\"/>\r\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/>\r\n <title>${title}</title>\r\n <style>\r\n body{margin:0;height:100vh;display:grid;place-items:center;font-family:system-ui,-apple-system,Segoe UI,Roboto;background:#0b0f19;color:#fff}\r\n .box{max-width:560px;padding:28px 26px;border-radius:18px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04)}\r\n h1{margin:0 0 10px;font-size:28px}\r\n p{margin:0 0 18px;opacity:.85;line-height:1.5}\r\n .row{display:flex;gap:10px;flex-wrap:wrap}\r\n button,a{appearance:none;border:0;border-radius:12px;padding:10px 14px;cursor:pointer;text-decoration:none}\r\n button{background:#fff;color:#111}\r\n a{background:rgba(255,255,255,.1);color:#fff}\r\n </style>\r\n</head>\r\n<body>\r\n <div class=\"box\">\r\n <h1>⚡ You’re Offline</h1>\r\n <p>No internet connection detected. You can retry, or go back to the homepage (if cached).</p>\r\n <div class=\"row\">\r\n <button onclick=\"location.reload()\">Retry</button>\r\n <a href=\"/\">Go Home</a>\r\n </div>\r\n </div>\r\n</body>\r\n</html>`;\r\n}","export function offlineSvgTemplate() {\r\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1200\" height=\"630\" viewBox=\"0 0 1200 630\">\r\n <rect width=\"1200\" height=\"630\" fill=\"#0b0f19\"/>\r\n <text x=\"80\" y=\"220\" fill=\"#ffffff\" font-size=\"64\" font-family=\"system-ui, -apple-system, Segoe UI, Roboto\">You’re Offline</text>\r\n <text x=\"80\" y=\"300\" fill=\"#cbd5e1\" font-size=\"28\" font-family=\"system-ui, -apple-system, Segoe UI, Roboto\">Please check your connection and try again.</text>\r\n <circle cx=\"1040\" cy=\"220\" r=\"90\" fill=\"rgba(255,255,255,0.08)\"/>\r\n <path d=\"M980 220c40-40 120-40 160 0\" stroke=\"#fff\" stroke-width=\"10\" fill=\"none\" opacity=\"0.6\"/>\r\n <path d=\"M1010 250c25-25 75-25 100 0\" stroke=\"#fff\" stroke-width=\"10\" fill=\"none\" opacity=\"0.6\"/>\r\n <circle cx=\"1060\" cy=\"290\" r=\"10\" fill=\"#fff\" opacity=\"0.7\"/>\r\n</svg>`;\r\n}","import type { OfflineKitBuildOptions } from \"../types\";\r\n\r\nconst DEFAULT_EXTS = [\r\n \"js\", \"css\", \"map\", \"ico\", \"png\", \"jpg\", \"jpeg\", \"webp\", \"svg\", \"gif\",\r\n \"woff2\", \"woff\", \"ttf\", \"eot\", \"json\", \"txt\", \"xml\", \"webmanifest\"\r\n];\r\n\r\nfunction jsString(v: unknown) {\r\n return JSON.stringify(v);\r\n}\r\n\r\nexport function buildServiceWorkerJS(options: Required<OfflineKitBuildOptions>) {\r\n const {\r\n cacheName,\r\n offlinePage,\r\n offlineImage,\r\n precache,\r\n htmlStrategy,\r\n assetStrategy,\r\n imageStrategy,\r\n assetExtensions,\r\n apiPrefixes,\r\n } = options;\r\n\r\n // precache already normalized in CLI; still keep it safe\r\n const precacheList = Array.from(\r\n new Set([offlinePage, offlineImage, ...(precache ?? [])].filter(Boolean))\r\n );\r\n\r\n return `/* offline-page-kit service worker */\r\nconst CACHE_NAME = ${jsString(cacheName)};\r\nconst OFFLINE_PAGE = ${jsString(offlinePage)};\r\nconst OFFLINE_IMAGE = ${jsString(offlineImage)};\r\nconst PRECACHE = ${jsString(precacheList)};\r\n\r\nconst HTML_STRATEGY = ${jsString(htmlStrategy)};\r\nconst ASSET_STRATEGY = ${jsString(assetStrategy)};\r\nconst IMAGE_STRATEGY = ${jsString(imageStrategy)};\r\n\r\nconst ASSET_EXTS = new Set(${jsString(assetExtensions.length ? assetExtensions : DEFAULT_EXTS)});\r\nconst API_PREFIXES = ${jsString(apiPrefixes || [])};\r\n\r\nconst SAME_ORIGIN_ONLY = true;\r\n\r\n// ---------------------------\r\n// helpers\r\n// ---------------------------\r\nconst isSameOrigin = (url) => url.origin === self.location.origin;\r\n\r\nconst isApi = (url) => {\r\n if (!API_PREFIXES || API_PREFIXES.length === 0) return false;\r\n return API_PREFIXES.some((p) => {\r\n try {\r\n // allow either absolute prefix or pathname prefix\r\n return url.href.startsWith(p) || url.pathname.startsWith(p);\r\n } catch {\r\n return false;\r\n }\r\n });\r\n};\r\n\r\nconst extOf = (pathname) => {\r\n const i = pathname.lastIndexOf(\".\");\r\n return i === -1 ? \"\" : pathname.slice(i + 1).toLowerCase();\r\n};\r\n\r\nconst isImageExt = (ext) => [\"png\",\"jpg\",\"jpeg\",\"webp\",\"gif\",\"svg\",\"ico\"].includes(ext);\r\n\r\n// Only cache successful, basic responses (avoid caching errors)\r\nconst isCacheableResponse = (res) => res && (res.ok || res.type === \"opaque\");\r\n\r\n// Cache helpers\r\nasync function cacheGet(reqOrUrl) {\r\n const cache = await caches.open(CACHE_NAME);\r\n return cache.match(reqOrUrl);\r\n}\r\n\r\nasync function cachePut(req, res) {\r\n try {\r\n if (!isCacheableResponse(res)) return;\r\n const cache = await caches.open(CACHE_NAME);\r\n await cache.put(req, res);\r\n } catch {\r\n // ignore quota / put errors\r\n }\r\n}\r\n\r\nasync function cleanOldCaches() {\r\n const keys = await caches.keys();\r\n await Promise.all(keys.map((k) => (k === CACHE_NAME ? null : caches.delete(k))));\r\n}\r\n\r\n// ---------------------------\r\n// strategies\r\n// ---------------------------\r\nasync function networkFirst(req, fallbackUrl) {\r\n try {\r\n const res = await fetch(req);\r\n await cachePut(req, res.clone());\r\n return res;\r\n } catch {\r\n const cached = await cacheGet(req);\r\n if (cached) return cached;\r\n if (fallbackUrl) {\r\n const fb = await cacheGet(fallbackUrl);\r\n if (fb) return fb;\r\n }\r\n return new Response(\"Offline\", { status: 503, headers: { \"content-type\": \"text/plain\" } });\r\n }\r\n}\r\n\r\nasync function cacheFirst(req, fallbackUrl) {\r\n const cached = await cacheGet(req);\r\n if (cached) return cached;\r\n\r\n try {\r\n const res = await fetch(req);\r\n await cachePut(req, res.clone());\r\n return res;\r\n } catch {\r\n if (fallbackUrl) {\r\n const fb = await cacheGet(fallbackUrl);\r\n if (fb) return fb;\r\n }\r\n return new Response(\"Offline\", { status: 503, headers: { \"content-type\": \"text/plain\" } });\r\n }\r\n}\r\n\r\nasync function staleWhileRevalidate(req) {\r\n const cached = await cacheGet(req);\r\n\r\n const fetchPromise = fetch(req)\r\n .then(async (res) => {\r\n await cachePut(req, res.clone());\r\n return res;\r\n })\r\n .catch(() => null);\r\n\r\n return cached || (await fetchPromise) || new Response(\"Offline\", { status: 503 });\r\n}\r\n\r\nfunction pickStrategy(name) {\r\n if (name === \"cacheFirst\") return cacheFirst;\r\n if (name === \"staleWhileRevalidate\") return staleWhileRevalidate;\r\n return networkFirst;\r\n}\r\n\r\n// ---------------------------\r\n// lifecycle\r\n// ---------------------------\r\nself.addEventListener(\"install\", (event) => {\r\n event.waitUntil((async () => {\r\n const cache = await caches.open(CACHE_NAME);\r\n\r\n // ✅ fail-safe install (never redundant from a single bad file)\r\n await Promise.allSettled(PRECACHE.map((u) => cache.add(u)));\r\n\r\n await self.skipWaiting();\r\n })());\r\n});\r\n\r\nself.addEventListener(\"activate\", (event) => {\r\n event.waitUntil((async () => {\r\n await cleanOldCaches();\r\n await self.clients.claim();\r\n })());\r\n});\r\n\r\n// Allow app to trigger update instantly:\r\n// navigator.serviceWorker.controller?.postMessage({ type: \"SKIP_WAITING\" })\r\nself.addEventListener(\"message\", (event) => {\r\n if (event?.data?.type === \"SKIP_WAITING\") {\r\n self.skipWaiting();\r\n }\r\n});\r\n\r\n// ---------------------------\r\n// fetch routing\r\n// ---------------------------\r\nself.addEventListener(\"fetch\", (event) => {\r\n const req = event.request;\r\n\r\n // Don't touch non-GET requests\r\n if (req.method && req.method !== \"GET\") return;\r\n\r\n const url = new URL(req.url);\r\n\r\n // Safe default: same-origin only\r\n if (SAME_ORIGIN_ONLY && !isSameOrigin(url)) return;\r\n\r\n const accept = req.headers.get(\"accept\") || \"\";\r\n const ext = extOf(url.pathname);\r\n\r\n // 1) HTML / navigations -> offline page fallback\r\n const isHtml = req.mode === \"navigate\" || accept.includes(\"text/html\");\r\n if (isHtml) {\r\n const fn = pickStrategy(HTML_STRATEGY);\r\n event.respondWith(fn(req, OFFLINE_PAGE));\r\n return;\r\n }\r\n\r\n // 2) API calls (network-first by default)\r\n if (isApi(url)) {\r\n event.respondWith(networkFirst(req));\r\n return;\r\n }\r\n\r\n // 3) Images (cache-first default) with OFFLINE_IMAGE fallback\r\n if (isImageExt(ext)) {\r\n const fn = pickStrategy(IMAGE_STRATEGY);\r\n event.respondWith(fn(req, OFFLINE_IMAGE));\r\n return;\r\n }\r\n\r\n // 4) Static assets (js/css/fonts/json/etc.)\r\n if (ASSET_EXTS.has(ext)) {\r\n const fn = pickStrategy(ASSET_STRATEGY);\r\n if (fn === staleWhileRevalidate) {\r\n event.respondWith(staleWhileRevalidate(req));\r\n } else {\r\n event.respondWith(fn(req));\r\n }\r\n return;\r\n }\r\n\r\n // Everything else: do nothing (network as normal)\r\n});\r\n`;\r\n}","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\n\r\ntype ScanOptions = {\r\n outDir: string; // absolute path to public\r\n extensions: string[];\r\n ignorePrefixes: string[]; // url-style (\"/_next\", \"/sw.js\")\r\n maxFiles: number;\r\n maxFileSizeKB: number;\r\n};\r\n\r\nfunction normalizeExts(exts: string[]) {\r\n return new Set(exts.map(e => e.replace(/^\\./, \"\").toLowerCase()));\r\n}\r\n\r\nfunction toUrlPath(outDirAbs: string, fileAbs: string) {\r\n // convert /abs/public/assets/a.css -> /assets/a.css\r\n const rel = path.relative(outDirAbs, fileAbs).split(path.sep).join(\"/\");\r\n return \"/\" + rel.replace(/^\\/+/, \"\");\r\n}\r\n\r\nfunction startsWithAny(urlPath: string, prefixes: string[]) {\r\n return prefixes.some(p => urlPath.startsWith(p));\r\n}\r\n\r\nexport function scanPrecacheFiles(opts: ScanOptions): string[] {\r\n const exts = normalizeExts(opts.extensions);\r\n const results: string[] = [];\r\n\r\n const walk = (dirAbs: string) => {\r\n if (results.length >= opts.maxFiles) return;\r\n\r\n const entries = fs.readdirSync(dirAbs, { withFileTypes: true });\r\n for (const ent of entries) {\r\n if (results.length >= opts.maxFiles) break;\r\n\r\n const abs = path.join(dirAbs, ent.name);\r\n\r\n if (ent.isDirectory()) {\r\n walk(abs);\r\n continue;\r\n }\r\n\r\n if (!ent.isFile()) continue;\r\n\r\n // file size limit\r\n try {\r\n const st = fs.statSync(abs);\r\n if (st.size > opts.maxFileSizeKB * 1024) continue;\r\n } catch {\r\n continue;\r\n }\r\n\r\n const urlPath = toUrlPath(opts.outDir, abs);\r\n\r\n // ignore list\r\n if (startsWithAny(urlPath, opts.ignorePrefixes)) continue;\r\n\r\n // extension check\r\n const dot = urlPath.lastIndexOf(\".\");\r\n const ext = dot === -1 ? \"\" : urlPath.slice(dot + 1).toLowerCase();\r\n if (!exts.has(ext)) continue;\r\n\r\n results.push(urlPath);\r\n }\r\n };\r\n\r\n walk(opts.outDir);\r\n return results;\r\n}"],"mappings":"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","names":["path","options","fs","path","path"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/core/utils.ts","../src/core/offlineHtml.ts","../src/core/offlineSvg.ts","../src/core/swTemplate.ts"],"sourcesContent":["#!/usr/bin/env node\r\nimport path from \"node:path\";\r\nimport { parseArgs, splitList, writeFileSafe, exists } from \"./core/utils\";\r\nimport { offlineHtmlTemplate } from \"./core/offlineHtml\";\r\nimport { offlineSvgTemplate } from \"./core/offlineSvg\";\r\nimport { buildServiceWorkerJS } from \"./core/swTemplate\";\r\nimport type { OfflineKitBuildOptions } from \"./types\";\r\n\r\nfunction normalizePublicPath(p: string) {\r\n if (!p.startsWith(\"/\")) return \"/\" + p;\r\n return p;\r\n}\r\n\r\nfunction withDefaults(o: OfflineKitBuildOptions): Required<OfflineKitBuildOptions> {\r\n return {\r\n outDir: o.outDir ?? \"public\",\r\n swFileName: o.swFileName ?? \"sw.js\",\r\n offlinePage: normalizePublicPath(o.offlinePage ?? \"/offline.html\"),\r\n offlineImage: normalizePublicPath(o.offlineImage ?? \"/offline.svg\"),\r\n cacheName: o.cacheName ?? \"offline-page-kit\",\r\n precache: o.precache ?? [],\r\n htmlStrategy: o.htmlStrategy ?? \"networkFirst\",\r\n assetStrategy: o.assetStrategy ?? \"staleWhileRevalidate\",\r\n imageStrategy: o.imageStrategy ?? \"cacheFirst\",\r\n assetExtensions: o.assetExtensions ?? [],\r\n apiPrefixes: o.apiPrefixes ?? [],\r\n };\r\n}\r\n\r\nconst args = parseArgs(process.argv.slice(2));\r\nconst cmd = process.argv.slice(2).find(a => !a.startsWith(\"--\")) || \"init\";\r\n\r\nconst outDir = path.resolve(process.cwd(), args.get(\"outDir\") || \"public\");\r\n\r\nconst options = withDefaults({\r\n outDir,\r\n swFileName: args.get(\"swFileName\") || \"sw.js\",\r\n offlinePage: args.get(\"offlinePage\") || \"/offline.html\",\r\n offlineImage: args.get(\"offlineImage\") || \"/offline.svg\",\r\n cacheName: args.get(\"cacheName\") || \"offline-page-kit\",\r\n precache: splitList(args.get(\"precache\")),\r\n htmlStrategy: (args.get(\"htmlStrategy\") as any) || \"networkFirst\",\r\n assetStrategy: (args.get(\"assetStrategy\") as any) || \"staleWhileRevalidate\",\r\n imageStrategy: (args.get(\"imageStrategy\") as any) || \"cacheFirst\",\r\n assetExtensions: splitList(args.get(\"assetExtensions\")),\r\n apiPrefixes: splitList(args.get(\"apiPrefixes\")),\r\n} as OfflineKitBuildOptions);\r\n\r\nconst swOut = path.join(outDir, options.swFileName);\r\nconst offlineHtmlOut = path.join(outDir, options.offlinePage.replace(/^\\//, \"\"));\r\nconst offlineSvgOut = path.join(outDir, options.offlineImage.replace(/^\\//, \"\"));\r\n\r\nif (cmd === \"init\" || cmd === \"build\") {\r\n // generate offline page if missing OR force (when build)\r\n if (cmd === \"build\" || !exists(offlineHtmlOut)) {\r\n writeFileSafe(offlineHtmlOut, offlineHtmlTemplate());\r\n }\r\n if (cmd === \"build\" || !exists(offlineSvgOut)) {\r\n writeFileSafe(offlineSvgOut, offlineSvgTemplate());\r\n }\r\n\r\n const sw = buildServiceWorkerJS(options);\r\n writeFileSafe(swOut, sw);\r\n\r\n console.log(`[offline-page-kit] Generated:\r\n- ${swOut}\r\n- ${offlineHtmlOut}\r\n- ${offlineSvgOut}\r\n`);\r\n} else {\r\n console.log(`[offline-page-kit] Unknown command: ${cmd}\r\nUse:\r\n offline-page-kit init --outDir public\r\n offline-page-kit build --outDir public\r\n`);\r\n}","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\n\r\nexport function ensureDir(p: string) {\r\n fs.mkdirSync(p, { recursive: true });\r\n}\r\n\r\nexport function writeFileSafe(filePath: string, content: string) {\r\n ensureDir(path.dirname(filePath));\r\n fs.writeFileSync(filePath, content, \"utf8\");\r\n}\r\n\r\nexport function exists(filePath: string) {\r\n try { fs.accessSync(filePath); return true; } catch { return false; }\r\n}\r\n\r\nexport function parseArgs(argv: string[]) {\r\n const m = new Map<string, string>();\r\n\r\n const norm = (k: string) => k.replace(/-/g, \"\").toLowerCase();\r\n\r\n for (let i = 0; i < argv.length; i++) {\r\n const a = argv[i];\r\n if (!a.startsWith(\"--\")) continue;\r\n\r\n const rawKey = a.slice(2);\r\n const key = norm(rawKey);\r\n\r\n const value = argv[i + 1] && !argv[i + 1].startsWith(\"--\") ? argv[++i] : \"true\";\r\n m.set(key, value);\r\n }\r\n\r\n return {\r\n get(name: string) {\r\n return m.get(norm(name));\r\n }\r\n } as unknown as Map<string, string>;\r\n}\r\n\r\nexport function splitList(v: string | undefined) {\r\n return (v || \"\")\r\n .split(\",\")\r\n .map(s => s.trim())\r\n .filter(Boolean);\r\n}","export function offlineHtmlTemplate(title = \"You're Offline\") {\r\n return `<!doctype html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\"/>\r\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/>\r\n <title>${title}</title>\r\n <style>\r\n body{margin:0;height:100vh;display:grid;place-items:center;font-family:system-ui,-apple-system,Segoe UI,Roboto;background:#0b0f19;color:#fff}\r\n .box{max-width:560px;padding:28px 26px;border-radius:18px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04)}\r\n h1{margin:0 0 10px;font-size:28px}\r\n p{margin:0 0 18px;opacity:.85;line-height:1.5}\r\n .row{display:flex;gap:10px;flex-wrap:wrap}\r\n button,a{appearance:none;border:0;border-radius:12px;padding:10px 14px;cursor:pointer;text-decoration:none}\r\n button{background:#fff;color:#111}\r\n a{background:rgba(255,255,255,.1);color:#fff}\r\n </style>\r\n</head>\r\n<body>\r\n <div class=\"box\">\r\n <h1>⚡ You’re Offline</h1>\r\n <p>No internet connection detected. You can retry, or go back to the homepage (if cached).</p>\r\n <div class=\"row\">\r\n <button onclick=\"location.reload()\">Retry</button>\r\n <a href=\"/\">Go Home</a>\r\n </div>\r\n </div>\r\n</body>\r\n</html>`;\r\n}","export function offlineSvgTemplate() {\r\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1200\" height=\"630\" viewBox=\"0 0 1200 630\">\r\n <rect width=\"1200\" height=\"630\" fill=\"#0b0f19\"/>\r\n <text x=\"80\" y=\"220\" fill=\"#ffffff\" font-size=\"64\" font-family=\"system-ui, -apple-system, Segoe UI, Roboto\">You’re Offline</text>\r\n <text x=\"80\" y=\"300\" fill=\"#cbd5e1\" font-size=\"28\" font-family=\"system-ui, -apple-system, Segoe UI, Roboto\">Please check your connection and try again.</text>\r\n <circle cx=\"1040\" cy=\"220\" r=\"90\" fill=\"rgba(255,255,255,0.08)\"/>\r\n <path d=\"M980 220c40-40 120-40 160 0\" stroke=\"#fff\" stroke-width=\"10\" fill=\"none\" opacity=\"0.6\"/>\r\n <path d=\"M1010 250c25-25 75-25 100 0\" stroke=\"#fff\" stroke-width=\"10\" fill=\"none\" opacity=\"0.6\"/>\r\n <circle cx=\"1060\" cy=\"290\" r=\"10\" fill=\"#fff\" opacity=\"0.7\"/>\r\n</svg>`;\r\n}","import type { OfflineKitBuildOptions } from \"../types\";\r\n\r\nconst js = (v: unknown) => JSON.stringify(v);\r\n\r\nexport function buildServiceWorkerJS(options: Required<OfflineKitBuildOptions>) {\r\n const { cacheName, offlinePage, offlineImage } = options;\r\n\r\n return `/* offline-page-kit service worker (minimal) */\r\nconst CACHE_NAME = ${js(cacheName)};\r\nconst OFFLINE_PAGE = ${js(offlinePage)};\r\nconst OFFLINE_IMAGE = ${js(offlineImage)};\r\n\r\nself.addEventListener(\"install\", (event) => {\r\n event.waitUntil((async () => {\r\n const cache = await caches.open(CACHE_NAME);\r\n\r\n // ✅ Do not let one 404 kill the install\r\n await Promise.allSettled([\r\n cache.add(OFFLINE_PAGE),\r\n cache.add(OFFLINE_IMAGE),\r\n ]);\r\n\r\n await self.skipWaiting();\r\n })());\r\n});\r\n\r\nself.addEventListener(\"activate\", (event) => {\r\n event.waitUntil((async () => {\r\n await self.clients.claim();\r\n })());\r\n});\r\n\r\nself.addEventListener(\"fetch\", (event) => {\r\n const req = event.request;\r\n\r\n // ✅ Offline fallback only for page navigations\r\n if (req.mode === \"navigate\") {\r\n event.respondWith((async () => {\r\n try {\r\n return await fetch(req);\r\n } catch {\r\n const cache = await caches.open(CACHE_NAME);\r\n return (await cache.match(OFFLINE_PAGE)) || new Response(\"Offline\", { status: 503 });\r\n }\r\n })());\r\n }\r\n});\r\n`;\r\n}"],"mappings":"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","names":["path","options","path"]}
package/dist/index.d.cts CHANGED
@@ -14,14 +14,9 @@ type OfflineKitBuildOptions = {
14
14
  offlineImage?: string;
15
15
  cacheName?: string;
16
16
  precache?: string[];
17
- autoPrecache?: boolean;
18
- precacheExtensions?: string[];
19
- precacheIgnore?: string[];
20
- precacheMaxFiles?: number;
21
- precacheMaxFileSizeKB?: number;
22
- htmlStrategy?: "networkFirst" | "cacheFirst" | "staleWhileRevalidate";
23
- assetStrategy?: "networkFirst" | "cacheFirst" | "staleWhileRevalidate";
24
- imageStrategy?: "networkFirst" | "cacheFirst" | "staleWhileRevalidate";
17
+ htmlStrategy?: Strategy;
18
+ assetStrategy?: Strategy;
19
+ imageStrategy?: Strategy;
25
20
  assetExtensions?: string[];
26
21
  apiPrefixes?: string[];
27
22
  };
package/dist/index.d.ts CHANGED
@@ -14,14 +14,9 @@ type OfflineKitBuildOptions = {
14
14
  offlineImage?: string;
15
15
  cacheName?: string;
16
16
  precache?: string[];
17
- autoPrecache?: boolean;
18
- precacheExtensions?: string[];
19
- precacheIgnore?: string[];
20
- precacheMaxFiles?: number;
21
- precacheMaxFileSizeKB?: number;
22
- htmlStrategy?: "networkFirst" | "cacheFirst" | "staleWhileRevalidate";
23
- assetStrategy?: "networkFirst" | "cacheFirst" | "staleWhileRevalidate";
24
- imageStrategy?: "networkFirst" | "cacheFirst" | "staleWhileRevalidate";
17
+ htmlStrategy?: Strategy;
18
+ assetStrategy?: Strategy;
19
+ imageStrategy?: Strategy;
25
20
  assetExtensions?: string[];
26
21
  apiPrefixes?: string[];
27
22
  };