#!/usr/bin/env node /** * Verify PWA Configuration * * Checks that all PWA assets and configuration are present and valid. */ import { readFile, access } from 'fs/promises'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const publicDir = join(__dirname, '..', 'public'); const configPath = join(__dirname, '..', 'nuxt.config.ts'); let errors = []; let warnings = []; async function checkFileExists(path, description) { try { await access(path); console.log(`āœ“ ${description}`); return true; } catch { errors.push(`āœ— ${description} - File not found: ${path}`); return false; } } async function verifyPWA() { console.log('šŸ” Verifying PWA Configuration...\n'); // Check icons console.log('Icons:'); await checkFileExists(join(publicDir, 'icon.svg'), 'Source icon (SVG)'); await checkFileExists(join(publicDir, 'icon-192x192.png'), 'Icon 192x192'); await checkFileExists(join(publicDir, 'icon-512x512.png'), 'Icon 512x512'); await checkFileExists(join(publicDir, 'icon-192x192-maskable.png'), 'Maskable icon 192x192'); await checkFileExists(join(publicDir, 'icon-512x512-maskable.png'), 'Maskable icon 512x512'); await checkFileExists(join(publicDir, 'favicon.ico'), 'Favicon'); await checkFileExists(join(publicDir, 'apple-touch-icon.png'), 'Apple touch icon'); // Check screenshots console.log('\nScreenshots:'); await checkFileExists(join(publicDir, 'screenshot-mobile.png'), 'Mobile screenshot'); await checkFileExists(join(publicDir, 'screenshot-desktop.png'), 'Desktop screenshot'); // Check Nuxt config console.log('\nConfiguration:'); const configExists = await checkFileExists(configPath, 'Nuxt config file'); if (configExists) { const config = await readFile(configPath, 'utf-8'); // Check for required PWA configuration if (config.includes('@vite-pwa/nuxt')) { console.log('āœ“ @vite-pwa/nuxt module configured'); } else { errors.push('āœ— @vite-pwa/nuxt module not found in config'); } if (config.includes('registerType')) { console.log('āœ“ Service worker registration configured'); } else { warnings.push('⚠ Service worker registration type not set'); } if (config.includes('manifest')) { console.log('āœ“ PWA manifest configured'); } else { errors.push('āœ— PWA manifest configuration missing'); } if (config.includes('workbox')) { console.log('āœ“ Workbox configured'); } else { warnings.push('⚠ Workbox configuration missing'); } // Check for important manifest fields if (config.includes('theme_color')) { console.log('āœ“ Theme color configured'); } else { warnings.push('⚠ Theme color not configured'); } if (config.includes('display')) { console.log('āœ“ Display mode configured'); } else { warnings.push('⚠ Display mode not configured'); } } // Check composables console.log('\nComposables:'); await checkFileExists(join(__dirname, '..', 'composables', 'usePWAInstall.ts'), 'usePWAInstall composable'); await checkFileExists(join(__dirname, '..', 'composables', 'useOnlineStatus.ts'), 'useOnlineStatus composable'); // Check components console.log('\nComponents:'); await checkFileExists(join(__dirname, '..', 'components', 'InstallPrompt.vue'), 'InstallPrompt component'); await checkFileExists(join(__dirname, '..', 'components', 'OfflineBanner.vue'), 'OfflineBanner component'); // Check pages console.log('\nPages:'); await checkFileExists(join(__dirname, '..', 'pages', 'offline.vue'), 'Offline fallback page'); // Print summary console.log('\n' + '='.repeat(60)); if (errors.length === 0 && warnings.length === 0) { console.log('āœ… PWA configuration is valid!'); console.log('\nNext steps:'); console.log('1. Run `npm run dev` and test in browser'); console.log('2. Check DevTools → Application → Manifest'); console.log('3. Test offline functionality'); console.log('4. Run Lighthouse PWA audit'); return 0; } if (warnings.length > 0) { console.log('\nāš ļø Warnings:'); warnings.forEach(w => console.log(w)); } if (errors.length > 0) { console.log('\nāŒ Errors:'); errors.forEach(e => console.log(e)); console.log('\nPWA configuration is incomplete. Please fix the errors above.'); return 1; } console.log('\nāœ… PWA configuration is mostly valid (with warnings).'); return 0; } verifyPWA() .then(code => process.exit(code)) .catch(error => { console.error('\nāŒ Verification failed:', error.message); process.exit(1); });