@sovereignbase/pwa 0.0.2 → 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/dist/index.js CHANGED
@@ -14,16 +14,25 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { t as documentMarkup } from "./htmlDocument-DABSNDvf.js";
17
+ import { t as documentMarkup } from "./htmlDocument-C533Sj5O.js";
18
+ import { createHash } from "node:crypto";
18
19
  import { existsSync } from "node:fs";
19
- import { cp, mkdir, readdir, writeFile } from "node:fs/promises";
20
- import { basename, join, relative, sep } from "node:path";
20
+ import { cp, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
21
+ import { basename, dirname, extname, join, relative, sep } from "node:path";
22
+ import { Bytes } from "@sovereignbase/bytecodec";
21
23
  import { build } from "esbuild";
22
24
  import { transform } from "lightningcss";
23
25
  import { minify } from "html-minifier-terser";
24
26
  import { fileURLToPath } from "node:url";
25
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
26
34
  //#region src/minifyCss/index.ts
35
+ const minifiedOutputs$2 = /* @__PURE__ */ new Map();
27
36
  /** Bundles and minifies a CSS entrypoint into a dense string. */
28
37
  async function minifyCss(entrypoint) {
29
38
  const bundled = await build({
@@ -35,18 +44,26 @@ async function minifyCss(entrypoint) {
35
44
  write: false,
36
45
  external: ["/assets/*"]
37
46
  });
47
+ const source = bundled.outputFiles[0].text;
48
+ const cached = minifiedOutputs$2.get(source);
49
+ if (cached !== void 0) return cached;
38
50
  const { code } = transform({
39
51
  code: bundled.outputFiles[0].contents,
40
52
  filename: entrypoint.toString(),
41
53
  minify: true
42
54
  });
43
- return new TextDecoder().decode(code).trim();
55
+ const output = new TextDecoder().decode(code).trim();
56
+ minifiedOutputs$2.set(source, output);
57
+ return output;
44
58
  }
45
59
  //#endregion
46
60
  //#region src/minifyHtml/index.ts
61
+ const minifiedOutputs$1 = /* @__PURE__ */ new Map();
47
62
  /** Minifies a complete HTML document, including inline CSS and JavaScript. */
48
63
  async function minifyHtml(source) {
49
- return minify(source, {
64
+ const cached = minifiedOutputs$1.get(source);
65
+ if (cached !== void 0) return cached;
66
+ const output = await minify(source, {
50
67
  collapseBooleanAttributes: true,
51
68
  collapseInlineTagWhitespace: true,
52
69
  collapseWhitespace: true,
@@ -72,17 +89,21 @@ async function minifyHtml(source) {
72
89
  sortClassName: true,
73
90
  useShortDoctype: true
74
91
  });
92
+ minifiedOutputs$1.set(source, output);
93
+ return output;
75
94
  }
76
95
  //#endregion
77
96
  //#region src/minifyJs/index.ts
97
+ const minifiedOutputs = /* @__PURE__ */ new Map();
78
98
  /** Bundles, tree-shakes, mangles, and repeatedly minifies JavaScript. */
79
- async function minifyJs(input, { define, passes = 3 } = {}) {
80
- let output = (await build({
99
+ async function minifyJs(input, { banner, define, passes = 3 } = {}) {
100
+ const output = (await build({
81
101
  ...typeof input === "object" && "source" in input ? { stdin: {
82
102
  contents: input.source,
83
103
  resolveDir: process.cwd()
84
104
  } } : { entryPoints: [input instanceof URL ? fileURLToPath(input) : input.toString()] },
85
105
  bundle: true,
106
+ banner: banner === void 0 ? void 0 : { js: banner },
86
107
  define,
87
108
  format: "esm",
88
109
  legalComments: "none",
@@ -91,6 +112,15 @@ async function minifyJs(input, { define, passes = 3 } = {}) {
91
112
  treeShaking: true,
92
113
  write: false
93
114
  })).outputFiles[0].text;
115
+ const cacheKey = `${passes}\0${output}`;
116
+ const cached = minifiedOutputs.get(cacheKey);
117
+ if (cached !== void 0) return cached;
118
+ const result = await repeatedlyMinify(output, passes);
119
+ minifiedOutputs.set(cacheKey, result);
120
+ return result;
121
+ }
122
+ async function repeatedlyMinify(source, passes) {
123
+ let output = source;
94
124
  for (let round = 0; round < passes; round += 1) {
95
125
  const result = await minify$1(output, {
96
126
  compress: {
@@ -108,6 +138,7 @@ async function minifyJs(input, { define, passes = 3 } = {}) {
108
138
  module: true,
109
139
  toplevel: true
110
140
  });
141
+ /* v8 ignore next 3 -- Terser returns code or rejects for this input form. */
111
142
  if (result.code === void 0) throw new Error("Terser did not produce JavaScript output");
112
143
  output = result.code;
113
144
  }
@@ -158,67 +189,149 @@ const webManifest = ({ name, shortName, description, startUrl, themeColor, icon1
158
189
  //#region src/index.ts
159
190
  async function pwaize(config) {
160
191
  const outputDirectory = join(config.outDir.toString(), "web");
161
- const buildId = crypto.randomUUID();
192
+ const languages = [.../* @__PURE__ */ new Set([config.defaultLanguage, ...config.alternateLanguages])];
162
193
  const minifyPasses = config.minifyPasses ?? 3;
194
+ const buildIdUrl = "/@sovereignbase/pwa/pwaize-build-id.txt";
163
195
  const serviceWorkerPath = "/ServiceWorker";
164
196
  await mkdir(outputDirectory, { recursive: true });
165
- for (const directory of [config.assetsDir, config.i18nDir]) {
166
- if (directory === void 0) continue;
167
- const sourceDirectory = directory.toString();
197
+ if (config.assetsDir !== void 0) {
198
+ const sourceDirectory = config.assetsDir.toString();
168
199
  await cp(sourceDirectory, join(outputDirectory, basename(sourceDirectory)), { recursive: true });
169
200
  }
201
+ if (config.i18nDir !== void 0) {
202
+ const sourceDirectory = config.i18nDir.toString();
203
+ await buildScriptDirectory(sourceDirectory, join(outputDirectory, basename(sourceDirectory)), minifyPasses);
204
+ }
170
205
  const stylesheet = await minifyCss(config.stylesheet);
171
206
  const entrypoint = await minifyJs(config.entrypoint, { passes: minifyPasses });
172
- const installer = await minifyJs({ source: `const registration=await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:"/",type:"module"});await navigator.serviceWorker.ready;if(!navigator.serviceWorker.controller)location.reload();` }, { passes: minifyPasses });
173
- const languages = [config.defaultLanguage, ...config.alternateLanguages];
207
+ const installer = await minifyJs({ source: `await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:"/",type:"module"});await navigator.serviceWorker.ready;location.reload();` }, { passes: minifyPasses });
208
+ const documentOptions = {};
209
+ const contentSecurityPolicies = {};
210
+ const installerDocuments = [];
174
211
  for (const language of languages) {
175
- const localized = config.languages[language];
176
- if (localized === void 0) throw new Error(`Missing PWA configuration for language "${language}"`);
212
+ const localized = localizeConfig(config, language, languages);
177
213
  const languageDirectory = join(outputDirectory, language);
178
214
  const manifestPath = `/${language}/manifest.webmanifest`;
179
- const manifest = webManifest({
180
- ...localized.manifest,
181
- lang: language
182
- });
215
+ const manifest = webManifest(localized.manifest);
216
+ documentOptions[language] = localized.document;
183
217
  await mkdir(languageDirectory, { recursive: true });
184
218
  await writeFile(join(languageDirectory, "manifest.webmanifest"), manifest);
185
219
  const installerDocument = await minifyHtml(await documentMarkup({
186
220
  ...localized.document,
187
- language,
188
- stylesheet: "",
189
221
  entrypoint: installer,
222
+ language,
190
223
  manifestUrl: manifestPath
191
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);
192
233
  await writeFile(join(languageDirectory, "index.html"), installerDocument);
193
234
  if (language === config.defaultLanguage) {
194
235
  await writeFile(join(outputDirectory, "index.html"), installerDocument);
195
236
  await writeFile(join(outputDirectory, "manifest.webmanifest"), manifest);
196
237
  }
197
238
  }
198
- const buildIdPath = join(outputDirectory, "@sovereignbase", "pwa", "pwaize-build-id.txt");
199
- await mkdir(join(outputDirectory, "@sovereignbase", "pwa"), { recursive: true });
200
- await writeFile(buildIdPath, buildId);
201
- 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`);
202
- const precache = [...await publicFiles(outputDirectory), ...config.serviceWorker?.precache ?? []];
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
+ }
244
+ const generatedFiles = (await publicFiles(outputDirectory)).filter((url) => url !== serviceWorkerPath && url !== buildIdUrl);
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();
203
247
  const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule);
204
- const compiledServiceWorker = new URL("./serviceWorker/entrypoint.js", import.meta.url);
205
- const serviceWorker = await minifyJs(existsSync(compiledServiceWorker) ? compiledServiceWorker : new URL("./serviceWorker/entrypoint.ts", import.meta.url), {
206
- define: {
207
- buildId: JSON.stringify(buildId),
208
- buildIdUrl: JSON.stringify("/@sovereignbase/pwa/pwaize-build-id.txt"),
209
- bypassRules: JSON.stringify(bypassRules),
210
- customInitialize: config.serviceWorker?.initialize === void 0 ? "undefined" : `(${config.serviceWorker.initialize.toString()})`,
211
- customWaitUntil: config.serviceWorker?.waitUntil === void 0 ? "undefined" : `(${config.serviceWorker.waitUntil.toString()})`,
212
- defaultLanguage: JSON.stringify(config.defaultLanguage),
213
- documentOptions: JSON.stringify(Object.fromEntries(languages.map((language) => [language, config.languages[language].document]))),
214
- entrypoint: JSON.stringify(entrypoint),
215
- precache: JSON.stringify(precache),
216
- stylesheet: JSON.stringify(stylesheet)
217
- },
218
- passes: minifyPasses
248
+ const initialize = config.serviceWorker?.initialize === void 0 ? "undefined" : functionExpression(config.serviceWorker.initialize);
249
+ const waitUntil = config.serviceWorker?.waitUntil === void 0 ? "undefined" : functionExpression(config.serviceWorker.waitUntil);
250
+ const buildId = await contentBuildId(outputDirectory, generatedFiles, {
251
+ bypassRules,
252
+ contentSecurityPolicies,
253
+ documentOptions,
254
+ entrypoint,
255
+ initialize,
256
+ precache,
257
+ staticRoutes,
258
+ stylesheet,
259
+ waitUntil
219
260
  });
261
+ const buildIdDirectory = join(outputDirectory, "@sovereignbase", "pwa");
262
+ await mkdir(buildIdDirectory, { recursive: true });
263
+ await writeFile(join(buildIdDirectory, "pwaize-build-id.txt"), buildId);
264
+ const compiledServiceWorker = new URL("./serviceWorker/entrypoint.js", import.meta.url);
265
+ const serviceWorker = await minifyJs(
266
+ /* v8 ignore next -- the packaged .js path is exercised by runtime tests */
267
+ existsSync(compiledServiceWorker) ? compiledServiceWorker : new URL("./serviceWorker/entrypoint.ts", import.meta.url),
268
+ {
269
+ banner: `const __pwaInitialize=${initialize},__pwaWaitUntil=${waitUntil};`,
270
+ define: {
271
+ buildId: JSON.stringify(buildId),
272
+ buildIdUrl: JSON.stringify(buildIdUrl),
273
+ bypassRules: JSON.stringify(bypassRules),
274
+ customInitialize: "__pwaInitialize",
275
+ customWaitUntil: "__pwaWaitUntil",
276
+ defaultLanguage: JSON.stringify(config.defaultLanguage),
277
+ contentSecurityPolicies: JSON.stringify(contentSecurityPolicies),
278
+ documentOptions: JSON.stringify(documentOptions),
279
+ entrypoint: JSON.stringify(entrypoint),
280
+ precache: JSON.stringify(precache),
281
+ staticRoutes: JSON.stringify(staticRoutes),
282
+ stylesheet: JSON.stringify(stylesheet)
283
+ },
284
+ passes: minifyPasses
285
+ }
286
+ );
220
287
  await writeFile(join(outputDirectory, serviceWorkerPath.slice(1)), serviceWorker);
221
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
+ }
310
+ async function buildScriptDirectory(sourceDirectory, outputDirectory, passes, root = sourceDirectory) {
311
+ for (const entry of await readdir(sourceDirectory, { withFileTypes: true })) {
312
+ const source = join(sourceDirectory, entry.name);
313
+ if (entry.isDirectory()) {
314
+ await buildScriptDirectory(source, outputDirectory, passes, root);
315
+ continue;
316
+ }
317
+ if (!entry.isFile() || entry.name.endsWith(".d.ts")) continue;
318
+ const relativePath = relative(root, source);
319
+ const extension = extname(relativePath);
320
+ const output = join(outputDirectory, /\.[cm]?[jt]sx?$/.test(extension) ? `${relativePath.slice(0, -extension.length)}.js` : relativePath);
321
+ await mkdir(dirname(output), { recursive: true });
322
+ if (/\.[cm]?[jt]sx?$/.test(extension)) await writeFile(output, await minifyJs(source, { passes }));
323
+ else await cp(source, output);
324
+ }
325
+ }
326
+ async function contentBuildId(outputDirectory, files, configuration) {
327
+ const hash = createHash("sha256");
328
+ hash.update(JSON.stringify(configuration));
329
+ for (const file of files) {
330
+ hash.update(file);
331
+ hash.update(await readFile(join(outputDirectory, ...file.slice(1).split("/"))));
332
+ }
333
+ return hash.digest("hex");
334
+ }
222
335
  async function publicFiles(directory, root = directory) {
223
336
  const entries = await readdir(directory, { withFileTypes: true });
224
337
  const files = [];
@@ -252,6 +365,118 @@ function globRule(pattern) {
252
365
  source: `${source}$`
253
366
  };
254
367
  }
368
+ function functionExpression(callback) {
369
+ const source = callback.toString();
370
+ if (/^(?:async\s+)?function\b|^(?:async\s+)?\(/.test(source)) return `(${source})`;
371
+ if (source.startsWith("async ")) return `(async function ${source.slice(6)})`;
372
+ return `(function ${source})`;
373
+ }
374
+ function localizeConfig(config, language, languages) {
375
+ const get = (value, empty) => localizedValue(value, language, config.defaultLanguage, empty);
376
+ const applicationName = get(config.applicationName, "");
377
+ const description = get(config.description, "");
378
+ const icon192 = get(config.icons.icon192, "");
379
+ const icon512 = get(config.icons.icon512, "");
380
+ const origin = get(config.origin, "");
381
+ const pageUrl = origin === "" ? "" : new URL(`/${language}`, origin).href;
382
+ const organizationLogo = origin === "" || icon512 === "" ? "" : new URL(icon512, origin).href;
383
+ const themeColor = get(config.themeColor, "");
384
+ const title = get(config.title, "");
385
+ return {
386
+ document: {
387
+ applicationName,
388
+ appleStatusBarStyle: get(config.appleStatusBarStyle, "black-translucent"),
389
+ appleTouchIconUrl: get(config.icons.appleTouchIconUrl, icon192),
390
+ bodyMarkup: get(config.bodyMarkup, ""),
391
+ colorScheme: get(config.colorScheme, "light dark"),
392
+ headMarkup: get(config.headMarkup, ""),
393
+ iconUrl: get(config.icons.iconUrl, icon512),
394
+ maskIconColor: themeColor,
395
+ maskIconUrl: get(config.icons.maskIconUrl, ""),
396
+ seo: {
397
+ jsonLD: {
398
+ application: {
399
+ applicationCategory: get(config.application?.category, ""),
400
+ browserRequirements: get(config.application?.browserRequirements, ""),
401
+ featureList: get(config.application?.featureList, []),
402
+ inLanguage: languages,
403
+ name: applicationName,
404
+ operatingSystem: get(config.application?.operatingSystem, ""),
405
+ url: origin
406
+ },
407
+ organization: {
408
+ logo: get(config.organization?.logoUrl, organizationLogo),
409
+ name: get(config.organization?.name, applicationName),
410
+ url: get(config.organization?.url, origin)
411
+ },
412
+ page: {
413
+ description,
414
+ inLanguage: language,
415
+ name: title,
416
+ url: pageUrl
417
+ },
418
+ site: {
419
+ name: applicationName,
420
+ url: origin
421
+ }
422
+ },
423
+ languageLinks: {
424
+ alternateLanguages: languages,
425
+ canonicalLanguage: config.canonicalLanguage,
426
+ defaultLanguage: config.defaultLanguage,
427
+ host: origin === "" ? "" : new URL(origin).host
428
+ },
429
+ openGraph: {
430
+ description,
431
+ imageAlt: get(config.socialImage.alt, ""),
432
+ imageHeight: get(config.socialImage.height, 630),
433
+ imageUrl: get(config.socialImage.url, ""),
434
+ imageWidth: get(config.socialImage.width, 1200),
435
+ locale: get(config.openGraphLocale, ""),
436
+ siteName: applicationName,
437
+ title,
438
+ url: pageUrl
439
+ },
440
+ twitter: {
441
+ creator: get(config.twitter.creator, ""),
442
+ description,
443
+ imageAlt: get(config.socialImage.alt, ""),
444
+ imageUrl: get(config.socialImage.url, ""),
445
+ site: get(config.twitter.site, ""),
446
+ title,
447
+ url: pageUrl
448
+ }
449
+ },
450
+ themeColor,
451
+ title
452
+ },
453
+ manifest: {
454
+ backgroundColor: get(config.backgroundColor, themeColor),
455
+ categories: get(config.manifest?.categories, []),
456
+ description,
457
+ display: get(config.manifest?.display, "standalone"),
458
+ icon192,
459
+ icon512,
460
+ id: get(config.manifest?.id, "/"),
461
+ lang: language,
462
+ maskableIcon512: get(config.icons.maskableIcon512, icon512),
463
+ name: applicationName,
464
+ orientation: get(config.manifest?.orientation, "any"),
465
+ scope: get(config.manifest?.scope, "/"),
466
+ screenshots: get(config.manifest?.screenshots, []),
467
+ shortName: get(config.shortName, applicationName),
468
+ shortcuts: get(config.manifest?.shortcuts, []),
469
+ startUrl: `/${language}`,
470
+ themeColor
471
+ }
472
+ };
473
+ }
474
+ function localizedValue(value, language, defaultLanguage, empty) {
475
+ if (value === void 0) return empty;
476
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return value;
477
+ const values = value;
478
+ return values[language] ?? values[defaultLanguage] ?? empty;
479
+ }
255
480
  //#endregion
256
481
  export { pwaize };
257
482
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["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\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 { code } = transform({\n code: bundled.outputFiles[0].contents,\n filename: entrypoint.toString(),\n minify: true,\n })\n\n return new TextDecoder().decode(code).trim()\n}\n","import { minify } from 'html-minifier-terser'\n\n/** Minifies a complete HTML document, including inline CSS and JavaScript. */\nexport default async function minifyHtml(source: string): Promise<string> {\n return 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}\n","import type { PathLike } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { build } from 'esbuild'\nimport { minify } from 'terser'\n\ntype JavaScriptInput = PathLike | { source: string }\n\ntype MinifyJsOptions = {\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 { 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 define,\n format: 'esm',\n legalComments: 'none',\n minify: true,\n platform: 'browser',\n treeShaking: true,\n write: false,\n })\n\n let output = bundled.outputFiles[0].text\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 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 { existsSync, type PathLike } from 'node:fs'\nimport { cp, mkdir, readdir, writeFile } from 'node:fs/promises'\nimport { basename, join, relative, sep } from 'node:path'\nimport type { BCP47LanguageTag } from '@sovereignbase/utils'\nimport type { DocumentMarkupOptions } 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 { webManifest, type WebManifestOptions } from './webManifest/index.js'\n\nexport async function pwaize(config: PWAizeConfig): Promise<void> {\n const outputDirectory = join(config.outDir.toString(), 'web')\n const buildId = crypto.randomUUID()\n const minifyPasses = config.minifyPasses ?? 3\n const serviceWorkerPath = '/ServiceWorker'\n\n await mkdir(outputDirectory, { recursive: true })\n\n for (const directory of [config.assetsDir, config.i18nDir]) {\n if (directory === undefined) continue\n\n const sourceDirectory = directory.toString()\n await cp(\n sourceDirectory,\n join(outputDirectory, basename(sourceDirectory)),\n {\n recursive: true,\n }\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: `const registration=await navigator.serviceWorker.register(${JSON.stringify(serviceWorkerPath)},{scope:\"/\",type:\"module\"});await navigator.serviceWorker.ready;if(!navigator.serviceWorker.controller)location.reload();`,\n },\n { passes: minifyPasses }\n )\n const languages = [config.defaultLanguage, ...config.alternateLanguages]\n\n for (const language of languages) {\n const localized = config.languages[language]\n if (localized === undefined) {\n throw new Error(`Missing PWA configuration for language \"${language}\"`)\n }\n\n const languageDirectory = join(outputDirectory, language)\n const manifestPath = `/${language}/manifest.webmanifest` as const\n const manifest = webManifest({\n ...localized.manifest,\n lang: language,\n })\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 language,\n stylesheet: '',\n entrypoint: installer,\n manifestUrl: manifestPath,\n })\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 const buildIdPath = join(\n outputDirectory,\n '@sovereignbase',\n 'pwa',\n 'pwaize-build-id.txt'\n )\n await mkdir(join(outputDirectory, '@sovereignbase', 'pwa'), {\n recursive: true,\n })\n await writeFile(buildIdPath, buildId)\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 precache = [\n ...(await publicFiles(outputDirectory)),\n ...(config.serviceWorker?.precache ?? []),\n ]\n const bypassRules = (config.serviceWorker?.bypass ?? []).map(globRule)\n const compiledServiceWorker = new URL(\n './serviceWorker/entrypoint.js',\n import.meta.url\n )\n const serviceWorker = await minifyJs(\n existsSync(compiledServiceWorker)\n ? compiledServiceWorker\n : new URL('./serviceWorker/entrypoint.ts', import.meta.url),\n {\n define: {\n buildId: JSON.stringify(buildId),\n buildIdUrl: JSON.stringify('/@sovereignbase/pwa/pwaize-build-id.txt'),\n bypassRules: JSON.stringify(bypassRules),\n customInitialize:\n config.serviceWorker?.initialize === undefined\n ? 'undefined'\n : `(${config.serviceWorker.initialize.toString()})`,\n customWaitUntil:\n config.serviceWorker?.waitUntil === undefined\n ? 'undefined'\n : `(${config.serviceWorker.waitUntil.toString()})`,\n defaultLanguage: JSON.stringify(config.defaultLanguage),\n documentOptions: JSON.stringify(\n Object.fromEntries(\n languages.map((language) => [\n language,\n config.languages[language].document,\n ])\n )\n ),\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 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 {\n absolute: true,\n flags: pattern.flags,\n source: pattern.source,\n }\n }\n\n let source = '^'\n for (let index = 0; index < pattern.length; index += 1) {\n const character = pattern[index]\n\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\nexport type PWAizeConfig = {\n defaultLanguage: BCP47LanguageTag\n canonicalLanguage: BCP47LanguageTag\n alternateLanguages: BCP47LanguageTag[]\n\n languages: Record<\n string,\n {\n document: Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n manifest: Omit<WebManifestOptions, 'lang'>\n }\n >\n\n stylesheet: PathLike\n entrypoint: PathLike\n outDir: PathLike\n\n assetsDir?: PathLike\n i18nDir?: PathLike\n minifyPasses?: number\n\n serviceWorker?: {\n bypass?: Array<string | RegExp>\n precache?: `/${string}`[]\n initialize?: () => void\n waitUntil?: () => Promise<void>\n }\n\n _headersFile?: boolean\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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"}
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- const require_htmlDocument = require("../htmlDocument-Cx-dprM5.cjs");
17
+ const require_htmlDocument = require("../htmlDocument-C3k13Sjr.cjs");
18
18
  //#region src/serviceWorker/entrypoint.ts
19
19
  const worker = self;
20
20
  const cachePrefix = "@sovereignbase/pwa:";
@@ -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) => {
@@ -45,10 +49,12 @@ worker.addEventListener("message", (event) => {
45
49
  if (event.data === "SKIP_WAITING") event.waitUntil(worker.skipWaiting());
46
50
  });
47
51
  async function buildDocumentResponse(event) {
52
+ const language = documentLanguage(event.request);
48
53
  const cache = await caches.open(cacheName);
49
- const cached = await cache.match(event.request);
50
- const rendered = renderDocument(event.request).then(async (response) => {
51
- await cache.put(event.request, response.clone());
54
+ const cacheKey = documentCacheKey(event.request, language);
55
+ const cached = await cache.match(cacheKey);
56
+ const rendered = renderDocument(language).then(async (response) => {
57
+ await cache.put(cacheKey, response.clone());
52
58
  return response;
53
59
  });
54
60
  if (cached === void 0) return rendered;
@@ -65,9 +71,8 @@ async function negotiateCache(event) {
65
71
  event.waitUntil(updated);
66
72
  return cached;
67
73
  }
68
- async function renderDocument(request) {
69
- const language = documentLanguage(request);
70
- const options = documentOptions[language] ?? documentOptions[defaultLanguage];
74
+ async function renderDocument(language) {
75
+ const options = documentOptions[language];
71
76
  const markup = await require_htmlDocument.documentMarkup({
72
77
  ...options,
73
78
  entrypoint,
@@ -76,10 +81,16 @@ async function renderDocument(request) {
76
81
  stylesheet
77
82
  });
78
83
  return new Response(markup, { headers: {
84
+ "content-security-policy": contentSecurityPolicies[language],
79
85
  "content-type": "text/html;charset=UTF-8",
80
86
  "x-pwaize-build-id": buildId
81
87
  } });
82
88
  }
89
+ function documentCacheKey(request, language) {
90
+ const url = new URL(request.url);
91
+ url.searchParams.set("__pwaize_language", language);
92
+ return new Request(url);
93
+ }
83
94
  function documentLanguage(request) {
84
95
  const pathLanguage = new URL(request.url).pathname.split("/").filter(Boolean)[0];
85
96
  if (pathLanguage in documentOptions) return pathLanguage;
@@ -113,11 +124,6 @@ async function activateServiceWorker() {
113
124
  worker.clients.claim(),
114
125
  backgroundStartup
115
126
  ]);
116
- const clients = await worker.clients.matchAll({
117
- includeUncontrolled: true,
118
- type: "window"
119
- });
120
- await Promise.all(clients.map((client) => client.navigate(client.url)));
121
127
  }
122
128
  async function deleteOldCaches() {
123
129
  const names = await caches.keys();