diff --git a/apps/pwa/package.json b/apps/pwa/package.json index d012e6a..70061f4 100644 --- a/apps/pwa/package.json +++ b/apps/pwa/package.json @@ -13,7 +13,7 @@ "test:e2e": "playwright test", "test:e2e:ui": "playwright test --ui", "test:e2e:headed": "playwright test --headed", - "pwa:icons": "pwa-assets-generator --config pwa-assets.config.ts && cp public/pwa-192x192.png public/icon-192.png && cp public/pwa-512x512.png public/icon-512.png && cp public/maskable-icon-512x512.png public/icon-maskable-512.png && cp public/apple-touch-icon-180x180.png public/apple-touch-icon.png && cp public/logo.svg public/favicon.svg" + "pwa:icons": "pwa-assets-generator --config pwa-assets.config.ts && node scripts/copy-pwa-icons.mjs" }, "dependencies": { "@dnd-kit/core": "^6.3.1", diff --git a/apps/pwa/scripts/copy-pwa-icons.mjs b/apps/pwa/scripts/copy-pwa-icons.mjs new file mode 100644 index 0000000..4bd85c1 --- /dev/null +++ b/apps/pwa/scripts/copy-pwa-icons.mjs @@ -0,0 +1,46 @@ +/** + * copy-pwa-icons.mjs — rename the @vite-pwa/assets-generator outputs to the + * stable filenames the hand-maintained manifest references (WR-08). + * + * The generator emits preset-named files (pwa-192x192.png, …). The manifest in + * vite.config.ts references stable names (/icon-192.png, …) so a generator + * version bump that renames its outputs surfaces here as a clear, named error + * rather than an opaque shell `cp: cannot stat`. This replaces a Unix-only `cp` + * chain so Windows contributors and minimal CI containers can run `pwa:icons`. + * + * Keep COPIES in sync with the manifest `icons` array in vite.config.ts. + */ +import { copyFileSync, existsSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const here = dirname(fileURLToPath(import.meta.url)); +const publicDir = join(here, '..', 'public'); + +/** [generated source name, stable destination name referenced by the manifest] */ +const COPIES = [ + ['pwa-192x192.png', 'icon-192.png'], + ['pwa-512x512.png', 'icon-512.png'], + ['maskable-icon-512x512.png', 'icon-maskable-512.png'], + ['apple-touch-icon-180x180.png', 'apple-touch-icon.png'], + ['logo.svg', 'favicon.svg'], +]; + +let failed = false; +for (const [src, dest] of COPIES) { + const from = join(publicDir, src); + const to = join(publicDir, dest); + if (!existsSync(from)) { + console.error( + `[pwa:icons] expected generated file not found: public/${src}\n` + + ` The assets generator output names may have changed — update COPIES in\n` + + ` apps/pwa/scripts/copy-pwa-icons.mjs and the manifest in vite.config.ts.`, + ); + failed = true; + continue; + } + copyFileSync(from, to); + console.log(`[pwa:icons] public/${src} → public/${dest}`); +} + +if (failed) process.exit(1); diff --git a/apps/pwa/vite.config.ts b/apps/pwa/vite.config.ts index 6e2081f..e2a9661 100644 --- a/apps/pwa/vite.config.ts +++ b/apps/pwa/vite.config.ts @@ -35,6 +35,10 @@ export default defineConfig({ display: 'standalone', scope: '/', start_url: '/', + // WR-08: these stable icon filenames are produced by the `pwa:icons` + // npm script, which runs the assets generator and then + // `scripts/copy-pwa-icons.mjs` to rename the preset outputs to these + // names. Keep this list in sync with the COPIES table in that script. icons: [ { src: '/icon-192.png', sizes: '192x192', type: 'image/png' }, { src: '/icon-512.png', sizes: '512x512', type: 'image/png' },