@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 CHANGED
@@ -1,15 +1,35 @@
1
- # @sovereignbase/pwa
1
+ [![npm version](https://img.shields.io/npm/v/@sovereignbase/pwa)](https://www.npmjs.com/package/@sovereignbase/pwa)
2
+ [![JSR](https://jsr.io/badges/@sovereignbase/pwa)](https://jsr.io/@sovereignbase/pwa)
3
+ [![CI](https://github.com/sovereignbase/pwa/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/sovereignbase/pwa/actions/workflows/ci.yaml)
4
+ [![codecov](https://codecov.io/gh/sovereignbase/pwa/branch/master/graph/badge.svg)](https://codecov.io/gh/sovereignbase/pwa)
5
+ [![license](https://img.shields.io/npm/l/@sovereignbase/pwa)](LICENSE)
2
6
 
3
- Build a TypeScript or JavaScript web project into a localized, offline-first and search-engine-optimized PWA. The package has one runtime export: `pwaize`.
7
+ # pwa
4
8
 
5
- ## Install
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
- Every semantic value is declared once. Any leaf value that may vary by language accepts either a scalar or a language record. Resolution is requested language, then `defaultLanguage`, then the field's empty/default value. A scalar or just the default-language value is therefore enough for shared content.
73
+ ## API
74
+
75
+ ### `pwaize(config)`
54
76
 
55
- ## Typed language modules
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
- Files under `i18nDir` ending in TypeScript or JavaScript are individually bundled, tree-shaken and minified to `.js`. Relative imports inside those modules are bundled. Other files are copied, and declaration files are ignored.
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 in the application bundle. For example, `en.ts` becomes `/i18n/en.js` and is included in the Service Worker precache.
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 belong to `defaultLanguage`. Each language also receives an indexed installer and manifest. Installer pages contain the inline Service Worker installer but not the application stylesheet or entrypoint. The Service Worker renders the actual localized HTML with the bundled application CSS and JavaScript.
96
-
97
- The worker uses stale-while-revalidate caching, precaches generated and copied public files, claims clients on activation, deletes older build caches and checks the deterministic content build ID for updates. `serviceWorker.bypass` accepts regular expressions and glob strings: `*` stays within one URL path segment, `**` crosses segments, and absolute patterns match the complete URL.
98
-
99
- Repeated builds in the same process reuse unchanged Terser, Lightning CSS and HTML minification results. Identical output keeps the same build ID; changing application, language, asset or worker content produces a new ID.
100
-
101
- See [example/entrypoint.js](./example/entrypoint.js) for the sample application and [test/index.js](./test/index.js) for its build driver.
102
-
103
- ## Verification
104
-
105
- ```sh
106
- npm test
107
- ```
108
-
109
- The suite includes TypeScript checks, 100% Vitest coverage, Node and Bun runtime builds, and Playwright desktop/mobile Chromium behavior tests for installation, localization, offline navigation and Service Worker bypass rules.
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) 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/*\n X-Content-Type-Options: nosniff\n`);
223
- const buildIdUrl = "/@sovereignbase/pwa/pwaize-build-id.txt";
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);
@@ -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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"}
@@ -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;;;;iBC5BQ,OAAO,QAAQ,eAAe;KAqYxC,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"}
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"}
@@ -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;;;;iBC5BQ,OAAO,QAAQ,eAAe;KAqYxC,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"}
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) await writeFile(join(outputDirectory, "_headers"), `/${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`);
222
- const buildIdUrl = "/@sovereignbase/pwa/pwaize-build-id.txt";
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
- const route = event.request.mode === "navigate" ? routes.document : routes.static;
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 : 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-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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"}
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
- const route = event.request.mode === "navigate" ? routes.document : routes.static;
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 : 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-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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"}
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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sovereignbase/pwa",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Build offline-first, search-engine-optimized progressive web applications.",
5
5
  "keywords": [
6
6
  "build-tool",