import { defineConfig } from "vite"; // The ported desktop modules import node:* modules; in the browser they map to small shims. // Root-relative paths on purpose: an absolute path made "node:fs" a different module URL than the // worker's own "./vfs.js" import, so two vfs instances existed and the ported modules saw no mounts. const nodeShims = { "node:fs": "/src/worker/vfs.js", "node:fs/promises": "/src/worker/shims/fs-promises.js", "node:zlib": "/src/worker/shims/zlib.js", "node:crypto": "/src/worker/shims/crypto.js", "node:path": "path-browserify", path: "path-browserify", "node:os": "/src/worker/shims/os.js", "node:child_process": "/src/worker/shims/child_process.js", electron: "/src/worker/shims/electron.js", }; // Exact matches only: "node:fs" must not also rewrite "node:fs/promises". const aliases = Object.entries(nodeShims).map(([find, replacement]) => ({ find: new RegExp(`^${find.replace(/[/:]/g, "\\$&")}$`), replacement })); // Dev only: /__testgame/ serves files from LSTOOLS_TEST_DIR (a COPY of a client folder is // best), used with ?devgame=rs.iop,map.iop to test pages without the native folder picker. const testGame = { name: "losadev-test-game", apply: "serve", configureServer(server) { const dir = process.env.LSTOOLS_TEST_DIR; if (!dir) return; // Range requests: the worker reads the packs piecewise with sync XHR (vfs.remoteFile). server.middlewares.use("/__testgame/", async (req, res) => { const { createReadStream, statSync } = await import("node:fs"); const { join, basename } = await import("node:path"); const name = basename(decodeURIComponent(req.url.split("?")[0])); const file = join(dir, name); let size; try { size = statSync(file).size; } catch { res.statusCode = 404; return res.end(); } res.setHeader("Accept-Ranges", "bytes"); res.setHeader("Cache-Control", "no-store"); if (req.method === "HEAD") { res.setHeader("Content-Length", size); return res.end(); } const m = /bytes=(\d+)-(\d*)/.exec(req.headers.range || ""); if (m) { const start = Number(m[1]); const end = Math.min(size - 1, m[2] ? Number(m[2]) : size - 1); res.statusCode = 206; res.setHeader("Content-Range", `bytes ${start}-${end}/${size}`); res.setHeader("Content-Length", end - start + 1); return createReadStream(file, { start, end }).pipe(res); } res.setHeader("Content-Length", size); createReadStream(file).pipe(res); }); }, }; export default defineConfig({ server: { port: 4700 }, plugins: [testGame], define: { __LEGACY_VER__: JSON.stringify(String(Date.now())) }, resolve: { alias: aliases }, worker: { format: "es", plugins: () => [] }, build: { target: "es2022", sourcemap: true }, });