import { execFileSync } from "node:child_process"; import { existsSync, mkdirSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { fileURLToPath, URL } from "node:url"; import tailwindcss from "@tailwindcss/vite"; import { tanstackRouter } from "@tanstack/router-plugin/vite"; import viteReact from "@vitejs/plugin-react"; import { defineConfig, loadEnv } from "vite"; import tsConfigPaths from "vite-tsconfig-paths"; function getDevHttpsOptions() { const certDir = path.join(tmpdir(), "orphion-vite-https"); const keyPath = path.join(certDir, "localhost-key.pem"); const certPath = path.join(certDir, "localhost-cert.pem"); if (!existsSync(keyPath) || !existsSync(certPath)) { mkdirSync(certDir, { recursive: true }); execFileSync( "openssl", [ "req", "-x509", "-newkey", "rsa:2048", "-nodes", "-sha256", "-days", "365", "-subj", "/CN=localhost", "-addext", "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:0.0.0.0", "-keyout", keyPath, "-out", certPath, ], { stdio: "ignore" }, ); } return { key: readFileSync(keyPath), cert: readFileSync(certPath), }; } export default defineConfig(({ command, mode }) => { const viteEnv = loadEnv(mode, process.cwd(), ""); const serviceHost = viteEnv.VITE_ORPHION_SERVICE_HOST || "127.0.0.1"; const apiPort = viteEnv.VITE_API_PORT || "4000"; const apiProxyTarget = viteEnv.VITE_API_PROXY_TARGET || `http://${serviceHost}:${apiPort}`; const https = command === "serve" ? getDevHttpsOptions() : undefined; return { plugins: [ tanstackRouter({ target: "react", routesDirectory: "./src/routes", generatedRouteTree: "./src/routeTree.gen.ts", autoCodeSplitting: true, }), tailwindcss(), tsConfigPaths({ projects: ["./tsconfig.json"] }), viteReact(), ], resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)), }, dedupe: ["react", "react-dom", "@tanstack/react-query", "@tanstack/query-core"], }, server: { ...(https ? { https } : {}), proxy: { "/api": { target: apiProxyTarget, changeOrigin: true, }, }, }, ...(https ? { preview: { https } } : {}), build: { rollupOptions: { output: { manualChunks(id) { if (!id.includes("node_modules")) return undefined; if (id.includes("recharts") || id.includes("d3-")) return "charts"; if (id.includes("framer-motion") || id.includes("motion-")) return "motion"; if (id.includes("@tanstack")) return "tanstack"; if (id.includes("@radix-ui")) return "radix"; if (id.includes("lucide-react")) return "icons"; return undefined; }, }, }, }, }; });