import { readFileSync } from "node:fs";
import { defineConfig, type Plugin } from "vite";
import { VitePWA } from "vite-plugin-pwa";
const VERSION: number = JSON.parse(readFileSync(new URL("./version.json", import.meta.url), "utf8")).version;
// dist/version.json lets a running app ask "what version is live right now?"
// (it is deliberately NOT precached — see globPatterns — so the fetch hits the network)
const emitVersion: Plugin = {
name: "emit-version",
generateBundle() {
this.emitFile({ type: "asset", fileName: "version.json", source: JSON.stringify({ version: VERSION }) });
},
};
// base './' is load-bearing: the app is served both at https://chat.ardegazu.ro/
// and from IPFS gateway paths like /ipfs/<cid>/ — all asset URLs must be relative.
export default defineConfig({
base: "./",
build: { target: "es2022" },
define: { __APP_VERSION__: JSON.stringify(VERSION) },
server: {
proxy: {
// local dev: `go run ./server --dev` listens on :8080
"/ws": { target: "ws://localhost:8080", ws: true },
"/turn-credentials": { target: "http://localhost:8080" },
},
},
plugins: [
emitVersion,
VitePWA({
registerType: "prompt",
includeAssets: ["icons/apple-touch-icon.png"],
manifest: {
name: "sueta",
short_name: "sueta",
description: "p2p end-to-end encrypted chat",
start_url: "./",
scope: "./",
display: "standalone",
background_color: "#0d1117",
theme_color: "#0d1117",
icons: [
{ src: "icons/icon-192.png", sizes: "192x192", type: "image/png" },
{ src: "icons/icon-512.png", sizes: "512x512", type: "image/png" },
{ src: "icons/icon-512-maskable.png", sizes: "512x512", type: "image/png", purpose: "maskable" },
],
},
workbox: {
globPatterns: ["**/*.{js,css,html,png,svg,webmanifest}"],
navigateFallback: "index.html",
// prompt-mode update flow: the new SW must claim open pages, else
// controllerchange never fires on first-visit pages and the one-tap
// update banner can't reload into the new version
clientsClaim: true,
skipWaiting: false,
},
}),
],
});