@alxia/react-router 0.9.0 → 0.10.0

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 (51) hide show
  1. package/README.md +126 -13
  2. package/dist/chunks/index-59vhfj6n.js +10 -0
  3. package/dist/chunks/index-59vhfj6n.js.map +10 -0
  4. package/dist/chunks/index-5gqcpyyg.js +34 -0
  5. package/dist/chunks/index-5gqcpyyg.js.map +10 -0
  6. package/dist/chunks/{index-zqa30gr7.js → index-9xv2a8et.js} +7 -38
  7. package/dist/chunks/index-9xv2a8et.js.map +11 -0
  8. package/dist/chunks/index-mppz0806.js +119 -0
  9. package/dist/chunks/index-mppz0806.js.map +11 -0
  10. package/dist/chunks/index-rfr02vg4.js +40 -0
  11. package/dist/chunks/index-rfr02vg4.js.map +10 -0
  12. package/dist/chunks/index-zdbqzcjp.js +97 -0
  13. package/dist/chunks/index-zdbqzcjp.js.map +12 -0
  14. package/dist/pwa/build/build-worker.d.ts +41 -0
  15. package/dist/pwa/build/build-worker.d.ts.map +1 -0
  16. package/dist/pwa/build/index.d.ts +9 -0
  17. package/dist/pwa/build/index.d.ts.map +1 -0
  18. package/dist/pwa/build/index.js +9 -0
  19. package/dist/pwa/build/index.js.map +9 -0
  20. package/dist/pwa/build/precache.d.ts +17 -0
  21. package/dist/pwa/build/precache.d.ts.map +1 -0
  22. package/dist/pwa/index.js +34 -134
  23. package/dist/pwa/index.js.map +4 -8
  24. package/dist/pwa/react/index.js +1 -1
  25. package/dist/pwa/worker/index.d.ts +9 -0
  26. package/dist/pwa/worker/index.d.ts.map +1 -0
  27. package/dist/pwa/worker/index.js +144 -0
  28. package/dist/pwa/worker/index.js.map +12 -0
  29. package/dist/pwa/worker/injected.d.ts +15 -0
  30. package/dist/pwa/worker/injected.d.ts.map +1 -0
  31. package/dist/pwa/worker/plan.d.ts +65 -0
  32. package/dist/pwa/worker/plan.d.ts.map +1 -0
  33. package/dist/pwa/worker/scope.d.ts +18 -0
  34. package/dist/pwa/worker/scope.d.ts.map +1 -0
  35. package/dist/pwa/worker/start-worker.d.ts +17 -0
  36. package/dist/pwa/worker/start-worker.d.ts.map +1 -0
  37. package/dist/vite/index.d.ts +10 -0
  38. package/dist/vite/index.d.ts.map +1 -1
  39. package/dist/vite/index.js +49 -3
  40. package/dist/vite/index.js.map +6 -5
  41. package/dist/vite/runtime.d.ts +1 -1
  42. package/dist/vite/runtime.d.ts.map +1 -1
  43. package/dist/vite/worker.d.ts +16 -0
  44. package/dist/vite/worker.d.ts.map +1 -0
  45. package/docs/README.md +1 -1
  46. package/docs/guide/how-it-works.md +7 -1
  47. package/docs/guide/pwa.md +372 -211
  48. package/docs/roadmap.md +19 -5
  49. package/docs/troubleshooting.md +208 -3
  50. package/package.json +46 -4
  51. package/dist/chunks/index-zqa30gr7.js.map +0 -12
