build: migrate build system to Vite and test runner to Vitest & Remove depracated husky usage (#2703)

- Replace Webpack with Vite for faster client bundling and HMR.
- Migrate tests from Jest to Vitest and update configuration.
- Update Web Worker instantiation to standard ESM syntax.
- Implement Env utility in `src/core` for safe, hybrid environment
variable access (Vite vs Node).
- Refactor configuration loaders to remove direct `process.env`
dependencies in shared code.
- Update TypeScript environment definitions and project scripts for the
new toolchain.
- Remove the [depracated usage of the
husky](https://github.com/typicode/husky/releases/tag/v9.0.1).

## Description:

migrate build system to Vite and test runner to Vitest & Remove
depracated husky usage

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

wraith4081

---------

Co-authored-by: evanpelle <evanpelle@gmail.com>
This commit is contained in:
Wraith
2025-12-28 22:10:26 -08:00
committed by GitHub
co-authored by evanpelle
parent f6412a5979
commit 26f5d40819
75 changed files with 2765 additions and 10503 deletions
+3 -2
View File
@@ -3,6 +3,7 @@ import { GameConfig } from "../Schemas";
import { Config, GameEnv, ServerConfig } from "./Config";
import { DefaultConfig } from "./DefaultConfig";
import { DevConfig, DevServerConfig } from "./DevConfig";
import { Env } from "./Env";
import { preprodConfig } from "./PreprodConfig";
import { prodConfig } from "./ProdConfig";
@@ -22,7 +23,7 @@ export async function getConfig(
console.log("using prod config");
return new DefaultConfig(sc, gameConfig, userSettings, isReplay);
default:
throw Error(`unsupported server configuration: ${process.env.GAME_ENV}`);
throw Error(`unsupported server configuration: ${Env.GAME_ENV}`);
}
}
export async function getServerConfigFromClient(): Promise<ServerConfig> {
@@ -44,7 +45,7 @@ export async function getServerConfigFromClient(): Promise<ServerConfig> {
return cachedSC;
}
export function getServerConfigFromServer(): ServerConfig {
const gameEnv = process.env.GAME_ENV ?? "dev";
const gameEnv = Env.GAME_ENV;
return getServerConfig(gameEnv);
}
export function getServerConfig(gameEnv: string) {
+11 -10
View File
@@ -27,6 +27,7 @@ import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
import { NukeType } from "../StatsSchemas";
import { assertNever, sigmoid, simpleHash, within } from "../Util";
import { Config, GameEnv, NukeMagnitude, ServerConfig, Theme } from "./Config";
import { Env } from "./Env";
import { PastelTheme } from "./PastelTheme";
import { PastelThemeDark } from "./PastelThemeDark";
@@ -88,20 +89,20 @@ const numPlayersConfig = {
export abstract class DefaultServerConfig implements ServerConfig {
turnstileSecretKey(): string {
return process.env.TURNSTILE_SECRET_KEY ?? "";
return Env.TURNSTILE_SECRET_KEY ?? "";
}
abstract turnstileSiteKey(): string;
allowedFlares(): string[] | undefined {
return;
}
stripePublishableKey(): string {
return process.env.STRIPE_PUBLISHABLE_KEY ?? "";
return Env.STRIPE_PUBLISHABLE_KEY ?? "";
}
domain(): string {
return process.env.DOMAIN ?? "";
return Env.DOMAIN ?? "";
}
subdomain(): string {
return process.env.SUBDOMAIN ?? "";
return Env.SUBDOMAIN ?? "";
}
private publicKey: JWK;
@@ -134,24 +135,24 @@ export abstract class DefaultServerConfig implements ServerConfig {
);
}
otelEndpoint(): string {
return process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "";
return Env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "";
}
otelAuthHeader(): string {
return process.env.OTEL_AUTH_HEADER ?? "";
return Env.OTEL_AUTH_HEADER ?? "";
}
gitCommit(): string {
return process.env.GIT_COMMIT ?? "";
return Env.GIT_COMMIT ?? "";
}
apiKey(): string {
return process.env.API_KEY ?? "";
return Env.API_KEY ?? "";
}
adminHeader(): string {
return "x-admin-key";
}
adminToken(): string {
const token = process.env.ADMIN_TOKEN;
const token = Env.ADMIN_TOKEN;
if (!token) {
throw new Error("ADMIN_TOKEN not set");
}
@@ -225,7 +226,7 @@ export class DefaultConfig implements Config {
) {}
stripePublishableKey(): string {
return process.env.STRIPE_PUBLISHABLE_KEY ?? "";
return Env.STRIPE_PUBLISHABLE_KEY ?? "";
}
isReplay(): boolean {
+92
View File
@@ -0,0 +1,92 @@
/**
* Safely access environment variables in both Node.js and Vite environments.
* - In Vite (Browser), it uses `import.meta.env`.
* - In Node.js (Server), it uses `process.env`.
*/
declare global {
interface ImportMetaEnv {
[key: string]: string | boolean | undefined;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
}
function getEnv(key: string, viteKey?: string): string | undefined {
const vKey = viteKey ?? key;
// Try import.meta.env (Vite/Browser)
// We use a try-catch block or check existence to avoid ReferenceErrors
try {
if (typeof import.meta !== "undefined" && import.meta.env) {
const val = import.meta.env[vKey] ?? import.meta.env[key];
if (val !== undefined) {
return String(val);
}
}
} catch {
// Ignore errors accessing import.meta
}
// Try process.env (Node.js)
try {
if (typeof process !== "undefined" && process.env) {
const val = process.env[key];
if (val !== undefined) {
return val;
}
}
} catch {
// Ignore errors accessing process
}
return undefined;
}
export const Env = {
get GAME_ENV(): string {
// Check MODE for Vite, GAME_ENV for Node
try {
if (
typeof import.meta !== "undefined" &&
import.meta.env &&
import.meta.env.MODE
) {
return import.meta.env.MODE;
}
} catch {
// Ignore errors accessing import.meta
}
return getEnv("GAME_ENV") ?? "dev";
},
get TURNSTILE_SECRET_KEY() {
return getEnv("TURNSTILE_SECRET_KEY");
},
get STRIPE_PUBLISHABLE_KEY() {
return getEnv("STRIPE_PUBLISHABLE_KEY");
},
get DOMAIN() {
return getEnv("DOMAIN");
},
get SUBDOMAIN() {
return getEnv("SUBDOMAIN");
},
get OTEL_EXPORTER_OTLP_ENDPOINT() {
return getEnv("OTEL_EXPORTER_OTLP_ENDPOINT");
},
get OTEL_AUTH_HEADER() {
return getEnv("OTEL_AUTH_HEADER");
},
get GIT_COMMIT() {
return getEnv("GIT_COMMIT");
},
get API_KEY() {
return getEnv("API_KEY");
},
get ADMIN_TOKEN() {
return getEnv("ADMIN_TOKEN");
},
};