@vite-pwa/nuxt 1.1.0 → 2.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.
Files changed (50) hide show
  1. package/README.md +28 -59
  2. package/config/index.d.mts +1 -0
  3. package/config/index.mjs +3 -0
  4. package/configuration.d.ts +3 -0
  5. package/dist/chunks/create-nuxt-pwa-context.mjs +27 -0
  6. package/dist/chunks/prepare-module.mjs +871 -0
  7. package/dist/chunks/prepare-pwa-icons.mjs +161 -0
  8. package/dist/module.d.mts +42 -89
  9. package/dist/module.json +5 -5
  10. package/dist/module.mjs +40 -8
  11. package/dist/runtime/components/NuxtPwaAssets.d.ts +1 -1
  12. package/dist/runtime/components/NuxtPwaAssets.js +8 -4
  13. package/dist/runtime/components/{VitePwaManifest.d.ts → NuxtPwaManifest.d.ts} +1 -1
  14. package/dist/runtime/components/{VitePwaManifest.js → NuxtPwaManifest.js} +2 -2
  15. package/dist/runtime/{composables/index.d.ts → composables.d.ts} +12 -28
  16. package/dist/runtime/{composables/index.js → composables.js} +1 -11
  17. package/dist/runtime/plugins/pwa-install.client.d.ts +6 -0
  18. package/dist/runtime/plugins/pwa-install.client.js +70 -0
  19. package/dist/runtime/plugins/pwa.client.d.ts +1 -1
  20. package/dist/runtime/plugins/pwa.client.js +90 -77
  21. package/dist/runtime/plugins/types.d.ts +70 -129
  22. package/dist/runtime/plugins/types.js +0 -0
  23. package/dist/types.d.mts +5 -5
  24. package/package.json +40 -59
  25. package/dist/chunks/dev.mjs +0 -37
  26. package/dist/chunks/pwa-icons.mjs +0 -155
  27. package/dist/module.cjs +0 -5
  28. package/dist/module.d.ts +0 -110
  29. package/dist/runtime/components/PwaAppleImage.vue +0 -12
  30. package/dist/runtime/components/PwaAppleImage.vue.d.ts +0 -2
  31. package/dist/runtime/components/PwaAppleSplashScreenImage.vue +0 -12
  32. package/dist/runtime/components/PwaAppleSplashScreenImage.vue.d.ts +0 -2
  33. package/dist/runtime/components/PwaFaviconImage.vue +0 -12
  34. package/dist/runtime/components/PwaFaviconImage.vue.d.ts +0 -2
  35. package/dist/runtime/components/PwaMaskableImage.vue +0 -12
  36. package/dist/runtime/components/PwaMaskableImage.vue.d.ts +0 -2
  37. package/dist/runtime/components/PwaTransparentImage.vue +0 -12
  38. package/dist/runtime/components/PwaTransparentImage.vue.d.ts +0 -2
  39. package/dist/runtime/components/nuxt4/PwaAppleImage.d.ts +0 -4
  40. package/dist/runtime/components/nuxt4/PwaAppleImage.js +0 -15
  41. package/dist/runtime/components/nuxt4/PwaAppleSplashScreenImage.d.ts +0 -4
  42. package/dist/runtime/components/nuxt4/PwaAppleSplashScreenImage.js +0 -15
  43. package/dist/runtime/components/nuxt4/PwaFaviconImage.d.ts +0 -4
  44. package/dist/runtime/components/nuxt4/PwaFaviconImage.js +0 -15
  45. package/dist/runtime/components/nuxt4/PwaMaskableImage.d.ts +0 -4
  46. package/dist/runtime/components/nuxt4/PwaMaskableImage.js +0 -15
  47. package/dist/runtime/components/nuxt4/PwaTransparentImage.d.ts +0 -4
  48. package/dist/runtime/components/nuxt4/PwaTransparentImage.js +0 -15
  49. package/dist/shared/nuxt.00c26fe8.mjs +0 -734
  50. package/dist/types.d.ts +0 -15
