@sovereignbase/pwa 1.0.0 → 1.0.1
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 +97 -26
- package/dist/index.cjs +49 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -2
- package/dist/index.js.map +1 -1
- package/dist/serviceWorker/entrypoint.cjs +6 -1
- package/dist/serviceWorker/entrypoint.cjs.map +1 -1
- package/dist/serviceWorker/entrypoint.js +6 -1
- package/dist/serviceWorker/entrypoint.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,15 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
[](https://www.npmjs.com/package/@sovereignbase/pwa)
|
|
2
|
+
[](https://jsr.io/@sovereignbase/pwa)
|
|
3
|
+
[](https://github.com/sovereignbase/pwa/actions/workflows/ci.yaml)
|
|
4
|
+
[](https://codecov.io/gh/sovereignbase/pwa)
|
|
5
|
+
[](LICENSE)
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
# pwa
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
Build tool for localized, offline-first, search-engine-optimized progressive
|
|
10
|
+
web applications.
|
|
11
|
+
|
|
12
|
+
## Compatibility
|
|
13
|
+
|
|
14
|
+
- Runtimes: Node.js and Bun.
|
|
15
|
+
- Input: TypeScript or JavaScript, CSS, assets, and typed language modules.
|
|
16
|
+
- Output: static installers, localized manifests, immutable assets, and a
|
|
17
|
+
self-rendering Service Worker.
|
|
18
|
+
- Module format: ESM or CJS.
|
|
19
|
+
- Types: bundled `.d.ts`.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
6
22
|
|
|
7
23
|
```sh
|
|
8
24
|
npm install --save-dev @sovereignbase/pwa
|
|
25
|
+
# or
|
|
26
|
+
pnpm add --save-dev @sovereignbase/pwa
|
|
27
|
+
# or
|
|
28
|
+
yarn add --dev @sovereignbase/pwa
|
|
29
|
+
# or
|
|
30
|
+
bun add --dev @sovereignbase/pwa
|
|
9
31
|
```
|
|
10
32
|
|
|
11
|
-
Node.js 20 or newer and Bun are supported.
|
|
12
|
-
|
|
13
33
|
## Usage
|
|
14
34
|
|
|
15
35
|
```ts
|
|
@@ -50,11 +70,27 @@ await pwaize({
|
|
|
50
70
|
})
|
|
51
71
|
```
|
|
52
72
|
|
|
53
|
-
|
|
73
|
+
## API
|
|
74
|
+
|
|
75
|
+
### `pwaize(config)`
|
|
54
76
|
|
|
55
|
-
|
|
77
|
+
The package's only runtime export. It bundles, tree-shakes, repeatedly
|
|
78
|
+
minifies, and writes the complete site to `<outDir>/web`.
|
|
56
79
|
|
|
57
|
-
|
|
80
|
+
Values such as titles, descriptions, colors, icons, and metadata are declared
|
|
81
|
+
once. Localizable fields accept either one value or a language record. Lookup
|
|
82
|
+
order is the requested language, `defaultLanguage`, and finally the field's
|
|
83
|
+
empty or default value.
|
|
84
|
+
|
|
85
|
+
`serviceWorker.bypass` accepts regular expressions and glob strings. `*`
|
|
86
|
+
matches within one path segment, `**` crosses path segments, and an absolute
|
|
87
|
+
pattern matches the complete URL.
|
|
88
|
+
|
|
89
|
+
## Language modules
|
|
90
|
+
|
|
91
|
+
TypeScript and JavaScript files under `i18nDir` are individually bundled,
|
|
92
|
+
tree-shaken, and minified to `.js`. Relative imports are bundled, declaration
|
|
93
|
+
files are ignored, and other files are copied.
|
|
58
94
|
|
|
59
95
|
```ts
|
|
60
96
|
// src/client/i18n/en.ts
|
|
@@ -72,12 +108,11 @@ const content = (await import(`/i18n/${language}.js`)).default
|
|
|
72
108
|
document.querySelector('h1')!.textContent = content.title
|
|
73
109
|
```
|
|
74
110
|
|
|
75
|
-
The non-literal import remains dynamic
|
|
111
|
+
The non-literal import remains dynamic. Generated language modules are included
|
|
112
|
+
in the Service Worker precache.
|
|
76
113
|
|
|
77
114
|
## Output
|
|
78
115
|
|
|
79
|
-
`pwaize` writes to `<outDir>/web`:
|
|
80
|
-
|
|
81
116
|
```text
|
|
82
117
|
web/
|
|
83
118
|
├── ServiceWorker
|
|
@@ -92,18 +127,54 @@ web/
|
|
|
92
127
|
└── @sovereignbase/pwa/pwaize-build-id.txt
|
|
93
128
|
```
|
|
94
129
|
|
|
95
|
-
The root installer and manifest
|
|
96
|
-
|
|
97
|
-
The
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
130
|
+
The root installer and manifest use `defaultLanguage`. Each language also gets
|
|
131
|
+
an indexed installer and manifest. Installers contain only the Service Worker
|
|
132
|
+
loader. The Service Worker renders the application document with its localized
|
|
133
|
+
SEO metadata, bundled stylesheet, and bundled entrypoint.
|
|
134
|
+
|
|
135
|
+
## Behavior
|
|
136
|
+
|
|
137
|
+
- JavaScript is bundled and tree-shaken with esbuild, then repeatedly compressed
|
|
138
|
+
and mangled with Terser.
|
|
139
|
+
- CSS is bundled with esbuild and minified with Lightning CSS.
|
|
140
|
+
- HTML and its inline content are emitted as dense strings.
|
|
141
|
+
- Generated and copied files are precached.
|
|
142
|
+
- Precached static URLs remain files when opened directly in the browser; only
|
|
143
|
+
application routes use document rendering.
|
|
144
|
+
- Navigation and static resources use stale-while-revalidate caching.
|
|
145
|
+
- Activation deletes old build caches and claims clients.
|
|
146
|
+
- The worker checks a deterministic content build ID and requests an update when
|
|
147
|
+
deployed content changes.
|
|
148
|
+
- Repeated builds reuse unchanged JavaScript, CSS, and HTML minification results.
|
|
149
|
+
- Generated `_headers` keeps the Service Worker and build ID uncached and gives
|
|
150
|
+
the assets directory a one-year immutable browser cache.
|
|
151
|
+
|
|
152
|
+
## Security headers
|
|
153
|
+
|
|
154
|
+
Generated installers and Service Worker application responses include a
|
|
155
|
+
`Content-Security-Policy`. `script-src` and `style-src` contain SHA-256 hashes
|
|
156
|
+
calculated from the final inline content. They also contain `'unsafe-inline'`
|
|
157
|
+
as a CSP1 fallback; browsers implementing CSP2 or newer ignore that fallback
|
|
158
|
+
when a hash source is present.
|
|
159
|
+
|
|
160
|
+
The policy also restricts base URLs, framing, forms, objects, workers, fonts,
|
|
161
|
+
media, images, and network connections. Generated `_headers` adds
|
|
162
|
+
`X-Content-Type-Options: nosniff`.
|
|
163
|
+
|
|
164
|
+
## Example
|
|
165
|
+
|
|
166
|
+
- Application: [example/entrypoint.js](./example/entrypoint.js)
|
|
167
|
+
- Typed languages: [example/i18n/en.ts](./example/i18n/en.ts) and
|
|
168
|
+
[example/i18n/fi.ts](./example/i18n/fi.ts)
|
|
169
|
+
- Build driver: [test/index.js](./test/index.js)
|
|
170
|
+
|
|
171
|
+
## Tests
|
|
172
|
+
|
|
173
|
+
- Unit and integration tests in Vitest with TypeScript.
|
|
174
|
+
- Browser behavior tests in Playwright with TypeScript.
|
|
175
|
+
- Runtime build tests in Node.js and Bun, including ESM and CJS package wiring.
|
|
176
|
+
- Coverage: 100% statements, branches, functions, and lines.
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
Apache-2.0
|
package/dist/index.cjs
CHANGED
|
@@ -20,11 +20,18 @@ let node_crypto = require("node:crypto");
|
|
|
20
20
|
let node_fs = require("node:fs");
|
|
21
21
|
let node_fs_promises = require("node:fs/promises");
|
|
22
22
|
let node_path = require("node:path");
|
|
23
|
+
let _sovereignbase_bytecodec = require("@sovereignbase/bytecodec");
|
|
23
24
|
let esbuild = require("esbuild");
|
|
24
25
|
let lightningcss = require("lightningcss");
|
|
25
26
|
let html_minifier_terser = require("html-minifier-terser");
|
|
26
27
|
let node_url = require("node:url");
|
|
27
28
|
let terser = require("terser");
|
|
29
|
+
//#region src/cspHash/index.ts
|
|
30
|
+
const cspHash = async (source) => {
|
|
31
|
+
const digest = await crypto.subtle.digest("SHA-256", _sovereignbase_bytecodec.Bytes.fromString(source));
|
|
32
|
+
return `sha256-${_sovereignbase_bytecodec.Bytes.toBase64String(digest)}`;
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
28
35
|
//#region src/minifyCss/index.ts
|
|
29
36
|
const minifiedOutputs$2 = /* @__PURE__ */ new Map();
|
|
30
37
|
/** Bundles and minifies a CSS entrypoint into a dense string. */
|
|
@@ -185,6 +192,7 @@ async function pwaize(config) {
|
|
|
185
192
|
const outputDirectory = (0, node_path.join)(config.outDir.toString(), "web");
|
|
186
193
|
const languages = [.../* @__PURE__ */ new Set([config.defaultLanguage, ...config.alternateLanguages])];
|
|
187
194
|
const minifyPasses = config.minifyPasses ?? 3;
|
|
195
|
+
const buildIdUrl = "/@sovereignbase/pwa/pwaize-build-id.txt";
|
|
188
196
|
const serviceWorkerPath = "/ServiceWorker";
|
|
189
197
|
await (0, node_fs_promises.mkdir)(outputDirectory, { recursive: true });
|
|
190
198
|
if (config.assetsDir !== void 0) {
|
|
@@ -199,6 +207,8 @@ async function pwaize(config) {
|
|
|
199
207
|
const entrypoint = await minifyJs(config.entrypoint, { passes: minifyPasses });
|
|
200
208
|
const installer = await minifyJs({ source: `await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:"/",type:"module"});await navigator.serviceWorker.ready;location.reload();` }, { passes: minifyPasses });
|
|
201
209
|
const documentOptions = {};
|
|
210
|
+
const contentSecurityPolicies = {};
|
|
211
|
+
const installerDocuments = [];
|
|
202
212
|
for (const language of languages) {
|
|
203
213
|
const localized = localizeConfig(config, language, languages);
|
|
204
214
|
const languageDirectory = (0, node_path.join)(outputDirectory, language);
|
|
@@ -213,25 +223,39 @@ async function pwaize(config) {
|
|
|
213
223
|
language,
|
|
214
224
|
manifestUrl: manifestPath
|
|
215
225
|
}));
|
|
226
|
+
contentSecurityPolicies[language] = await contentSecurityPolicy([await require_htmlDocument.documentMarkup({
|
|
227
|
+
...localized.document,
|
|
228
|
+
entrypoint,
|
|
229
|
+
language,
|
|
230
|
+
manifestUrl: manifestPath,
|
|
231
|
+
stylesheet
|
|
232
|
+
})]);
|
|
233
|
+
installerDocuments.push(installerDocument);
|
|
216
234
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(languageDirectory, "index.html"), installerDocument);
|
|
217
235
|
if (language === config.defaultLanguage) {
|
|
218
236
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(outputDirectory, "index.html"), installerDocument);
|
|
219
237
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(outputDirectory, "manifest.webmanifest"), manifest);
|
|
220
238
|
}
|
|
221
239
|
}
|
|
222
|
-
if (config._headersFile === true)
|
|
223
|
-
|
|
240
|
+
if (config._headersFile === true) {
|
|
241
|
+
const installerContentSecurityPolicy = await contentSecurityPolicy(installerDocuments);
|
|
242
|
+
const assetsHeaders = config.assetsDir === void 0 ? "" : `/${(0, node_path.basename)(config.assetsDir.toString())}/*\n Cache-Control: public, max-age=31536000, immutable\n\n`;
|
|
243
|
+
await (0, node_fs_promises.writeFile)((0, node_path.join)(outputDirectory, "_headers"), `/${serviceWorkerPath.slice(1)}\n Cache-Control: no-cache\n Content-Type: text/javascript;charset=UTF-8\n\n${buildIdUrl}\n Cache-Control: no-cache, no-store, must-revalidate\n Content-Type: text/plain;charset=UTF-8\n\n${assetsHeaders}/*\n Content-Security-Policy: ${installerContentSecurityPolicy}\n X-Content-Type-Options: nosniff\n`);
|
|
244
|
+
}
|
|
224
245
|
const generatedFiles = (await publicFiles(outputDirectory)).filter((url) => url !== serviceWorkerPath && url !== buildIdUrl);
|
|
225
246
|
const precache = [.../* @__PURE__ */ new Set([...generatedFiles, ...config.serviceWorker?.precache ?? []])].sort();
|
|
247
|
+
const staticRoutes = [...new Set(precache.map((url) => new URL(url, "https://pwaize.invalid").pathname).filter((url) => !url.endsWith("/index.html") && url !== "/index.html"))].sort();
|
|
226
248
|
const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule);
|
|
227
249
|
const initialize = config.serviceWorker?.initialize === void 0 ? "undefined" : functionExpression(config.serviceWorker.initialize);
|
|
228
250
|
const waitUntil = config.serviceWorker?.waitUntil === void 0 ? "undefined" : functionExpression(config.serviceWorker.waitUntil);
|
|
229
251
|
const buildId = await contentBuildId(outputDirectory, generatedFiles, {
|
|
230
252
|
bypassRules,
|
|
253
|
+
contentSecurityPolicies,
|
|
231
254
|
documentOptions,
|
|
232
255
|
entrypoint,
|
|
233
256
|
initialize,
|
|
234
257
|
precache,
|
|
258
|
+
staticRoutes,
|
|
235
259
|
stylesheet,
|
|
236
260
|
waitUntil
|
|
237
261
|
});
|
|
@@ -251,9 +275,11 @@ async function pwaize(config) {
|
|
|
251
275
|
customInitialize: "__pwaInitialize",
|
|
252
276
|
customWaitUntil: "__pwaWaitUntil",
|
|
253
277
|
defaultLanguage: JSON.stringify(config.defaultLanguage),
|
|
278
|
+
contentSecurityPolicies: JSON.stringify(contentSecurityPolicies),
|
|
254
279
|
documentOptions: JSON.stringify(documentOptions),
|
|
255
280
|
entrypoint: JSON.stringify(entrypoint),
|
|
256
281
|
precache: JSON.stringify(precache),
|
|
282
|
+
staticRoutes: JSON.stringify(staticRoutes),
|
|
257
283
|
stylesheet: JSON.stringify(stylesheet)
|
|
258
284
|
},
|
|
259
285
|
passes: minifyPasses
|
|
@@ -261,6 +287,27 @@ async function pwaize(config) {
|
|
|
261
287
|
);
|
|
262
288
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(outputDirectory, serviceWorkerPath.slice(1)), serviceWorker);
|
|
263
289
|
}
|
|
290
|
+
async function contentSecurityPolicy(documents) {
|
|
291
|
+
const inlineScripts = documents.flatMap((document) => [...document.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script>/gi)].map((match) => match[1]));
|
|
292
|
+
const inlineStyles = documents.flatMap((document) => [...document.matchAll(/<style\b[^>]*>([\s\S]*?)<\/style>/gi)].map((match) => match[1]));
|
|
293
|
+
const hashes = async (sources) => (await Promise.all([...new Set(sources.length === 0 ? [""] : sources)].map(cspHash))).map((hash) => `'${hash}'`).join(" ");
|
|
294
|
+
return [
|
|
295
|
+
`default-src 'self'`,
|
|
296
|
+
`base-uri 'self'`,
|
|
297
|
+
`connect-src 'self' https: wss:`,
|
|
298
|
+
`font-src 'self' data:`,
|
|
299
|
+
`form-action 'self'`,
|
|
300
|
+
`frame-ancestors 'none'`,
|
|
301
|
+
`img-src 'self' data: https:`,
|
|
302
|
+
`manifest-src 'self'`,
|
|
303
|
+
`media-src 'self' data: blob: https:`,
|
|
304
|
+
`object-src 'none'`,
|
|
305
|
+
`script-src 'self' 'unsafe-inline' ${await hashes(inlineScripts)}`,
|
|
306
|
+
`style-src 'self' 'unsafe-inline' ${await hashes(inlineStyles)}`,
|
|
307
|
+
`worker-src 'self' blob:`,
|
|
308
|
+
"upgrade-insecure-requests"
|
|
309
|
+
].join("; ");
|
|
310
|
+
}
|
|
264
311
|
async function buildScriptDirectory(sourceDirectory, outputDirectory, passes, root = sourceDirectory) {
|
|
265
312
|
for (const entry of await (0, node_fs_promises.readdir)(sourceDirectory, { withFileTypes: true })) {
|
|
266
313
|
const source = (0, node_path.join)(sourceDirectory, entry.name);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["minifiedOutputs","build","transform","minifiedOutputs","minify","build","fileURLToPath","minify","join","mkdir","cp","basename","writeFile","documentMarkup","existsSync","readdir","relative","extname","dirname","createHash","readFile","sep"],"sources":["../src/minifyCss/index.ts","../src/minifyHtml/index.ts","../src/minifyJs/index.ts","../src/webManifest/index.ts","../src/index.ts"],"sourcesContent":["import type { PathLike } from 'node:fs'\nimport { build } from 'esbuild'\nimport { transform } from 'lightningcss'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Bundles and minifies a CSS entrypoint into a dense string. */\nexport default async function minifyCss(entrypoint: PathLike): Promise<string> {\n const bundled = await build({\n entryPoints: [entrypoint.toString()],\n bundle: true,\n legalComments: 'none',\n minify: true,\n treeShaking: true,\n write: false,\n external: ['/assets/*'],\n })\n const source = bundled.outputFiles[0].text\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const { code } = transform({\n code: bundled.outputFiles[0].contents,\n filename: entrypoint.toString(),\n minify: true,\n })\n\n const output = new TextDecoder().decode(code).trim()\n minifiedOutputs.set(source, output)\n return output\n}\n","import { minify } from 'html-minifier-terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Minifies a complete HTML document, including inline CSS and JavaScript. */\nexport default async function minifyHtml(source: string): Promise<string> {\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const output = await minify(source, {\n collapseBooleanAttributes: true,\n collapseInlineTagWhitespace: true,\n collapseWhitespace: true,\n decodeEntities: true,\n html5: true,\n minifyCSS: true,\n minifyJS: {\n compress: {\n dead_code: true,\n passes: 3,\n toplevel: true,\n unused: true,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n },\n removeAttributeQuotes: true,\n removeComments: true,\n removeEmptyAttributes: true,\n removeRedundantAttributes: true,\n sortAttributes: true,\n sortClassName: true,\n useShortDoctype: true,\n })\n minifiedOutputs.set(source, output)\n return output\n}\n","import type { PathLike } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { build } from 'esbuild'\nimport { minify } from 'terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\ntype JavaScriptInput = PathLike | { source: string }\n\ntype MinifyJsOptions = {\n banner?: string\n define?: Record<string, string>\n passes?: number\n}\n\n/** Bundles, tree-shakes, mangles, and repeatedly minifies JavaScript. */\nexport default async function minifyJs(\n input: JavaScriptInput,\n { banner, define, passes = 3 }: MinifyJsOptions = {}\n): Promise<string> {\n const bundled = await build({\n ...(typeof input === 'object' && 'source' in input\n ? { stdin: { contents: input.source, resolveDir: process.cwd() } }\n : {\n entryPoints: [\n input instanceof URL ? fileURLToPath(input) : input.toString(),\n ],\n }),\n bundle: true,\n banner: banner === undefined ? undefined : { js: banner },\n define,\n format: 'esm',\n legalComments: 'none',\n minify: true,\n platform: 'browser',\n treeShaking: true,\n write: false,\n })\n\n const output = bundled.outputFiles[0].text\n const cacheKey = `${passes}\\0${output}`\n const cached = minifiedOutputs.get(cacheKey)\n if (cached !== undefined) return cached\n\n const result = await repeatedlyMinify(output, passes)\n minifiedOutputs.set(cacheKey, result)\n return result\n}\n\nasync function repeatedlyMinify(\n source: string,\n passes: number\n): Promise<string> {\n let output = source\n\n for (let round = 0; round < passes; round += 1) {\n const result = await minify(output, {\n compress: {\n dead_code: true,\n passes,\n toplevel: true,\n unused: true,\n },\n ecma: 2024,\n format: {\n beautify: false,\n comments: false,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n })\n\n /* v8 ignore next 3 -- Terser returns code or rejects for this input form. */\n if (result.code === undefined) {\n throw new Error('Terser did not produce JavaScript output')\n }\n\n output = result.code\n }\n\n return output\n}\n","import type { BCP47LanguageTag } from '@sovereignbase/utils'\n\ntype Path = `/${string}`\ntype ImageURL = Path | `https://${string}`\n\nexport interface WebManifestScreenshot {\n src: ImageURL\n sizes: `${number}x${number}`\n type?: `image/${string}`\n form_factor?: 'narrow' | 'wide'\n label?: string\n}\n\nexport interface WebManifestShortcut {\n name: string\n url: Path\n description?: string\n icons?: {\n src: ImageURL\n sizes: `${number}x${number}` | 'any'\n type?: `image/${string}`\n }[]\n}\n\nexport interface WebManifestOptions {\n name: string\n shortName: string\n description: string\n startUrl: Path\n themeColor: string\n icon192: ImageURL\n icon512: ImageURL\n maskableIcon512: ImageURL\n id?: Path\n scope?: Path\n backgroundColor?: string\n lang?: BCP47LanguageTag\n display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser'\n orientation?:\n | 'any'\n | 'natural'\n | 'portrait'\n | 'portrait-primary'\n | 'portrait-secondary'\n | 'landscape'\n | 'landscape-primary'\n | 'landscape-secondary'\n categories?: string[]\n screenshots?: WebManifestScreenshot[]\n shortcuts?: WebManifestShortcut[]\n}\n\n/**\n * Generates a standards-based Web App Manifest JSON string.\n */\nexport const webManifest = ({\n name,\n shortName,\n description,\n startUrl,\n themeColor,\n icon192,\n icon512,\n maskableIcon512,\n id = '/',\n scope = '/',\n backgroundColor = themeColor,\n lang,\n display = 'standalone',\n orientation,\n categories,\n screenshots,\n shortcuts,\n}: WebManifestOptions): string =>\n JSON.stringify({\n id,\n name,\n short_name: shortName,\n description,\n start_url: startUrl,\n scope,\n display,\n theme_color: themeColor,\n background_color: backgroundColor,\n ...(lang ? { lang } : {}),\n ...(orientation ? { orientation } : {}),\n ...(categories?.length ? { categories } : {}),\n ...(screenshots?.length ? { screenshots } : {}),\n ...(shortcuts?.length ? { shortcuts } : {}),\n icons: [\n {\n src: icon192,\n sizes: '192x192',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: icon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: maskableIcon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'maskable',\n },\n ],\n })\n","import { createHash } from 'node:crypto'\nimport { existsSync, type PathLike } from 'node:fs'\nimport { cp, mkdir, readFile, readdir, writeFile } from 'node:fs/promises'\nimport { basename, dirname, extname, join, relative, sep } from 'node:path'\nimport type { BCP47LanguageTag, OpenGraphLocale } from '@sovereignbase/utils'\nimport type {\n DocumentMarkupOptions,\n HTTPSUrl,\n URLPath,\n} from './.types/index.js'\nimport { documentMarkup } from './htmlDocument/index.js'\nimport minifyCss from './minifyCss/index.js'\nimport minifyHtml from './minifyHtml/index.js'\nimport minifyJs from './minifyJs/index.js'\nimport {\n webManifest,\n type WebManifestOptions,\n type WebManifestScreenshot,\n type WebManifestShortcut,\n} from './webManifest/index.js'\n\nexport async function pwaize(config: PWAizeConfig): Promise<void> {\n const outputDirectory = join(config.outDir.toString(), 'web')\n const languages = [\n ...new Set([config.defaultLanguage, ...config.alternateLanguages]),\n ]\n const minifyPasses = config.minifyPasses ?? 3\n const serviceWorkerPath = '/ServiceWorker'\n\n await mkdir(outputDirectory, { recursive: true })\n\n if (config.assetsDir !== undefined) {\n const sourceDirectory = config.assetsDir.toString()\n await cp(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n { recursive: true }\n )\n }\n\n if (config.i18nDir !== undefined) {\n const sourceDirectory = config.i18nDir.toString()\n await buildScriptDirectory(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n minifyPasses\n )\n }\n\n const stylesheet = await minifyCss(config.stylesheet)\n const entrypoint = await minifyJs(config.entrypoint, {\n passes: minifyPasses,\n })\n const installer = await minifyJs(\n {\n source: `await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:\"/\",type:\"module\"});await navigator.serviceWorker.ready;location.reload();`,\n },\n { passes: minifyPasses }\n )\n const documentOptions: Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n > = {}\n\n for (const language of languages) {\n const localized = localizeConfig(config, language, languages)\n const languageDirectory = join(outputDirectory, language)\n const manifestPath = `/${language}/manifest.webmanifest` as const\n const manifest = webManifest(localized.manifest)\n documentOptions[language] = localized.document\n\n await mkdir(languageDirectory, { recursive: true })\n await writeFile(join(languageDirectory, 'manifest.webmanifest'), manifest)\n\n const installerDocument = await minifyHtml(\n await documentMarkup({\n ...localized.document,\n entrypoint: installer,\n language,\n manifestUrl: manifestPath,\n })\n )\n await writeFile(join(languageDirectory, 'index.html'), installerDocument)\n\n if (language === config.defaultLanguage) {\n await writeFile(join(outputDirectory, 'index.html'), installerDocument)\n await writeFile(join(outputDirectory, 'manifest.webmanifest'), manifest)\n }\n }\n\n if (config._headersFile === true) {\n await writeFile(\n join(outputDirectory, '_headers'),\n `/${serviceWorkerPath.slice(1)}\\n Cache-Control: no-cache\\n Content-Type: text/javascript;charset=UTF-8\\n\\n/*\\n X-Content-Type-Options: nosniff\\n`\n )\n }\n\n const buildIdUrl = '/@sovereignbase/pwa/pwaize-build-id.txt'\n const generatedFiles = (await publicFiles(outputDirectory)).filter(\n (url) => url !== serviceWorkerPath && url !== buildIdUrl\n )\n const precache = [\n ...new Set([...generatedFiles, ...(config.serviceWorker?.precache ?? [])]),\n ].sort()\n const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule)\n const initialize =\n config.serviceWorker?.initialize === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.initialize)\n const waitUntil =\n config.serviceWorker?.waitUntil === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.waitUntil)\n const buildId = await contentBuildId(outputDirectory, generatedFiles, {\n bypassRules,\n documentOptions,\n entrypoint,\n initialize,\n precache,\n stylesheet,\n waitUntil,\n })\n const buildIdDirectory = join(outputDirectory, '@sovereignbase', 'pwa')\n await mkdir(buildIdDirectory, { recursive: true })\n await writeFile(join(buildIdDirectory, 'pwaize-build-id.txt'), buildId)\n const compiledServiceWorker = new URL(\n './serviceWorker/entrypoint.js',\n import.meta.url\n )\n const serviceWorker = await minifyJs(\n /* v8 ignore next -- the packaged .js path is exercised by runtime tests */\n existsSync(compiledServiceWorker)\n ? compiledServiceWorker\n : new URL('./serviceWorker/entrypoint.ts', import.meta.url),\n {\n banner: `const __pwaInitialize=${initialize},__pwaWaitUntil=${waitUntil};`,\n define: {\n buildId: JSON.stringify(buildId),\n buildIdUrl: JSON.stringify(buildIdUrl),\n bypassRules: JSON.stringify(bypassRules),\n customInitialize: '__pwaInitialize',\n customWaitUntil: '__pwaWaitUntil',\n defaultLanguage: JSON.stringify(config.defaultLanguage),\n documentOptions: JSON.stringify(documentOptions),\n entrypoint: JSON.stringify(entrypoint),\n precache: JSON.stringify(precache),\n stylesheet: JSON.stringify(stylesheet),\n },\n passes: minifyPasses,\n }\n )\n\n await writeFile(\n join(outputDirectory, serviceWorkerPath.slice(1)),\n serviceWorker\n )\n}\n\nasync function buildScriptDirectory(\n sourceDirectory: string,\n outputDirectory: string,\n passes: number,\n root = sourceDirectory\n): Promise<void> {\n for (const entry of await readdir(sourceDirectory, { withFileTypes: true })) {\n const source = join(sourceDirectory, entry.name)\n if (entry.isDirectory()) {\n await buildScriptDirectory(source, outputDirectory, passes, root)\n continue\n }\n if (!entry.isFile() || entry.name.endsWith('.d.ts')) continue\n\n const relativePath = relative(root, source)\n const extension = extname(relativePath)\n const output = join(\n outputDirectory,\n /\\.[cm]?[jt]sx?$/.test(extension)\n ? `${relativePath.slice(0, -extension.length)}.js`\n : relativePath\n )\n await mkdir(dirname(output), { recursive: true })\n if (/\\.[cm]?[jt]sx?$/.test(extension)) {\n await writeFile(output, await minifyJs(source, { passes }))\n } else {\n await cp(source, output)\n }\n }\n}\n\nasync function contentBuildId(\n outputDirectory: string,\n files: string[],\n configuration: unknown\n): Promise<string> {\n const hash = createHash('sha256')\n hash.update(JSON.stringify(configuration))\n for (const file of files) {\n hash.update(file)\n hash.update(\n await readFile(join(outputDirectory, ...file.slice(1).split('/')))\n )\n }\n return hash.digest('hex')\n}\n\nasync function publicFiles(\n directory: string,\n root = directory\n): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true })\n const files: string[] = []\n\n for (const entry of entries) {\n const path = join(directory, entry.name)\n if (entry.isDirectory()) {\n files.push(...(await publicFiles(path, root)))\n } else if (entry.isFile() && entry.name !== '_headers') {\n files.push(`/${relative(root, path).split(sep).join('/')}`)\n }\n }\n\n return files.sort()\n}\n\nfunction globRule(pattern: string | RegExp): {\n absolute: boolean\n flags: string\n source: string\n} {\n if (pattern instanceof RegExp) {\n return { absolute: true, flags: pattern.flags, source: pattern.source }\n }\n\n let source = '^'\n for (let index = 0; index < pattern.length; index += 1) {\n const character = pattern[index]\n if (character === '*') {\n if (pattern[index + 1] === '*') {\n source += '.*'\n index += 1\n } else {\n source += '[^/]*'\n }\n } else if (character === '?') {\n source += '.'\n } else {\n source += character.replace(/[|\\\\{}()[\\]^$+?.]/g, '\\\\$&')\n }\n }\n\n return {\n absolute: pattern.includes('://'),\n flags: '',\n source: `${source}$`,\n }\n}\n\nfunction functionExpression(\n callback: (...arguments_: never[]) => unknown\n): string {\n const source = callback.toString()\n if (/^(?:async\\s+)?function\\b|^(?:async\\s+)?\\(/.test(source)) {\n return `(${source})`\n }\n if (source.startsWith('async ')) {\n return `(async function ${source.slice('async '.length)})`\n }\n return `(function ${source})`\n}\n\nfunction localizeConfig(\n config: PWAizeConfig,\n language: BCP47LanguageTag,\n languages: BCP47LanguageTag[]\n): {\n document: Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n manifest: WebManifestOptions\n} {\n const get = <T>(value: Localized<T> | undefined, empty: T): T =>\n localizedValue(value, language, config.defaultLanguage, empty)\n const applicationName = get(config.applicationName, '')\n const description = get(config.description, '')\n const icon192 = get<string>(config.icons.icon192, '')\n const icon512 = get<string>(config.icons.icon512, '')\n const origin = get<string>(config.origin, '')\n const pageUrl = (\n origin === '' ? '' : new URL(`/${language}`, origin).href\n ) as HTTPSUrl\n const organizationLogo = (\n origin === '' || icon512 === '' ? '' : new URL(icon512, origin).href\n ) as HTTPSUrl\n const themeColor = get(config.themeColor, '')\n const title = get(config.title, '')\n\n return {\n document: {\n applicationName,\n appleStatusBarStyle: get(config.appleStatusBarStyle, 'black-translucent'),\n appleTouchIconUrl: get(\n config.icons.appleTouchIconUrl,\n icon192 as URLPath\n ),\n bodyMarkup: get(config.bodyMarkup, ''),\n colorScheme: get(config.colorScheme, 'light dark'),\n headMarkup: get(config.headMarkup, ''),\n iconUrl: get(config.icons.iconUrl, icon512 as URLPath),\n maskIconColor: themeColor,\n maskIconUrl: get(config.icons.maskIconUrl, '' as URLPath),\n seo: {\n jsonLD: {\n application: {\n applicationCategory: get(config.application?.category, ''),\n browserRequirements: get(\n config.application?.browserRequirements,\n ''\n ),\n featureList: get(config.application?.featureList, []),\n inLanguage: languages,\n name: applicationName,\n operatingSystem: get(config.application?.operatingSystem, ''),\n url: origin as HTTPSUrl,\n },\n organization: {\n logo: get(config.organization?.logoUrl, organizationLogo),\n name: get(config.organization?.name, applicationName),\n url: get<string>(config.organization?.url, origin) as HTTPSUrl,\n },\n page: {\n description,\n inLanguage: language,\n name: title,\n url: pageUrl,\n },\n site: { name: applicationName, url: origin as HTTPSUrl },\n },\n languageLinks: {\n alternateLanguages: languages,\n canonicalLanguage: config.canonicalLanguage,\n defaultLanguage: config.defaultLanguage,\n host: (origin === ''\n ? ''\n : new URL(origin).host) as `${string}.${string}`,\n },\n openGraph: {\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageHeight: get(config.socialImage.height, 630),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n imageWidth: get(config.socialImage.width, 1200),\n locale: get(config.openGraphLocale, '' as OpenGraphLocale),\n siteName: applicationName,\n title,\n url: pageUrl,\n },\n twitter: {\n creator: get(config.twitter.creator, '' as `@${string}`),\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n site: get(config.twitter.site, '' as `@${string}`),\n title,\n url: pageUrl,\n },\n },\n themeColor,\n title,\n },\n manifest: {\n backgroundColor: get(config.backgroundColor, themeColor),\n categories: get(config.manifest?.categories, []),\n description,\n display: get(config.manifest?.display, 'standalone'),\n icon192: icon192 as URLPath,\n icon512: icon512 as URLPath,\n id: get(config.manifest?.id, '/' as URLPath),\n lang: language,\n maskableIcon512: get(config.icons.maskableIcon512, icon512 as URLPath),\n name: applicationName,\n orientation: get(config.manifest?.orientation, 'any'),\n scope: get(config.manifest?.scope, '/' as URLPath),\n screenshots: get(config.manifest?.screenshots, []),\n shortName: get(config.shortName, applicationName),\n shortcuts: get(config.manifest?.shortcuts, []),\n startUrl: `/${language}`,\n themeColor,\n },\n }\n}\n\nfunction localizedValue<T>(\n value: Localized<T> | undefined,\n language: BCP47LanguageTag,\n defaultLanguage: BCP47LanguageTag,\n empty: T\n): T {\n if (value === undefined) return empty\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return value as T\n }\n\n const values = value as Partial<Record<BCP47LanguageTag, T>>\n return values[language] ?? values[defaultLanguage] ?? empty\n}\n\nexport type Localized<T> = T | Partial<Record<BCP47LanguageTag, T>>\n\nexport type PWAizeConfig = {\n _headersFile?: boolean\n alternateLanguages: BCP47LanguageTag[]\n application?: {\n browserRequirements?: Localized<string>\n category?: Localized<string>\n featureList?: Localized<string[]>\n operatingSystem?: Localized<string>\n }\n applicationName: Localized<string>\n appleStatusBarStyle?: Localized<'black' | 'black-translucent' | 'default'>\n assetsDir?: PathLike\n backgroundColor?: Localized<string>\n bodyMarkup?: Localized<string>\n canonicalLanguage: BCP47LanguageTag\n colorScheme?: Localized<'dark' | 'dark light' | 'light' | 'light dark'>\n defaultLanguage: BCP47LanguageTag\n description: Localized<string>\n entrypoint: PathLike\n headMarkup?: Localized<string>\n i18nDir?: PathLike\n icons: {\n appleTouchIconUrl?: Localized<URLPath>\n icon192: Localized<URLPath>\n icon512: Localized<URLPath>\n iconUrl?: Localized<URLPath>\n maskableIcon512: Localized<URLPath>\n maskIconUrl?: Localized<URLPath>\n }\n manifest?: {\n categories?: Localized<string[]>\n display?: Localized<'browser' | 'fullscreen' | 'minimal-ui' | 'standalone'>\n id?: Localized<URLPath>\n orientation?: Localized<WebManifestOptions['orientation']>\n scope?: Localized<URLPath>\n screenshots?: Localized<WebManifestScreenshot[]>\n shortcuts?: Localized<WebManifestShortcut[]>\n }\n minifyPasses?: number\n openGraphLocale: Localized<OpenGraphLocale>\n organization?: {\n logoUrl?: Localized<HTTPSUrl>\n name?: Localized<string>\n url?: Localized<HTTPSUrl>\n }\n origin: Localized<HTTPSUrl>\n outDir: PathLike\n serviceWorker?: {\n bypass?: Array<string | RegExp>\n initialize?: () => void\n precache?: URLPath[]\n waitUntil?: () => Promise<void>\n }\n shortName?: Localized<string>\n socialImage: {\n alt: Localized<string>\n height?: Localized<number>\n url: Localized<HTTPSUrl>\n width?: Localized<number>\n }\n stylesheet: PathLike\n themeColor: Localized<string>\n title: Localized<string>\n twitter: {\n creator: Localized<`@${string}`>\n site: Localized<`@${string}`>\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Bytes","minifiedOutputs","build","transform","minifiedOutputs","minify","build","fileURLToPath","minify","join","mkdir","cp","basename","writeFile","documentMarkup","existsSync","readdir","relative","extname","dirname","createHash","readFile","sep"],"sources":["../src/cspHash/index.ts","../src/minifyCss/index.ts","../src/minifyHtml/index.ts","../src/minifyJs/index.ts","../src/webManifest/index.ts","../src/index.ts"],"sourcesContent":["import { Bytes } from '@sovereignbase/bytecodec'\n\nexport const cspHash = async (source: string): Promise<`sha256-${string}`> => {\n const digest = await crypto.subtle.digest(\n 'SHA-256',\n Bytes.fromString(source) as BufferSource\n )\n\n return `sha256-${Bytes.toBase64String(digest)}`\n}\n","import type { PathLike } from 'node:fs'\nimport { build } from 'esbuild'\nimport { transform } from 'lightningcss'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Bundles and minifies a CSS entrypoint into a dense string. */\nexport default async function minifyCss(entrypoint: PathLike): Promise<string> {\n const bundled = await build({\n entryPoints: [entrypoint.toString()],\n bundle: true,\n legalComments: 'none',\n minify: true,\n treeShaking: true,\n write: false,\n external: ['/assets/*'],\n })\n const source = bundled.outputFiles[0].text\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const { code } = transform({\n code: bundled.outputFiles[0].contents,\n filename: entrypoint.toString(),\n minify: true,\n })\n\n const output = new TextDecoder().decode(code).trim()\n minifiedOutputs.set(source, output)\n return output\n}\n","import { minify } from 'html-minifier-terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Minifies a complete HTML document, including inline CSS and JavaScript. */\nexport default async function minifyHtml(source: string): Promise<string> {\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const output = await minify(source, {\n collapseBooleanAttributes: true,\n collapseInlineTagWhitespace: true,\n collapseWhitespace: true,\n decodeEntities: true,\n html5: true,\n minifyCSS: true,\n minifyJS: {\n compress: {\n dead_code: true,\n passes: 3,\n toplevel: true,\n unused: true,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n },\n removeAttributeQuotes: true,\n removeComments: true,\n removeEmptyAttributes: true,\n removeRedundantAttributes: true,\n sortAttributes: true,\n sortClassName: true,\n useShortDoctype: true,\n })\n minifiedOutputs.set(source, output)\n return output\n}\n","import type { PathLike } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { build } from 'esbuild'\nimport { minify } from 'terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\ntype JavaScriptInput = PathLike | { source: string }\n\ntype MinifyJsOptions = {\n banner?: string\n define?: Record<string, string>\n passes?: number\n}\n\n/** Bundles, tree-shakes, mangles, and repeatedly minifies JavaScript. */\nexport default async function minifyJs(\n input: JavaScriptInput,\n { banner, define, passes = 3 }: MinifyJsOptions = {}\n): Promise<string> {\n const bundled = await build({\n ...(typeof input === 'object' && 'source' in input\n ? { stdin: { contents: input.source, resolveDir: process.cwd() } }\n : {\n entryPoints: [\n input instanceof URL ? fileURLToPath(input) : input.toString(),\n ],\n }),\n bundle: true,\n banner: banner === undefined ? undefined : { js: banner },\n define,\n format: 'esm',\n legalComments: 'none',\n minify: true,\n platform: 'browser',\n treeShaking: true,\n write: false,\n })\n\n const output = bundled.outputFiles[0].text\n const cacheKey = `${passes}\\0${output}`\n const cached = minifiedOutputs.get(cacheKey)\n if (cached !== undefined) return cached\n\n const result = await repeatedlyMinify(output, passes)\n minifiedOutputs.set(cacheKey, result)\n return result\n}\n\nasync function repeatedlyMinify(\n source: string,\n passes: number\n): Promise<string> {\n let output = source\n\n for (let round = 0; round < passes; round += 1) {\n const result = await minify(output, {\n compress: {\n dead_code: true,\n passes,\n toplevel: true,\n unused: true,\n },\n ecma: 2024,\n format: {\n beautify: false,\n comments: false,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n })\n\n /* v8 ignore next 3 -- Terser returns code or rejects for this input form. */\n if (result.code === undefined) {\n throw new Error('Terser did not produce JavaScript output')\n }\n\n output = result.code\n }\n\n return output\n}\n","import type { BCP47LanguageTag } from '@sovereignbase/utils'\n\ntype Path = `/${string}`\ntype ImageURL = Path | `https://${string}`\n\nexport interface WebManifestScreenshot {\n src: ImageURL\n sizes: `${number}x${number}`\n type?: `image/${string}`\n form_factor?: 'narrow' | 'wide'\n label?: string\n}\n\nexport interface WebManifestShortcut {\n name: string\n url: Path\n description?: string\n icons?: {\n src: ImageURL\n sizes: `${number}x${number}` | 'any'\n type?: `image/${string}`\n }[]\n}\n\nexport interface WebManifestOptions {\n name: string\n shortName: string\n description: string\n startUrl: Path\n themeColor: string\n icon192: ImageURL\n icon512: ImageURL\n maskableIcon512: ImageURL\n id?: Path\n scope?: Path\n backgroundColor?: string\n lang?: BCP47LanguageTag\n display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser'\n orientation?:\n | 'any'\n | 'natural'\n | 'portrait'\n | 'portrait-primary'\n | 'portrait-secondary'\n | 'landscape'\n | 'landscape-primary'\n | 'landscape-secondary'\n categories?: string[]\n screenshots?: WebManifestScreenshot[]\n shortcuts?: WebManifestShortcut[]\n}\n\n/**\n * Generates a standards-based Web App Manifest JSON string.\n */\nexport const webManifest = ({\n name,\n shortName,\n description,\n startUrl,\n themeColor,\n icon192,\n icon512,\n maskableIcon512,\n id = '/',\n scope = '/',\n backgroundColor = themeColor,\n lang,\n display = 'standalone',\n orientation,\n categories,\n screenshots,\n shortcuts,\n}: WebManifestOptions): string =>\n JSON.stringify({\n id,\n name,\n short_name: shortName,\n description,\n start_url: startUrl,\n scope,\n display,\n theme_color: themeColor,\n background_color: backgroundColor,\n ...(lang ? { lang } : {}),\n ...(orientation ? { orientation } : {}),\n ...(categories?.length ? { categories } : {}),\n ...(screenshots?.length ? { screenshots } : {}),\n ...(shortcuts?.length ? { shortcuts } : {}),\n icons: [\n {\n src: icon192,\n sizes: '192x192',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: icon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: maskableIcon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'maskable',\n },\n ],\n })\n","import { createHash } from 'node:crypto'\nimport { existsSync, type PathLike } from 'node:fs'\nimport { cp, mkdir, readFile, readdir, writeFile } from 'node:fs/promises'\nimport { basename, dirname, extname, join, relative, sep } from 'node:path'\nimport type { BCP47LanguageTag, OpenGraphLocale } from '@sovereignbase/utils'\nimport type {\n DocumentMarkupOptions,\n HTTPSUrl,\n URLPath,\n} from './.types/index.js'\nimport { cspHash } from './cspHash/index.js'\nimport { documentMarkup } from './htmlDocument/index.js'\nimport minifyCss from './minifyCss/index.js'\nimport minifyHtml from './minifyHtml/index.js'\nimport minifyJs from './minifyJs/index.js'\nimport {\n webManifest,\n type WebManifestOptions,\n type WebManifestScreenshot,\n type WebManifestShortcut,\n} from './webManifest/index.js'\n\nexport async function pwaize(config: PWAizeConfig): Promise<void> {\n const outputDirectory = join(config.outDir.toString(), 'web')\n const languages = [\n ...new Set([config.defaultLanguage, ...config.alternateLanguages]),\n ]\n const minifyPasses = config.minifyPasses ?? 3\n const buildIdUrl = '/@sovereignbase/pwa/pwaize-build-id.txt'\n const serviceWorkerPath = '/ServiceWorker'\n\n await mkdir(outputDirectory, { recursive: true })\n\n if (config.assetsDir !== undefined) {\n const sourceDirectory = config.assetsDir.toString()\n await cp(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n { recursive: true }\n )\n }\n\n if (config.i18nDir !== undefined) {\n const sourceDirectory = config.i18nDir.toString()\n await buildScriptDirectory(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n minifyPasses\n )\n }\n\n const stylesheet = await minifyCss(config.stylesheet)\n const entrypoint = await minifyJs(config.entrypoint, {\n passes: minifyPasses,\n })\n const installer = await minifyJs(\n {\n source: `await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:\"/\",type:\"module\"});await navigator.serviceWorker.ready;location.reload();`,\n },\n { passes: minifyPasses }\n )\n const documentOptions: Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n > = {}\n const contentSecurityPolicies: Record<string, string> = {}\n const installerDocuments: string[] = []\n\n for (const language of languages) {\n const localized = localizeConfig(config, language, languages)\n const languageDirectory = join(outputDirectory, language)\n const manifestPath = `/${language}/manifest.webmanifest` as const\n const manifest = webManifest(localized.manifest)\n documentOptions[language] = localized.document\n\n await mkdir(languageDirectory, { recursive: true })\n await writeFile(join(languageDirectory, 'manifest.webmanifest'), manifest)\n\n const installerDocument = await minifyHtml(\n await documentMarkup({\n ...localized.document,\n entrypoint: installer,\n language,\n manifestUrl: manifestPath,\n })\n )\n const applicationDocument = await documentMarkup({\n ...localized.document,\n entrypoint,\n language,\n manifestUrl: manifestPath,\n stylesheet,\n })\n contentSecurityPolicies[language] = await contentSecurityPolicy([\n applicationDocument,\n ])\n installerDocuments.push(installerDocument)\n await writeFile(join(languageDirectory, 'index.html'), installerDocument)\n\n if (language === config.defaultLanguage) {\n await writeFile(join(outputDirectory, 'index.html'), installerDocument)\n await writeFile(join(outputDirectory, 'manifest.webmanifest'), manifest)\n }\n }\n\n if (config._headersFile === true) {\n const installerContentSecurityPolicy =\n await contentSecurityPolicy(installerDocuments)\n const assetsHeaders =\n config.assetsDir === undefined\n ? ''\n : `/${basename(config.assetsDir.toString())}/*\\n Cache-Control: public, max-age=31536000, immutable\\n\\n`\n await writeFile(\n join(outputDirectory, '_headers'),\n `/${serviceWorkerPath.slice(1)}\\n Cache-Control: no-cache\\n Content-Type: text/javascript;charset=UTF-8\\n\\n${buildIdUrl}\\n Cache-Control: no-cache, no-store, must-revalidate\\n Content-Type: text/plain;charset=UTF-8\\n\\n${assetsHeaders}/*\\n Content-Security-Policy: ${installerContentSecurityPolicy}\\n X-Content-Type-Options: nosniff\\n`\n )\n }\n\n const generatedFiles = (await publicFiles(outputDirectory)).filter(\n (url) => url !== serviceWorkerPath && url !== buildIdUrl\n )\n const precache = [\n ...new Set([...generatedFiles, ...(config.serviceWorker?.precache ?? [])]),\n ].sort()\n const staticRoutes = [\n ...new Set(\n precache\n .map((url) => new URL(url, 'https://pwaize.invalid').pathname)\n .filter((url) => !url.endsWith('/index.html') && url !== '/index.html')\n ),\n ].sort()\n const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule)\n const initialize =\n config.serviceWorker?.initialize === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.initialize)\n const waitUntil =\n config.serviceWorker?.waitUntil === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.waitUntil)\n const buildId = await contentBuildId(outputDirectory, generatedFiles, {\n bypassRules,\n contentSecurityPolicies,\n documentOptions,\n entrypoint,\n initialize,\n precache,\n staticRoutes,\n stylesheet,\n waitUntil,\n })\n const buildIdDirectory = join(outputDirectory, '@sovereignbase', 'pwa')\n await mkdir(buildIdDirectory, { recursive: true })\n await writeFile(join(buildIdDirectory, 'pwaize-build-id.txt'), buildId)\n const compiledServiceWorker = new URL(\n './serviceWorker/entrypoint.js',\n import.meta.url\n )\n const serviceWorker = await minifyJs(\n /* v8 ignore next -- the packaged .js path is exercised by runtime tests */\n existsSync(compiledServiceWorker)\n ? compiledServiceWorker\n : new URL('./serviceWorker/entrypoint.ts', import.meta.url),\n {\n banner: `const __pwaInitialize=${initialize},__pwaWaitUntil=${waitUntil};`,\n define: {\n buildId: JSON.stringify(buildId),\n buildIdUrl: JSON.stringify(buildIdUrl),\n bypassRules: JSON.stringify(bypassRules),\n customInitialize: '__pwaInitialize',\n customWaitUntil: '__pwaWaitUntil',\n defaultLanguage: JSON.stringify(config.defaultLanguage),\n contentSecurityPolicies: JSON.stringify(contentSecurityPolicies),\n documentOptions: JSON.stringify(documentOptions),\n entrypoint: JSON.stringify(entrypoint),\n precache: JSON.stringify(precache),\n staticRoutes: JSON.stringify(staticRoutes),\n stylesheet: JSON.stringify(stylesheet),\n },\n passes: minifyPasses,\n }\n )\n\n await writeFile(\n join(outputDirectory, serviceWorkerPath.slice(1)),\n serviceWorker\n )\n}\n\nasync function contentSecurityPolicy(documents: string[]): Promise<string> {\n const inlineScripts = documents.flatMap((document) =>\n [...document.matchAll(/<script\\b[^>]*>([\\s\\S]*?)<\\/script>/gi)].map(\n (match) => match[1]\n )\n )\n const inlineStyles = documents.flatMap((document) =>\n [...document.matchAll(/<style\\b[^>]*>([\\s\\S]*?)<\\/style>/gi)].map(\n (match) => match[1]\n )\n )\n const hashes = async (sources: string[]): Promise<string> =>\n (\n await Promise.all(\n [...new Set(sources.length === 0 ? [''] : sources)].map(cspHash)\n )\n )\n .map((hash) => `'${hash}'`)\n .join(' ')\n\n return [\n `default-src 'self'`,\n `base-uri 'self'`,\n `connect-src 'self' https: wss:`,\n `font-src 'self' data:`,\n `form-action 'self'`,\n `frame-ancestors 'none'`,\n `img-src 'self' data: https:`,\n `manifest-src 'self'`,\n `media-src 'self' data: blob: https:`,\n `object-src 'none'`,\n `script-src 'self' 'unsafe-inline' ${await hashes(inlineScripts)}`,\n `style-src 'self' 'unsafe-inline' ${await hashes(inlineStyles)}`,\n `worker-src 'self' blob:`,\n 'upgrade-insecure-requests',\n ].join('; ')\n}\n\nasync function buildScriptDirectory(\n sourceDirectory: string,\n outputDirectory: string,\n passes: number,\n root = sourceDirectory\n): Promise<void> {\n for (const entry of await readdir(sourceDirectory, { withFileTypes: true })) {\n const source = join(sourceDirectory, entry.name)\n if (entry.isDirectory()) {\n await buildScriptDirectory(source, outputDirectory, passes, root)\n continue\n }\n if (!entry.isFile() || entry.name.endsWith('.d.ts')) continue\n\n const relativePath = relative(root, source)\n const extension = extname(relativePath)\n const output = join(\n outputDirectory,\n /\\.[cm]?[jt]sx?$/.test(extension)\n ? `${relativePath.slice(0, -extension.length)}.js`\n : relativePath\n )\n await mkdir(dirname(output), { recursive: true })\n if (/\\.[cm]?[jt]sx?$/.test(extension)) {\n await writeFile(output, await minifyJs(source, { passes }))\n } else {\n await cp(source, output)\n }\n }\n}\n\nasync function contentBuildId(\n outputDirectory: string,\n files: string[],\n configuration: unknown\n): Promise<string> {\n const hash = createHash('sha256')\n hash.update(JSON.stringify(configuration))\n for (const file of files) {\n hash.update(file)\n hash.update(\n await readFile(join(outputDirectory, ...file.slice(1).split('/')))\n )\n }\n return hash.digest('hex')\n}\n\nasync function publicFiles(\n directory: string,\n root = directory\n): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true })\n const files: string[] = []\n\n for (const entry of entries) {\n const path = join(directory, entry.name)\n if (entry.isDirectory()) {\n files.push(...(await publicFiles(path, root)))\n } else if (entry.isFile() && entry.name !== '_headers') {\n files.push(`/${relative(root, path).split(sep).join('/')}`)\n }\n }\n\n return files.sort()\n}\n\nfunction globRule(pattern: string | RegExp): {\n absolute: boolean\n flags: string\n source: string\n} {\n if (pattern instanceof RegExp) {\n return { absolute: true, flags: pattern.flags, source: pattern.source }\n }\n\n let source = '^'\n for (let index = 0; index < pattern.length; index += 1) {\n const character = pattern[index]\n if (character === '*') {\n if (pattern[index + 1] === '*') {\n source += '.*'\n index += 1\n } else {\n source += '[^/]*'\n }\n } else if (character === '?') {\n source += '.'\n } else {\n source += character.replace(/[|\\\\{}()[\\]^$+?.]/g, '\\\\$&')\n }\n }\n\n return {\n absolute: pattern.includes('://'),\n flags: '',\n source: `${source}$`,\n }\n}\n\nfunction functionExpression(\n callback: (...arguments_: never[]) => unknown\n): string {\n const source = callback.toString()\n if (/^(?:async\\s+)?function\\b|^(?:async\\s+)?\\(/.test(source)) {\n return `(${source})`\n }\n if (source.startsWith('async ')) {\n return `(async function ${source.slice('async '.length)})`\n }\n return `(function ${source})`\n}\n\nfunction localizeConfig(\n config: PWAizeConfig,\n language: BCP47LanguageTag,\n languages: BCP47LanguageTag[]\n): {\n document: Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n manifest: WebManifestOptions\n} {\n const get = <T>(value: Localized<T> | undefined, empty: T): T =>\n localizedValue(value, language, config.defaultLanguage, empty)\n const applicationName = get(config.applicationName, '')\n const description = get(config.description, '')\n const icon192 = get<string>(config.icons.icon192, '')\n const icon512 = get<string>(config.icons.icon512, '')\n const origin = get<string>(config.origin, '')\n const pageUrl = (\n origin === '' ? '' : new URL(`/${language}`, origin).href\n ) as HTTPSUrl\n const organizationLogo = (\n origin === '' || icon512 === '' ? '' : new URL(icon512, origin).href\n ) as HTTPSUrl\n const themeColor = get(config.themeColor, '')\n const title = get(config.title, '')\n\n return {\n document: {\n applicationName,\n appleStatusBarStyle: get(config.appleStatusBarStyle, 'black-translucent'),\n appleTouchIconUrl: get(\n config.icons.appleTouchIconUrl,\n icon192 as URLPath\n ),\n bodyMarkup: get(config.bodyMarkup, ''),\n colorScheme: get(config.colorScheme, 'light dark'),\n headMarkup: get(config.headMarkup, ''),\n iconUrl: get(config.icons.iconUrl, icon512 as URLPath),\n maskIconColor: themeColor,\n maskIconUrl: get(config.icons.maskIconUrl, '' as URLPath),\n seo: {\n jsonLD: {\n application: {\n applicationCategory: get(config.application?.category, ''),\n browserRequirements: get(\n config.application?.browserRequirements,\n ''\n ),\n featureList: get(config.application?.featureList, []),\n inLanguage: languages,\n name: applicationName,\n operatingSystem: get(config.application?.operatingSystem, ''),\n url: origin as HTTPSUrl,\n },\n organization: {\n logo: get(config.organization?.logoUrl, organizationLogo),\n name: get(config.organization?.name, applicationName),\n url: get<string>(config.organization?.url, origin) as HTTPSUrl,\n },\n page: {\n description,\n inLanguage: language,\n name: title,\n url: pageUrl,\n },\n site: { name: applicationName, url: origin as HTTPSUrl },\n },\n languageLinks: {\n alternateLanguages: languages,\n canonicalLanguage: config.canonicalLanguage,\n defaultLanguage: config.defaultLanguage,\n host: (origin === ''\n ? ''\n : new URL(origin).host) as `${string}.${string}`,\n },\n openGraph: {\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageHeight: get(config.socialImage.height, 630),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n imageWidth: get(config.socialImage.width, 1200),\n locale: get(config.openGraphLocale, '' as OpenGraphLocale),\n siteName: applicationName,\n title,\n url: pageUrl,\n },\n twitter: {\n creator: get(config.twitter.creator, '' as `@${string}`),\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n site: get(config.twitter.site, '' as `@${string}`),\n title,\n url: pageUrl,\n },\n },\n themeColor,\n title,\n },\n manifest: {\n backgroundColor: get(config.backgroundColor, themeColor),\n categories: get(config.manifest?.categories, []),\n description,\n display: get(config.manifest?.display, 'standalone'),\n icon192: icon192 as URLPath,\n icon512: icon512 as URLPath,\n id: get(config.manifest?.id, '/' as URLPath),\n lang: language,\n maskableIcon512: get(config.icons.maskableIcon512, icon512 as URLPath),\n name: applicationName,\n orientation: get(config.manifest?.orientation, 'any'),\n scope: get(config.manifest?.scope, '/' as URLPath),\n screenshots: get(config.manifest?.screenshots, []),\n shortName: get(config.shortName, applicationName),\n shortcuts: get(config.manifest?.shortcuts, []),\n startUrl: `/${language}`,\n themeColor,\n },\n }\n}\n\nfunction localizedValue<T>(\n value: Localized<T> | undefined,\n language: BCP47LanguageTag,\n defaultLanguage: BCP47LanguageTag,\n empty: T\n): T {\n if (value === undefined) return empty\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return value as T\n }\n\n const values = value as Partial<Record<BCP47LanguageTag, T>>\n return values[language] ?? values[defaultLanguage] ?? empty\n}\n\nexport type Localized<T> = T | Partial<Record<BCP47LanguageTag, T>>\n\nexport type PWAizeConfig = {\n _headersFile?: boolean\n alternateLanguages: BCP47LanguageTag[]\n application?: {\n browserRequirements?: Localized<string>\n category?: Localized<string>\n featureList?: Localized<string[]>\n operatingSystem?: Localized<string>\n }\n applicationName: Localized<string>\n appleStatusBarStyle?: Localized<'black' | 'black-translucent' | 'default'>\n assetsDir?: PathLike\n backgroundColor?: Localized<string>\n bodyMarkup?: Localized<string>\n canonicalLanguage: BCP47LanguageTag\n colorScheme?: Localized<'dark' | 'dark light' | 'light' | 'light dark'>\n defaultLanguage: BCP47LanguageTag\n description: Localized<string>\n entrypoint: PathLike\n headMarkup?: Localized<string>\n i18nDir?: PathLike\n icons: {\n appleTouchIconUrl?: Localized<URLPath>\n icon192: Localized<URLPath>\n icon512: Localized<URLPath>\n iconUrl?: Localized<URLPath>\n maskableIcon512: Localized<URLPath>\n maskIconUrl?: Localized<URLPath>\n }\n manifest?: {\n categories?: Localized<string[]>\n display?: Localized<'browser' | 'fullscreen' | 'minimal-ui' | 'standalone'>\n id?: Localized<URLPath>\n orientation?: Localized<WebManifestOptions['orientation']>\n scope?: Localized<URLPath>\n screenshots?: Localized<WebManifestScreenshot[]>\n shortcuts?: Localized<WebManifestShortcut[]>\n }\n minifyPasses?: number\n openGraphLocale: Localized<OpenGraphLocale>\n organization?: {\n logoUrl?: Localized<HTTPSUrl>\n name?: Localized<string>\n url?: Localized<HTTPSUrl>\n }\n origin: Localized<HTTPSUrl>\n outDir: PathLike\n serviceWorker?: {\n bypass?: Array<string | RegExp>\n initialize?: () => void\n precache?: URLPath[]\n waitUntil?: () => Promise<void>\n }\n shortName?: Localized<string>\n socialImage: {\n alt: Localized<string>\n height?: Localized<number>\n url: Localized<HTTPSUrl>\n width?: Localized<number>\n }\n stylesheet: PathLike\n themeColor: Localized<string>\n title: Localized<string>\n twitter: {\n creator: Localized<`@${string}`>\n site: Localized<`@${string}`>\n }\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/.types/index.ts","../src/webManifest/index.ts","../src/index.ts"],"mappings":";;;;KAEY;KACA;;;KCDP;KACA,WAAW;UAEC;EACf,KAAK;EACL;EACA;EACA;EACA;;UAGe;EACf;EACA,KAAK;EACL;EACA;IACE,KAAK;IACL;IACA;;;UAIa;EACf;EACA;EACA;EACA,UAAU;EACV;EACA,SAAS;EACT,SAAS;EACT,iBAAiB;EACjB,KAAK;EACL,QAAQ;EACR;EACA,OAAO;EACP;EACA;EASA;EACA,cAAc;EACd,YAAY;;;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/.types/index.ts","../src/webManifest/index.ts","../src/index.ts"],"mappings":";;;;KAEY;KACA;;;KCDP;KACA,WAAW;UAEC;EACf,KAAK;EACL;EACA;EACA;EACA;;UAGe;EACf;EACA,KAAK;EACL;EACA;IACE,KAAK;IACL;IACA;;;UAIa;EACf;EACA;EACA;EACA,UAAU;EACV;EACA,SAAS;EACT,SAAS;EACT,iBAAiB;EACjB,KAAK;EACL,QAAQ;EACR;EACA,OAAO;EACP;EACA;EASA;EACA,cAAc;EACd,YAAY;;;;iBC3BQ,OAAO,QAAQ,eAAe;KAycxC,UAAU,KAAK,IAAI,QAAQ,OAAO,kBAAkB;KAEpD;EACV;EACA,oBAAoB;EACpB;IACE,sBAAsB;IACtB,WAAW;IACX,cAAc;IACd,kBAAkB;;EAEpB,iBAAiB;EACjB,sBAAsB;EACtB,YAAY;EACZ,kBAAkB;EAClB,aAAa;EACb,mBAAmB;EACnB,cAAc;EACd,iBAAiB;EACjB,aAAa;EACb,YAAY;EACZ,aAAa;EACb,UAAU;EACV;IACE,oBAAoB,UAAU;IAC9B,SAAS,UAAU;IACnB,SAAS,UAAU;IACnB,UAAU,UAAU;IACpB,iBAAiB,UAAU;IAC3B,cAAc,UAAU;;EAE1B;IACE,aAAa;IACb,UAAU;IACV,KAAK,UAAU;IACf,cAAc,UAAU;IACxB,QAAQ,UAAU;IAClB,cAAc,UAAU;IACxB,YAAY,UAAU;;EAExB;EACA,iBAAiB,UAAU;EAC3B;IACE,UAAU,UAAU;IACpB,OAAO;IACP,MAAM,UAAU;;EAElB,QAAQ,UAAU;EAClB,QAAQ;EACR;IACE,SAAS,eAAe;IACxB;IACA,WAAW;IACX,kBAAkB;;EAEpB,YAAY;EACZ;IACE,KAAK;IACL,SAAS;IACT,KAAK,UAAU;IACf,QAAQ;;EAEV,YAAY;EACZ,YAAY;EACZ,OAAO;EACP;IACE,SAAS;IACT,MAAM"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/.types/index.ts","../src/webManifest/index.ts","../src/index.ts"],"mappings":";;;;KAEY;KACA;;;KCDP;KACA,WAAW;UAEC;EACf,KAAK;EACL;EACA;EACA;EACA;;UAGe;EACf;EACA,KAAK;EACL;EACA;IACE,KAAK;IACL;IACA;;;UAIa;EACf;EACA;EACA;EACA,UAAU;EACV;EACA,SAAS;EACT,SAAS;EACT,iBAAiB;EACjB,KAAK;EACL,QAAQ;EACR;EACA,OAAO;EACP;EACA;EASA;EACA,cAAc;EACd,YAAY;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/.types/index.ts","../src/webManifest/index.ts","../src/index.ts"],"mappings":";;;;KAEY;KACA;;;KCDP;KACA,WAAW;UAEC;EACf,KAAK;EACL;EACA;EACA;EACA;;UAGe;EACf;EACA,KAAK;EACL;EACA;IACE,KAAK;IACL;IACA;;;UAIa;EACf;EACA;EACA;EACA,UAAU;EACV;EACA,SAAS;EACT,SAAS;EACT,iBAAiB;EACjB,KAAK;EACL,QAAQ;EACR;EACA,OAAO;EACP;EACA;EASA;EACA,cAAc;EACd,YAAY;;;;iBC3BQ,OAAO,QAAQ,eAAe;KAycxC,UAAU,KAAK,IAAI,QAAQ,OAAO,kBAAkB;KAEpD;EACV;EACA,oBAAoB;EACpB;IACE,sBAAsB;IACtB,WAAW;IACX,cAAc;IACd,kBAAkB;;EAEpB,iBAAiB;EACjB,sBAAsB;EACtB,YAAY;EACZ,kBAAkB;EAClB,aAAa;EACb,mBAAmB;EACnB,cAAc;EACd,iBAAiB;EACjB,aAAa;EACb,YAAY;EACZ,aAAa;EACb,UAAU;EACV;IACE,oBAAoB,UAAU;IAC9B,SAAS,UAAU;IACnB,SAAS,UAAU;IACnB,UAAU,UAAU;IACpB,iBAAiB,UAAU;IAC3B,cAAc,UAAU;;EAE1B;IACE,aAAa;IACb,UAAU;IACV,KAAK,UAAU;IACf,cAAc,UAAU;IACxB,QAAQ,UAAU;IAClB,cAAc,UAAU;IACxB,YAAY,UAAU;;EAExB;EACA,iBAAiB,UAAU;EAC3B;IACE,UAAU,UAAU;IACpB,OAAO;IACP,MAAM,UAAU;;EAElB,QAAQ,UAAU;EAClB,QAAQ;EACR;IACE,SAAS,eAAe;IACxB;IACA,WAAW;IACX,kBAAkB;;EAEpB,YAAY;EACZ;IACE,KAAK;IACL,SAAS;IACT,KAAK,UAAU;IACf,QAAQ;;EAEV,YAAY;EACZ,YAAY;EACZ,OAAO;EACP;IACE,SAAS;IACT,MAAM"}
|
package/dist/index.js
CHANGED
|
@@ -19,11 +19,18 @@ import { createHash } from "node:crypto";
|
|
|
19
19
|
import { existsSync } from "node:fs";
|
|
20
20
|
import { cp, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
21
21
|
import { basename, dirname, extname, join, relative, sep } from "node:path";
|
|
22
|
+
import { Bytes } from "@sovereignbase/bytecodec";
|
|
22
23
|
import { build } from "esbuild";
|
|
23
24
|
import { transform } from "lightningcss";
|
|
24
25
|
import { minify } from "html-minifier-terser";
|
|
25
26
|
import { fileURLToPath } from "node:url";
|
|
26
27
|
import { minify as minify$1 } from "terser";
|
|
28
|
+
//#region src/cspHash/index.ts
|
|
29
|
+
const cspHash = async (source) => {
|
|
30
|
+
const digest = await crypto.subtle.digest("SHA-256", Bytes.fromString(source));
|
|
31
|
+
return `sha256-${Bytes.toBase64String(digest)}`;
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
27
34
|
//#region src/minifyCss/index.ts
|
|
28
35
|
const minifiedOutputs$2 = /* @__PURE__ */ new Map();
|
|
29
36
|
/** Bundles and minifies a CSS entrypoint into a dense string. */
|
|
@@ -184,6 +191,7 @@ async function pwaize(config) {
|
|
|
184
191
|
const outputDirectory = join(config.outDir.toString(), "web");
|
|
185
192
|
const languages = [.../* @__PURE__ */ new Set([config.defaultLanguage, ...config.alternateLanguages])];
|
|
186
193
|
const minifyPasses = config.minifyPasses ?? 3;
|
|
194
|
+
const buildIdUrl = "/@sovereignbase/pwa/pwaize-build-id.txt";
|
|
187
195
|
const serviceWorkerPath = "/ServiceWorker";
|
|
188
196
|
await mkdir(outputDirectory, { recursive: true });
|
|
189
197
|
if (config.assetsDir !== void 0) {
|
|
@@ -198,6 +206,8 @@ async function pwaize(config) {
|
|
|
198
206
|
const entrypoint = await minifyJs(config.entrypoint, { passes: minifyPasses });
|
|
199
207
|
const installer = await minifyJs({ source: `await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:"/",type:"module"});await navigator.serviceWorker.ready;location.reload();` }, { passes: minifyPasses });
|
|
200
208
|
const documentOptions = {};
|
|
209
|
+
const contentSecurityPolicies = {};
|
|
210
|
+
const installerDocuments = [];
|
|
201
211
|
for (const language of languages) {
|
|
202
212
|
const localized = localizeConfig(config, language, languages);
|
|
203
213
|
const languageDirectory = join(outputDirectory, language);
|
|
@@ -212,25 +222,39 @@ async function pwaize(config) {
|
|
|
212
222
|
language,
|
|
213
223
|
manifestUrl: manifestPath
|
|
214
224
|
}));
|
|
225
|
+
contentSecurityPolicies[language] = await contentSecurityPolicy([await documentMarkup({
|
|
226
|
+
...localized.document,
|
|
227
|
+
entrypoint,
|
|
228
|
+
language,
|
|
229
|
+
manifestUrl: manifestPath,
|
|
230
|
+
stylesheet
|
|
231
|
+
})]);
|
|
232
|
+
installerDocuments.push(installerDocument);
|
|
215
233
|
await writeFile(join(languageDirectory, "index.html"), installerDocument);
|
|
216
234
|
if (language === config.defaultLanguage) {
|
|
217
235
|
await writeFile(join(outputDirectory, "index.html"), installerDocument);
|
|
218
236
|
await writeFile(join(outputDirectory, "manifest.webmanifest"), manifest);
|
|
219
237
|
}
|
|
220
238
|
}
|
|
221
|
-
if (config._headersFile === true)
|
|
222
|
-
|
|
239
|
+
if (config._headersFile === true) {
|
|
240
|
+
const installerContentSecurityPolicy = await contentSecurityPolicy(installerDocuments);
|
|
241
|
+
const assetsHeaders = config.assetsDir === void 0 ? "" : `/${basename(config.assetsDir.toString())}/*\n Cache-Control: public, max-age=31536000, immutable\n\n`;
|
|
242
|
+
await writeFile(join(outputDirectory, "_headers"), `/${serviceWorkerPath.slice(1)}\n Cache-Control: no-cache\n Content-Type: text/javascript;charset=UTF-8\n\n${buildIdUrl}\n Cache-Control: no-cache, no-store, must-revalidate\n Content-Type: text/plain;charset=UTF-8\n\n${assetsHeaders}/*\n Content-Security-Policy: ${installerContentSecurityPolicy}\n X-Content-Type-Options: nosniff\n`);
|
|
243
|
+
}
|
|
223
244
|
const generatedFiles = (await publicFiles(outputDirectory)).filter((url) => url !== serviceWorkerPath && url !== buildIdUrl);
|
|
224
245
|
const precache = [.../* @__PURE__ */ new Set([...generatedFiles, ...config.serviceWorker?.precache ?? []])].sort();
|
|
246
|
+
const staticRoutes = [...new Set(precache.map((url) => new URL(url, "https://pwaize.invalid").pathname).filter((url) => !url.endsWith("/index.html") && url !== "/index.html"))].sort();
|
|
225
247
|
const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule);
|
|
226
248
|
const initialize = config.serviceWorker?.initialize === void 0 ? "undefined" : functionExpression(config.serviceWorker.initialize);
|
|
227
249
|
const waitUntil = config.serviceWorker?.waitUntil === void 0 ? "undefined" : functionExpression(config.serviceWorker.waitUntil);
|
|
228
250
|
const buildId = await contentBuildId(outputDirectory, generatedFiles, {
|
|
229
251
|
bypassRules,
|
|
252
|
+
contentSecurityPolicies,
|
|
230
253
|
documentOptions,
|
|
231
254
|
entrypoint,
|
|
232
255
|
initialize,
|
|
233
256
|
precache,
|
|
257
|
+
staticRoutes,
|
|
234
258
|
stylesheet,
|
|
235
259
|
waitUntil
|
|
236
260
|
});
|
|
@@ -250,9 +274,11 @@ async function pwaize(config) {
|
|
|
250
274
|
customInitialize: "__pwaInitialize",
|
|
251
275
|
customWaitUntil: "__pwaWaitUntil",
|
|
252
276
|
defaultLanguage: JSON.stringify(config.defaultLanguage),
|
|
277
|
+
contentSecurityPolicies: JSON.stringify(contentSecurityPolicies),
|
|
253
278
|
documentOptions: JSON.stringify(documentOptions),
|
|
254
279
|
entrypoint: JSON.stringify(entrypoint),
|
|
255
280
|
precache: JSON.stringify(precache),
|
|
281
|
+
staticRoutes: JSON.stringify(staticRoutes),
|
|
256
282
|
stylesheet: JSON.stringify(stylesheet)
|
|
257
283
|
},
|
|
258
284
|
passes: minifyPasses
|
|
@@ -260,6 +286,27 @@ async function pwaize(config) {
|
|
|
260
286
|
);
|
|
261
287
|
await writeFile(join(outputDirectory, serviceWorkerPath.slice(1)), serviceWorker);
|
|
262
288
|
}
|
|
289
|
+
async function contentSecurityPolicy(documents) {
|
|
290
|
+
const inlineScripts = documents.flatMap((document) => [...document.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script>/gi)].map((match) => match[1]));
|
|
291
|
+
const inlineStyles = documents.flatMap((document) => [...document.matchAll(/<style\b[^>]*>([\s\S]*?)<\/style>/gi)].map((match) => match[1]));
|
|
292
|
+
const hashes = async (sources) => (await Promise.all([...new Set(sources.length === 0 ? [""] : sources)].map(cspHash))).map((hash) => `'${hash}'`).join(" ");
|
|
293
|
+
return [
|
|
294
|
+
`default-src 'self'`,
|
|
295
|
+
`base-uri 'self'`,
|
|
296
|
+
`connect-src 'self' https: wss:`,
|
|
297
|
+
`font-src 'self' data:`,
|
|
298
|
+
`form-action 'self'`,
|
|
299
|
+
`frame-ancestors 'none'`,
|
|
300
|
+
`img-src 'self' data: https:`,
|
|
301
|
+
`manifest-src 'self'`,
|
|
302
|
+
`media-src 'self' data: blob: https:`,
|
|
303
|
+
`object-src 'none'`,
|
|
304
|
+
`script-src 'self' 'unsafe-inline' ${await hashes(inlineScripts)}`,
|
|
305
|
+
`style-src 'self' 'unsafe-inline' ${await hashes(inlineStyles)}`,
|
|
306
|
+
`worker-src 'self' blob:`,
|
|
307
|
+
"upgrade-insecure-requests"
|
|
308
|
+
].join("; ");
|
|
309
|
+
}
|
|
263
310
|
async function buildScriptDirectory(sourceDirectory, outputDirectory, passes, root = sourceDirectory) {
|
|
264
311
|
for (const entry of await readdir(sourceDirectory, { withFileTypes: true })) {
|
|
265
312
|
const source = join(sourceDirectory, entry.name);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["minifiedOutputs","minifiedOutputs","minify"],"sources":["../src/minifyCss/index.ts","../src/minifyHtml/index.ts","../src/minifyJs/index.ts","../src/webManifest/index.ts","../src/index.ts"],"sourcesContent":["import type { PathLike } from 'node:fs'\nimport { build } from 'esbuild'\nimport { transform } from 'lightningcss'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Bundles and minifies a CSS entrypoint into a dense string. */\nexport default async function minifyCss(entrypoint: PathLike): Promise<string> {\n const bundled = await build({\n entryPoints: [entrypoint.toString()],\n bundle: true,\n legalComments: 'none',\n minify: true,\n treeShaking: true,\n write: false,\n external: ['/assets/*'],\n })\n const source = bundled.outputFiles[0].text\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const { code } = transform({\n code: bundled.outputFiles[0].contents,\n filename: entrypoint.toString(),\n minify: true,\n })\n\n const output = new TextDecoder().decode(code).trim()\n minifiedOutputs.set(source, output)\n return output\n}\n","import { minify } from 'html-minifier-terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Minifies a complete HTML document, including inline CSS and JavaScript. */\nexport default async function minifyHtml(source: string): Promise<string> {\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const output = await minify(source, {\n collapseBooleanAttributes: true,\n collapseInlineTagWhitespace: true,\n collapseWhitespace: true,\n decodeEntities: true,\n html5: true,\n minifyCSS: true,\n minifyJS: {\n compress: {\n dead_code: true,\n passes: 3,\n toplevel: true,\n unused: true,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n },\n removeAttributeQuotes: true,\n removeComments: true,\n removeEmptyAttributes: true,\n removeRedundantAttributes: true,\n sortAttributes: true,\n sortClassName: true,\n useShortDoctype: true,\n })\n minifiedOutputs.set(source, output)\n return output\n}\n","import type { PathLike } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { build } from 'esbuild'\nimport { minify } from 'terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\ntype JavaScriptInput = PathLike | { source: string }\n\ntype MinifyJsOptions = {\n banner?: string\n define?: Record<string, string>\n passes?: number\n}\n\n/** Bundles, tree-shakes, mangles, and repeatedly minifies JavaScript. */\nexport default async function minifyJs(\n input: JavaScriptInput,\n { banner, define, passes = 3 }: MinifyJsOptions = {}\n): Promise<string> {\n const bundled = await build({\n ...(typeof input === 'object' && 'source' in input\n ? { stdin: { contents: input.source, resolveDir: process.cwd() } }\n : {\n entryPoints: [\n input instanceof URL ? fileURLToPath(input) : input.toString(),\n ],\n }),\n bundle: true,\n banner: banner === undefined ? undefined : { js: banner },\n define,\n format: 'esm',\n legalComments: 'none',\n minify: true,\n platform: 'browser',\n treeShaking: true,\n write: false,\n })\n\n const output = bundled.outputFiles[0].text\n const cacheKey = `${passes}\\0${output}`\n const cached = minifiedOutputs.get(cacheKey)\n if (cached !== undefined) return cached\n\n const result = await repeatedlyMinify(output, passes)\n minifiedOutputs.set(cacheKey, result)\n return result\n}\n\nasync function repeatedlyMinify(\n source: string,\n passes: number\n): Promise<string> {\n let output = source\n\n for (let round = 0; round < passes; round += 1) {\n const result = await minify(output, {\n compress: {\n dead_code: true,\n passes,\n toplevel: true,\n unused: true,\n },\n ecma: 2024,\n format: {\n beautify: false,\n comments: false,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n })\n\n /* v8 ignore next 3 -- Terser returns code or rejects for this input form. */\n if (result.code === undefined) {\n throw new Error('Terser did not produce JavaScript output')\n }\n\n output = result.code\n }\n\n return output\n}\n","import type { BCP47LanguageTag } from '@sovereignbase/utils'\n\ntype Path = `/${string}`\ntype ImageURL = Path | `https://${string}`\n\nexport interface WebManifestScreenshot {\n src: ImageURL\n sizes: `${number}x${number}`\n type?: `image/${string}`\n form_factor?: 'narrow' | 'wide'\n label?: string\n}\n\nexport interface WebManifestShortcut {\n name: string\n url: Path\n description?: string\n icons?: {\n src: ImageURL\n sizes: `${number}x${number}` | 'any'\n type?: `image/${string}`\n }[]\n}\n\nexport interface WebManifestOptions {\n name: string\n shortName: string\n description: string\n startUrl: Path\n themeColor: string\n icon192: ImageURL\n icon512: ImageURL\n maskableIcon512: ImageURL\n id?: Path\n scope?: Path\n backgroundColor?: string\n lang?: BCP47LanguageTag\n display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser'\n orientation?:\n | 'any'\n | 'natural'\n | 'portrait'\n | 'portrait-primary'\n | 'portrait-secondary'\n | 'landscape'\n | 'landscape-primary'\n | 'landscape-secondary'\n categories?: string[]\n screenshots?: WebManifestScreenshot[]\n shortcuts?: WebManifestShortcut[]\n}\n\n/**\n * Generates a standards-based Web App Manifest JSON string.\n */\nexport const webManifest = ({\n name,\n shortName,\n description,\n startUrl,\n themeColor,\n icon192,\n icon512,\n maskableIcon512,\n id = '/',\n scope = '/',\n backgroundColor = themeColor,\n lang,\n display = 'standalone',\n orientation,\n categories,\n screenshots,\n shortcuts,\n}: WebManifestOptions): string =>\n JSON.stringify({\n id,\n name,\n short_name: shortName,\n description,\n start_url: startUrl,\n scope,\n display,\n theme_color: themeColor,\n background_color: backgroundColor,\n ...(lang ? { lang } : {}),\n ...(orientation ? { orientation } : {}),\n ...(categories?.length ? { categories } : {}),\n ...(screenshots?.length ? { screenshots } : {}),\n ...(shortcuts?.length ? { shortcuts } : {}),\n icons: [\n {\n src: icon192,\n sizes: '192x192',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: icon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: maskableIcon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'maskable',\n },\n ],\n })\n","import { createHash } from 'node:crypto'\nimport { existsSync, type PathLike } from 'node:fs'\nimport { cp, mkdir, readFile, readdir, writeFile } from 'node:fs/promises'\nimport { basename, dirname, extname, join, relative, sep } from 'node:path'\nimport type { BCP47LanguageTag, OpenGraphLocale } from '@sovereignbase/utils'\nimport type {\n DocumentMarkupOptions,\n HTTPSUrl,\n URLPath,\n} from './.types/index.js'\nimport { documentMarkup } from './htmlDocument/index.js'\nimport minifyCss from './minifyCss/index.js'\nimport minifyHtml from './minifyHtml/index.js'\nimport minifyJs from './minifyJs/index.js'\nimport {\n webManifest,\n type WebManifestOptions,\n type WebManifestScreenshot,\n type WebManifestShortcut,\n} from './webManifest/index.js'\n\nexport async function pwaize(config: PWAizeConfig): Promise<void> {\n const outputDirectory = join(config.outDir.toString(), 'web')\n const languages = [\n ...new Set([config.defaultLanguage, ...config.alternateLanguages]),\n ]\n const minifyPasses = config.minifyPasses ?? 3\n const serviceWorkerPath = '/ServiceWorker'\n\n await mkdir(outputDirectory, { recursive: true })\n\n if (config.assetsDir !== undefined) {\n const sourceDirectory = config.assetsDir.toString()\n await cp(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n { recursive: true }\n )\n }\n\n if (config.i18nDir !== undefined) {\n const sourceDirectory = config.i18nDir.toString()\n await buildScriptDirectory(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n minifyPasses\n )\n }\n\n const stylesheet = await minifyCss(config.stylesheet)\n const entrypoint = await minifyJs(config.entrypoint, {\n passes: minifyPasses,\n })\n const installer = await minifyJs(\n {\n source: `await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:\"/\",type:\"module\"});await navigator.serviceWorker.ready;location.reload();`,\n },\n { passes: minifyPasses }\n )\n const documentOptions: Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n > = {}\n\n for (const language of languages) {\n const localized = localizeConfig(config, language, languages)\n const languageDirectory = join(outputDirectory, language)\n const manifestPath = `/${language}/manifest.webmanifest` as const\n const manifest = webManifest(localized.manifest)\n documentOptions[language] = localized.document\n\n await mkdir(languageDirectory, { recursive: true })\n await writeFile(join(languageDirectory, 'manifest.webmanifest'), manifest)\n\n const installerDocument = await minifyHtml(\n await documentMarkup({\n ...localized.document,\n entrypoint: installer,\n language,\n manifestUrl: manifestPath,\n })\n )\n await writeFile(join(languageDirectory, 'index.html'), installerDocument)\n\n if (language === config.defaultLanguage) {\n await writeFile(join(outputDirectory, 'index.html'), installerDocument)\n await writeFile(join(outputDirectory, 'manifest.webmanifest'), manifest)\n }\n }\n\n if (config._headersFile === true) {\n await writeFile(\n join(outputDirectory, '_headers'),\n `/${serviceWorkerPath.slice(1)}\\n Cache-Control: no-cache\\n Content-Type: text/javascript;charset=UTF-8\\n\\n/*\\n X-Content-Type-Options: nosniff\\n`\n )\n }\n\n const buildIdUrl = '/@sovereignbase/pwa/pwaize-build-id.txt'\n const generatedFiles = (await publicFiles(outputDirectory)).filter(\n (url) => url !== serviceWorkerPath && url !== buildIdUrl\n )\n const precache = [\n ...new Set([...generatedFiles, ...(config.serviceWorker?.precache ?? [])]),\n ].sort()\n const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule)\n const initialize =\n config.serviceWorker?.initialize === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.initialize)\n const waitUntil =\n config.serviceWorker?.waitUntil === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.waitUntil)\n const buildId = await contentBuildId(outputDirectory, generatedFiles, {\n bypassRules,\n documentOptions,\n entrypoint,\n initialize,\n precache,\n stylesheet,\n waitUntil,\n })\n const buildIdDirectory = join(outputDirectory, '@sovereignbase', 'pwa')\n await mkdir(buildIdDirectory, { recursive: true })\n await writeFile(join(buildIdDirectory, 'pwaize-build-id.txt'), buildId)\n const compiledServiceWorker = new URL(\n './serviceWorker/entrypoint.js',\n import.meta.url\n )\n const serviceWorker = await minifyJs(\n /* v8 ignore next -- the packaged .js path is exercised by runtime tests */\n existsSync(compiledServiceWorker)\n ? compiledServiceWorker\n : new URL('./serviceWorker/entrypoint.ts', import.meta.url),\n {\n banner: `const __pwaInitialize=${initialize},__pwaWaitUntil=${waitUntil};`,\n define: {\n buildId: JSON.stringify(buildId),\n buildIdUrl: JSON.stringify(buildIdUrl),\n bypassRules: JSON.stringify(bypassRules),\n customInitialize: '__pwaInitialize',\n customWaitUntil: '__pwaWaitUntil',\n defaultLanguage: JSON.stringify(config.defaultLanguage),\n documentOptions: JSON.stringify(documentOptions),\n entrypoint: JSON.stringify(entrypoint),\n precache: JSON.stringify(precache),\n stylesheet: JSON.stringify(stylesheet),\n },\n passes: minifyPasses,\n }\n )\n\n await writeFile(\n join(outputDirectory, serviceWorkerPath.slice(1)),\n serviceWorker\n )\n}\n\nasync function buildScriptDirectory(\n sourceDirectory: string,\n outputDirectory: string,\n passes: number,\n root = sourceDirectory\n): Promise<void> {\n for (const entry of await readdir(sourceDirectory, { withFileTypes: true })) {\n const source = join(sourceDirectory, entry.name)\n if (entry.isDirectory()) {\n await buildScriptDirectory(source, outputDirectory, passes, root)\n continue\n }\n if (!entry.isFile() || entry.name.endsWith('.d.ts')) continue\n\n const relativePath = relative(root, source)\n const extension = extname(relativePath)\n const output = join(\n outputDirectory,\n /\\.[cm]?[jt]sx?$/.test(extension)\n ? `${relativePath.slice(0, -extension.length)}.js`\n : relativePath\n )\n await mkdir(dirname(output), { recursive: true })\n if (/\\.[cm]?[jt]sx?$/.test(extension)) {\n await writeFile(output, await minifyJs(source, { passes }))\n } else {\n await cp(source, output)\n }\n }\n}\n\nasync function contentBuildId(\n outputDirectory: string,\n files: string[],\n configuration: unknown\n): Promise<string> {\n const hash = createHash('sha256')\n hash.update(JSON.stringify(configuration))\n for (const file of files) {\n hash.update(file)\n hash.update(\n await readFile(join(outputDirectory, ...file.slice(1).split('/')))\n )\n }\n return hash.digest('hex')\n}\n\nasync function publicFiles(\n directory: string,\n root = directory\n): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true })\n const files: string[] = []\n\n for (const entry of entries) {\n const path = join(directory, entry.name)\n if (entry.isDirectory()) {\n files.push(...(await publicFiles(path, root)))\n } else if (entry.isFile() && entry.name !== '_headers') {\n files.push(`/${relative(root, path).split(sep).join('/')}`)\n }\n }\n\n return files.sort()\n}\n\nfunction globRule(pattern: string | RegExp): {\n absolute: boolean\n flags: string\n source: string\n} {\n if (pattern instanceof RegExp) {\n return { absolute: true, flags: pattern.flags, source: pattern.source }\n }\n\n let source = '^'\n for (let index = 0; index < pattern.length; index += 1) {\n const character = pattern[index]\n if (character === '*') {\n if (pattern[index + 1] === '*') {\n source += '.*'\n index += 1\n } else {\n source += '[^/]*'\n }\n } else if (character === '?') {\n source += '.'\n } else {\n source += character.replace(/[|\\\\{}()[\\]^$+?.]/g, '\\\\$&')\n }\n }\n\n return {\n absolute: pattern.includes('://'),\n flags: '',\n source: `${source}$`,\n }\n}\n\nfunction functionExpression(\n callback: (...arguments_: never[]) => unknown\n): string {\n const source = callback.toString()\n if (/^(?:async\\s+)?function\\b|^(?:async\\s+)?\\(/.test(source)) {\n return `(${source})`\n }\n if (source.startsWith('async ')) {\n return `(async function ${source.slice('async '.length)})`\n }\n return `(function ${source})`\n}\n\nfunction localizeConfig(\n config: PWAizeConfig,\n language: BCP47LanguageTag,\n languages: BCP47LanguageTag[]\n): {\n document: Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n manifest: WebManifestOptions\n} {\n const get = <T>(value: Localized<T> | undefined, empty: T): T =>\n localizedValue(value, language, config.defaultLanguage, empty)\n const applicationName = get(config.applicationName, '')\n const description = get(config.description, '')\n const icon192 = get<string>(config.icons.icon192, '')\n const icon512 = get<string>(config.icons.icon512, '')\n const origin = get<string>(config.origin, '')\n const pageUrl = (\n origin === '' ? '' : new URL(`/${language}`, origin).href\n ) as HTTPSUrl\n const organizationLogo = (\n origin === '' || icon512 === '' ? '' : new URL(icon512, origin).href\n ) as HTTPSUrl\n const themeColor = get(config.themeColor, '')\n const title = get(config.title, '')\n\n return {\n document: {\n applicationName,\n appleStatusBarStyle: get(config.appleStatusBarStyle, 'black-translucent'),\n appleTouchIconUrl: get(\n config.icons.appleTouchIconUrl,\n icon192 as URLPath\n ),\n bodyMarkup: get(config.bodyMarkup, ''),\n colorScheme: get(config.colorScheme, 'light dark'),\n headMarkup: get(config.headMarkup, ''),\n iconUrl: get(config.icons.iconUrl, icon512 as URLPath),\n maskIconColor: themeColor,\n maskIconUrl: get(config.icons.maskIconUrl, '' as URLPath),\n seo: {\n jsonLD: {\n application: {\n applicationCategory: get(config.application?.category, ''),\n browserRequirements: get(\n config.application?.browserRequirements,\n ''\n ),\n featureList: get(config.application?.featureList, []),\n inLanguage: languages,\n name: applicationName,\n operatingSystem: get(config.application?.operatingSystem, ''),\n url: origin as HTTPSUrl,\n },\n organization: {\n logo: get(config.organization?.logoUrl, organizationLogo),\n name: get(config.organization?.name, applicationName),\n url: get<string>(config.organization?.url, origin) as HTTPSUrl,\n },\n page: {\n description,\n inLanguage: language,\n name: title,\n url: pageUrl,\n },\n site: { name: applicationName, url: origin as HTTPSUrl },\n },\n languageLinks: {\n alternateLanguages: languages,\n canonicalLanguage: config.canonicalLanguage,\n defaultLanguage: config.defaultLanguage,\n host: (origin === ''\n ? ''\n : new URL(origin).host) as `${string}.${string}`,\n },\n openGraph: {\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageHeight: get(config.socialImage.height, 630),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n imageWidth: get(config.socialImage.width, 1200),\n locale: get(config.openGraphLocale, '' as OpenGraphLocale),\n siteName: applicationName,\n title,\n url: pageUrl,\n },\n twitter: {\n creator: get(config.twitter.creator, '' as `@${string}`),\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n site: get(config.twitter.site, '' as `@${string}`),\n title,\n url: pageUrl,\n },\n },\n themeColor,\n title,\n },\n manifest: {\n backgroundColor: get(config.backgroundColor, themeColor),\n categories: get(config.manifest?.categories, []),\n description,\n display: get(config.manifest?.display, 'standalone'),\n icon192: icon192 as URLPath,\n icon512: icon512 as URLPath,\n id: get(config.manifest?.id, '/' as URLPath),\n lang: language,\n maskableIcon512: get(config.icons.maskableIcon512, icon512 as URLPath),\n name: applicationName,\n orientation: get(config.manifest?.orientation, 'any'),\n scope: get(config.manifest?.scope, '/' as URLPath),\n screenshots: get(config.manifest?.screenshots, []),\n shortName: get(config.shortName, applicationName),\n shortcuts: get(config.manifest?.shortcuts, []),\n startUrl: `/${language}`,\n themeColor,\n },\n }\n}\n\nfunction localizedValue<T>(\n value: Localized<T> | undefined,\n language: BCP47LanguageTag,\n defaultLanguage: BCP47LanguageTag,\n empty: T\n): T {\n if (value === undefined) return empty\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return value as T\n }\n\n const values = value as Partial<Record<BCP47LanguageTag, T>>\n return values[language] ?? values[defaultLanguage] ?? empty\n}\n\nexport type Localized<T> = T | Partial<Record<BCP47LanguageTag, T>>\n\nexport type PWAizeConfig = {\n _headersFile?: boolean\n alternateLanguages: BCP47LanguageTag[]\n application?: {\n browserRequirements?: Localized<string>\n category?: Localized<string>\n featureList?: Localized<string[]>\n operatingSystem?: Localized<string>\n }\n applicationName: Localized<string>\n appleStatusBarStyle?: Localized<'black' | 'black-translucent' | 'default'>\n assetsDir?: PathLike\n backgroundColor?: Localized<string>\n bodyMarkup?: Localized<string>\n canonicalLanguage: BCP47LanguageTag\n colorScheme?: Localized<'dark' | 'dark light' | 'light' | 'light dark'>\n defaultLanguage: BCP47LanguageTag\n description: Localized<string>\n entrypoint: PathLike\n headMarkup?: Localized<string>\n i18nDir?: PathLike\n icons: {\n appleTouchIconUrl?: Localized<URLPath>\n icon192: Localized<URLPath>\n icon512: Localized<URLPath>\n iconUrl?: Localized<URLPath>\n maskableIcon512: Localized<URLPath>\n maskIconUrl?: Localized<URLPath>\n }\n manifest?: {\n categories?: Localized<string[]>\n display?: Localized<'browser' | 'fullscreen' | 'minimal-ui' | 'standalone'>\n id?: Localized<URLPath>\n orientation?: Localized<WebManifestOptions['orientation']>\n scope?: Localized<URLPath>\n screenshots?: Localized<WebManifestScreenshot[]>\n shortcuts?: Localized<WebManifestShortcut[]>\n }\n minifyPasses?: number\n openGraphLocale: Localized<OpenGraphLocale>\n organization?: {\n logoUrl?: Localized<HTTPSUrl>\n name?: Localized<string>\n url?: Localized<HTTPSUrl>\n }\n origin: Localized<HTTPSUrl>\n outDir: PathLike\n serviceWorker?: {\n bypass?: Array<string | RegExp>\n initialize?: () => void\n precache?: URLPath[]\n waitUntil?: () => Promise<void>\n }\n shortName?: Localized<string>\n socialImage: {\n alt: Localized<string>\n height?: Localized<number>\n url: Localized<HTTPSUrl>\n width?: Localized<number>\n }\n stylesheet: PathLike\n themeColor: Localized<string>\n title: Localized<string>\n twitter: {\n creator: Localized<`@${string}`>\n site: Localized<`@${string}`>\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["minifiedOutputs","minifiedOutputs","minify"],"sources":["../src/cspHash/index.ts","../src/minifyCss/index.ts","../src/minifyHtml/index.ts","../src/minifyJs/index.ts","../src/webManifest/index.ts","../src/index.ts"],"sourcesContent":["import { Bytes } from '@sovereignbase/bytecodec'\n\nexport const cspHash = async (source: string): Promise<`sha256-${string}`> => {\n const digest = await crypto.subtle.digest(\n 'SHA-256',\n Bytes.fromString(source) as BufferSource\n )\n\n return `sha256-${Bytes.toBase64String(digest)}`\n}\n","import type { PathLike } from 'node:fs'\nimport { build } from 'esbuild'\nimport { transform } from 'lightningcss'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Bundles and minifies a CSS entrypoint into a dense string. */\nexport default async function minifyCss(entrypoint: PathLike): Promise<string> {\n const bundled = await build({\n entryPoints: [entrypoint.toString()],\n bundle: true,\n legalComments: 'none',\n minify: true,\n treeShaking: true,\n write: false,\n external: ['/assets/*'],\n })\n const source = bundled.outputFiles[0].text\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const { code } = transform({\n code: bundled.outputFiles[0].contents,\n filename: entrypoint.toString(),\n minify: true,\n })\n\n const output = new TextDecoder().decode(code).trim()\n minifiedOutputs.set(source, output)\n return output\n}\n","import { minify } from 'html-minifier-terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\n/** Minifies a complete HTML document, including inline CSS and JavaScript. */\nexport default async function minifyHtml(source: string): Promise<string> {\n const cached = minifiedOutputs.get(source)\n if (cached !== undefined) return cached\n\n const output = await minify(source, {\n collapseBooleanAttributes: true,\n collapseInlineTagWhitespace: true,\n collapseWhitespace: true,\n decodeEntities: true,\n html5: true,\n minifyCSS: true,\n minifyJS: {\n compress: {\n dead_code: true,\n passes: 3,\n toplevel: true,\n unused: true,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n },\n removeAttributeQuotes: true,\n removeComments: true,\n removeEmptyAttributes: true,\n removeRedundantAttributes: true,\n sortAttributes: true,\n sortClassName: true,\n useShortDoctype: true,\n })\n minifiedOutputs.set(source, output)\n return output\n}\n","import type { PathLike } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { build } from 'esbuild'\nimport { minify } from 'terser'\n\nconst minifiedOutputs = new Map<string, string>()\n\ntype JavaScriptInput = PathLike | { source: string }\n\ntype MinifyJsOptions = {\n banner?: string\n define?: Record<string, string>\n passes?: number\n}\n\n/** Bundles, tree-shakes, mangles, and repeatedly minifies JavaScript. */\nexport default async function minifyJs(\n input: JavaScriptInput,\n { banner, define, passes = 3 }: MinifyJsOptions = {}\n): Promise<string> {\n const bundled = await build({\n ...(typeof input === 'object' && 'source' in input\n ? { stdin: { contents: input.source, resolveDir: process.cwd() } }\n : {\n entryPoints: [\n input instanceof URL ? fileURLToPath(input) : input.toString(),\n ],\n }),\n bundle: true,\n banner: banner === undefined ? undefined : { js: banner },\n define,\n format: 'esm',\n legalComments: 'none',\n minify: true,\n platform: 'browser',\n treeShaking: true,\n write: false,\n })\n\n const output = bundled.outputFiles[0].text\n const cacheKey = `${passes}\\0${output}`\n const cached = minifiedOutputs.get(cacheKey)\n if (cached !== undefined) return cached\n\n const result = await repeatedlyMinify(output, passes)\n minifiedOutputs.set(cacheKey, result)\n return result\n}\n\nasync function repeatedlyMinify(\n source: string,\n passes: number\n): Promise<string> {\n let output = source\n\n for (let round = 0; round < passes; round += 1) {\n const result = await minify(output, {\n compress: {\n dead_code: true,\n passes,\n toplevel: true,\n unused: true,\n },\n ecma: 2024,\n format: {\n beautify: false,\n comments: false,\n },\n mangle: {\n toplevel: true,\n },\n module: true,\n toplevel: true,\n })\n\n /* v8 ignore next 3 -- Terser returns code or rejects for this input form. */\n if (result.code === undefined) {\n throw new Error('Terser did not produce JavaScript output')\n }\n\n output = result.code\n }\n\n return output\n}\n","import type { BCP47LanguageTag } from '@sovereignbase/utils'\n\ntype Path = `/${string}`\ntype ImageURL = Path | `https://${string}`\n\nexport interface WebManifestScreenshot {\n src: ImageURL\n sizes: `${number}x${number}`\n type?: `image/${string}`\n form_factor?: 'narrow' | 'wide'\n label?: string\n}\n\nexport interface WebManifestShortcut {\n name: string\n url: Path\n description?: string\n icons?: {\n src: ImageURL\n sizes: `${number}x${number}` | 'any'\n type?: `image/${string}`\n }[]\n}\n\nexport interface WebManifestOptions {\n name: string\n shortName: string\n description: string\n startUrl: Path\n themeColor: string\n icon192: ImageURL\n icon512: ImageURL\n maskableIcon512: ImageURL\n id?: Path\n scope?: Path\n backgroundColor?: string\n lang?: BCP47LanguageTag\n display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser'\n orientation?:\n | 'any'\n | 'natural'\n | 'portrait'\n | 'portrait-primary'\n | 'portrait-secondary'\n | 'landscape'\n | 'landscape-primary'\n | 'landscape-secondary'\n categories?: string[]\n screenshots?: WebManifestScreenshot[]\n shortcuts?: WebManifestShortcut[]\n}\n\n/**\n * Generates a standards-based Web App Manifest JSON string.\n */\nexport const webManifest = ({\n name,\n shortName,\n description,\n startUrl,\n themeColor,\n icon192,\n icon512,\n maskableIcon512,\n id = '/',\n scope = '/',\n backgroundColor = themeColor,\n lang,\n display = 'standalone',\n orientation,\n categories,\n screenshots,\n shortcuts,\n}: WebManifestOptions): string =>\n JSON.stringify({\n id,\n name,\n short_name: shortName,\n description,\n start_url: startUrl,\n scope,\n display,\n theme_color: themeColor,\n background_color: backgroundColor,\n ...(lang ? { lang } : {}),\n ...(orientation ? { orientation } : {}),\n ...(categories?.length ? { categories } : {}),\n ...(screenshots?.length ? { screenshots } : {}),\n ...(shortcuts?.length ? { shortcuts } : {}),\n icons: [\n {\n src: icon192,\n sizes: '192x192',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: icon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'any',\n },\n {\n src: maskableIcon512,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'maskable',\n },\n ],\n })\n","import { createHash } from 'node:crypto'\nimport { existsSync, type PathLike } from 'node:fs'\nimport { cp, mkdir, readFile, readdir, writeFile } from 'node:fs/promises'\nimport { basename, dirname, extname, join, relative, sep } from 'node:path'\nimport type { BCP47LanguageTag, OpenGraphLocale } from '@sovereignbase/utils'\nimport type {\n DocumentMarkupOptions,\n HTTPSUrl,\n URLPath,\n} from './.types/index.js'\nimport { cspHash } from './cspHash/index.js'\nimport { documentMarkup } from './htmlDocument/index.js'\nimport minifyCss from './minifyCss/index.js'\nimport minifyHtml from './minifyHtml/index.js'\nimport minifyJs from './minifyJs/index.js'\nimport {\n webManifest,\n type WebManifestOptions,\n type WebManifestScreenshot,\n type WebManifestShortcut,\n} from './webManifest/index.js'\n\nexport async function pwaize(config: PWAizeConfig): Promise<void> {\n const outputDirectory = join(config.outDir.toString(), 'web')\n const languages = [\n ...new Set([config.defaultLanguage, ...config.alternateLanguages]),\n ]\n const minifyPasses = config.minifyPasses ?? 3\n const buildIdUrl = '/@sovereignbase/pwa/pwaize-build-id.txt'\n const serviceWorkerPath = '/ServiceWorker'\n\n await mkdir(outputDirectory, { recursive: true })\n\n if (config.assetsDir !== undefined) {\n const sourceDirectory = config.assetsDir.toString()\n await cp(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n { recursive: true }\n )\n }\n\n if (config.i18nDir !== undefined) {\n const sourceDirectory = config.i18nDir.toString()\n await buildScriptDirectory(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n minifyPasses\n )\n }\n\n const stylesheet = await minifyCss(config.stylesheet)\n const entrypoint = await minifyJs(config.entrypoint, {\n passes: minifyPasses,\n })\n const installer = await minifyJs(\n {\n source: `await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:\"/\",type:\"module\"});await navigator.serviceWorker.ready;location.reload();`,\n },\n { passes: minifyPasses }\n )\n const documentOptions: Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n > = {}\n const contentSecurityPolicies: Record<string, string> = {}\n const installerDocuments: string[] = []\n\n for (const language of languages) {\n const localized = localizeConfig(config, language, languages)\n const languageDirectory = join(outputDirectory, language)\n const manifestPath = `/${language}/manifest.webmanifest` as const\n const manifest = webManifest(localized.manifest)\n documentOptions[language] = localized.document\n\n await mkdir(languageDirectory, { recursive: true })\n await writeFile(join(languageDirectory, 'manifest.webmanifest'), manifest)\n\n const installerDocument = await minifyHtml(\n await documentMarkup({\n ...localized.document,\n entrypoint: installer,\n language,\n manifestUrl: manifestPath,\n })\n )\n const applicationDocument = await documentMarkup({\n ...localized.document,\n entrypoint,\n language,\n manifestUrl: manifestPath,\n stylesheet,\n })\n contentSecurityPolicies[language] = await contentSecurityPolicy([\n applicationDocument,\n ])\n installerDocuments.push(installerDocument)\n await writeFile(join(languageDirectory, 'index.html'), installerDocument)\n\n if (language === config.defaultLanguage) {\n await writeFile(join(outputDirectory, 'index.html'), installerDocument)\n await writeFile(join(outputDirectory, 'manifest.webmanifest'), manifest)\n }\n }\n\n if (config._headersFile === true) {\n const installerContentSecurityPolicy =\n await contentSecurityPolicy(installerDocuments)\n const assetsHeaders =\n config.assetsDir === undefined\n ? ''\n : `/${basename(config.assetsDir.toString())}/*\\n Cache-Control: public, max-age=31536000, immutable\\n\\n`\n await writeFile(\n join(outputDirectory, '_headers'),\n `/${serviceWorkerPath.slice(1)}\\n Cache-Control: no-cache\\n Content-Type: text/javascript;charset=UTF-8\\n\\n${buildIdUrl}\\n Cache-Control: no-cache, no-store, must-revalidate\\n Content-Type: text/plain;charset=UTF-8\\n\\n${assetsHeaders}/*\\n Content-Security-Policy: ${installerContentSecurityPolicy}\\n X-Content-Type-Options: nosniff\\n`\n )\n }\n\n const generatedFiles = (await publicFiles(outputDirectory)).filter(\n (url) => url !== serviceWorkerPath && url !== buildIdUrl\n )\n const precache = [\n ...new Set([...generatedFiles, ...(config.serviceWorker?.precache ?? [])]),\n ].sort()\n const staticRoutes = [\n ...new Set(\n precache\n .map((url) => new URL(url, 'https://pwaize.invalid').pathname)\n .filter((url) => !url.endsWith('/index.html') && url !== '/index.html')\n ),\n ].sort()\n const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule)\n const initialize =\n config.serviceWorker?.initialize === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.initialize)\n const waitUntil =\n config.serviceWorker?.waitUntil === undefined\n ? 'undefined'\n : functionExpression(config.serviceWorker.waitUntil)\n const buildId = await contentBuildId(outputDirectory, generatedFiles, {\n bypassRules,\n contentSecurityPolicies,\n documentOptions,\n entrypoint,\n initialize,\n precache,\n staticRoutes,\n stylesheet,\n waitUntil,\n })\n const buildIdDirectory = join(outputDirectory, '@sovereignbase', 'pwa')\n await mkdir(buildIdDirectory, { recursive: true })\n await writeFile(join(buildIdDirectory, 'pwaize-build-id.txt'), buildId)\n const compiledServiceWorker = new URL(\n './serviceWorker/entrypoint.js',\n import.meta.url\n )\n const serviceWorker = await minifyJs(\n /* v8 ignore next -- the packaged .js path is exercised by runtime tests */\n existsSync(compiledServiceWorker)\n ? compiledServiceWorker\n : new URL('./serviceWorker/entrypoint.ts', import.meta.url),\n {\n banner: `const __pwaInitialize=${initialize},__pwaWaitUntil=${waitUntil};`,\n define: {\n buildId: JSON.stringify(buildId),\n buildIdUrl: JSON.stringify(buildIdUrl),\n bypassRules: JSON.stringify(bypassRules),\n customInitialize: '__pwaInitialize',\n customWaitUntil: '__pwaWaitUntil',\n defaultLanguage: JSON.stringify(config.defaultLanguage),\n contentSecurityPolicies: JSON.stringify(contentSecurityPolicies),\n documentOptions: JSON.stringify(documentOptions),\n entrypoint: JSON.stringify(entrypoint),\n precache: JSON.stringify(precache),\n staticRoutes: JSON.stringify(staticRoutes),\n stylesheet: JSON.stringify(stylesheet),\n },\n passes: minifyPasses,\n }\n )\n\n await writeFile(\n join(outputDirectory, serviceWorkerPath.slice(1)),\n serviceWorker\n )\n}\n\nasync function contentSecurityPolicy(documents: string[]): Promise<string> {\n const inlineScripts = documents.flatMap((document) =>\n [...document.matchAll(/<script\\b[^>]*>([\\s\\S]*?)<\\/script>/gi)].map(\n (match) => match[1]\n )\n )\n const inlineStyles = documents.flatMap((document) =>\n [...document.matchAll(/<style\\b[^>]*>([\\s\\S]*?)<\\/style>/gi)].map(\n (match) => match[1]\n )\n )\n const hashes = async (sources: string[]): Promise<string> =>\n (\n await Promise.all(\n [...new Set(sources.length === 0 ? [''] : sources)].map(cspHash)\n )\n )\n .map((hash) => `'${hash}'`)\n .join(' ')\n\n return [\n `default-src 'self'`,\n `base-uri 'self'`,\n `connect-src 'self' https: wss:`,\n `font-src 'self' data:`,\n `form-action 'self'`,\n `frame-ancestors 'none'`,\n `img-src 'self' data: https:`,\n `manifest-src 'self'`,\n `media-src 'self' data: blob: https:`,\n `object-src 'none'`,\n `script-src 'self' 'unsafe-inline' ${await hashes(inlineScripts)}`,\n `style-src 'self' 'unsafe-inline' ${await hashes(inlineStyles)}`,\n `worker-src 'self' blob:`,\n 'upgrade-insecure-requests',\n ].join('; ')\n}\n\nasync function buildScriptDirectory(\n sourceDirectory: string,\n outputDirectory: string,\n passes: number,\n root = sourceDirectory\n): Promise<void> {\n for (const entry of await readdir(sourceDirectory, { withFileTypes: true })) {\n const source = join(sourceDirectory, entry.name)\n if (entry.isDirectory()) {\n await buildScriptDirectory(source, outputDirectory, passes, root)\n continue\n }\n if (!entry.isFile() || entry.name.endsWith('.d.ts')) continue\n\n const relativePath = relative(root, source)\n const extension = extname(relativePath)\n const output = join(\n outputDirectory,\n /\\.[cm]?[jt]sx?$/.test(extension)\n ? `${relativePath.slice(0, -extension.length)}.js`\n : relativePath\n )\n await mkdir(dirname(output), { recursive: true })\n if (/\\.[cm]?[jt]sx?$/.test(extension)) {\n await writeFile(output, await minifyJs(source, { passes }))\n } else {\n await cp(source, output)\n }\n }\n}\n\nasync function contentBuildId(\n outputDirectory: string,\n files: string[],\n configuration: unknown\n): Promise<string> {\n const hash = createHash('sha256')\n hash.update(JSON.stringify(configuration))\n for (const file of files) {\n hash.update(file)\n hash.update(\n await readFile(join(outputDirectory, ...file.slice(1).split('/')))\n )\n }\n return hash.digest('hex')\n}\n\nasync function publicFiles(\n directory: string,\n root = directory\n): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true })\n const files: string[] = []\n\n for (const entry of entries) {\n const path = join(directory, entry.name)\n if (entry.isDirectory()) {\n files.push(...(await publicFiles(path, root)))\n } else if (entry.isFile() && entry.name !== '_headers') {\n files.push(`/${relative(root, path).split(sep).join('/')}`)\n }\n }\n\n return files.sort()\n}\n\nfunction globRule(pattern: string | RegExp): {\n absolute: boolean\n flags: string\n source: string\n} {\n if (pattern instanceof RegExp) {\n return { absolute: true, flags: pattern.flags, source: pattern.source }\n }\n\n let source = '^'\n for (let index = 0; index < pattern.length; index += 1) {\n const character = pattern[index]\n if (character === '*') {\n if (pattern[index + 1] === '*') {\n source += '.*'\n index += 1\n } else {\n source += '[^/]*'\n }\n } else if (character === '?') {\n source += '.'\n } else {\n source += character.replace(/[|\\\\{}()[\\]^$+?.]/g, '\\\\$&')\n }\n }\n\n return {\n absolute: pattern.includes('://'),\n flags: '',\n source: `${source}$`,\n }\n}\n\nfunction functionExpression(\n callback: (...arguments_: never[]) => unknown\n): string {\n const source = callback.toString()\n if (/^(?:async\\s+)?function\\b|^(?:async\\s+)?\\(/.test(source)) {\n return `(${source})`\n }\n if (source.startsWith('async ')) {\n return `(async function ${source.slice('async '.length)})`\n }\n return `(function ${source})`\n}\n\nfunction localizeConfig(\n config: PWAizeConfig,\n language: BCP47LanguageTag,\n languages: BCP47LanguageTag[]\n): {\n document: Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n manifest: WebManifestOptions\n} {\n const get = <T>(value: Localized<T> | undefined, empty: T): T =>\n localizedValue(value, language, config.defaultLanguage, empty)\n const applicationName = get(config.applicationName, '')\n const description = get(config.description, '')\n const icon192 = get<string>(config.icons.icon192, '')\n const icon512 = get<string>(config.icons.icon512, '')\n const origin = get<string>(config.origin, '')\n const pageUrl = (\n origin === '' ? '' : new URL(`/${language}`, origin).href\n ) as HTTPSUrl\n const organizationLogo = (\n origin === '' || icon512 === '' ? '' : new URL(icon512, origin).href\n ) as HTTPSUrl\n const themeColor = get(config.themeColor, '')\n const title = get(config.title, '')\n\n return {\n document: {\n applicationName,\n appleStatusBarStyle: get(config.appleStatusBarStyle, 'black-translucent'),\n appleTouchIconUrl: get(\n config.icons.appleTouchIconUrl,\n icon192 as URLPath\n ),\n bodyMarkup: get(config.bodyMarkup, ''),\n colorScheme: get(config.colorScheme, 'light dark'),\n headMarkup: get(config.headMarkup, ''),\n iconUrl: get(config.icons.iconUrl, icon512 as URLPath),\n maskIconColor: themeColor,\n maskIconUrl: get(config.icons.maskIconUrl, '' as URLPath),\n seo: {\n jsonLD: {\n application: {\n applicationCategory: get(config.application?.category, ''),\n browserRequirements: get(\n config.application?.browserRequirements,\n ''\n ),\n featureList: get(config.application?.featureList, []),\n inLanguage: languages,\n name: applicationName,\n operatingSystem: get(config.application?.operatingSystem, ''),\n url: origin as HTTPSUrl,\n },\n organization: {\n logo: get(config.organization?.logoUrl, organizationLogo),\n name: get(config.organization?.name, applicationName),\n url: get<string>(config.organization?.url, origin) as HTTPSUrl,\n },\n page: {\n description,\n inLanguage: language,\n name: title,\n url: pageUrl,\n },\n site: { name: applicationName, url: origin as HTTPSUrl },\n },\n languageLinks: {\n alternateLanguages: languages,\n canonicalLanguage: config.canonicalLanguage,\n defaultLanguage: config.defaultLanguage,\n host: (origin === ''\n ? ''\n : new URL(origin).host) as `${string}.${string}`,\n },\n openGraph: {\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageHeight: get(config.socialImage.height, 630),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n imageWidth: get(config.socialImage.width, 1200),\n locale: get(config.openGraphLocale, '' as OpenGraphLocale),\n siteName: applicationName,\n title,\n url: pageUrl,\n },\n twitter: {\n creator: get(config.twitter.creator, '' as `@${string}`),\n description,\n imageAlt: get(config.socialImage.alt, ''),\n imageUrl: get(config.socialImage.url, '' as HTTPSUrl),\n site: get(config.twitter.site, '' as `@${string}`),\n title,\n url: pageUrl,\n },\n },\n themeColor,\n title,\n },\n manifest: {\n backgroundColor: get(config.backgroundColor, themeColor),\n categories: get(config.manifest?.categories, []),\n description,\n display: get(config.manifest?.display, 'standalone'),\n icon192: icon192 as URLPath,\n icon512: icon512 as URLPath,\n id: get(config.manifest?.id, '/' as URLPath),\n lang: language,\n maskableIcon512: get(config.icons.maskableIcon512, icon512 as URLPath),\n name: applicationName,\n orientation: get(config.manifest?.orientation, 'any'),\n scope: get(config.manifest?.scope, '/' as URLPath),\n screenshots: get(config.manifest?.screenshots, []),\n shortName: get(config.shortName, applicationName),\n shortcuts: get(config.manifest?.shortcuts, []),\n startUrl: `/${language}`,\n themeColor,\n },\n }\n}\n\nfunction localizedValue<T>(\n value: Localized<T> | undefined,\n language: BCP47LanguageTag,\n defaultLanguage: BCP47LanguageTag,\n empty: T\n): T {\n if (value === undefined) return empty\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return value as T\n }\n\n const values = value as Partial<Record<BCP47LanguageTag, T>>\n return values[language] ?? values[defaultLanguage] ?? empty\n}\n\nexport type Localized<T> = T | Partial<Record<BCP47LanguageTag, T>>\n\nexport type PWAizeConfig = {\n _headersFile?: boolean\n alternateLanguages: BCP47LanguageTag[]\n application?: {\n browserRequirements?: Localized<string>\n category?: Localized<string>\n featureList?: Localized<string[]>\n operatingSystem?: Localized<string>\n }\n applicationName: Localized<string>\n appleStatusBarStyle?: Localized<'black' | 'black-translucent' | 'default'>\n assetsDir?: PathLike\n backgroundColor?: Localized<string>\n bodyMarkup?: Localized<string>\n canonicalLanguage: BCP47LanguageTag\n colorScheme?: Localized<'dark' | 'dark light' | 'light' | 'light dark'>\n defaultLanguage: BCP47LanguageTag\n description: Localized<string>\n entrypoint: PathLike\n headMarkup?: Localized<string>\n i18nDir?: PathLike\n icons: {\n appleTouchIconUrl?: Localized<URLPath>\n icon192: Localized<URLPath>\n icon512: Localized<URLPath>\n iconUrl?: Localized<URLPath>\n maskableIcon512: Localized<URLPath>\n maskIconUrl?: Localized<URLPath>\n }\n manifest?: {\n categories?: Localized<string[]>\n display?: Localized<'browser' | 'fullscreen' | 'minimal-ui' | 'standalone'>\n id?: Localized<URLPath>\n orientation?: Localized<WebManifestOptions['orientation']>\n scope?: Localized<URLPath>\n screenshots?: Localized<WebManifestScreenshot[]>\n shortcuts?: Localized<WebManifestShortcut[]>\n }\n minifyPasses?: number\n openGraphLocale: Localized<OpenGraphLocale>\n organization?: {\n logoUrl?: Localized<HTTPSUrl>\n name?: Localized<string>\n url?: Localized<HTTPSUrl>\n }\n origin: Localized<HTTPSUrl>\n outDir: PathLike\n serviceWorker?: {\n bypass?: Array<string | RegExp>\n initialize?: () => void\n precache?: URLPath[]\n waitUntil?: () => Promise<void>\n }\n shortName?: Localized<string>\n socialImage: {\n alt: Localized<string>\n height?: Localized<number>\n url: Localized<HTTPSUrl>\n width?: Localized<number>\n }\n stylesheet: PathLike\n themeColor: Localized<string>\n title: Localized<string>\n twitter: {\n creator: Localized<`@${string}`>\n site: Localized<`@${string}`>\n }\n}\n"],"mappings":"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"}
|
|
@@ -28,7 +28,11 @@ const routes = Object.freeze({
|
|
|
28
28
|
worker.addEventListener("fetch", (event) => {
|
|
29
29
|
event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]));
|
|
30
30
|
if (event.request.method !== "GET" || bypassesServiceWorker(event.request)) return;
|
|
31
|
-
|
|
31
|
+
if (new URL(event.request.url).pathname === buildIdUrl) {
|
|
32
|
+
event.respondWith(fetch(event.request, { cache: "no-store" }));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const route = event.request.mode === "navigate" && !staticRoutes.includes(new URL(event.request.url).pathname) ? routes.document : routes.static;
|
|
32
36
|
event.respondWith(route(event));
|
|
33
37
|
});
|
|
34
38
|
worker.addEventListener("install", (event) => {
|
|
@@ -77,6 +81,7 @@ async function renderDocument(language) {
|
|
|
77
81
|
stylesheet
|
|
78
82
|
});
|
|
79
83
|
return new Response(markup, { headers: {
|
|
84
|
+
"content-security-policy": contentSecurityPolicies[language],
|
|
80
85
|
"content-type": "text/html;charset=UTF-8",
|
|
81
86
|
"x-pwaize-build-id": buildId
|
|
82
87
|
} });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoint.cjs","names":["documentMarkup"],"sources":["../../src/serviceWorker/entrypoint.ts"],"sourcesContent":["import type { DocumentMarkupOptions } from '../.types/index.js'\nimport { documentMarkup } from '../htmlDocument/index.js'\n\ndeclare const buildId: string\ndeclare const buildIdUrl: string\ndeclare const bypassRules: ReadonlyArray<{\n absolute: boolean\n flags: string\n source: string\n}>\ndeclare const customInitialize: (() => void) | undefined\ndeclare const customWaitUntil: (() => Promise<void>) | undefined\ndeclare const defaultLanguage: DocumentMarkupOptions['language']\ndeclare const documentOptions: Readonly<\n Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n >\n>\ndeclare const entrypoint: string\ndeclare const precache: readonly string[]\ndeclare const stylesheet: string\n\nconst worker = self as unknown as ServiceWorkerGlobalScope\nconst cachePrefix = '@sovereignbase/pwa:'\nconst cacheName = `${cachePrefix}${buildId}`\nconst backgroundStartup = Promise.resolve(customWaitUntil?.())\n\ncustomInitialize?.()\n\nconst routes = Object.freeze({\n document: buildDocumentResponse,\n static: negotiateCache,\n})\n\nworker.addEventListener('fetch', (event) => {\n event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]))\n\n if (event.request.method !== 'GET' || bypassesServiceWorker(event.request)) {\n return\n }\n\n const route =\n event.request.mode === 'navigate' ? routes.document
|
|
1
|
+
{"version":3,"file":"entrypoint.cjs","names":["documentMarkup"],"sources":["../../src/serviceWorker/entrypoint.ts"],"sourcesContent":["import type { DocumentMarkupOptions } from '../.types/index.js'\nimport { documentMarkup } from '../htmlDocument/index.js'\n\ndeclare const buildId: string\ndeclare const buildIdUrl: string\ndeclare const bypassRules: ReadonlyArray<{\n absolute: boolean\n flags: string\n source: string\n}>\ndeclare const customInitialize: (() => void) | undefined\ndeclare const customWaitUntil: (() => Promise<void>) | undefined\ndeclare const defaultLanguage: DocumentMarkupOptions['language']\ndeclare const contentSecurityPolicies: Readonly<Record<string, string>>\ndeclare const documentOptions: Readonly<\n Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n >\n>\ndeclare const entrypoint: string\ndeclare const precache: readonly string[]\ndeclare const staticRoutes: readonly string[]\ndeclare const stylesheet: string\n\nconst worker = self as unknown as ServiceWorkerGlobalScope\nconst cachePrefix = '@sovereignbase/pwa:'\nconst cacheName = `${cachePrefix}${buildId}`\nconst backgroundStartup = Promise.resolve(customWaitUntil?.())\n\ncustomInitialize?.()\n\nconst routes = Object.freeze({\n document: buildDocumentResponse,\n static: negotiateCache,\n})\n\nworker.addEventListener('fetch', (event) => {\n event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]))\n\n if (event.request.method !== 'GET' || bypassesServiceWorker(event.request)) {\n return\n }\n\n if (new URL(event.request.url).pathname === buildIdUrl) {\n event.respondWith(fetch(event.request, { cache: 'no-store' }))\n return\n }\n\n const route =\n event.request.mode === 'navigate' &&\n !staticRoutes.includes(new URL(event.request.url).pathname)\n ? routes.document\n : routes.static\n event.respondWith(route(event))\n})\n\nworker.addEventListener('install', (event) => {\n event.waitUntil(\n Promise.all([\n caches.open(cacheName).then((cache) => cache.addAll(precache)),\n worker.skipWaiting(),\n backgroundStartup,\n ])\n )\n})\n\nworker.addEventListener('activate', (event) => {\n event.waitUntil(activateServiceWorker())\n})\n\nworker.addEventListener('message', (event) => {\n if (event.data === 'SKIP_WAITING') {\n event.waitUntil(worker.skipWaiting())\n }\n})\n\nasync function buildDocumentResponse(event: FetchEvent): Promise<Response> {\n const language = documentLanguage(event.request)\n const cache = await caches.open(cacheName)\n const cacheKey = documentCacheKey(event.request, language)\n const cached = await cache.match(cacheKey)\n const rendered = renderDocument(language).then(async (response) => {\n await cache.put(cacheKey, response.clone())\n return response\n })\n\n if (cached === undefined) return rendered\n\n event.waitUntil(rendered)\n return cached\n}\n\nasync function negotiateCache(event: FetchEvent): Promise<Response> {\n const cached = await caches.match(event.request)\n const updated = fetch(event.request).then(async (response) => {\n if (response.ok) {\n const cache = await caches.open(cacheName)\n await cache.put(event.request, response.clone())\n }\n return response\n })\n\n if (cached === undefined) return updated\n\n event.waitUntil(updated)\n return cached\n}\n\nasync function renderDocument(\n language: DocumentMarkupOptions['language']\n): Promise<Response> {\n const options = documentOptions[language]\n const markup = await documentMarkup({\n ...options,\n entrypoint,\n language,\n manifestUrl: `/${language}/manifest.webmanifest`,\n stylesheet,\n })\n\n return new Response(markup, {\n headers: {\n 'content-security-policy': contentSecurityPolicies[language],\n 'content-type': 'text/html;charset=UTF-8',\n 'x-pwaize-build-id': buildId,\n },\n })\n}\n\nfunction documentCacheKey(\n request: Request,\n language: DocumentMarkupOptions['language']\n): Request {\n const url = new URL(request.url)\n url.searchParams.set('__pwaize_language', language)\n return new Request(url)\n}\n\nfunction documentLanguage(request: Request): DocumentMarkupOptions['language'] {\n const pathLanguage = new URL(request.url).pathname\n .split('/')\n .filter(Boolean)[0]\n if (pathLanguage in documentOptions) {\n return pathLanguage as DocumentMarkupOptions['language']\n }\n\n const accepted = request.headers.get('accept-language') ?? ''\n for (const preference of accepted.split(',')) {\n const language = preference.split(';')[0].trim()\n if (language in documentOptions) {\n return language as DocumentMarkupOptions['language']\n }\n\n const baseLanguage = language.split('-')[0]\n if (baseLanguage in documentOptions) {\n return baseLanguage as DocumentMarkupOptions['language']\n }\n }\n\n return defaultLanguage\n}\n\nfunction bypassesServiceWorker(request: Request): boolean {\n const url = new URL(request.url)\n\n for (const rule of bypassRules) {\n const value = rule.absolute ? url.href : `${url.pathname}${url.search}`\n if (new RegExp(rule.source, rule.flags).test(value)) return true\n }\n\n return false\n}\n\nasync function checkForUpdate(): Promise<void> {\n try {\n const response = await fetch(buildIdUrl, { cache: 'no-store' })\n if (!response.ok || (await response.text()).trim() === buildId) return\n\n await worker.registration.update()\n } catch {\n // Offline version checks must not prevent offline responses.\n }\n}\n\nasync function activateServiceWorker(): Promise<void> {\n await Promise.all([\n deleteOldCaches(),\n worker.clients.claim(),\n backgroundStartup,\n ])\n}\n\nasync function deleteOldCaches(): Promise<void> {\n const names = await caches.keys()\n await Promise.all(\n names\n .filter((name) => name.startsWith(cachePrefix) && name !== cacheName)\n .map((name) => caches.delete(name))\n )\n}\n"],"mappings":"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"}
|
|
@@ -28,7 +28,11 @@ const routes = Object.freeze({
|
|
|
28
28
|
worker.addEventListener("fetch", (event) => {
|
|
29
29
|
event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]));
|
|
30
30
|
if (event.request.method !== "GET" || bypassesServiceWorker(event.request)) return;
|
|
31
|
-
|
|
31
|
+
if (new URL(event.request.url).pathname === buildIdUrl) {
|
|
32
|
+
event.respondWith(fetch(event.request, { cache: "no-store" }));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const route = event.request.mode === "navigate" && !staticRoutes.includes(new URL(event.request.url).pathname) ? routes.document : routes.static;
|
|
32
36
|
event.respondWith(route(event));
|
|
33
37
|
});
|
|
34
38
|
worker.addEventListener("install", (event) => {
|
|
@@ -77,6 +81,7 @@ async function renderDocument(language) {
|
|
|
77
81
|
stylesheet
|
|
78
82
|
});
|
|
79
83
|
return new Response(markup, { headers: {
|
|
84
|
+
"content-security-policy": contentSecurityPolicies[language],
|
|
80
85
|
"content-type": "text/html;charset=UTF-8",
|
|
81
86
|
"x-pwaize-build-id": buildId
|
|
82
87
|
} });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoint.js","names":[],"sources":["../../src/serviceWorker/entrypoint.ts"],"sourcesContent":["import type { DocumentMarkupOptions } from '../.types/index.js'\nimport { documentMarkup } from '../htmlDocument/index.js'\n\ndeclare const buildId: string\ndeclare const buildIdUrl: string\ndeclare const bypassRules: ReadonlyArray<{\n absolute: boolean\n flags: string\n source: string\n}>\ndeclare const customInitialize: (() => void) | undefined\ndeclare const customWaitUntil: (() => Promise<void>) | undefined\ndeclare const defaultLanguage: DocumentMarkupOptions['language']\ndeclare const documentOptions: Readonly<\n Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n >\n>\ndeclare const entrypoint: string\ndeclare const precache: readonly string[]\ndeclare const stylesheet: string\n\nconst worker = self as unknown as ServiceWorkerGlobalScope\nconst cachePrefix = '@sovereignbase/pwa:'\nconst cacheName = `${cachePrefix}${buildId}`\nconst backgroundStartup = Promise.resolve(customWaitUntil?.())\n\ncustomInitialize?.()\n\nconst routes = Object.freeze({\n document: buildDocumentResponse,\n static: negotiateCache,\n})\n\nworker.addEventListener('fetch', (event) => {\n event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]))\n\n if (event.request.method !== 'GET' || bypassesServiceWorker(event.request)) {\n return\n }\n\n const route =\n event.request.mode === 'navigate' ? routes.document
|
|
1
|
+
{"version":3,"file":"entrypoint.js","names":[],"sources":["../../src/serviceWorker/entrypoint.ts"],"sourcesContent":["import type { DocumentMarkupOptions } from '../.types/index.js'\nimport { documentMarkup } from '../htmlDocument/index.js'\n\ndeclare const buildId: string\ndeclare const buildIdUrl: string\ndeclare const bypassRules: ReadonlyArray<{\n absolute: boolean\n flags: string\n source: string\n}>\ndeclare const customInitialize: (() => void) | undefined\ndeclare const customWaitUntil: (() => Promise<void>) | undefined\ndeclare const defaultLanguage: DocumentMarkupOptions['language']\ndeclare const contentSecurityPolicies: Readonly<Record<string, string>>\ndeclare const documentOptions: Readonly<\n Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n >\n>\ndeclare const entrypoint: string\ndeclare const precache: readonly string[]\ndeclare const staticRoutes: readonly string[]\ndeclare const stylesheet: string\n\nconst worker = self as unknown as ServiceWorkerGlobalScope\nconst cachePrefix = '@sovereignbase/pwa:'\nconst cacheName = `${cachePrefix}${buildId}`\nconst backgroundStartup = Promise.resolve(customWaitUntil?.())\n\ncustomInitialize?.()\n\nconst routes = Object.freeze({\n document: buildDocumentResponse,\n static: negotiateCache,\n})\n\nworker.addEventListener('fetch', (event) => {\n event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]))\n\n if (event.request.method !== 'GET' || bypassesServiceWorker(event.request)) {\n return\n }\n\n if (new URL(event.request.url).pathname === buildIdUrl) {\n event.respondWith(fetch(event.request, { cache: 'no-store' }))\n return\n }\n\n const route =\n event.request.mode === 'navigate' &&\n !staticRoutes.includes(new URL(event.request.url).pathname)\n ? routes.document\n : routes.static\n event.respondWith(route(event))\n})\n\nworker.addEventListener('install', (event) => {\n event.waitUntil(\n Promise.all([\n caches.open(cacheName).then((cache) => cache.addAll(precache)),\n worker.skipWaiting(),\n backgroundStartup,\n ])\n )\n})\n\nworker.addEventListener('activate', (event) => {\n event.waitUntil(activateServiceWorker())\n})\n\nworker.addEventListener('message', (event) => {\n if (event.data === 'SKIP_WAITING') {\n event.waitUntil(worker.skipWaiting())\n }\n})\n\nasync function buildDocumentResponse(event: FetchEvent): Promise<Response> {\n const language = documentLanguage(event.request)\n const cache = await caches.open(cacheName)\n const cacheKey = documentCacheKey(event.request, language)\n const cached = await cache.match(cacheKey)\n const rendered = renderDocument(language).then(async (response) => {\n await cache.put(cacheKey, response.clone())\n return response\n })\n\n if (cached === undefined) return rendered\n\n event.waitUntil(rendered)\n return cached\n}\n\nasync function negotiateCache(event: FetchEvent): Promise<Response> {\n const cached = await caches.match(event.request)\n const updated = fetch(event.request).then(async (response) => {\n if (response.ok) {\n const cache = await caches.open(cacheName)\n await cache.put(event.request, response.clone())\n }\n return response\n })\n\n if (cached === undefined) return updated\n\n event.waitUntil(updated)\n return cached\n}\n\nasync function renderDocument(\n language: DocumentMarkupOptions['language']\n): Promise<Response> {\n const options = documentOptions[language]\n const markup = await documentMarkup({\n ...options,\n entrypoint,\n language,\n manifestUrl: `/${language}/manifest.webmanifest`,\n stylesheet,\n })\n\n return new Response(markup, {\n headers: {\n 'content-security-policy': contentSecurityPolicies[language],\n 'content-type': 'text/html;charset=UTF-8',\n 'x-pwaize-build-id': buildId,\n },\n })\n}\n\nfunction documentCacheKey(\n request: Request,\n language: DocumentMarkupOptions['language']\n): Request {\n const url = new URL(request.url)\n url.searchParams.set('__pwaize_language', language)\n return new Request(url)\n}\n\nfunction documentLanguage(request: Request): DocumentMarkupOptions['language'] {\n const pathLanguage = new URL(request.url).pathname\n .split('/')\n .filter(Boolean)[0]\n if (pathLanguage in documentOptions) {\n return pathLanguage as DocumentMarkupOptions['language']\n }\n\n const accepted = request.headers.get('accept-language') ?? ''\n for (const preference of accepted.split(',')) {\n const language = preference.split(';')[0].trim()\n if (language in documentOptions) {\n return language as DocumentMarkupOptions['language']\n }\n\n const baseLanguage = language.split('-')[0]\n if (baseLanguage in documentOptions) {\n return baseLanguage as DocumentMarkupOptions['language']\n }\n }\n\n return defaultLanguage\n}\n\nfunction bypassesServiceWorker(request: Request): boolean {\n const url = new URL(request.url)\n\n for (const rule of bypassRules) {\n const value = rule.absolute ? url.href : `${url.pathname}${url.search}`\n if (new RegExp(rule.source, rule.flags).test(value)) return true\n }\n\n return false\n}\n\nasync function checkForUpdate(): Promise<void> {\n try {\n const response = await fetch(buildIdUrl, { cache: 'no-store' })\n if (!response.ok || (await response.text()).trim() === buildId) return\n\n await worker.registration.update()\n } catch {\n // Offline version checks must not prevent offline responses.\n }\n}\n\nasync function activateServiceWorker(): Promise<void> {\n await Promise.all([\n deleteOldCaches(),\n worker.clients.claim(),\n backgroundStartup,\n ])\n}\n\nasync function deleteOldCaches(): Promise<void> {\n const names = await caches.keys()\n await Promise.all(\n names\n .filter((name) => name.startsWith(cachePrefix) && name !== cacheName)\n .map((name) => caches.delete(name))\n )\n}\n"],"mappings":"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"}
|