diff --git a/index.html b/index.html index a72a7b0c2..c6a0f11d1 100644 --- a/index.html +++ b/index.html @@ -58,6 +58,9 @@ window.GIT_COMMIT = <%- gitCommit %>; window.INSTANCE_ID = <%- instanceId %>; window.ASSET_MANIFEST = <%- assetManifest %>; + window.BOOTSTRAP_CONFIG = { + gameEnv: <%- gameEnv %>, + }; document.documentElement.style.setProperty( "--background-image-url", `url("<%- backgroundImageUrl %>")`, diff --git a/src/core/configuration/ConfigLoader.ts b/src/core/configuration/ConfigLoader.ts index 15771873b..0b8c79c8a 100644 --- a/src/core/configuration/ConfigLoader.ts +++ b/src/core/configuration/ConfigLoader.ts @@ -9,6 +9,14 @@ import { prodConfig } from "./ProdConfig"; export let cachedSC: ServerConfig | null = null; +declare global { + interface Window { + BOOTSTRAP_CONFIG?: { + gameEnv?: string; + }; + } +} + export async function getConfig( gameConfig: GameConfig, userSettings: UserSettings | null, @@ -30,16 +38,20 @@ export async function getServerConfigFromClient(): Promise { if (cachedSC) { return cachedSC; } - const response = await fetch("/api/env"); + const bootstrapGameEnv = window.BOOTSTRAP_CONFIG?.gameEnv; + if (bootstrapGameEnv) { + cachedSC = getServerConfig(bootstrapGameEnv); + return cachedSC; + } + + const response = await fetch("/api/env"); if (!response.ok) { throw new Error( `Failed to fetch server config: ${response.status} ${response.statusText}`, ); } const config = await response.json(); - // Log the retrieved configuration - console.log("Server config loaded:", config); cachedSC = getServerConfig(config.game_env); return cachedSC; @@ -63,3 +75,7 @@ export function getServerConfig(gameEnv: string) { throw Error(`unsupported server configuration: ${gameEnv}`); } } + +export function clearCachedServerConfig(): void { + cachedSC = null; +} diff --git a/src/server/RenderHtml.ts b/src/server/RenderHtml.ts index 2b2b3db17..9c31b2721 100644 --- a/src/server/RenderHtml.ts +++ b/src/server/RenderHtml.ts @@ -11,6 +11,7 @@ export async function renderHtmlContent(htmlPath: string): Promise { gitCommit: JSON.stringify(process.env.GIT_COMMIT ?? "undefined"), instanceId: JSON.stringify(process.env.INSTANCE_ID ?? "undefined"), assetManifest: JSON.stringify(assetManifest), + gameEnv: JSON.stringify(process.env.GAME_ENV ?? "dev"), manifestHref: buildAssetUrl("manifest.json", assetManifest), faviconHref: buildAssetUrl("images/Favicon.svg", assetManifest), gameplayScreenshotUrl: buildAssetUrl( diff --git a/tests/core/configuration/ConfigLoader.test.ts b/tests/core/configuration/ConfigLoader.test.ts new file mode 100644 index 000000000..65fd81757 --- /dev/null +++ b/tests/core/configuration/ConfigLoader.test.ts @@ -0,0 +1,24 @@ +import { beforeEach, describe, expect, test, vi } from "vitest"; +import { GameEnv } from "../../../src/core/configuration/Config"; +import { + clearCachedServerConfig, + getServerConfigFromClient, +} from "../../../src/core/configuration/ConfigLoader"; + +describe("ConfigLoader", () => { + beforeEach(() => { + vi.restoreAllMocks(); + window.BOOTSTRAP_CONFIG = undefined; + clearCachedServerConfig(); + }); + + test("uses bootstrap config without fetching /api/env", async () => { + window.BOOTSTRAP_CONFIG = { gameEnv: "prod" }; + const fetchSpy = vi.spyOn(globalThis, "fetch"); + + const config = await getServerConfigFromClient(); + + expect(config.env()).toBe(GameEnv.Prod); + expect(fetchSpy).not.toHaveBeenCalled(); + }); +}); diff --git a/vite.config.ts b/vite.config.ts index 5fa1b9912..eefc073c2 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -27,6 +27,7 @@ export default defineConfig(({ mode }) => { : {}; const htmlAssetData = { assetManifest: JSON.stringify(assetManifest), + gameEnv: JSON.stringify(env.GAME_ENV ?? "dev"), manifestHref: buildAssetUrl("manifest.json", assetManifest), faviconHref: buildAssetUrl("images/Favicon.svg", assetManifest), gameplayScreenshotUrl: buildAssetUrl(