Files
healer-man/vite.config.ts
T

131 lines
5.5 KiB
TypeScript

import { readFileSync } from "node:fs";
import path from "node:path";
import { configDefaults, defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
// @ts-expect-error Shared Node HTTP middleware also serves production bundles.
import { createBundledContentHandler } from "./server/bundled-content.mjs";
// @ts-expect-error Local-only Node middleware is activated only in balance-lab-gui mode.
import { createLocalBalanceLabApi } from "./server/local-balance-lab-api.mjs";
const packageVersion = (JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8")) as { version: string }).version;
export default defineConfig(({ mode }) => {
const androidBuild = mode === "android";
const shelvedModesEnabled = mode === "shelved";
const balanceLabRuntime = mode === "balance-lab";
const localBalanceLabGui = mode === "balance-lab-gui";
const downloadableBuild = androidBuild || mode === "production" || shelvedModesEnabled;
return {
plugins: [react(), {
name: "local-balance-lab-api",
configureServer(server) {
if (!localBalanceLabGui) return;
const api = createLocalBalanceLabApi();
server.httpServer?.once("close", () => api.close());
server.middlewares.use((request, response, next) => {
void api.handle(request, response).then((handled: boolean) => {
if (!handled) next();
}).catch(next);
});
},
}, {
name: "bundled-content-preview",
configurePreviewServer(server) {
const serve = createBundledContentHandler(path.resolve(androidBuild ? "dist-android" : "dist"));
server.middlewares.use((request, response, next) => {
if (!serve(request, response, new URL(request.url ?? "/", "http://localhost").pathname)) next();
});
},
}, {
name: "bundle-module-report",
generateBundle(_options, bundle) {
const chunks = Object.values(bundle)
.filter((entry): entry is Extract<typeof entry, { type: "chunk" }> => entry.type === "chunk")
.map((chunk) => ({
file: chunk.fileName,
entry: chunk.isEntry,
dynamicEntry: chunk.isDynamicEntry,
modules: Object.keys(chunk.modules).map((moduleId) => (
path.relative(process.cwd(), moduleId).split(path.sep).join("/")
)).sort(),
}));
this.emitFile({
type: "asset",
fileName: "bundle-module-report.json",
source: `${JSON.stringify({ shelvedModesEnabled, chunks }, null, 2)}\n`,
});
},
}],
publicDir: balanceLabRuntime ? false : androidBuild ? ".android-public" : downloadableBuild ? ".web-public" : "public",
define: {
"import.meta.env.VITE_APP_VERSION": JSON.stringify(packageVersion),
"import.meta.env.VITE_CONTENT_MODE": JSON.stringify(downloadableBuild ? "downloadable" : "bundled"),
"import.meta.env.VITE_SHELVED_MODES_ENABLED": JSON.stringify(shelvedModesEnabled ? "true" : "false"),
"import.meta.env.VITE_LOCAL_BALANCE_LAB_GUI": JSON.stringify(localBalanceLabGui ? "true" : "false"),
},
resolve: {
alias: {
"@dungeonAssetModules": path.resolve(
androidBuild || mode === "production" ? "src/game/dungeonAssetModules.android.ts" : "src/game/dungeonAssetModules.ts",
),
"@shelvedGameRuntime": path.resolve(
shelvedModesEnabled ? "src/app/ShelvedGameRuntime.enabled.tsx" : "src/app/ShelvedGameRuntime.disabled.tsx",
),
"@shelvedGameScene": path.resolve(
shelvedModesEnabled ? "src/scene/ShelvedGameScene.enabled.tsx" : "src/scene/ShelvedGameScene.disabled.tsx",
),
"@shelvedModeRoutes": path.resolve(
shelvedModesEnabled ? "src/app/ShelvedModeRoutes.tsx" : "src/app/ShelvedModeRoutes.disabled.tsx",
),
"@shelvedOnlineGroupRuntime": path.resolve(
shelvedModesEnabled ? "src/app/ShelvedOnlineGroupRuntime.enabled.ts" : "src/app/ShelvedOnlineGroupRuntime.disabled.ts",
),
"@shelvedDungeonSession": path.resolve(
shelvedModesEnabled ? "src/game/ShelvedDungeonSession.enabled.ts" : "src/game/ShelvedDungeonSession.disabled.ts",
),
"@shelvedCompanionPanel": path.resolve(
shelvedModesEnabled ? "src/ui/ShelvedCompanionPanel.enabled.tsx" : "src/ui/ShelvedCompanionPanel.disabled.tsx",
),
"@shelvedHud": path.resolve(
shelvedModesEnabled ? "src/ui/ShelvedHud.enabled.tsx" : "src/ui/ShelvedHud.disabled.tsx",
),
},
},
server: {
proxy: {
"/api": "http://127.0.0.1:4173",
"/content": "http://127.0.0.1:4173",
},
watch: {
// Asset-pipeline staging files are large, short-lived, and can be locked
// while iCloud or conversion tools are writing them. They are not app
// source, so watching them only risks taking the dev server down with
// EBUSY on Windows.
ignored: balanceLabRuntime
? ["**/*"]
: [
"**/dungeon-pipeline/**",
"**/playtest-artifacts/**",
...(localBalanceLabGui ? ["**/artifacts/balance-lab-gui-runtime/**"] : []),
],
},
},
build: {
target: "es2022",
sourcemap: false,
emptyOutDir: true,
outDir: androidBuild ? "dist-android" : "dist",
},
test: {
environment: "node",
include: ["src/**/*.test.ts"],
exclude: [
...configDefaults.exclude,
"**/._*",
"**/._*/**",
],
maxWorkers: 4,
},
};
});