@alxia/react-router 0.8.1 → 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.
- package/README.md +222 -10
- package/dist/chunks/index-59vhfj6n.js +10 -0
- package/dist/chunks/index-59vhfj6n.js.map +10 -0
- package/dist/chunks/index-5gqcpyyg.js +34 -0
- package/dist/chunks/index-5gqcpyyg.js.map +10 -0
- package/dist/chunks/index-9xv2a8et.js +108 -0
- package/dist/chunks/index-9xv2a8et.js.map +11 -0
- package/dist/chunks/index-mppz0806.js +119 -0
- package/dist/chunks/index-mppz0806.js.map +11 -0
- package/dist/chunks/index-rfr02vg4.js +40 -0
- package/dist/chunks/index-rfr02vg4.js.map +10 -0
- package/dist/chunks/index-zdbqzcjp.js +97 -0
- package/dist/chunks/index-zdbqzcjp.js.map +12 -0
- package/dist/pwa/build/build-worker.d.ts +41 -0
- package/dist/pwa/build/build-worker.d.ts.map +1 -0
- package/dist/pwa/build/index.d.ts +9 -0
- package/dist/pwa/build/index.d.ts.map +1 -0
- package/dist/pwa/build/index.js +9 -0
- package/dist/pwa/build/index.js.map +9 -0
- package/dist/pwa/build/precache.d.ts +17 -0
- package/dist/pwa/build/precache.d.ts.map +1 -0
- package/dist/pwa/index.d.ts +14 -0
- package/dist/pwa/index.d.ts.map +1 -0
- package/dist/pwa/index.js +65 -0
- package/dist/pwa/index.js.map +10 -0
- package/dist/pwa/model/caching.d.ts +46 -0
- package/dist/pwa/model/caching.d.ts.map +1 -0
- package/dist/pwa/model/clear-app-caches.d.ts +9 -0
- package/dist/pwa/model/clear-app-caches.d.ts.map +1 -0
- package/dist/pwa/model/manifest.d.ts +80 -0
- package/dist/pwa/model/manifest.d.ts.map +1 -0
- package/dist/pwa/model/precache-list.d.ts +40 -0
- package/dist/pwa/model/precache-list.d.ts.map +1 -0
- package/dist/pwa/model/registration.d.ts +39 -0
- package/dist/pwa/model/registration.d.ts.map +1 -0
- package/dist/pwa/model/start-service-worker.d.ts +24 -0
- package/dist/pwa/model/start-service-worker.d.ts.map +1 -0
- package/dist/pwa/model/storable.d.ts +8 -0
- package/dist/pwa/model/storable.d.ts.map +1 -0
- package/dist/pwa/model/update-notice.d.ts +38 -0
- package/dist/pwa/model/update-notice.d.ts.map +1 -0
- package/dist/pwa/model/worker-contract.d.ts +61 -0
- package/dist/pwa/model/worker-contract.d.ts.map +1 -0
- package/dist/pwa/react/index.d.ts +9 -0
- package/dist/pwa/react/index.d.ts.map +1 -0
- package/dist/pwa/react/index.js +75 -0
- package/dist/pwa/react/index.js.map +13 -0
- package/dist/pwa/react/use-online.d.ts +6 -0
- package/dist/pwa/react/use-online.d.ts.map +1 -0
- package/dist/pwa/react/use-service-worker.d.ts +33 -0
- package/dist/pwa/react/use-service-worker.d.ts.map +1 -0
- package/dist/pwa/react/use-update-notice.d.ts +14 -0
- package/dist/pwa/react/use-update-notice.d.ts.map +1 -0
- package/dist/pwa/server/index.d.ts +7 -0
- package/dist/pwa/server/index.d.ts.map +1 -0
- package/dist/pwa/server/index.js +18 -0
- package/dist/pwa/server/index.js.map +10 -0
- package/dist/pwa/server/no-cache.d.ts +22 -0
- package/dist/pwa/server/no-cache.d.ts.map +1 -0
- package/dist/pwa/worker/index.d.ts +9 -0
- package/dist/pwa/worker/index.d.ts.map +1 -0
- package/dist/pwa/worker/index.js +144 -0
- package/dist/pwa/worker/index.js.map +12 -0
- package/dist/pwa/worker/injected.d.ts +15 -0
- package/dist/pwa/worker/injected.d.ts.map +1 -0
- package/dist/pwa/worker/plan.d.ts +65 -0
- package/dist/pwa/worker/plan.d.ts.map +1 -0
- package/dist/pwa/worker/scope.d.ts +18 -0
- package/dist/pwa/worker/scope.d.ts.map +1 -0
- package/dist/pwa/worker/start-worker.d.ts +17 -0
- package/dist/pwa/worker/start-worker.d.ts.map +1 -0
- package/dist/vite/index.d.ts +10 -0
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +49 -3
- package/dist/vite/index.js.map +6 -5
- package/dist/vite/runtime.d.ts +1 -1
- package/dist/vite/runtime.d.ts.map +1 -1
- package/dist/vite/worker.d.ts +16 -0
- package/dist/vite/worker.d.ts.map +1 -0
- package/docs/README.md +12 -3
- package/docs/guide/beside-the-pages.md +178 -0
- package/docs/guide/csp-nonce.md +100 -0
- package/docs/guide/customising-the-server.md +292 -0
- package/docs/guide/deploying.md +99 -0
- package/docs/guide/getting-started.md +112 -0
- package/docs/guide/how-it-works.md +268 -0
- package/docs/guide/openapi.md +51 -0
- package/docs/guide/pwa.md +636 -0
- package/docs/guide/testing.md +42 -0
- package/docs/guide/typing-the-loaders.md +311 -0
- package/docs/guide.md +27 -1391
- package/docs/roadmap.md +39 -1
- package/docs/troubleshooting.md +402 -11
- package/package.json +70 -6
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/pwa/build/build-worker.ts", "../src/pwa/build/precache.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { existsSync } from 'node:fs';\nimport { readdir, readFile, stat } from 'node:fs/promises';\nimport { basename, dirname, join, resolve, sep } from 'node:path';\nimport type { PrecacheEntry } from '../model/precache-list';\nimport {\n\tOFFLINE_URL,\n\tSERVICE_WORKER_URL,\n\ttype WorkerContract,\n} from '../model/worker-contract';\nimport { PRECACHE_DEFINE } from '../worker/injected';\nimport { browserManifestFile, revisionOf, workerPrecache } from './precache';\n\nexport interface BuildWorkerOptions {\n\t/**\n\t * The worker's source, relative to `root`: `app/service-worker.ts`. Named\n\t * `file`, not `entry`: `reveal` reads `alxia({ entry })`.\n\t */\n\tfile: string;\n\t/** `process.cwd()` by default. */\n\troot?: string;\n\t/** The client build, relative to `root`: `build/client` by default. */\n\tclient?: string;\n\t/** Where the worker is written and which offline page is precached. */\n\tcontract?: Pick<WorkerContract, 'serviceWorkerUrl' | 'offlineUrl'>;\n\t/** Precache the offline page, which must then exist. `true` by default. */\n\toffline?: boolean;\n\t/** More files of `assets/` to precache, such as fonts: the app's regex. */\n\tprecacheAssets?: RegExp;\n\t/** `true` by default. */\n\tminify?: boolean;\n}\n\nexport interface WorkerBuild {\n\t/** The absolute path of the worker written. */\n\tfile: string;\n\tprecache: PrecacheEntry[];\n\t/** The precached files' size, before compression. */\n\tprecacheBytes: number;\n\t/** The worker's own size. */\n\tbytes: number;\n}\n\n/** Not `requireBun` of `vite/`: `/pwa/build` imports Node's built-ins only. */\nexport function assertBun(\n\tonBun = (globalThis as { Bun?: unknown }).Bun !== undefined,\n): void {\n\tif (onBun) return;\n\tthrow new Error(\n\t\t'buildWorker() runs on Bun: it is running on Node. Run it with bun, or run react-router build with bun --bun.',\n\t);\n}\n\n/**\n * The file a root-relative URL names inside `client`. It fails closed: a URL\n * that is absolute, protocol-relative, not rooted at `/`, or that resolves to\n * `client` itself or outside it, is refused.\n */\nfunction urlInClient(client: string, url: string): string {\n\tconst path = join(client, url);\n\tif (\n\t\t!url.startsWith('/') ||\n\t\t/^[a-z][a-z0-9+.-]*:|^\\/\\//i.test(url) ||\n\t\t!path.startsWith(client + sep) ||\n\t\tpath.endsWith(sep)\n\t) {\n\t\tthrow new Error(`buildWorker(): ${url} is outside ${client}.`);\n\t}\n\treturn path;\n}\n\n/**\n * Bundles the worker (Workbox included) into the client build, after\n * `react-router build`, with the precache list written in: the offline page\n * by its content, every route's code and `precacheAssets`. A new build\n * changes the list, so the worker's bytes, so the browser installs it.\n * Runs on Bun; the only imports of this module are Node's built-ins.\n */\nexport async function buildWorker(\n\toptions: BuildWorkerOptions,\n): Promise<WorkerBuild> {\n\tassertBun();\n\tconst root = resolve(options.root ?? process.cwd());\n\tconst client = resolve(root, options.client ?? 'build/client');\n\tconst source = resolve(root, options.file);\n\tconst workerUrl = options.contract?.serviceWorkerUrl ?? SERVICE_WORKER_URL;\n\tconst offlineUrl = options.contract?.offlineUrl ?? OFFLINE_URL;\n\tif (!existsSync(source)) {\n\t\tthrow new Error(`buildWorker(): ${options.file} does not exist.`);\n\t}\n\tconst assets = join(client, 'assets');\n\tconst files = await readdir(assets).catch(() => []);\n\tconst manifest = browserManifestFile(files);\n\tlet offline: PrecacheEntry | undefined;\n\tif (options.offline !== false) {\n\t\tconst page = urlInClient(client, offlineUrl);\n\t\tif (!existsSync(page)) {\n\t\t\tthrow new Error(\n\t\t\t\t`buildWorker(): ${options.client ?? 'build/client'}${offlineUrl} does not exist. Add public${offlineUrl}, or pass offline: false (\\`worker: { offline: false }\\` in alxia()), or pass the app's contract (\\`worker: { contract }\\` in alxia()).`,\n\t\t\t);\n\t\t}\n\t\toffline = { url: offlineUrl, revision: revisionOf(await readFile(page)) };\n\t}\n\tconst precache = workerPrecache({\n\t\tmanifestSource: await readFile(join(assets, manifest), 'utf8'),\n\t\tassetFiles: files,\n\t\toffline,\n\t\tinclude: options.precacheAssets,\n\t});\n\tconst out = urlInClient(client, workerUrl);\n\tconst result = await Bun.build({\n\t\tentrypoints: [source],\n\t\toutdir: dirname(out),\n\t\tnaming: basename(out),\n\t\ttarget: 'browser',\n\t\tformat: 'iife',\n\t\tminify: options.minify ?? true,\n\t\tdefine: {\n\t\t\t// Workbox's production build: no logging, no dev assertions.\n\t\t\t'process.env.NODE_ENV': '\"production\"',\n\t\t\t[PRECACHE_DEFINE]: JSON.stringify(precache),\n\t\t},\n\t}).catch((error: unknown) => {\n\t\tconst detail =\n\t\t\terror instanceof AggregateError\n\t\t\t\t? error.errors.map(String).join('\\n')\n\t\t\t\t: String(error);\n\t\tthrow new Error(`buildWorker(): Bun.build failed:\\n${detail}`);\n\t});\n\tif (!result.success) {\n\t\tthrow new Error(\n\t\t\t`buildWorker(): Bun.build failed:\\n${result.logs.map(String).join('\\n')}`,\n\t\t);\n\t}\n\tlet precacheBytes = 0;\n\tfor (const { url } of precache) {\n\t\tprecacheBytes += (await stat(join(client, url))).size;\n\t}\n\treturn {\n\t\tfile: out,\n\t\tprecache,\n\t\tprecacheBytes,\n\t\tbytes: (await stat(out)).size,\n\t};\n}\n",
|
|
6
|
+
"import { createHash } from 'node:crypto';\nimport {\n\tassetPrecache,\n\ttype PrecacheEntry,\n\tparseBrowserManifest,\n\tprecacheList,\n} from '../model/precache-list';\n\n/** The one React Router browser manifest among the names in build/client/assets. */\nexport function browserManifestFile(files: readonly string[]): string {\n\tconst found = files.filter((file) => /^manifest-[\\w-]+\\.js$/.test(file));\n\tconst [only] = found;\n\tif (found.length !== 1 || only === undefined) {\n\t\tthrow new Error(\n\t\t\t`buildWorker(): expected one React Router browser manifest, build/client/assets/manifest-*.js, found ${found.length}. Run react-router build first.`,\n\t\t);\n\t}\n\treturn only;\n}\n\n/** A file's revision: the first 16 hex characters of its sha256. */\nexport function revisionOf(bytes: Uint8Array): string {\n\treturn createHash('sha256').update(bytes).digest('hex').slice(0, 16);\n}\n\n/**\n * The worker's precache list: the offline page (revisioned by its content),\n * every route's code, then the asset files `include` matches. Each URL once,\n * the first kept.\n */\nexport function workerPrecache(input: {\n\tmanifestSource: string;\n\tassetFiles: readonly string[];\n\toffline?: PrecacheEntry | undefined;\n\tinclude?: RegExp | undefined;\n}): PrecacheEntry[] {\n\tconst all = [\n\t\t...(input.offline ? [input.offline] : []),\n\t\t...precacheList(parseBrowserManifest(input.manifestSource)),\n\t\t...(input.include ? assetPrecache(input.assetFiles, input.include) : []),\n\t];\n\tconst seen = new Set<string>();\n\treturn all.filter(({ url }) => !seen.has(url) && seen.add(url));\n}\n"
|
|
7
|
+
],
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "763F0D0F0869B4B964756E2164756E21",
|
|
10
|
+
"names": []
|
|
11
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/pwa/model/worker-contract.ts
|
|
2
|
+
var SERVICE_WORKER_URL2 = "/service-worker.js";
|
|
3
|
+
var OFFLINE_URL2 = "/offline.html";
|
|
4
|
+
var SKIP_WAITING2 = "SKIP_WAITING";
|
|
5
|
+
function defineWorkerContract2(options) {
|
|
6
|
+
const { cachePrefix } = options;
|
|
7
|
+
if (typeof cachePrefix !== "string" || cachePrefix === "") {
|
|
8
|
+
throw new TypeError(`defineWorkerContract(): cachePrefix must be a non-empty name, such as 'my-app'; got '${String(cachePrefix)}'.`);
|
|
9
|
+
}
|
|
10
|
+
if (cachePrefix.endsWith("-")) {
|
|
11
|
+
throw new TypeError(`defineWorkerContract(): cachePrefix must not end with '-', which the contract adds; got '${cachePrefix}'. Use '${cachePrefix.replace(/-+$/, "")}'.`);
|
|
12
|
+
}
|
|
13
|
+
const cacheVersion = options.cacheVersion ?? "v1";
|
|
14
|
+
if (typeof cacheVersion !== "string" || cacheVersion === "" || cacheVersion.includes("-")) {
|
|
15
|
+
throw new TypeError(`defineWorkerContract(): cacheVersion must be a non-empty name without '-', such as 'v2'; got '${String(cacheVersion)}'.`);
|
|
16
|
+
}
|
|
17
|
+
const cacheNames = Object.freeze({
|
|
18
|
+
precache: `${cachePrefix}-precache-${cacheVersion}`,
|
|
19
|
+
assets: `${cachePrefix}-assets-${cacheVersion}`,
|
|
20
|
+
static: `${cachePrefix}-static-${cacheVersion}`
|
|
21
|
+
});
|
|
22
|
+
const current = new Set(Object.values(cacheNames));
|
|
23
|
+
const shape = new RegExp(`^${cachePrefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}-[a-z0-9]+-[^-]+$`);
|
|
24
|
+
const owned = (name) => shape.test(name);
|
|
25
|
+
const contract = {
|
|
26
|
+
cachePrefix,
|
|
27
|
+
cacheVersion,
|
|
28
|
+
serviceWorkerUrl: options.serviceWorkerUrl ?? SERVICE_WORKER_URL2,
|
|
29
|
+
offlineUrl: options.offlineUrl ?? OFFLINE_URL2,
|
|
30
|
+
cacheNames,
|
|
31
|
+
obsoleteCaches: (names) => names.filter((name) => owned(name) && !current.has(name)),
|
|
32
|
+
clearableCaches: (names) => names.filter((name) => owned(name) && name !== cacheNames.precache)
|
|
33
|
+
};
|
|
34
|
+
return Object.freeze(contract);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { SERVICE_WORKER_URL2, OFFLINE_URL2, SKIP_WAITING2, defineWorkerContract2 };
|
|
38
|
+
|
|
39
|
+
//# debugId=5CED7E20833AD98364756E2164756E21
|
|
40
|
+
//# sourceMappingURL=index-rfr02vg4.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/pwa/model/worker-contract.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * What the service worker and the page agree on: the worker's address, the\n * offline page, the message that applies an update, and the names of the\n * caches the worker owns. Dependency-free: the worker bundles it, with no\n * DOM and no React.\n */\n\n/** Where the build writes the worker; registered with scope `/`. */\nexport const SERVICE_WORKER_URL = '/service-worker.js';\n\n/** The page served when a navigation fails for want of a network. */\nexport const OFFLINE_URL = '/offline.html';\n\n/** The message a page posts to a waiting worker to make it take over. */\nexport const SKIP_WAITING = 'SKIP_WAITING';\n\nexport interface WorkerContractOptions {\n\t/**\n\t * Every Cache Storage cache the worker owns is named\n\t * `<cachePrefix>-<kind>-<version>` (kind: letters and digits; version:\n\t * no `-`); a cache of another shape is never swept.\n\t * Required: two apps on one origin must not share it.\n\t */\n\tcachePrefix: string;\n\t/**\n\t * Bumped when a cache's content changes shape: the next worker deletes\n\t * every cache of the prefix that has another version when it activates.\n\t * `'v1'` by default; not empty, and without a `-`.\n\t */\n\tcacheVersion?: string;\n\t/** `SERVICE_WORKER_URL` by default. */\n\tserviceWorkerUrl?: string;\n\t/** `OFFLINE_URL` by default. */\n\tofflineUrl?: string;\n}\n\nexport type CacheNames = {\n\t/**\n\t * The offline page and the hashed scripts and stylesheets of every route.\n\t * `<prefix>-precache-<version>` is the name Workbox builds from\n\t * `setCacheNameDetails({ prefix, precache: 'precache', suffix: version })`.\n\t */\n\treadonly precache: string;\n\t/** `/assets/*` bundles: hashed names, so cache-first. */\n\treadonly assets: string;\n\t/** Icons, sprites, the logo: stale-while-revalidate. */\n\treadonly static: string;\n};\n\nexport interface WorkerContract {\n\treadonly cachePrefix: string;\n\treadonly cacheVersion: string;\n\treadonly serviceWorkerUrl: string;\n\treadonly offlineUrl: string;\n\treadonly cacheNames: CacheNames;\n\t/** The caches a worker deletes on activate: the prefix's, of another version. */\n\tobsoleteCaches(names: readonly string[]): string[];\n\t/**\n\t * The caches `clearAppCaches()` deletes: all of the prefix's but the\n\t * current precache, which holds the offline page and the app's code, never\n\t * a user's data.\n\t */\n\tclearableCaches(names: readonly string[]): string[];\n}\n\n/** Builds the contract of one app from its cache prefix. */\nexport function defineWorkerContract(\n\toptions: WorkerContractOptions,\n): WorkerContract {\n\tconst { cachePrefix } = options;\n\tif (typeof cachePrefix !== 'string' || cachePrefix === '') {\n\t\tthrow new TypeError(\n\t\t\t`defineWorkerContract(): cachePrefix must be a non-empty name, such as 'my-app'; got '${String(cachePrefix)}'.`,\n\t\t);\n\t}\n\tif (cachePrefix.endsWith('-')) {\n\t\tthrow new TypeError(\n\t\t\t`defineWorkerContract(): cachePrefix must not end with '-', which the contract adds; got '${cachePrefix}'. Use '${cachePrefix.replace(/-+$/, '')}'.`,\n\t\t);\n\t}\n\tconst cacheVersion = options.cacheVersion ?? 'v1';\n\tif (\n\t\ttypeof cacheVersion !== 'string' ||\n\t\tcacheVersion === '' ||\n\t\tcacheVersion.includes('-')\n\t) {\n\t\tthrow new TypeError(\n\t\t\t`defineWorkerContract(): cacheVersion must be a non-empty name without '-', such as 'v2'; got '${String(cacheVersion)}'.`,\n\t\t);\n\t}\n\tconst cacheNames: CacheNames = Object.freeze({\n\t\tprecache: `${cachePrefix}-precache-${cacheVersion}`,\n\t\tassets: `${cachePrefix}-assets-${cacheVersion}`,\n\t\tstatic: `${cachePrefix}-static-${cacheVersion}`,\n\t});\n\tconst current = new Set<string>(Object.values(cacheNames));\n\t// Exactly `<prefix>-<kind>-<version>`: the prefix 'app' must not claim\n\t// 'app-admin-assets-v1' (one segment too many), but still owns a retired\n\t// kind such as 'app-pages-v0'.\n\tconst shape = new RegExp(\n\t\t`^${cachePrefix.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}-[a-z0-9]+-[^-]+$`,\n\t);\n\tconst owned = (name: string) => shape.test(name);\n\tconst contract: WorkerContract = {\n\t\tcachePrefix,\n\t\tcacheVersion,\n\t\tserviceWorkerUrl: options.serviceWorkerUrl ?? SERVICE_WORKER_URL,\n\t\tofflineUrl: options.offlineUrl ?? OFFLINE_URL,\n\t\tcacheNames,\n\t\tobsoleteCaches: (names) =>\n\t\t\tnames.filter((name) => owned(name) && !current.has(name)),\n\t\tclearableCaches: (names) =>\n\t\t\tnames.filter((name) => owned(name) && name !== cacheNames.precache),\n\t};\n\treturn Object.freeze(contract);\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAQO,IAAM,sBAAqB;AAG3B,IAAM,eAAc;AAGpB,IAAM,gBAAe;AAoDrB,SAAS,qBAAoB,CACnC,SACiB;AAAA,EACjB,QAAQ,gBAAgB;AAAA,EACxB,IAAI,OAAO,gBAAgB,YAAY,gBAAgB,IAAI;AAAA,IAC1D,MAAM,IAAI,UACT,wFAAwF,OAAO,WAAW,KAC3G;AAAA,EACD;AAAA,EACA,IAAI,YAAY,SAAS,GAAG,GAAG;AAAA,IAC9B,MAAM,IAAI,UACT,4FAA4F,sBAAsB,YAAY,QAAQ,OAAO,EAAE,KAChJ;AAAA,EACD;AAAA,EACA,MAAM,eAAe,QAAQ,gBAAgB;AAAA,EAC7C,IACC,OAAO,iBAAiB,YACxB,iBAAiB,MACjB,aAAa,SAAS,GAAG,GACxB;AAAA,IACD,MAAM,IAAI,UACT,iGAAiG,OAAO,YAAY,KACrH;AAAA,EACD;AAAA,EACA,MAAM,aAAyB,OAAO,OAAO;AAAA,IAC5C,UAAU,GAAG,wBAAwB;AAAA,IACrC,QAAQ,GAAG,sBAAsB;AAAA,IACjC,QAAQ,GAAG,sBAAsB;AAAA,EAClC,CAAC;AAAA,EACD,MAAM,UAAU,IAAI,IAAY,OAAO,OAAO,UAAU,CAAC;AAAA,EAIzD,MAAM,QAAQ,IAAI,OACjB,IAAI,YAAY,QAAQ,uBAAuB,MAAM,oBACtD;AAAA,EACA,MAAM,QAAQ,CAAC,SAAiB,MAAM,KAAK,IAAI;AAAA,EAC/C,MAAM,WAA2B;AAAA,IAChC;AAAA,IACA;AAAA,IACA,kBAAkB,QAAQ,oBAAoB;AAAA,IAC9C,YAAY,QAAQ,cAAc;AAAA,IAClC;AAAA,IACA,gBAAgB,CAAC,UAChB,MAAM,OAAO,CAAC,SAAS,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC;AAAA,IACzD,iBAAiB,CAAC,UACjB,MAAM,OAAO,CAAC,SAAS,MAAM,IAAI,KAAK,SAAS,WAAW,QAAQ;AAAA,EACpE;AAAA,EACA,OAAO,OAAO,OAAO,QAAQ;AAAA;",
|
|
8
|
+
"debugId": "5CED7E20833AD98364756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -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": ";;;;;AACO,IAAM,iBAAgB;AAOtB,IAAM,oBAAmB;AAAA,EAC/B,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,MAAM;AAAA,EACN,2BAA2B;AAC5B;AAOO,SAAS,aAAY,CAC3B,UACA,OAAe,gBACN;AAAA,EACT,OAAO,GAAG,aAAa,mBAAmB,QAAQ;AAAA;AAO5C,SAAS,iBAAkC,CACjD,KACA,WACA,UACI;AAAA,EACJ,MAAM,YAAY,IAAI,aAAa,IAAI,MAAM;AAAA,EAC7C,OAAO,UAAU,KAAK,CAAC,aAAa,aAAa,SAAS,KAAK;AAAA;AAczD,IAAM,sBAA8C,OAAO,OACjE;AAAA,EACC,EAAE,KAAK,kBAAkB,OAAO,SAAS,MAAM,YAAY;AAAA,EAC3D,EAAE,KAAK,oBAAoB,OAAO,WAAW,MAAM,YAAY;AAAA,EAC/D,EAAE,KAAK,oBAAoB,OAAO,WAAW,MAAM,YAAY;AAAA,EAC/D;AAAA,IACC,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,EACV;AACD,EAAE,IAAI,CAAC,SAAS,OAAO,OAAO,IAAI,CAAC,CACpC;AA+CO,SAAS,eAAc,CAAC,SAAgD;AAAA,EAC9E,OAAO;AAAA,IACN,IAAI,QAAQ,MAAM;AAAA,IAClB,MAAM,QAAQ;AAAA,IACd,YAAY,QAAQ,aAAa,QAAQ;AAAA,IACzC,aAAa,QAAQ;AAAA,IACrB,MAAM,QAAQ;AAAA,IACd,KAAK,QAAQ,OAAO;AAAA,IACpB,WAAW,QAAQ,YAAY;AAAA,IAC/B,OAAO,QAAQ,SAAS;AAAA,IACxB,SAAS,QAAQ,WAAW;AAAA,IAC5B,aAAa,QAAQ;AAAA,IACrB,kBAAkB,QAAQ;AAAA,OACtB,QAAQ,cAAc,EAAE,YAAY,CAAC,GAAG,QAAQ,UAAU,EAAE;AAAA,IAChE,QAAQ,QAAQ,SAAS,qBAAoB,IAAI,CAAC,UAAU,KAAK,KAAK,EAAE;AAAA,EACzE;AAAA;;;AC7ED,IAAM,mBACL;AAED,IAAM,cAAc,CAAC,SAAiB,KAAK,WAAW,UAAU;AAGzD,SAAS,WAAU,CACzB,SACA,QACA,UAA0B,CAAC,GACjB;AAAA,EACV,IAAI,QAAQ,WAAW;AAAA,IAAO,OAAO;AAAA,EACrC,IAAI,QAAQ,SAAS;AAAA,IAAY,OAAO;AAAA,EACxC,MAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAAA,EAC/B,IAAI,IAAI,WAAW;AAAA,IAAQ,OAAO;AAAA,EAClC,IAAI,QAAQ,QAAQ,IAAI,eAAe;AAAA,IAAG,OAAO;AAAA,EACjD,IAAI,IAAI;AAAA,IAAQ,OAAO;AAAA,EACvB,MAAM,OAAO,IAAI;AAAA,EACjB,IACC,KAAK,SAAS,OAAO,KACrB,SAAS,iBACT,UACE,QAAQ,oBACR,QAAQ,UAAU,oBAClB,wBACF,UAAU,QAAQ,gBAAgB,mBAClC,QAAQ,QAAQ,IAAI,GACnB;AAAA,IACD,OAAO;AAAA,EACR;AAAA,EACA,IAAI,QAAQ,gBAAgB,cAAc,QAAQ,gBAAgB;AAAA,IACjE,OAAO;AAAA,EACR,IAAI,CAAC,iBAAiB,KAAK,IAAI;AAAA,IAAG,OAAO;AAAA,EACzC,QAAQ,QAAQ,aAAa,aAAa,IAAI,IAAI,cAAc;AAAA;;;AC5EjE,IAAM,sBACL;AAQM,SAAS,WAAU,CAAC,UAA6B;AAAA,EACvD,IAAI,SAAS,WAAW;AAAA,IAAK,OAAO;AAAA,EACpC,IAAI,SAAS,SAAS,WAAW,SAAS,SAAS;AAAA,IAAW,OAAO;AAAA,EACrE,MAAM,eAAe,SAAS,QAAQ,IAAI,cAAc,KAAK,IAC3D,MAAM,GAAG,EAAE,IACV,KAAK;AAAA,EACR,IAAI,CAAC,eAAe,CAAC,oBAAoB,KAAK,WAAW;AAAA,IAAG,OAAO;AAAA,EACnE,MAAM,eAAe,SAAS,QAAQ,IAAI,eAAe,KAAK;AAAA,EAC9D,IAAI,CAAC,cAAc,KAAK,YAAY;AAAA,IAAG,OAAO;AAAA,EAC9C,IAAI,4BAA4B,KAAK,YAAY;AAAA,IAAG,OAAO;AAAA,EAC3D,MAAM,OAAO,SAAS,QAAQ,IAAI,MAAM,KAAK;AAAA,EAC7C,OAAO,CAAC,mDAAmD,KAAK,IAAI;AAAA;",
|
|
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,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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@alxia/react-router/pwa`: the code with no UI an installable app shares.
|
|
3
|
+
* No import at all, so the page, the service worker, a build script and the
|
|
4
|
+
* server can each import it.
|
|
5
|
+
*/
|
|
6
|
+
export { type Caching, type CachingOptions, cachingFor, type RequestFacts, } from './model/caching';
|
|
7
|
+
export { clearAppCaches } from './model/clear-app-caches';
|
|
8
|
+
export { MANIFEST_HEADERS, MANIFEST_PATH, type ManifestIcon, MINIMAL_2023_ICONS, manifestHref, manifestLanguage, type WebAppManifest, type WebAppManifestOptions, webAppManifest, } from './model/manifest';
|
|
9
|
+
export { assetPrecache, type BrowserManifest, type PrecacheEntry, parseBrowserManifest, precacheList, } from './model/precache-list';
|
|
10
|
+
export { type ApplyUpdate, afterLoad, createUpdater, type RegisterOptions, registerServiceWorker, type ServiceWorkerContainerLike, watchForUpdates, } from './model/registration';
|
|
11
|
+
export { isStorable } from './model/storable';
|
|
12
|
+
export { createUpdateNotice, type NoticeStorage, sessionStore, UPDATE_LATER_KEY, type UpdateNotice, type UpdateNoticeStore, } from './model/update-notice';
|
|
13
|
+
export { type CacheNames, defineWorkerContract, OFFLINE_URL, SERVICE_WORKER_URL, SKIP_WAITING, type WorkerContract, type WorkerContractOptions, } from './model/worker-contract';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pwa/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,UAAU,EACV,KAAK,YAAY,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EACN,gBAAgB,EAChB,aAAa,EACb,KAAK,YAAY,EACjB,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,cAAc,GACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,oBAAoB,EACpB,YAAY,GACZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,KAAK,WAAW,EAChB,SAAS,EACT,aAAa,EACb,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,eAAe,GACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACN,kBAAkB,EAClB,KAAK,aAAa,EAClB,YAAY,EACZ,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,KAAK,UAAU,EACf,oBAAoB,EACpB,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,KAAK,cAAc,EACnB,KAAK,qBAAqB,GAC1B,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {
|
|
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 {
|
|
12
|
+
watchForUpdates2,
|
|
13
|
+
createUpdater2,
|
|
14
|
+
afterLoad2,
|
|
15
|
+
registerServiceWorker2,
|
|
16
|
+
UPDATE_LATER_KEY2,
|
|
17
|
+
createUpdateNotice2,
|
|
18
|
+
sessionStore2
|
|
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";
|
|
31
|
+
// src/pwa/model/clear-app-caches.ts
|
|
32
|
+
async function clearAppCaches(contract) {
|
|
33
|
+
if (typeof caches === "undefined")
|
|
34
|
+
return;
|
|
35
|
+
const names = contract.clearableCaches(await caches.keys());
|
|
36
|
+
await Promise.all(names.map((name) => caches.delete(name)));
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
MANIFEST_HEADERS2 as MANIFEST_HEADERS,
|
|
40
|
+
MANIFEST_PATH2 as MANIFEST_PATH,
|
|
41
|
+
MINIMAL_2023_ICONS2 as MINIMAL_2023_ICONS,
|
|
42
|
+
OFFLINE_URL2 as OFFLINE_URL,
|
|
43
|
+
SERVICE_WORKER_URL2 as SERVICE_WORKER_URL,
|
|
44
|
+
SKIP_WAITING2 as SKIP_WAITING,
|
|
45
|
+
UPDATE_LATER_KEY2 as UPDATE_LATER_KEY,
|
|
46
|
+
afterLoad2 as afterLoad,
|
|
47
|
+
assetPrecache2 as assetPrecache,
|
|
48
|
+
cachingFor2 as cachingFor,
|
|
49
|
+
clearAppCaches,
|
|
50
|
+
createUpdateNotice2 as createUpdateNotice,
|
|
51
|
+
createUpdater2 as createUpdater,
|
|
52
|
+
defineWorkerContract2 as defineWorkerContract,
|
|
53
|
+
isStorable2 as isStorable,
|
|
54
|
+
manifestHref2 as manifestHref,
|
|
55
|
+
manifestLanguage2 as manifestLanguage,
|
|
56
|
+
parseBrowserManifest2 as parseBrowserManifest,
|
|
57
|
+
precacheList2 as precacheList,
|
|
58
|
+
registerServiceWorker2 as registerServiceWorker,
|
|
59
|
+
sessionStore2 as sessionStore,
|
|
60
|
+
watchForUpdates2 as watchForUpdates,
|
|
61
|
+
webAppManifest2 as webAppManifest
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
//# debugId=7B8375F7BF1AB78E64756E2164756E21
|
|
65
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/pwa/model/clear-app-caches.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
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"
|
|
6
|
+
],
|
|
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",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type WorkerContract } from './worker-contract';
|
|
2
|
+
/**
|
|
3
|
+
* Which requests the service worker caches, and how. Pure, so that what is
|
|
4
|
+
* never cached is tested, not hoped for.
|
|
5
|
+
*
|
|
6
|
+
* - `navigation`: a page load. Always from the network, never stored; the
|
|
7
|
+
* offline page answers only when the network fails.
|
|
8
|
+
* - `immutable`: a hashed bundle: cache-first.
|
|
9
|
+
* - `static`: another same-origin static file (icon, sprite, logo):
|
|
10
|
+
* stale-while-revalidate.
|
|
11
|
+
* - `none`: left to the browser, untouched: every non-GET, any other
|
|
12
|
+
* origin, React Router's `.data` and `/__manifest`, the worker and the
|
|
13
|
+
* manifest themselves, the app's own `never` paths, and anything carrying
|
|
14
|
+
* credentials.
|
|
15
|
+
*/
|
|
16
|
+
export type Caching = 'navigation' | 'immutable' | 'static' | 'none';
|
|
17
|
+
/** What a `Request` exposes that the decision reads. */
|
|
18
|
+
export interface RequestFacts {
|
|
19
|
+
readonly method: string;
|
|
20
|
+
readonly url: string;
|
|
21
|
+
readonly mode: string;
|
|
22
|
+
readonly destination: string;
|
|
23
|
+
readonly headers: Pick<Headers, 'has'>;
|
|
24
|
+
}
|
|
25
|
+
export interface CachingOptions {
|
|
26
|
+
/**
|
|
27
|
+
* The worker's own path, never cached. Wins over `contract`;
|
|
28
|
+
* `SERVICE_WORKER_URL` when neither is given.
|
|
29
|
+
*/
|
|
30
|
+
serviceWorkerUrl?: string;
|
|
31
|
+
/** The app's contract, whose `serviceWorkerUrl` is never cached. */
|
|
32
|
+
contract?: Pick<WorkerContract, 'serviceWorkerUrl'>;
|
|
33
|
+
/** The web app manifest's path, never cached. `MANIFEST_PATH` by default. */
|
|
34
|
+
manifestPath?: string;
|
|
35
|
+
/** Paths of the app answered fresh every time, such as `(p) => p.startsWith('/api/')`. */
|
|
36
|
+
never?: (path: string) => boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Which static paths are immutable (cache-first) rather than static.
|
|
39
|
+
* `(path) => path.startsWith('/assets/')` by default, as `serveClient`
|
|
40
|
+
* serves them.
|
|
41
|
+
*/
|
|
42
|
+
immutable?: (path: string) => boolean;
|
|
43
|
+
}
|
|
44
|
+
/** How the worker answers `request`, for an app served at `origin`. */
|
|
45
|
+
export declare function cachingFor(request: RequestFacts, origin: string, options?: CachingOptions): Caching;
|
|
46
|
+
//# sourceMappingURL=caching.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caching.d.ts","sourceRoot":"","sources":["../../../src/pwa/model/caching.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE5E;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;AAErE,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC9B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IACpD,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0FAA0F;IAC1F,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACtC;AAOD,uEAAuE;AACvE,wBAAgB,UAAU,CACzB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAwBT"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { WorkerContract } from './worker-contract';
|
|
2
|
+
/**
|
|
3
|
+
* Deletes every cache the service worker filled, but the offline page.
|
|
4
|
+
* For sign-out: what the caches hold is static and public by design, and
|
|
5
|
+
* clearing them leaves nothing behind anyway. Safe where Cache Storage does
|
|
6
|
+
* not exist (server, old browsers).
|
|
7
|
+
*/
|
|
8
|
+
export declare function clearAppCaches(contract: Pick<WorkerContract, 'clearableCaches'>): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=clear-app-caches.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clear-app-caches.d.ts","sourceRoot":"","sources":["../../../src/pwa/model/clear-app-caches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;GAKG;AACH,wBAAsB,cAAc,CACnC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/** Where the server serves the manifest, and the document head links it. */
|
|
2
|
+
export declare const MANIFEST_PATH = "/manifest.webmanifest";
|
|
3
|
+
/**
|
|
4
|
+
* Cacheable for an hour, like the icons; the language travels in `?lang=`.
|
|
5
|
+
* Its own policy, which loads nothing: the pages' one carries a nonce, and
|
|
6
|
+
* a nonce never goes in a response a cache may keep.
|
|
7
|
+
*/
|
|
8
|
+
export declare const MANIFEST_HEADERS: {
|
|
9
|
+
readonly 'content-type': "application/manifest+json; charset=utf-8";
|
|
10
|
+
readonly 'cache-control': "public, max-age=3600";
|
|
11
|
+
readonly vary: "Accept-Language";
|
|
12
|
+
readonly 'content-security-policy': "default-src 'none'; frame-ancestors 'none'";
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* The manifest's URL for a page in `language`. A browser fetches the
|
|
16
|
+
* manifest without cookies, so a `language` cookie would not reach it: the
|
|
17
|
+
* page names its language in the query instead.
|
|
18
|
+
*/
|
|
19
|
+
export declare function manifestHref(language: string, path?: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* `?lang=` when it names one of `supported`, else `fallback`: the request's
|
|
22
|
+
* Accept-Language, never its cookie, so `Vary: Accept-Language` holds.
|
|
23
|
+
*/
|
|
24
|
+
export declare function manifestLanguage<L extends string>(url: URL, supported: readonly L[], fallback: L): L;
|
|
25
|
+
export type ManifestIcon = {
|
|
26
|
+
src: string;
|
|
27
|
+
sizes: string;
|
|
28
|
+
type: string;
|
|
29
|
+
purpose?: 'any' | 'maskable' | 'monochrome';
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* The four icons `@vite-pwa/assets-generator`'s `minimal2023Preset` writes
|
|
33
|
+
* to `public/`: 64, 192 and 512 pixels, and a maskable 512.
|
|
34
|
+
*/
|
|
35
|
+
export declare const MINIMAL_2023_ICONS: readonly ManifestIcon[];
|
|
36
|
+
export interface WebAppManifestOptions {
|
|
37
|
+
name: string;
|
|
38
|
+
/** `name` by default. */
|
|
39
|
+
shortName?: string;
|
|
40
|
+
description: string;
|
|
41
|
+
/** The language of `name` and `description`. */
|
|
42
|
+
lang: string;
|
|
43
|
+
/** `'ltr'` by default. */
|
|
44
|
+
dir?: 'ltr' | 'rtl' | 'auto';
|
|
45
|
+
themeColor: string;
|
|
46
|
+
backgroundColor: string;
|
|
47
|
+
categories?: readonly string[];
|
|
48
|
+
/** `MINIMAL_2023_ICONS` by default. */
|
|
49
|
+
icons?: readonly ManifestIcon[];
|
|
50
|
+
/** `'/'` by default: the same in every language, so a language switch never makes a second app. */
|
|
51
|
+
id?: string;
|
|
52
|
+
/** `'/'` by default. */
|
|
53
|
+
startUrl?: string;
|
|
54
|
+
/** `'/'` by default. */
|
|
55
|
+
scope?: string;
|
|
56
|
+
/** `'standalone'` by default. */
|
|
57
|
+
display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';
|
|
58
|
+
}
|
|
59
|
+
/** The web app manifest's JSON, with its snake_case keys. */
|
|
60
|
+
export type WebAppManifest = {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
short_name: string;
|
|
64
|
+
description: string;
|
|
65
|
+
lang: string;
|
|
66
|
+
dir: 'ltr' | 'rtl' | 'auto';
|
|
67
|
+
start_url: string;
|
|
68
|
+
scope: string;
|
|
69
|
+
display: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';
|
|
70
|
+
theme_color: string;
|
|
71
|
+
background_color: string;
|
|
72
|
+
categories?: string[];
|
|
73
|
+
icons: ManifestIcon[];
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* A web app manifest from the app's own (translated) texts and colours.
|
|
77
|
+
* `id`, `start_url` and `scope` default to `'/'` whatever the language.
|
|
78
|
+
*/
|
|
79
|
+
export declare function webAppManifest(options: WebAppManifestOptions): WebAppManifest;
|
|
80
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/pwa/model/manifest.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,eAAO,MAAM,aAAa,0BAA0B,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;;CAKnB,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,YAAY,CAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,MAAsB,GAC1B,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,EAChD,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,SAAS,CAAC,EAAE,EACvB,QAAQ,EAAE,CAAC,GACT,CAAC,CAGH;AAED,MAAM,MAAM,YAAY,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,KAAK,GAAG,UAAU,GAAG,YAAY,CAAC;CAC5C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,YAAY,EAYrD,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,uCAAuC;IACvC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAChC,mGAAmG;IACnG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,OAAO,CAAC,EAAE,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,CAAC;CACjE;AAED,6DAA6D;AAC7D,MAAM,MAAM,cAAc,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,CAAC;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,YAAY,EAAE,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,cAAc,CAgB7E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the service worker precaches, read from a build: every script and
|
|
3
|
+
* stylesheet React Router's manifest names (the client entry and each
|
|
4
|
+
* route's module, imports and CSS), and the manifest itself, so a client
|
|
5
|
+
* navigation offline to a route never visited still finds its code. Only
|
|
6
|
+
* hashed `/assets/` files: a new build names new files, so each precaches
|
|
7
|
+
* under its own URL, revision `null`. Chunks only a component loads on
|
|
8
|
+
* demand stay out: a cache-first route stores them the first time they load.
|
|
9
|
+
*
|
|
10
|
+
* Dependency-free: a build script runs it at build time.
|
|
11
|
+
*/
|
|
12
|
+
/** A route or the entry, as `window.__reactRouterManifest` lists it. */
|
|
13
|
+
type ManifestModule = {
|
|
14
|
+
module?: string;
|
|
15
|
+
imports?: string[];
|
|
16
|
+
css?: string[];
|
|
17
|
+
};
|
|
18
|
+
/** The parts of React Router's browser manifest the list reads. */
|
|
19
|
+
export type BrowserManifest = {
|
|
20
|
+
url: string;
|
|
21
|
+
entry: ManifestModule;
|
|
22
|
+
routes: Record<string, ManifestModule>;
|
|
23
|
+
};
|
|
24
|
+
/** A Workbox precache entry: a hashed URL needs no revision. */
|
|
25
|
+
export type PrecacheEntry = {
|
|
26
|
+
url: string;
|
|
27
|
+
revision: string | null;
|
|
28
|
+
};
|
|
29
|
+
/** Reads `window.__reactRouterManifest={…};` (build/client/assets/manifest-*.js). */
|
|
30
|
+
export declare function parseBrowserManifest(source: string): BrowserManifest;
|
|
31
|
+
/** The hashed scripts and stylesheets every route needs, the manifest's own file first. */
|
|
32
|
+
export declare function precacheList(manifest: BrowserManifest): PrecacheEntry[];
|
|
33
|
+
/**
|
|
34
|
+
* The precache entries of the files among `assetFiles` (the names in
|
|
35
|
+
* build/client/assets) that `include` matches, sorted, under `base`: fonts
|
|
36
|
+
* an app keeps offline, say. The regex is the app's.
|
|
37
|
+
*/
|
|
38
|
+
export declare function assetPrecache(assetFiles: readonly string[], include: RegExp, base?: string): PrecacheEntry[];
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=precache-list.d.ts.map
|