@@ -1,734 +0,0 @@
1
- import { addPluginTemplate, addTypeTemplate, addImports, createResolver, getNuxtVersion, resolveAlias, addPlugin, addComponent, extendWebpackConfig, addDevServerHandler, defineNuxtModule } from '@nuxt/kit';
2
- import { lstat, writeFile, mkdir } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- import { VitePWA } from 'vite-plugin-pwa';
5
- import { createHash } from 'node:crypto';
6
- import { createReadStream } from 'node:fs';
7
- import { resolve } from 'pathe';
8
-
9
- const version = "1.1.0";
10
-
11
- function configurePWAOptions(ctx, nitroConfig) {
12
- const { nuxt3_8, options, nuxt } = ctx;
13
- if (!options.outDir) {
14
- const publicDir = nitroConfig.output?.publicDir ?? nuxt.options.nitro?.output?.publicDir;
15
- options.outDir = publicDir ? resolve(publicDir) : resolve(nuxt.options.buildDir, "../.output/public");
16
- }
17
- if (options.devOptions?.enabled)
18
- options.devOptions.resolveTempFolder = () => resolve(nuxt.options.buildDir, "dev-sw-dist");
19
- let config;
20
- if (options.strategies === "injectManifest") {
21
- options.injectManifest = options.injectManifest ?? {};
22
- config = options.injectManifest;
23
- } else {
24
- options.strategies = "generateSW";
25
- options.workbox = options.workbox ?? {};
26
- if (options.registerType === "autoUpdate" && (options.client?.registerPlugin || options.injectRegister === "script" || options.injectRegister === "inline")) {
27
- options.workbox.clientsClaim = true;
28
- options.workbox.skipWaiting = true;
29
- }
30
- if (nuxt.options.dev) {
31
- options.workbox.navigateFallback = options.workbox.navigateFallback ?? nuxt.options.app.baseURL ?? "/";
32
- if (options.devOptions?.enabled && !options.devOptions.navigateFallbackAllowlist) {
33
- const baseURL = nuxt.options.app.baseURL;
34
- options.devOptions.navigateFallbackAllowlist = [baseURL ? new RegExp(`^${baseURL.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")}$`) : /^\/$/];
35
- }
36
- }
37
- if (!("navigateFallback" in options.workbox))
38
- options.workbox.navigateFallback = nuxt.options.app.baseURL ?? "/";
39
- config = options.workbox;
40
- }
41
- let buildAssetsDir = nuxt.options.app.buildAssetsDir ?? "_nuxt/";
42
- if (buildAssetsDir[0] === "/")
43
- buildAssetsDir = buildAssetsDir.slice(1);
44
- if (buildAssetsDir[buildAssetsDir.length - 1] !== "/")
45
- buildAssetsDir += "/";
46
- if (!("dontCacheBustURLsMatching" in config))
47
- config.dontCacheBustURLsMatching = new RegExp(buildAssetsDir);
48
- if (nuxt.options.experimental.payloadExtraction) {
49
- const enableGlobPatterns = nuxt.options.nitro.static || nuxt.options._generate || (!!nitroConfig.prerender?.routes?.length || Object.values(nitroConfig.routeRules ?? {}).some((r) => r.prerender));
50
- if (enableGlobPatterns) {
51
- config.globPatterns = config.globPatterns ?? [];
52
- config.globPatterns.push("**/_payload.json");
53
- if (options.strategies === "generateSW" && options.experimental?.enableWorkboxPayloadQueryParams) {
54
- options.workbox.runtimeCaching = options.workbox.runtimeCaching ?? [];
55
- options.workbox.runtimeCaching.push({
56
- urlPattern: /\/_payload\.json\?/,
57
- handler: "NetworkOnly",
58
- options: {
59
- plugins: [{
60
- /* this callback will be called when the fetch call fails */
61
- handlerDidError: async ({ request }) => {
62
- const url = new URL(request.url);
63
- url.search = "";
64
- return Response.redirect(url.href, 302);
65
- },
66
- /* this callback will prevent caching the response */
67
- cacheWillUpdate: async () => null
68
- }]
69
- }
70
- });
71
- }
72
- }
73
- }
74
- let appManifestFolder;
75
- if (nuxt3_8 && nuxt.options.experimental.appManifest) {
76
- config.globPatterns = config.globPatterns ?? [];
77
- appManifestFolder = `${buildAssetsDir}builds/`;
78
- config.globPatterns.push(`${appManifestFolder}**/*.json`);
79
- }
80
- if (!nuxt.options.dev && !config.manifestTransforms)
81
- config.manifestTransforms = [createManifestTransform(nuxt.options.app.baseURL ?? "/", options.outDir, appManifestFolder)];
82
- if (options.pwaAssets) {
83
- options.pwaAssets.integration = {
84
- baseUrl: nuxt.options.app.baseURL ?? "/",
85
- publicDir: ctx.publicDirFolder,
86
- outDir: options.outDir
87
- };
88
- }
89
- const integration = options.integration ?? {};
90
- const {
91
- beforeBuildServiceWorker: original,
92
- ...rest
93
- } = integration;
94
- options.integration = {
95
- ...rest,
96
- async beforeBuildServiceWorker(resolvedPwaOptions) {
97
- await original?.(resolvedPwaOptions);
98
- await nuxt.callHook("pwa:beforeBuildServiceWorker", resolvedPwaOptions);
99
- }
100
- };
101
- }
102
- function createManifestTransform(base, publicFolder, appManifestFolder) {
103
- return async (entries) => {
104
- entries.filter((e) => e.url.endsWith(".html")).forEach((e) => {
105
- const url = e.url.startsWith("/") ? e.url.slice(1) : e.url;
106
- if (url === "index.html") {
107
- e.url = base;
108
- } else {
109
- const parts = url.split("/");
110
- parts[parts.length - 1] = parts[parts.length - 1].replace(/\.html$/, "");
111
- e.url = parts.length > 1 ? parts.slice(0, parts.length - 1).join("/") : parts[0];
112
- }
113
- });
114
- if (appManifestFolder) {
115
- const regExp = /(\/)?[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}\.json$/i;
116
- entries.filter((e) => e.url.startsWith(appManifestFolder) && regExp.test(e.url)).forEach((e) => {
117
- e.revision = null;
118
- });
119
- const latest = `${appManifestFolder}latest.json`;
120
- const latestJson = resolve(publicFolder, latest);
121
- const data = await lstat(latestJson).catch(() => void 0);
122
- if (data?.isFile()) {
123
- const revision = await new Promise((resolve2, reject) => {
124
- const cHash = createHash("MD5");
125
- const stream = createReadStream(latestJson);
126
- stream.on("error", (err) => {
127
- reject(err);
128
- });
129
- stream.on("data", (chunk) => cHash.update(chunk));
130
- stream.on("end", () => {
131
- resolve2(cHash.digest("hex"));
132
- });
133
- });
134
- const latestEntry = entries.find((e) => e.url === latest);
135
- if (latestEntry)
136
- latestEntry.revision = revision;
137
- else
138
- entries.push({ url: latest, revision, size: data.size });
139
- } else {
140
- entries = entries.filter((e) => e.url !== latest);
141
- }
142
- }
143
- return { manifest: entries, warnings: [] };
144
- };
145
- }
146
-
147
- function addPwaTypeTemplate(filename, isNuxt4, content) {
148
- if (content?.length) {
149
- return addTypeTemplate({
150
- write: true,
151
- filename: `pwa-icons/${filename}.d.ts`,
152
- getContents: () => content
153
- }).dst;
154
- } else {
155
- return addTypeTemplate({
156
- write: true,
157
- getContents: () => generatePwaImageType(filename, isNuxt4),
158
- filename: `pwa-icons/${filename}.d.ts`
159
- }).dst;
160
- }
161
- }
162
- function pwaIcons(types) {
163
- return `// Generated by @vite-pwa/nuxt
164
- import type { AppleSplashScreenLink, FaviconLink, HtmlLink, IconAsset } from '@vite-pwa/assets-generator/api'
165
-
166
- export interface PWAAssetIconImage {
167
- width?: number
168
- height?: number
169
- key: string
170
- src: string
171
- }
172
- export type PWAAssetIcon<T extends HtmlLink> = Omit<IconAsset<T>, 'buffer'> & {
173
- asImage: PWAAssetIconImage
174
- }
175
- export interface PWAIcons {
176
- transparent: Record<${generateTypes(types?.transparent)}, PWAAssetIcon<HtmlLink>>
177
- maskable: Record<${generateTypes(types?.maskable)}, PWAAssetIcon<HtmlLink>>
178
- favicon: Record<${generateTypes(types?.favicon)}, PWAAssetIcon<FaviconLink>>
179
- apple: Record<${generateTypes(types?.apple)}, PWAAssetIcon<HtmlLink>>
180
- appleSplashScreen: Record<${generateTypes(types?.appleSplashScreen)}, PWAAssetIcon<AppleSplashScreenLink>>
181
- }
182
-
183
- declare module '#app' {
184
- interface NuxtApp {
185
- $pwaIcons?: PWAIcons
186
- }
187
- }
188
-
189
- declare module 'vue' {
190
- interface ComponentCustomProperties {
191
- $pwaIcons?: PWAIcons
192
- }
193
- }
194
-
195
- export {}
196
- `;
197
- }
198
- function generatePwaImageType(filename, isNuxt4, names) {
199
- const propsName = `${filename}Props`;
200
- if (isNuxt4) {
201
- return `// Generated by @vite-pwa/nuxt
202
- export interface ${propsName} {
203
- image: ${generateTypes(names)}
204
- alt?: string
205
- width?: number
206
- height?: number
207
- crossorigin?: '' | 'anonymous' | 'use-credentials'
208
- loading?: 'lazy' | 'eager'
209
- decoding?: 'async' | 'auto' | 'sync'
210
- nonce?: string
211
- }
212
- `;
213
- }
214
- return `// Generated by @vite-pwa/nuxt
215
- export interface ${propsName} {
216
- image: ${generateTypes(names)}
217
- alt?: string
218
- width?: number
219
- height?: number
220
- crossorigin?: '' | 'anonymous' | 'use-credentials'
221
- loading?: 'lazy' | 'eager'
222
- decoding?: 'async' | 'auto' | 'sync'
223
- nonce?: string
224
- }
225
- type __VLS_NonUndefinedable<T> = T extends undefined ? never : T
226
- type __VLS_TypePropsToRuntimeProps<T> = {
227
- [K in keyof T]-?: {} extends Pick<T, K> ? {
228
- type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>
229
- } : {
230
- type: import('vue').PropType<T[K]>
231
- required: true
232
- }
233
- }
234
- declare const _default: import('vue').DefineComponent<__VLS_TypePropsToRuntimeProps<${propsName}>, {}, unknown, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<${propsName}>>>, {}, {}>
235
- export default _default
236
- `;
237
- }
238
- function generateTypes(types) {
239
- return types?.length ? types.map((name) => `'${name}'`).join(" | ") : "string";
240
- }
241
- function addPWAIconsPluginTemplate(pwaAssetsEnabled) {
242
- if (pwaAssetsEnabled) {
243
- addPluginTemplate({
244
- filename: "pwa-icons-plugin.ts",
245
- name: "vite-pwa:nuxt:pwa-icons-plugin",
246
- write: true,
247
- getContents: () => `// Generated by @vite-pwa/nuxt
248
- import { defineNuxtPlugin } from '#imports'
249
- import { pwaAssetsIcons } from 'virtual:pwa-assets/icons'
250
- import type { PWAAssetIcon, PWAIcons } from '#build/pwa-icons/pwa-icons'
251
-
252
- export default defineNuxtPlugin(() => {
253
- return {
254
- provide: {
255
- pwaIcons: {
256
- transparent: configureEntry('transparent'),
257
- maskable: configureEntry('maskable'),
258
- favicon: configureEntry('favicon'),
259
- apple: configureEntry('apple'),
260
- appleSplashScreen: configureEntry('appleSplashScreen')
261
- } satisfies PWAIcons
262
- }
263
- }
264
- })
265
-
266
- function configureEntry<K extends keyof PWAIcons>(key: K) {
267
- return Object.values(pwaAssetsIcons[key] ?? {}).reduce((acc, icon) => {
268
- const entry: PWAAssetIcon<any> = {
269
- ...icon,
270
- asImage: {
271
- src: icon.url,
272
- key: \`\${key}-\${icon.name}\`
273
- }
274
- }
275
- if (icon.width && icon.height) {
276
- entry.asImage.width = icon.width
277
- entry.asImage.height = icon.height
278
- }
279
- ;(acc as unknown as any)[icon.name] = entry
280
- return acc
281
- }, {} as PWAIcons[typeof key])
282
- }
283
- `
284
- });
285
- } else {
286
- addPluginTemplate({
287
- filename: "pwa-icons-plugin.ts",
288
- name: "vite-pwa:nuxt:pwa-icons-plugin",
289
- write: true,
290
- getContents: () => `// Generated by @vite-pwa/nuxt
291
- import { defineNuxtPlugin } from '#imports'
292
- import type { PWAIcons } from '#build/pwa-icons/pwa-icons'
293
-
294
- export default defineNuxtPlugin(() => {
295
- return {
296
- provide: {
297
- pwaIcons: {
298
- transparent: {},
299
- maskable: {},
300
- favicon: {},
301
- apple: {},
302
- appleSplashScreen: {}
303
- } satisfies PWAIcons
304
- }
305
- }
306
- })
307
- `
308
- });
309
- }
310
- }
311
-
312
- async function registerPwaIconsTypes(ctx, runtimeDir) {
313
- const { options, nuxt, resolver } = ctx;
314
- const pwaAssets = options.pwaAssets && !options.pwaAssets.disabled;
315
- let dts;
316
- if (pwaAssets) {
317
- try {
318
- const { preparePWAIconTypes } = await import('../chunks/pwa-icons.mjs');
319
- dts = await preparePWAIconTypes(ctx);
320
- } catch {
321
- dts = void 0;
322
- }
323
- }
324
- nuxt.options.alias["#pwa"] = resolver.resolve(runtimeDir, "composables/index");
325
- nuxt.options.build.transpile.push("#pwa");
326
- addImports([
327
- "usePWA",
328
- "useTransparentPwaIcon",
329
- "useMaskablePwaIcon",
330
- "useFaviconPwaIcon",
331
- "useApplePwaIcon",
332
- "useAppleSplashScreenPwaIcon"
333
- ].map((key) => ({
334
- name: key,
335
- as: key,
336
- from: resolver.resolve(runtimeDir, "composables/index")
337
- })));
338
- const templates = [];
339
- const isNuxt4 = ctx.nuxt4;
340
- const dtsContent = dts?.dts;
341
- if (dtsContent) {
342
- templates.push(addTypeTemplate({
343
- write: true,
344
- filename: "pwa-icons/pwa-icons.d.ts",
345
- getContents: () => dtsContent
346
- }).dst);
347
- } else {
348
- templates.push(addTypeTemplate({
349
- write: true,
350
- filename: "pwa-icons/pwa-icons.d.ts",
351
- getContents: () => pwaIcons()
352
- }).dst);
353
- }
354
- templates.push(addPwaTypeTemplate("PwaTransparentImage", isNuxt4, dts?.transparent));
355
- templates.push(addPwaTypeTemplate("PwaMaskableImage", isNuxt4, dts?.maskable));
356
- templates.push(addPwaTypeTemplate("PwaFaviconImage", isNuxt4, dts?.favicon));
357
- templates.push(addPwaTypeTemplate("PwaAppleImage", isNuxt4, dts?.apple));
358
- templates.push(addPwaTypeTemplate("PwaAppleSplashScreenImage", isNuxt4, dts?.appleSplashScreen));
359
- if (ctx.nuxt4) {
360
- ctx.nuxt.hook("prepare:types", (context) => {
361
- const nodeReferences = context.nodeReferences;
362
- for (const path of templates) {
363
- nodeReferences.push({ path });
364
- }
365
- });
366
- }
367
- return !!dts;
368
- }
369
-
370
- async function regeneratePWA(_dir, pwaAssets, api) {
371
- if (pwaAssets) {
372
- const pwaAssetsGenerator = await api?.pwaAssetsGenerator();
373
- if (pwaAssetsGenerator)
374
- await pwaAssetsGenerator.generate();
375
- }
376
- if (!api || api.disabled)
377
- return;
378
- await api.generateSW();
379
- }
380
- async function writeWebManifest(dir, path, api, pwaAssets) {
381
- if (pwaAssets) {
382
- const pwaAssetsGenerator = await api.pwaAssetsGenerator();
383
- if (pwaAssetsGenerator)
384
- pwaAssetsGenerator.injectManifestIcons();
385
- }
386
- const manifest = api.generateBundle({})?.[path];
387
- if (manifest && "source" in manifest)
388
- await writeFile(resolve(dir, path), manifest.source, "utf-8");
389
- }
390
-
391
- async function doSetup(options, nuxt) {
392
- const resolver = createResolver(import.meta.url);
393
- const nuxtVersion = getNuxtVersion(nuxt).split(".").map((v) => Number.parseInt(v));
394
- const nuxt3_8 = nuxtVersion.length > 1 && (nuxtVersion[0] > 3 || nuxtVersion[0] === 3 && nuxtVersion[1] >= 8);
395
- const nuxt4 = nuxtVersion.length > 1 && nuxtVersion[0] >= 4;
396
- const future = nuxt.options.future;
397
- const ctx = {
398
- nuxt,
399
- nuxt3_8,
400
- nuxt4,
401
- // included at v3.12.0, then removed and included back again for v5 compatibility: we only need the layout to configure correctly the pwa assets image
402
- // https://github.com/nuxt/nuxt/releases/tag/v3.12.0
403
- nuxt4Compat: nuxt4 ? true : "compatibilityVersion" in future && typeof future.compatibilityVersion === "number" && future.compatibilityVersion >= 4,
404
- resolver: createResolver(import.meta.url),
405
- options,
406
- publicDirFolder: resolveAlias("public")
407
- };
408
- let vitePwaClientPlugin;
409
- const resolveVitePluginPWAAPI = () => {
410
- return vitePwaClientPlugin?.api;
411
- };
412
- const client = options.client ?? {
413
- registerPlugin: true,
414
- installPrompt: false,
415
- periodicSyncForUpdates: 0
416
- };
417
- const runtimeDir = resolver.resolve("../runtime");
418
- nuxt.options.build.transpile.push(runtimeDir);
419
- if (client.registerPlugin) {
420
- addPlugin({
421
- src: resolver.resolve(runtimeDir, "plugins/pwa.client"),
422
- mode: "client"
423
- });
424
- }
425
- const pwaAssetsEnabled = !!options.pwaAssets && options.pwaAssets.disabled !== true;
426
- addPWAIconsPluginTemplate(pwaAssetsEnabled);
427
- if (ctx.nuxt4) {
428
- await Promise.all([
429
- addComponent({
430
- name: "VitePwaManifest",
431
- filePath: resolver.resolve(runtimeDir, "components/VitePwaManifest")
432
- }),
433
- addComponent({
434
- name: "NuxtPwaManifest",
435
- filePath: resolver.resolve(runtimeDir, "components/VitePwaManifest")
436
- }),
437
- addComponent({
438
- name: "NuxtPwaAssets",
439
- filePath: resolver.resolve(runtimeDir, "components/NuxtPwaAssets")
440
- }),
441
- addComponent({
442
- name: "PwaAppleImage",
443
- filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaAppleImage")
444
- }),
445
- addComponent({
446
- name: "PwaAppleSplashScreenImage",
447
- filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaAppleSplashScreenImage")
448
- }),
449
- addComponent({
450
- name: "PwaFaviconImage",
451
- filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaFaviconImage")
452
- }),
453
- addComponent({
454
- name: "PwaMaskableImage",
455
- filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaMaskableImage")
456
- }),
457
- addComponent({
458
- name: "PwaTransparentImage",
459
- filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaTransparentImage")
460
- })
461
- ]);
462
- } else {
463
- await Promise.all([
464
- addComponent({
465
- name: "VitePwaManifest",
466
- filePath: resolver.resolve(runtimeDir, "components/VitePwaManifest")
467
- }),
468
- addComponent({
469
- name: "NuxtPwaManifest",
470
- filePath: resolver.resolve(runtimeDir, "components/VitePwaManifest")
471
- }),
472
- addComponent({
473
- name: "NuxtPwaAssets",
474
- filePath: resolver.resolve(runtimeDir, "components/NuxtPwaAssets")
475
- }),
476
- addComponent({
477
- name: "PwaAppleImage",
478
- filePath: resolver.resolve(runtimeDir, "components/PwaAppleImage.vue")
479
- }),
480
- addComponent({
481
- name: "PwaAppleSplashScreenImage",
482
- filePath: resolver.resolve(runtimeDir, "components/PwaAppleSplashScreenImage.vue")
483
- }),
484
- addComponent({
485
- name: "PwaFaviconImage",
486
- filePath: resolver.resolve(runtimeDir, "components/PwaFaviconImage.vue")
487
- }),
488
- addComponent({
489
- name: "PwaMaskableImage",
490
- filePath: resolver.resolve(runtimeDir, "components/PwaMaskableImage.vue")
491
- }),
492
- addComponent({
493
- name: "PwaTransparentImage",
494
- filePath: resolver.resolve(runtimeDir, "components/PwaTransparentImage.vue")
495
- })
496
- ]);
497
- }
498
- nuxt.hook("prepare:types", ({ references }) => {
499
- references.push({ path: resolver.resolve(runtimeDir, "plugins/types") });
500
- references.push({ types: "@vite-pwa/nuxt/configuration" });
501
- references.push({ types: "vite-plugin-pwa/vue" });
502
- references.push({ types: "vite-plugin-pwa/info" });
503
- references.push({ types: "vite-plugin-pwa/pwa-assets" });
504
- });
505
- const pwaAssets = await registerPwaIconsTypes(ctx, runtimeDir);
506
- const manifestDir = join(nuxt.options.buildDir, "manifests");
507
- nuxt.options.nitro.publicAssets = nuxt.options.nitro.publicAssets || [];
508
- nuxt.options.nitro.publicAssets.push({
509
- dir: manifestDir,
510
- maxAge: 0
511
- });
512
- nuxt.hook("nitro:init", (nitro) => {
513
- configurePWAOptions(ctx, nitro.options);
514
- });
515
- nuxt.hook("vite:extend", ({ config }) => {
516
- const plugin = config.plugins?.find((p) => p && typeof p === "object" && "name" in p && p.name === "vite-plugin-pwa");
517
- if (plugin)
518
- throw new Error("Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!");
519
- });
520
- nuxt.hook("vite:extendConfig", async (viteInlineConfig, { isClient }) => {
521
- viteInlineConfig.plugins = viteInlineConfig.plugins || [];
522
- const plugin = viteInlineConfig.plugins.find((p) => p && typeof p === "object" && "name" in p && p.name === "vite-plugin-pwa");
523
- if (plugin)
524
- throw new Error("Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!");
525
- if (options.manifest && isClient) {
526
- viteInlineConfig.plugins.push({
527
- name: "vite-pwa-nuxt:webmanifest:build",
528
- apply: "build",
529
- async writeBundle(_options, bundle) {
530
- if (options.disable || !bundle)
531
- return;
532
- const api = resolveVitePluginPWAAPI();
533
- if (api) {
534
- await mkdir(manifestDir, { recursive: true });
535
- await writeWebManifest(manifestDir, options.manifestFilename || "manifest.webmanifest", api, pwaAssets);
536
- }
537
- }
538
- });
539
- }
540
- if (isClient) {
541
- viteInlineConfig.plugins = viteInlineConfig.plugins || [];
542
- const configuration = "virtual:nuxt-pwa-configuration";
543
- const resolvedConfiguration = `\0${configuration}`;
544
- viteInlineConfig.plugins.push({
545
- name: "vite-pwa-nuxt:configuration",
546
- enforce: "pre",
547
- resolveId(id) {
548
- if (id === configuration)
549
- return resolvedConfiguration;
550
- },
551
- load(id) {
552
- if (id === resolvedConfiguration) {
553
- const display = typeof options.manifest !== "boolean" ? options.manifest?.display ?? "standalone" : "standalone";
554
- const installPrompt = typeof client.installPrompt === "undefined" || client.installPrompt === false ? void 0 : client.installPrompt === true || client.installPrompt.trim() === "" ? "vite-pwa:hide-install" : client.installPrompt.trim();
555
- return `export const enabled = ${client.registerPlugin}
556
- export const display = '${display}'
557
- export const installPrompt = ${JSON.stringify(installPrompt)}
558
- export const periodicSyncForUpdates = ${typeof client.periodicSyncForUpdates === "number" ? client.periodicSyncForUpdates : 0}
559
- `;
560
- }
561
- }
562
- });
563
- }
564
- const plugins = [...VitePWA(options).filter((p) => p.name !== "vite-plugin-pwa:build")];
565
- viteInlineConfig.plugins.push(plugins);
566
- if (isClient)
567
- vitePwaClientPlugin = plugins.find((p) => p.name === "vite-plugin-pwa");
568
- });
569
- extendWebpackConfig(() => {
570
- throw new Error("Webpack is not supported: @vite-pwa/nuxt module can only be used with Vite!");
571
- });
572
- if (nuxt.options.dev) {
573
- const webManifest = `${nuxt.options.app.baseURL}${options.devOptions?.webManifestUrl ?? options.manifestFilename ?? "manifest.webmanifest"}`;
574
- const devSw = `${nuxt.options.app.baseURL}dev-sw.js?dev-sw`;
575
- const workbox = `${nuxt.options.app.baseURL}workbox-`;
576
- const emptyHandle = (_req, _res, next) => {
577
- next();
578
- };
579
- nuxt.hook("vite:serverCreated", (viteServer, { isServer }) => {
580
- if (isServer)
581
- return;
582
- viteServer.middlewares.stack.push({ route: webManifest, handle: emptyHandle });
583
- viteServer.middlewares.stack.push({ route: devSw, handle: emptyHandle });
584
- if (options.pwaAssets) {
585
- viteServer.middlewares.stack.push({
586
- route: "",
587
- // @ts-expect-error just ignore
588
- handle: async (req, res, next) => {
589
- const url = req.url;
590
- if (!url)
591
- return next();
592
- if (!/\.(?:ico|png|svg|webp)$/.test(url))
593
- return next();
594
- const pwaAssetsGenerator = await resolveVitePluginPWAAPI()?.pwaAssetsGenerator();
595
- if (!pwaAssetsGenerator)
596
- return next();
597
- const icon = await pwaAssetsGenerator.findIconAsset(url);
598
- if (!icon)
599
- return next();
600
- if (icon.age > 0) {
601
- const ifModifiedSince = req.headers["if-modified-since"] ?? req.headers["If-Modified-Since"];
602
- const useIfModifiedSince = ifModifiedSince ? Array.isArray(ifModifiedSince) ? ifModifiedSince[0] : ifModifiedSince : void 0;
603
- if (useIfModifiedSince && new Date(icon.lastModified).getTime() / 1e3 >= new Date(useIfModifiedSince).getTime() / 1e3) {
604
- res.statusCode = 304;
605
- res.end();
606
- return;
607
- }
608
- }
609
- const buffer = await icon.buffer;
610
- res.setHeader("Age", icon.age / 1e3);
611
- res.setHeader("Content-Type", icon.mimeType);
612
- res.setHeader("Content-Length", buffer.length);
613
- res.setHeader("Last-Modified", new Date(icon.lastModified).toUTCString());
614
- res.statusCode = 200;
615
- res.end(buffer);
616
- }
617
- });
618
- }
619
- });
620
- if (!options.strategies || options.strategies === "generateSW") {
621
- nuxt.hook("vite:serverCreated", (viteServer, { isServer }) => {
622
- if (isServer)
623
- return;
624
- viteServer.middlewares.stack.push({ route: workbox, handle: emptyHandle });
625
- });
626
- if (options.devOptions?.suppressWarnings) {
627
- const suppressWarnings = `${nuxt.options.app.baseURL}suppress-warnings.js`;
628
- nuxt.hook("vite:serverCreated", (viteServer, { isServer }) => {
629
- if (isServer)
630
- return;
631
- viteServer.middlewares.stack.push({ route: suppressWarnings, handle: emptyHandle });
632
- });
633
- }
634
- const { sourcemap = nuxt.options.sourcemap.client === true } = options.workbox ?? {};
635
- if (sourcemap) {
636
- const swMap = `${nuxt.options.app.baseURL}${options.filename ?? "sw.js"}.map`;
637
- const resolvedSwMapFile = join(nuxt.options.buildDir, "dev-sw-dist", swMap);
638
- const worboxMap = `${nuxt.options.app.baseURL}workbox-`;
639
- addDevServerHandler({
640
- route: "",
641
- handler: await import('h3').then(({ defineLazyEventHandler }) => defineLazyEventHandler(async () => {
642
- const { dev } = await import('../chunks/dev.mjs');
643
- return dev(
644
- swMap,
645
- resolvedSwMapFile,
646
- worboxMap,
647
- nuxt.options.buildDir,
648
- nuxt.options.app.baseURL
649
- );
650
- }))
651
- });
652
- }
653
- }
654
- } else {
655
- if (!options.disable && options.registerWebManifestInRouteRules) {
656
- nuxt.hook("nitro:config", async (nitroConfig) => {
657
- nitroConfig.routeRules = nitroConfig.routeRules || {};
658
- let swName = options.filename || "sw.js";
659
- if (options.strategies === "injectManifest" && swName.endsWith(".ts"))
660
- swName = swName.replace(/\.ts$/, ".js");
661
- nitroConfig.routeRules[`${nuxt.options.app.baseURL}${swName}`] = {
662
- headers: {
663
- "Cache-Control": "public, max-age=0, must-revalidate"
664
- }
665
- };
666
- if (options.manifest) {
667
- nitroConfig.routeRules[`${nuxt.options.app.baseURL}${options.manifestFilename ?? "manifest.webmanifest"}`] = {
668
- headers: {
669
- "Content-Type": "application/manifest+json",
670
- "Cache-Control": "public, max-age=0, must-revalidate"
671
- }
672
- };
673
- }
674
- });
675
- }
676
- if (nuxt3_8) {
677
- nuxt.hook("nitro:build:public-assets", async () => {
678
- await regeneratePWA(
679
- options.outDir,
680
- pwaAssets,
681
- resolveVitePluginPWAAPI()
682
- );
683
- });
684
- } else {
685
- nuxt.hook("nitro:init", (nitro) => {
686
- nitro.hooks.hook("rollup:before", async () => {
687
- await regeneratePWA(
688
- options.outDir,
689
- pwaAssets,
690
- resolveVitePluginPWAAPI()
691
- );
692
- });
693
- });
694
- if (nuxt.options.nitro.static || nuxt.options._generate) {
695
- nuxt.hook("close", async () => {
696
- await regeneratePWA(
697
- options.outDir,
698
- pwaAssets,
699
- resolveVitePluginPWAAPI()
700
- );
701
- });
702
- }
703
- }
704
- }
705
- }
706
-
707
- const module = defineNuxtModule({
708
- meta: {
709
- name: "pwa",
710
- configKey: "pwa",
711
- compatibility: {
712
- nuxt: ">=3.6.5"
713
- },
714
- version
715
- },
716
- defaults: (nuxt) => ({
717
- base: nuxt.options.app.baseURL,
718
- scope: nuxt.options.app.baseURL,
719
- injectRegister: false,
720
- includeManifestIcons: false,
721
- registerPlugin: true,
722
- writePlugin: false,
723
- client: {
724
- registerPlugin: true,
725
- installPrompt: false,
726
- periodicSyncForUpdates: 0
727
- }
728
- }),
729
- async setup(options, nuxt) {
730
- await doSetup(options, nuxt);
731
- }
732
- });
733
-
734
- export { generatePwaImageType as g, module as m, pwaIcons as p };