@@ -0,0 +1,97 @@
1
+ import {
2
+ SERVICE_WORKER_URL2
3
+ } from "./index-rfr02vg4.js";
4
+
5
+ // src/pwa/model/manifest.ts
6
+ var MANIFEST_PATH2 = "/manifest.webmanifest";
7
+ var MANIFEST_HEADERS2 = {
8
+ "content-type": "application/manifest+json; charset=utf-8",
9
+ "cache-control": "public, max-age=3600",
10
+ vary: "Accept-Language",
11
+ "content-security-policy": "default-src 'none'; frame-ancestors 'none'"
12
+ };
13
+ function manifestHref2(language, path = MANIFEST_PATH2) {
14
+ return `${path}?lang=${encodeURIComponent(language)}`;
15
+ }
16
+ function manifestLanguage2(url, supported, fallback) {
17
+ const requested = url.searchParams.get("lang");
18
+ return supported.find((language) => language === requested) ?? fallback;
19
+ }
20
+ var MINIMAL_2023_ICONS2 = Object.freeze([
21
+ { src: "/pwa-64x64.png", sizes: "64x64", type: "image/png" },
22
+ { src: "/pwa-192x192.png", sizes: "192x192", type: "image/png" },
23
+ { src: "/pwa-512x512.png", sizes: "512x512", type: "image/png" },
24
+ {
25
+ src: "/maskable-icon-512x512.png",
26
+ sizes: "512x512",
27
+ type: "image/png",
28
+ purpose: "maskable"
29
+ }
30
+ ].map((icon) => Object.freeze(icon)));
31
+ function webAppManifest2(options) {
32
+ return {
33
+ id: options.id ?? "/",
34
+ name: options.name,
35
+ short_name: options.shortName ?? options.name,
36
+ description: options.description,
37
+ lang: options.lang,
38
+ dir: options.dir ?? "ltr",
39
+ start_url: options.startUrl ?? "/",
40
+ scope: options.scope ?? "/",
41
+ display: options.display ?? "standalone",
42
+ theme_color: options.themeColor,
43
+ background_color: options.backgroundColor,
44
+ ...options.categories && { categories: [...options.categories] },
45
+ icons: (options.icons ?? MINIMAL_2023_ICONS2).map((icon) => ({ ...icon }))
46
+ };
47
+ }
48
+
49
+ // src/pwa/model/caching.ts
50
+ var STATIC_EXTENSION = /\.(?:js|mjs|css|woff2?|ttf|otf|svg|png|jpe?g|webp|avif|gif|ico)$/i;
51
+ var underAssets = (path) => path.startsWith("/assets/");
52
+ function cachingFor2(request, origin, options = {}) {
53
+ if (request.method !== "GET")
54
+ return "none";
55
+ if (request.mode === "navigate")
56
+ return "navigation";
57
+ const url = new URL(request.url);
58
+ if (url.origin !== origin)
59
+ return "none";
60
+ if (request.headers.has("authorization"))
61
+ return "none";
62
+ if (url.search)
63
+ return "none";
64
+ const path = url.pathname;
65
+ if (path.endsWith(".data") || path === "/__manifest" || path === (options.serviceWorkerUrl ?? options.contract?.serviceWorkerUrl ?? SERVICE_WORKER_URL2) || path === (options.manifestPath ?? MANIFEST_PATH2) || options.never?.(path)) {
66
+ return "none";
67
+ }
68
+ if (request.destination === "document" || request.destination === "iframe")
69
+ return "none";
70
+ if (!STATIC_EXTENSION.test(path))
71
+ return "none";
72
+ return (options.immutable ?? underAssets)(path) ? "immutable" : "static";
73
+ }
74
+
75
+ // src/pwa/model/storable.ts
76
+ var STATIC_CONTENT_TYPE = /^(?:(?:text|application)\/(?:javascript|x-javascript|ecmascript)|text\/css|font\/[\w.+-]+|application\/(?:font-woff2?|x-font-[\w.+-]+|vnd\.ms-fontobject)|image\/[\w.+-]+)$/i;
77
+ function isStorable2(response) {
78
+ if (response.status !== 200)
79
+ return false;
80
+ if (response.type !== "basic" && response.type !== "default")
81
+ return false;
82
+ const contentType = (response.headers.get("content-type") ?? "").split(";")[0]?.trim();
83
+ if (!contentType || !STATIC_CONTENT_TYPE.test(contentType))
84
+ return false;
85
+ const cacheControl = response.headers.get("cache-control") ?? "";
86
+ if (!/\bpublic\b/i.test(cacheControl))
87
+ return false;
88
+ if (/\b(?:no-store|private)\b/i.test(cacheControl))
89
+ return false;
90
+ const vary = response.headers.get("vary") ?? "";
91
+ return !/(?:^|,)\s*(?:\*|cookie|authorization)\s*(?:,|$)/i.test(vary);
92
+ }
93
+
94
+ export { MANIFEST_PATH2, MANIFEST_HEADERS2, manifestHref2, manifestLanguage2, MINIMAL_2023_ICONS2, webAppManifest2, cachingFor2, isStorable2 };
95
+
96
+ //# debugId=E5DD035F8EB2F4B164756E2164756E21
97
+ //# sourceMappingURL=index-zdbqzcjp.js.map
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/pwa/model/manifest.ts", "../src/pwa/model/caching.ts", "../src/pwa/model/storable.ts"],
4
+ "sourcesContent": [
5
+ "/** Where the server serves the manifest, and the document head links it. */\nexport const MANIFEST_PATH = '/manifest.webmanifest';\n\n/**\n * Cacheable for an hour, like the icons; the language travels in `?lang=`.\n * Its own policy, which loads nothing: the pages' one carries a nonce, and\n * a nonce never goes in a response a cache may keep.\n */\nexport const MANIFEST_HEADERS = {\n\t'content-type': 'application/manifest+json; charset=utf-8',\n\t'cache-control': 'public, max-age=3600',\n\tvary: 'Accept-Language',\n\t'content-security-policy': \"default-src 'none'; frame-ancestors 'none'\",\n} as const;\n\n/**\n * The manifest's URL for a page in `language`. A browser fetches the\n * manifest without cookies, so a `language` cookie would not reach it: the\n * page names its language in the query instead.\n */\nexport function manifestHref(\n\tlanguage: string,\n\tpath: string = MANIFEST_PATH,\n): string {\n\treturn `${path}?lang=${encodeURIComponent(language)}`;\n}\n\n/**\n * `?lang=` when it names one of `supported`, else `fallback`: the request's\n * Accept-Language, never its cookie, so `Vary: Accept-Language` holds.\n */\nexport function manifestLanguage<L extends string>(\n\turl: URL,\n\tsupported: readonly L[],\n\tfallback: L,\n): L {\n\tconst requested = url.searchParams.get('lang');\n\treturn supported.find((language) => language === requested) ?? fallback;\n}\n\nexport type ManifestIcon = {\n\tsrc: string;\n\tsizes: string;\n\ttype: string;\n\tpurpose?: 'any' | 'maskable' | 'monochrome';\n};\n\n/**\n * The four icons `@vite-pwa/assets-generator`'s `minimal2023Preset` writes\n * to `public/`: 64, 192 and 512 pixels, and a maskable 512.\n */\nexport const MINIMAL_2023_ICONS: readonly ManifestIcon[] = Object.freeze(\n\t[\n\t\t{ src: '/pwa-64x64.png', sizes: '64x64', type: 'image/png' },\n\t\t{ src: '/pwa-192x192.png', sizes: '192x192', type: 'image/png' },\n\t\t{ src: '/pwa-512x512.png', sizes: '512x512', type: 'image/png' },\n\t\t{\n\t\t\tsrc: '/maskable-icon-512x512.png',\n\t\t\tsizes: '512x512',\n\t\t\ttype: 'image/png',\n\t\t\tpurpose: 'maskable' as const,\n\t\t},\n\t].map((icon) => Object.freeze(icon)),\n);\n\nexport interface WebAppManifestOptions {\n\tname: string;\n\t/** `name` by default. */\n\tshortName?: string;\n\tdescription: string;\n\t/** The language of `name` and `description`. */\n\tlang: string;\n\t/** `'ltr'` by default. */\n\tdir?: 'ltr' | 'rtl' | 'auto';\n\tthemeColor: string;\n\tbackgroundColor: string;\n\tcategories?: readonly string[];\n\t/** `MINIMAL_2023_ICONS` by default. */\n\ticons?: readonly ManifestIcon[];\n\t/** `'/'` by default: the same in every language, so a language switch never makes a second app. */\n\tid?: string;\n\t/** `'/'` by default. */\n\tstartUrl?: string;\n\t/** `'/'` by default. */\n\tscope?: string;\n\t/** `'standalone'` by default. */\n\tdisplay?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';\n}\n\n/** The web app manifest's JSON, with its snake_case keys. */\nexport type WebAppManifest = {\n\tid: string;\n\tname: string;\n\tshort_name: string;\n\tdescription: string;\n\tlang: string;\n\tdir: 'ltr' | 'rtl' | 'auto';\n\tstart_url: string;\n\tscope: string;\n\tdisplay: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';\n\ttheme_color: string;\n\tbackground_color: string;\n\tcategories?: string[];\n\ticons: ManifestIcon[];\n};\n\n/**\n * A web app manifest from the app's own (translated) texts and colours.\n * `id`, `start_url` and `scope` default to `'/'` whatever the language.\n */\nexport function webAppManifest(options: WebAppManifestOptions): WebAppManifest {\n\treturn {\n\t\tid: options.id ?? '/',\n\t\tname: options.name,\n\t\tshort_name: options.shortName ?? options.name,\n\t\tdescription: options.description,\n\t\tlang: options.lang,\n\t\tdir: options.dir ?? 'ltr',\n\t\tstart_url: options.startUrl ?? '/',\n\t\tscope: options.scope ?? '/',\n\t\tdisplay: options.display ?? 'standalone',\n\t\ttheme_color: options.themeColor,\n\t\tbackground_color: options.backgroundColor,\n\t\t...(options.categories && { categories: [...options.categories] }),\n\t\ticons: (options.icons ?? MINIMAL_2023_ICONS).map((icon) => ({ ...icon })),\n\t};\n}\n",
6
+ "import { MANIFEST_PATH } from './manifest';\nimport { SERVICE_WORKER_URL, type WorkerContract } from './worker-contract';\n\n/**\n * Which requests the service worker caches, and how. Pure, so that what is\n * never cached is tested, not hoped for.\n *\n * - `navigation`: a page load. Always from the network, never stored; the\n * offline page answers only when the network fails.\n * - `immutable`: a hashed bundle: cache-first.\n * - `static`: another same-origin static file (icon, sprite, logo):\n * stale-while-revalidate.\n * - `none`: left to the browser, untouched: every non-GET, any other\n * origin, React Router's `.data` and `/__manifest`, the worker and the\n * manifest themselves, the app's own `never` paths, and anything carrying\n * credentials.\n */\nexport type Caching = 'navigation' | 'immutable' | 'static' | 'none';\n\n/** What a `Request` exposes that the decision reads. */\nexport interface RequestFacts {\n\treadonly method: string;\n\treadonly url: string;\n\treadonly mode: string;\n\treadonly destination: string;\n\treadonly headers: Pick<Headers, 'has'>;\n}\n\nexport interface CachingOptions {\n\t/**\n\t * The worker's own path, never cached. Wins over `contract`;\n\t * `SERVICE_WORKER_URL` when neither is given.\n\t */\n\tserviceWorkerUrl?: string;\n\t/** The app's contract, whose `serviceWorkerUrl` is never cached. */\n\tcontract?: Pick<WorkerContract, 'serviceWorkerUrl'>;\n\t/** The web app manifest's path, never cached. `MANIFEST_PATH` by default. */\n\tmanifestPath?: string;\n\t/** Paths of the app answered fresh every time, such as `(p) => p.startsWith('/api/')`. */\n\tnever?: (path: string) => boolean;\n\t/**\n\t * Which static paths are immutable (cache-first) rather than static.\n\t * `(path) => path.startsWith('/assets/')` by default, as `serveClient`\n\t * serves them.\n\t */\n\timmutable?: (path: string) => boolean;\n}\n\nconst STATIC_EXTENSION =\n\t/\\.(?:js|mjs|css|woff2?|ttf|otf|svg|png|jpe?g|webp|avif|gif|ico)$/i;\n\nconst underAssets = (path: string) => path.startsWith('/assets/');\n\n/** How the worker answers `request`, for an app served at `origin`. */\nexport function cachingFor(\n\trequest: RequestFacts,\n\torigin: string,\n\toptions: CachingOptions = {},\n): Caching {\n\tif (request.method !== 'GET') return 'none';\n\tif (request.mode === 'navigate') return 'navigation';\n\tconst url = new URL(request.url);\n\tif (url.origin !== origin) return 'none';\n\tif (request.headers.has('authorization')) return 'none';\n\tif (url.search) return 'none';\n\tconst path = url.pathname;\n\tif (\n\t\tpath.endsWith('.data') || // React Router single fetch: loader data\n\t\tpath === '/__manifest' || // React Router route discovery\n\t\tpath ===\n\t\t\t(options.serviceWorkerUrl ??\n\t\t\t\toptions.contract?.serviceWorkerUrl ??\n\t\t\t\tSERVICE_WORKER_URL) ||\n\t\tpath === (options.manifestPath ?? MANIFEST_PATH) ||\n\t\toptions.never?.(path)\n\t) {\n\t\treturn 'none';\n\t}\n\tif (request.destination === 'document' || request.destination === 'iframe')\n\t\treturn 'none';\n\tif (!STATIC_EXTENSION.test(path)) return 'none';\n\treturn (options.immutable ?? underAssets)(path) ? 'immutable' : 'static';\n}\n",
7
+ "/**\n * The content types of the static extensions: scripts, styles, fonts and\n * images (SVG and icons included). A page, JSON or anything else served\n * under a static-looking path is refused all the same.\n */\nconst STATIC_CONTENT_TYPE =\n\t/^(?:(?:text|application)\\/(?:javascript|x-javascript|ecmascript)|text\\/css|font\\/[\\w.+-]+|application\\/(?:font-woff2?|x-font-[\\w.+-]+|vnd\\.ms-fontobject)|image\\/[\\w.+-]+)$/i;\n\n/**\n * Whether a response may be stored: a full, same-origin 200 of a static\n * content type, that the server marked `public` (alxia does on every\n * static file it serves; a route answering an image, a user's photo, does\n * not), not private nor no-store, and that does not vary on who asks.\n */\nexport function isStorable(response: Response): boolean {\n\tif (response.status !== 200) return false;\n\tif (response.type !== 'basic' && response.type !== 'default') return false;\n\tconst contentType = (response.headers.get('content-type') ?? '')\n\t\t.split(';')[0]\n\t\t?.trim();\n\tif (!contentType || !STATIC_CONTENT_TYPE.test(contentType)) return false;\n\tconst cacheControl = response.headers.get('cache-control') ?? '';\n\tif (!/\\bpublic\\b/i.test(cacheControl)) return false;\n\tif (/\\b(?:no-store|private)\\b/i.test(cacheControl)) return false;\n\tconst vary = response.headers.get('vary') ?? '';\n\treturn !/(?:^|,)\\s*(?:\\*|cookie|authorization)\\s*(?:,|$)/i.test(vary);\n}\n"
8
+ ],
9
+ "mappings": "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",
10
+ "debugId": "E5DD035F8EB2F4B164756E2164756E21",
11
+ "names": []
12
+ }
@@ -0,0 +1,41 @@
1
+ import type { PrecacheEntry } from '../model/precache-list';
2
+ import { type WorkerContract } from '../model/worker-contract';
3
+ export interface BuildWorkerOptions {
4
+ /**
5
+ * The worker's source, relative to `root`: `app/service-worker.ts`. Named
6
+ * `file`, not `entry`: `reveal` reads `alxia({ entry })`.
7
+ */
8
+ file: string;
9
+ /** `process.cwd()` by default. */
10
+ root?: string;
11
+ /** The client build, relative to `root`: `build/client` by default. */
12
+ client?: string;
13
+ /** Where the worker is written and which offline page is precached. */
14
+ contract?: Pick<WorkerContract, 'serviceWorkerUrl' | 'offlineUrl'>;
15
+ /** Precache the offline page, which must then exist. `true` by default. */
16
+ offline?: boolean;
17
+ /** More files of `assets/` to precache, such as fonts: the app's regex. */
18
+ precacheAssets?: RegExp;
19
+ /** `true` by default. */
20
+ minify?: boolean;
21
+ }
22
+ export interface WorkerBuild {
23
+ /** The absolute path of the worker written. */
24
+ file: string;
25
+ precache: PrecacheEntry[];
26
+ /** The precached files' size, before compression. */
27
+ precacheBytes: number;
28
+ /** The worker's own size. */
29
+ bytes: number;
30
+ }
31
+ /** Not `requireBun` of `vite/`: `/pwa/build` imports Node's built-ins only. */
32
+ export declare function assertBun(onBun?: boolean): void;
33
+ /**
34
+ * Bundles the worker (Workbox included) into the client build, after
35
+ * `react-router build`, with the precache list written in: the offline page
36
+ * by its content, every route's code and `precacheAssets`. A new build
37
+ * changes the list, so the worker's bytes, so the browser installs it.
38
+ * Runs on Bun; the only imports of this module are Node's built-ins.
39
+ */
40
+ export declare function buildWorker(options: BuildWorkerOptions): Promise<WorkerBuild>;
41
+ //# sourceMappingURL=build-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-worker.d.ts","sourceRoot":"","sources":["../../../src/pwa/build/build-worker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,0BAA0B,CAAC;AAIlC,MAAM,WAAW,kBAAkB;IAClC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,kBAAkB,GAAG,YAAY,CAAC,CAAC;IACnE,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yBAAyB;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC3B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,qDAAqD;IACrD,aAAa,EAAE,MAAM,CAAC;IACtB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;CACd;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CACxB,KAAK,UAAsD,GACzD,IAAI,CAKN;AAoBD;;;;;;GAMG;AACH,wBAAsB,WAAW,CAChC,OAAO,EAAE,kBAAkB,GACzB,OAAO,CAAC,WAAW,CAAC,CAgEtB"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `@alxia/react-router/pwa/build`: bundles the service worker into the
3
+ * client build with its precache list. Run it on Bun, after
4
+ * `react-router build`. Node's built-ins are its only imports, and Bun's
5
+ * global is read inside the function, never at load.
6
+ */
7
+ export type { BuildWorkerOptions, WorkerBuild } from './build-worker';
8
+ export { buildWorker } from './build-worker';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/pwa/build/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import {
2
+ buildWorker2
3
+ } from "../../chunks/index-mppz0806.js";
4
+ export {
5
+ buildWorker2 as buildWorker
6
+ };
7
+
8
+ //# debugId=9A338EBCFD5431FB64756E2164756E21
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "9A338EBCFD5431FB64756E2164756E21",
8
+ "names": []
9
+ }
@@ -0,0 +1,17 @@
1
+ import { type PrecacheEntry } from '../model/precache-list';
2
+ /** The one React Router browser manifest among the names in build/client/assets. */
3
+ export declare function browserManifestFile(files: readonly string[]): string;
4
+ /** A file's revision: the first 16 hex characters of its sha256. */
5
+ export declare function revisionOf(bytes: Uint8Array): string;
6
+ /**
7
+ * The worker's precache list: the offline page (revisioned by its content),
8
+ * every route's code, then the asset files `include` matches. Each URL once,
9
+ * the first kept.
10
+ */
11
+ export declare function workerPrecache(input: {
12
+ manifestSource: string;
13
+ assetFiles: readonly string[];
14
+ offline?: PrecacheEntry | undefined;
15
+ include?: RegExp | undefined;
16
+ }): PrecacheEntry[];
17
+ //# sourceMappingURL=precache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"precache.d.ts","sourceRoot":"","sources":["../../../src/pwa/build/precache.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,aAAa,EAGlB,MAAM,wBAAwB,CAAC;AAEhC,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CASpE;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,GAAG,aAAa,EAAE,CAQlB"}
package/dist/pwa/index.js CHANGED
@@ -1,8 +1,14 @@
1
1
  import {
2
- SERVICE_WORKER_URL2,
3
- OFFLINE_URL2,
4
- SKIP_WAITING2,
5
- defineWorkerContract2,
2
+ MANIFEST_PATH2,
3
+ MANIFEST_HEADERS2,
4
+ manifestHref2,
5
+ manifestLanguage2,
6
+ MINIMAL_2023_ICONS2,
7
+ webAppManifest2,
8
+ cachingFor2,
9
+ isStorable2
10
+ } from "../chunks/index-zdbqzcjp.js";
11
+ import {
6
12
  watchForUpdates2,
7
13
  createUpdater2,
8
14
  afterLoad2,
@@ -10,77 +16,18 @@ import {
10
16
  UPDATE_LATER_KEY2,
11
17
  createUpdateNotice2,
12
18
  sessionStore2
13
- } from "../chunks/index-zqa30gr7.js";
14
-
15
- // src/pwa/model/manifest.ts
16
- var MANIFEST_PATH = "/manifest.webmanifest";
17
- var MANIFEST_HEADERS = {
18
- "content-type": "application/manifest+json; charset=utf-8",
19
- "cache-control": "public, max-age=3600",
20
- vary: "Accept-Language",
21
- "content-security-policy": "default-src 'none'; frame-ancestors 'none'"
22
- };
23
- function manifestHref(language, path = MANIFEST_PATH) {
24
- return `${path}?lang=${encodeURIComponent(language)}`;
25
- }
26
- function manifestLanguage(url, supported, fallback) {
27
- const requested = url.searchParams.get("lang");
28
- return supported.find((language) => language === requested) ?? fallback;
29
- }
30
- var MINIMAL_2023_ICONS = Object.freeze([
31
- { src: "/pwa-64x64.png", sizes: "64x64", type: "image/png" },
32
- { src: "/pwa-192x192.png", sizes: "192x192", type: "image/png" },
33
- { src: "/pwa-512x512.png", sizes: "512x512", type: "image/png" },
34
- {
35
- src: "/maskable-icon-512x512.png",
36
- sizes: "512x512",
37
- type: "image/png",
38
- purpose: "maskable"
39
- }
40
- ].map((icon) => Object.freeze(icon)));
41
- function webAppManifest(options) {
42
- return {
43
- id: options.id ?? "/",
44
- name: options.name,
45
- short_name: options.shortName ?? options.name,
46
- description: options.description,
47
- lang: options.lang,
48
- dir: options.dir ?? "ltr",
49
- start_url: options.startUrl ?? "/",
50
- scope: options.scope ?? "/",
51
- display: options.display ?? "standalone",
52
- theme_color: options.themeColor,
53
- background_color: options.backgroundColor,
54
- ...options.categories && { categories: [...options.categories] },
55
- icons: (options.icons ?? MINIMAL_2023_ICONS).map((icon) => ({ ...icon }))
56
- };
57
- }
58
-
59
- // src/pwa/model/caching.ts
60
- var STATIC_EXTENSION = /\.(?:js|mjs|css|woff2?|ttf|otf|svg|png|jpe?g|webp|avif|gif|ico)$/i;
61
- var underAssets = (path) => path.startsWith("/assets/");
62
- function cachingFor(request, origin, options = {}) {
63
- if (request.method !== "GET")
64
- return "none";
65
- if (request.mode === "navigate")
66
- return "navigation";
67
- const url = new URL(request.url);
68
- if (url.origin !== origin)
69
- return "none";
70
- if (request.headers.has("authorization"))
71
- return "none";
72
- if (url.search)
73
- return "none";
74
- const path = url.pathname;
75
- if (path.endsWith(".data") || path === "/__manifest" || path === (options.serviceWorkerUrl ?? options.contract?.serviceWorkerUrl ?? SERVICE_WORKER_URL2) || path === (options.manifestPath ?? MANIFEST_PATH) || options.never?.(path)) {
76
- return "none";
77
- }
78
- if (request.destination === "document" || request.destination === "iframe")
79
- return "none";
80
- if (!STATIC_EXTENSION.test(path))
81
- return "none";
82
- return (options.immutable ?? underAssets)(path) ? "immutable" : "static";
83
- }
19
+ } from "../chunks/index-9xv2a8et.js";
20
+ import {
21
+ parseBrowserManifest2,
22
+ precacheList2,
23
+ assetPrecache2
24
+ } from "../chunks/index-5gqcpyyg.js";
25
+ import {
26
+ SERVICE_WORKER_URL2,
27
+ OFFLINE_URL2,
28
+ SKIP_WAITING2,
29
+ defineWorkerContract2
30
+ } from "../chunks/index-rfr02vg4.js";
84
31
  // src/pwa/model/clear-app-caches.ts
