Files

71 lines
2.7 KiB
JavaScript

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/<file> 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 },
});