/// import { defineConfig } from "vite"; import preact from "@preact/preset-vite"; function serviceWorker() { return { name: "habit-journal-service-worker", generateBundle(_: unknown, bundle: Record) { const assets = [ "/", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png", "/illustrations/hero-home.svg", "/illustrations/pending.svg", "/illustrations/scores.svg", "/illustrations/coach.svg", "/illustrations/empty.svg", ...Object.values(bundle).map((item) => `/${item.fileName}`), ]; const source = ` const CACHE = "habit-journal-v3"; const SHELL = ${JSON.stringify(assets)}; self.addEventListener("install", event => event.waitUntil(caches.open(CACHE).then(cache => cache.addAll(SHELL)).then(() => self.skipWaiting()))); self.addEventListener("activate", event => event.waitUntil(caches.keys().then(keys => Promise.all(keys.filter(key => key !== CACHE).map(key => caches.delete(key)))).then(() => self.clients.claim()))); self.addEventListener("fetch", event => { const request = event.request; const url = new URL(request.url); if (url.pathname.startsWith("/api/")) { event.respondWith(fetch(request)); return; } if (request.mode === "navigate") { event.respondWith(fetch(request).then(response => { const copy = response.clone(); caches.open(CACHE).then(cache => cache.put("/index.html", copy)); return response; }).catch(() => caches.match("/index.html"))); return; } event.respondWith(caches.match(request).then(hit => hit || fetch(request))); }); `; this.emitFile({ type: "asset", fileName: "sw.js", source }); }, }; } export default defineConfig({ plugins: [preact(), serviceWorker()], build: { outDir: "../static", emptyOutDir: true, sourcemap: true, }, server: { proxy: { "/api": { target: "http://127.0.0.1:7860", changeOrigin: true, }, }, }, test: { environment: "node", }, });