85
32
  async function clearAppCaches(contract) {
86
33
  if (typeof caches === "undefined")
@@ -88,78 +35,31 @@ async function clearAppCaches(contract) {
88
35
  const names = contract.clearableCaches(await caches.keys());
89
36
  await Promise.all(names.map((name) => caches.delete(name)));
90
37
  }
91
- // src/pwa/model/precache-list.ts
92
- var HASHED_ASSET = /^\/assets\/[^/]+-[\w-]{8}\.(?:js|css)$/;
93
- function parseBrowserManifest(source) {
94
- const start = source.indexOf("{");
95
- const end = source.lastIndexOf("}");
96
- if (start < 0 || end < start) {
97
- throw new Error("parseBrowserManifest(): not React Router's browser manifest (build/client/assets/manifest-*.js).");
98
- }
99
- return JSON.parse(source.slice(start, end + 1));
100
- }
101
- function precacheList(manifest) {
102
- const urls = new Set([manifest.url]);
103
- for (const part of [manifest.entry, ...Object.values(manifest.routes)]) {
104
- for (const url of [
105
- ...part.module ? [part.module] : [],
106
- ...part.imports ?? [],
107
- ...part.css ?? []
108
- ]) {
109
- urls.add(url);
110
- }
111
- }
112
- return [...urls].filter((url) => HASHED_ASSET.test(url)).map((url) => ({ url, revision: null }));
113
- }
114
- function assetPrecache(assetFiles, include, base = "/assets/") {
115
- return assetFiles.filter((file) => {
116
- include.lastIndex = 0;
117
- return include.test(file);
118
- }).sort().map((file) => ({ url: `${base}${file}`, revision: null }));
119
- }
120
- // src/pwa/model/storable.ts
121
- var STATIC_CONTENT_TYPE = /^(?:(?:text|application)\/(?:javascript|x-javascript|ecmascript)|text\/css|font\/[\w.+-]+|application\/(?:font-woff2?|x-font-[\w.+-]+|vnd\.ms-fontobject)|image\/[\w.+-]+)$/i;
122
- function isStorable(response) {
123
- if (response.status !== 200)
124
- return false;
125
- if (response.type !== "basic" && response.type !== "default")
126
- return false;
127
- const contentType = (response.headers.get("content-type") ?? "").split(";")[0]?.trim();
128
- if (!contentType || !STATIC_CONTENT_TYPE.test(contentType))
129
- return false;
130
- const cacheControl = response.headers.get("cache-control") ?? "";
131
- if (!/\bpublic\b/i.test(cacheControl))
132
- return false;
133
- if (/\b(?:no-store|private)\b/i.test(cacheControl))
134
- return false;
135
- const vary = response.headers.get("vary") ?? "";
136
- return !/(?:^|,)\s*(?:\*|cookie|authorization)\s*(?:,|$)/i.test(vary);
137
- }
138
38
  export {
139
- MANIFEST_HEADERS,
140
- MANIFEST_PATH,
141
- MINIMAL_2023_ICONS,
39
+ MANIFEST_HEADERS2 as MANIFEST_HEADERS,
40
+ MANIFEST_PATH2 as MANIFEST_PATH,
41
+ MINIMAL_2023_ICONS2 as MINIMAL_2023_ICONS,
142
42
  OFFLINE_URL2 as OFFLINE_URL,
143
43
  SERVICE_WORKER_URL2 as SERVICE_WORKER_URL,
144
44
  SKIP_WAITING2 as SKIP_WAITING,
145
45
  UPDATE_LATER_KEY2 as UPDATE_LATER_KEY,
146
46
  afterLoad2 as afterLoad,
147
- assetPrecache,
148
- cachingFor,
47
+ assetPrecache2 as assetPrecache,
48
+ cachingFor2 as cachingFor,
149
49
  clearAppCaches,
150
50
  createUpdateNotice2 as createUpdateNotice,
151
51
  createUpdater2 as createUpdater,
152
52
  defineWorkerContract2 as defineWorkerContract,
153
- isStorable,
154
- manifestHref,
155
- manifestLanguage,
156
- parseBrowserManifest,
157
- precacheList,
53
+ isStorable2 as isStorable,
54
+ manifestHref2 as manifestHref,
55
+ manifestLanguage2 as manifestLanguage,
56
+ parseBrowserManifest2 as parseBrowserManifest,
57
+ precacheList2 as precacheList,
158
58
  registerServiceWorker2 as registerServiceWorker,
159
59
  sessionStore2 as sessionStore,
160
60
  watchForUpdates2 as watchForUpdates,
161
- webAppManifest
61
+ webAppManifest2 as webAppManifest
162
62
  };
163
63
 
164
- //# debugId=941B31DB64DFC2AF64756E2164756E21
64
+ //# debugId=7B8375F7BF1AB78E64756E2164756E21
165
65
  //# sourceMappingURL=index.js.map
@@ -1,14 +1,10 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/pwa/model/manifest.ts", "../src/pwa/model/caching.ts", "../src/pwa/model/clear-app-caches.ts", "../src/pwa/model/precache-list.ts", "../src/pwa/model/storable.ts"],
3
+ "sources": ["../src/pwa/model/clear-app-caches.ts"],
4
4
  "sourcesContent": [
5
- "/** Where the server serves the manifest, and the document head links it. */\nexport const MANIFEST_PATH = '/manifest.webmanifest';\n\n/**\n * Cacheable for an hour, like the icons; the language travels in `?lang=`.\n * Its own policy, which loads nothing: the pages' one carries a nonce, and\n * a nonce never goes in a response a cache may keep.\n */\nexport const MANIFEST_HEADERS = {\n\t'content-type': 'application/manifest+json; charset=utf-8',\n\t'cache-control': 'public, max-age=3600',\n\tvary: 'Accept-Language',\n\t'content-security-policy': \"default-src 'none'; frame-ancestors 'none'\",\n} as const;\n\n/**\n * The manifest's URL for a page in `language`. A browser fetches the\n * manifest without cookies, so a `language` cookie would not reach it: the\n * page names its language in the query instead.\n */\nexport function manifestHref(\n\tlanguage: string,\n\tpath: string = MANIFEST_PATH,\n): string {\n\treturn `${path}?lang=${encodeURIComponent(language)}`;\n}\n\n/**\n * `?lang=` when it names one of `supported`, else `fallback`: the request's\n * Accept-Language, never its cookie, so `Vary: Accept-Language` holds.\n */\nexport function manifestLanguage<L extends string>(\n\turl: URL,\n\tsupported: readonly L[],\n\tfallback: L,\n): L {\n\tconst requested = url.searchParams.get('lang');\n\treturn supported.find((language) => language === requested) ?? fallback;\n}\n\nexport type ManifestIcon = {\n\tsrc: string;\n\tsizes: string;\n\ttype: string;\n\tpurpose?: 'any' | 'maskable' | 'monochrome';\n};\n\n/**\n * The four icons `@vite-pwa/assets-generator`'s `minimal2023Preset` writes\n * to `public/`: 64, 192 and 512 pixels, and a maskable 512.\n */\nexport const MINIMAL_2023_ICONS: readonly ManifestIcon[] = Object.freeze(\n\t[\n\t\t{ src: '/pwa-64x64.png', sizes: '64x64', type: 'image/png' },\n\t\t{ src: '/pwa-192x192.png', sizes: '192x192', type: 'image/png' },\n\t\t{ src: '/pwa-512x512.png', sizes: '512x512', type: 'image/png' },\n\t\t{\n\t\t\tsrc: '/maskable-icon-512x512.png',\n\t\t\tsizes: '512x512',\n\t\t\ttype: 'image/png',\n\t\t\tpurpose: 'maskable' as const,\n\t\t},\n\t].map((icon) => Object.freeze(icon)),\n);\n\nexport interface WebAppManifestOptions {\n\tname: string;\n\t/** `name` by default. */\n\tshortName?: string;\n\tdescription: string;\n\t/** The language of `name` and `description`. */\n\tlang: string;\n\t/** `'ltr'` by default. */\n\tdir?: 'ltr' | 'rtl' | 'auto';\n\tthemeColor: string;\n\tbackgroundColor: string;\n\tcategories?: readonly string[];\n\t/** `MINIMAL_2023_ICONS` by default. */\n\ticons?: readonly ManifestIcon[];\n\t/** `'/'` by default: the same in every language, so a language switch never makes a second app. */\n\tid?: string;\n\t/** `'/'` by default. */\n\tstartUrl?: string;\n\t/** `'/'` by default. */\n\tscope?: string;\n\t/** `'standalone'` by default. */\n\tdisplay?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';\n}\n\n/** The web app manifest's JSON, with its snake_case keys. */\nexport type WebAppManifest = {\n\tid: string;\n\tname: string;\n\tshort_name: string;\n\tdescription: string;\n\tlang: string;\n\tdir: 'ltr' | 'rtl' | 'auto';\n\tstart_url: string;\n\tscope: string;\n\tdisplay: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';\n\ttheme_color: string;\n\tbackground_color: string;\n\tcategories?: string[];\n\ticons: ManifestIcon[];\n};\n\n/**\n * A web app manifest from the app's own (translated) texts and colours.\n * `id`, `start_url` and `scope` default to `'/'` whatever the language.\n */\nexport function webAppManifest(options: WebAppManifestOptions): WebAppManifest {\n\treturn {\n\t\tid: options.id ?? '/',\n\t\tname: options.name,\n\t\tshort_name: options.shortName ?? options.name,\n\t\tdescription: options.description,\n\t\tlang: options.lang,\n\t\tdir: options.dir ?? 'ltr',\n\t\tstart_url: options.startUrl ?? '/',\n\t\tscope: options.scope ?? '/',\n\t\tdisplay: options.display ?? 'standalone',\n\t\ttheme_color: options.themeColor,\n\t\tbackground_color: options.backgroundColor,\n\t\t...(options.categories && { categories: [...options.categories] }),\n\t\ticons: (options.icons ?? MINIMAL_2023_ICONS).map((icon) => ({ ...icon })),\n\t};\n}\n",
6
- "import { MANIFEST_PATH } from './manifest';\nimport { SERVICE_WORKER_URL, type WorkerContract } from './worker-contract';\n\n/**\n * Which requests the service worker caches, and how. Pure, so that what is\n * never cached is tested, not hoped for.\n *\n * - `navigation`: a page load. Always from the network, never stored; the\n * offline page answers only when the network fails.\n * - `immutable`: a hashed bundle: cache-first.\n * - `static`: another same-origin static file (icon, sprite, logo):\n * stale-while-revalidate.\n * - `none`: left to the browser, untouched: every non-GET, any other\n * origin, React Router's `.data` and `/__manifest`, the worker and the\n * manifest themselves, the app's own `never` paths, and anything carrying\n * credentials.\n */\nexport type Caching = 'navigation' | 'immutable' | 'static' | 'none';\n\n/** What a `Request` exposes that the decision reads. */\nexport interface RequestFacts {\n\treadonly method: string;\n\treadonly url: string;\n\treadonly mode: string;\n\treadonly destination: string;\n\treadonly headers: Pick<Headers, 'has'>;\n}\n\nexport interface CachingOptions {\n\t/**\n\t * The worker's own path, never cached. Wins over `contract`;\n\t * `SERVICE_WORKER_URL` when neither is given.\n\t */\n\tserviceWorkerUrl?: string;\n\t/** The app's contract, whose `serviceWorkerUrl` is never cached. */\n\tcontract?: Pick<WorkerContract, 'serviceWorkerUrl'>;\n\t/** The web app manifest's path, never cached. `MANIFEST_PATH` by default. */\n\tmanifestPath?: string;\n\t/** Paths of the app answered fresh every time, such as `(p) => p.startsWith('/api/')`. */\n\tnever?: (path: string) => boolean;\n\t/**\n\t * Which static paths are immutable (cache-first) rather than static.\n\t * `(path) => path.startsWith('/assets/')` by default, as `serveClient`\n\t * serves them.\n\t */\n\timmutable?: (path: string) => boolean;\n}\n\nconst STATIC_EXTENSION =\n\t/\\.(?:js|mjs|css|woff2?|ttf|otf|svg|png|jpe?g|webp|avif|gif|ico)$/i;\n\nconst underAssets = (path: string) => path.startsWith('/assets/');\n\n/** How the worker answers `request`, for an app served at `origin`. */\nexport function cachingFor(\n\trequest: RequestFacts,\n\torigin: string,\n\toptions: CachingOptions = {},\n): Caching {\n\tif (request.method !== 'GET') return 'none';\n\tif (request.mode === 'navigate') return 'navigation';\n\tconst url = new URL(request.url);\n\tif (url.origin !== origin) return 'none';\n\tif (request.headers.has('authorization')) return 'none';\n\tif (url.search) return 'none';\n\tconst path = url.pathname;\n\tif (\n\t\tpath.endsWith('.data') || // React Router single fetch: loader data\n\t\tpath === '/__manifest' || // React Router route discovery\n\t\tpath ===\n\t\t\t(options.serviceWorkerUrl ??\n\t\t\t\toptions.contract?.serviceWorkerUrl ??\n\t\t\t\tSERVICE_WORKER_URL) ||\n\t\tpath === (options.manifestPath ?? MANIFEST_PATH) ||\n\t\toptions.never?.(path)\n\t) {\n\t\treturn 'none';\n\t}\n\tif (request.destination === 'document' || request.destination === 'iframe')\n\t\treturn 'none';\n\tif (!STATIC_EXTENSION.test(path)) return 'none';\n\treturn (options.immutable ?? underAssets)(path) ? 'immutable' : 'static';\n}\n",
7
- "import type { WorkerContract } from './worker-contract';\n\n/**\n * Deletes every cache the service worker filled, but the offline page.\n * For sign-out: what the caches hold is static and public by design, and\n * clearing them leaves nothing behind anyway. Safe where Cache Storage does\n * not exist (server, old browsers).\n */\nexport async function clearAppCaches(\n\tcontract: Pick<WorkerContract, 'clearableCaches'>,\n): Promise<void> {\n\tif (typeof caches === 'undefined') return;\n\tconst names = contract.clearableCaches(await caches.keys());\n\tawait Promise.all(names.map((name) => caches.delete(name)));\n}\n",
8
- "/**\n * What the service worker precaches, read from a build: every script and\n * stylesheet React Router's manifest names (the client entry and each\n * route's module, imports and CSS), and the manifest itself, so a client\n * navigation offline to a route never visited still finds its code. Only\n * hashed `/assets/` files: a new build names new files, so each precaches\n * under its own URL, revision `null`. Chunks only a component loads on\n * demand stay out: a cache-first route stores them the first time they load.\n *\n * Dependency-free: a build script runs it at build time.\n */\n\n/** A route or the entry, as `window.__reactRouterManifest` lists it. */\ntype ManifestModule = { module?: string; imports?: string[]; css?: string[] };\n\n/** The parts of React Router's browser manifest the list reads. */\nexport type BrowserManifest = {\n\turl: string;\n\tentry: ManifestModule;\n\troutes: Record<string, ManifestModule>;\n};\n\n/** A Workbox precache entry: a hashed URL needs no revision. */\nexport type PrecacheEntry = { url: string; revision: string | null };\n\n/** A Vite-hashed file under `/assets/`: `name-<8 hash chars>.js|css`. */\nconst HASHED_ASSET = /^\\/assets\\/[^/]+-[\\w-]{8}\\.(?:js|css)$/;\n\n/** Reads `window.__reactRouterManifest={…};` (build/client/assets/manifest-*.js). */\nexport function parseBrowserManifest(source: string): BrowserManifest {\n\tconst start = source.indexOf('{');\n\tconst end = source.lastIndexOf('}');\n\tif (start < 0 || end < start) {\n\t\tthrow new Error(\n\t\t\t\"parseBrowserManifest(): not React Router's browser manifest (build/client/assets/manifest-*.js).\",\n\t\t);\n\t}\n\treturn JSON.parse(source.slice(start, end + 1)) as BrowserManifest;\n}\n\n/** The hashed scripts and stylesheets every route needs, the manifest's own file first. */\nexport function precacheList(manifest: BrowserManifest): PrecacheEntry[] {\n\tconst urls = new Set<string>([manifest.url]);\n\tfor (const part of [manifest.entry, ...Object.values(manifest.routes)]) {\n\t\tfor (const url of [\n\t\t\t...(part.module ? [part.module] : []),\n\t\t\t...(part.imports ?? []),\n\t\t\t...(part.css ?? []),\n\t\t]) {\n\t\t\turls.add(url);\n\t\t}\n\t}\n\treturn [...urls]\n\t\t.filter((url) => HASHED_ASSET.test(url))\n\t\t.map((url) => ({ url, revision: null }));\n}\n\n/**\n * The precache entries of the files among `assetFiles` (the names in\n * build/client/assets) that `include` matches, sorted, under `base`: fonts\n * an app keeps offline, say. The regex is the app's.\n */\nexport function assetPrecache(\n\tassetFiles: readonly string[],\n\tinclude: RegExp,\n\tbase = '/assets/',\n): PrecacheEntry[] {\n\treturn assetFiles\n\t\t.filter((file) => {\n\t\t\tinclude.lastIndex = 0; // a /g or /y regex remembers its last match\n\t\t\treturn include.test(file);\n\t\t})\n\t\t.sort()\n\t\t.map((file) => ({ url: `${base}${file}`, revision: null }));\n}\n",
9
- "/**\n * The content types of the static extensions: scripts, styles, fonts and\n * images (SVG and icons included). A page, JSON or anything else served\n * under a static-looking path is refused all the same.\n */\nconst STATIC_CONTENT_TYPE =\n\t/^(?:(?:text|application)\\/(?:javascript|x-javascript|ecmascript)|text\\/css|font\\/[\\w.+-]+|application\\/(?:font-woff2?|x-font-[\\w.+-]+|vnd\\.ms-fontobject)|image\\/[\\w.+-]+)$/i;\n\n/**\n * Whether a response may be stored: a full, same-origin 200 of a static\n * content type, that the server marked `public` (alxia does on every\n * static file it serves; a route answering an image, a user's photo, does\n * not), not private nor no-store, and that does not vary on who asks.\n */\nexport function isStorable(response: Response): boolean {\n\tif (response.status !== 200) return false;\n\tif (response.type !== 'basic' && response.type !== 'default') return false;\n\tconst contentType = (response.headers.get('content-type') ?? '')\n\t\t.split(';')[0]\n\t\t?.trim();\n\tif (!contentType || !STATIC_CONTENT_TYPE.test(contentType)) return false;\n\tconst cacheControl = response.headers.get('cache-control') ?? '';\n\tif (!/\\bpublic\\b/i.test(cacheControl)) return false;\n\tif (/\\b(?:no-store|private)\\b/i.test(cacheControl)) return false;\n\tconst vary = response.headers.get('vary') ?? '';\n\treturn !/(?:^|,)\\s*(?:\\*|cookie|authorization)\\s*(?:,|$)/i.test(vary);\n}\n"
5
+ "import type { WorkerContract } from './worker-contract';\n\n/**\n * Deletes every cache the service worker filled, but the offline page.\n * For sign-out: what the caches hold is static and public by design, and\n * clearing them leaves nothing behind anyway. Safe where Cache Storage does\n * not exist (server, old browsers).\n */\nexport async function clearAppCaches(\n\tcontract: Pick<WorkerContract, 'clearableCaches'>,\n): Promise<void> {\n\tif (typeof caches === 'undefined') return;\n\tconst names = contract.clearableCaches(await caches.keys());\n\tawait Promise.all(names.map((name) => caches.delete(name)));\n}\n"
10
6
  ],
11
- "mappings": "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",
12
- "debugId": "941B31DB64DFC2AF64756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,eAAsB,cAAc,CACnC,UACgB;AAAA,EAChB,IAAI,OAAO,WAAW;AAAA,IAAa;AAAA,EACnC,MAAM,QAAQ,SAAS,gBAAgB,MAAM,OAAO,KAAK,CAAC;AAAA,EAC1D,MAAM,QAAQ,IAAI,MAAM,IAAI,CAAC,SAAS,OAAO,OAAO,IAAI,CAAC,CAAC;AAAA;",
8
+ "debugId": "7B8375F7BF1AB78E64756E2164756E21",
13
9
  "names": []
14
10
  }
@@ -3,7 +3,7 @@ import {
3
3
  registerServiceWorker2,
4
4
  createUpdateNotice2,
5
5
  sessionStore2
6
- } from "../../chunks/index-zqa30gr7.js";
6
+ } from "../../chunks/index-9xv2a8et.js";
7
7
 
8
8
  // src/pwa/react/use-online.ts
9
9
  import { useSyncExternalStore } from "react";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `@alxia/react-router/pwa/worker`: the service worker on Workbox. Import it
3
+ * from a service worker bundle alone, never from a page. The six `workbox-*`
4
+ * packages (`core`, `expiration`, `navigation-preload`, `precaching`,
5
+ * `routing`, `strategies`, optional peers) are its only package imports.
6
+ */
7
+ export type { ExpirationOptions, WorkerOptions } from './plan';
8
+ export { startWorker } from './start-worker';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/pwa/worker/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}