/** * Vite Plugin for TimeSafari Daily Notification Plugin * * Provides Vite-specific optimizations and integrations for the TimeSafari PWA. * Handles tree-shaking, SSR safety, and platform-specific builds. * * @author Matthew Raymer * @version 1.0.0 */ import type { Plugin } from 'vite'; export interface TimeSafariPluginOptions { /** * Enable SSR safety checks */ ssrSafe?: boolean; /** * Enable tree-shaking optimizations */ treeShaking?: boolean; /** * Platform-specific builds */ platforms?: ('android' | 'ios' | 'electron')[]; /** * Bundle size budget in KB */ bundleSizeBudget?: number; /** * Enable development mode optimizations */ devMode?: boolean; } /** * TimeSafari Vite Plugin * * Provides optimizations and integrations for TimeSafari PWA compatibility. */ export function timeSafariPlugin(options: TimeSafariPluginOptions = {}): Plugin { const { ssrSafe = true, treeShaking = true, platforms = ['android', 'ios'], bundleSizeBudget = 35, devMode = false } = options; return { name: 'timesafari-daily-notification', // Plugin configuration // eslint-disable-next-line @typescript-eslint/no-explicit-any config(config, { command }): any { const isDev = command === 'serve'; return { // Build optimizations build: { ...config.build, // Enable tree-shaking rollupOptions: { ...config.build?.rollupOptions, treeshake: treeShaking ? { moduleSideEffects: false, propertyReadSideEffects: false, unknownGlobalSideEffects: false } : false } }, // Define constants define: { ...config.define, __TIMESAFARI_SSR_SAFE__: ssrSafe, __TIMESAFARI_PLATFORMS__: JSON.stringify(platforms), __TIMESAFARI_BUNDLE_BUDGET__: bundleSizeBudget, __TIMESAFARI_DEV_MODE__: devMode || isDev } }; }, // Transform code for SSR safety // eslint-disable-next-line @typescript-eslint/no-explicit-any transform(code, _id): any { if (!ssrSafe) return null; // Check for SSR-unsafe code patterns const ssrUnsafePatterns = [ /window\./g, /document\./g, /navigator\./g, /localStorage\./g, /sessionStorage\./g, ]; let hasUnsafeCode = false; for (const pattern of ssrUnsafePatterns) { if (pattern.test(code)) { hasUnsafeCode = true; break; } } if (hasUnsafeCode) { // Wrap unsafe code in platform checks const wrappedCode = ` // SSR-safe wrapper for TimeSafari Daily Notification Plugin if (typeof window !== 'undefined' && typeof document !== 'undefined') { ${code} } else { // SSR fallback - return mock implementation // Running in SSR environment, using fallback implementation } `; return { code: wrappedCode, map: null }; } return null; }, // Generate platform-specific builds generateBundle(_options, bundle): void { // Remove any web-specific code (not applicable in native-first architecture) Object.keys(bundle).forEach(fileName => { if (fileName.includes('web') || fileName.includes('browser')) { delete bundle[fileName]; } }); if (!platforms.includes('android')) { // Remove Android-specific code Object.keys(bundle).forEach(fileName => { if (fileName.includes('android')) { delete bundle[fileName]; } }); } if (!platforms.includes('ios')) { // Remove iOS-specific code Object.keys(bundle).forEach(fileName => { if (fileName.includes('ios')) { delete bundle[fileName]; } }); } }, // Bundle size analysis writeBundle(_options, bundle): void { if (devMode) return; let totalSize = 0; const fileSizes: Record = {}; Object.entries(bundle).forEach(([fileName, chunk]) => { if (chunk.type === 'chunk') { const size = Buffer.byteLength(chunk.code, 'utf8'); fileSizes[fileName] = size; totalSize += size; } }); const totalSizeKB = totalSize / 1024; if (totalSizeKB > bundleSizeBudget) { // Bundle size exceeds budget // Log largest files for debugging (available in fileSizes) } else { // Bundle size within budget } }, // Development server middleware configureServer(server): void { if (!devMode) return; // Add development-specific middleware server.middlewares.use('/timesafari-plugin', (_req, res, _next) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ name: 'TimeSafari Daily Notification Plugin', version: process.env.npm_package_version || '1.0.0', platforms: platforms, ssrSafe: ssrSafe, treeShaking: treeShaking })); }); } }; } /** * Default export for easy usage */ export default timeSafariPlugin;