diff --git a/src/server/GamePreviewBuilder.ts b/src/server/GamePreviewBuilder.ts index 33d4be3fb..afd188c11 100644 --- a/src/server/GamePreviewBuilder.ts +++ b/src/server/GamePreviewBuilder.ts @@ -3,10 +3,7 @@ import { buildAssetUrl } from "../core/AssetUrls"; import { ClanTagSchema, GameInfo, UsernameSchema } from "../core/Schemas"; import { formatPlayerDisplayName } from "../core/Util"; import { GameMode } from "../core/game/Game"; -import { - buildPublicAssetManifest, - getResourcesDir, -} from "./PublicAssetManifest"; +import { getRuntimeAssetManifest } from "./RuntimeAssetManifest"; export const PlayerInfoSchema = z.object({ clientID: z.string().optional(), @@ -136,17 +133,14 @@ export function escapeHtml(value: string): string { .replace(/'/g, "'"); } -export function buildPreview( +export async function buildPreview( gameID: string, origin: string, workerPath: string, lobby: GameInfo | null, publicInfo: ExternalGameInfo | null, -): PreviewMeta { - const assetManifest = - process.env.GAME_ENV === "prod" - ? buildPublicAssetManifest(getResourcesDir()) - : {}; +): Promise { + const assetManifest = await getRuntimeAssetManifest(); const buildAbsoluteAssetUrl = (path: string) => new URL(buildAssetUrl(path, assetManifest), origin).toString(); const isFinished = !!publicInfo?.info?.end; diff --git a/src/server/GamePreviewRoute.ts b/src/server/GamePreviewRoute.ts index 01837ff19..9cf28f263 100644 --- a/src/server/GamePreviewRoute.ts +++ b/src/server/GamePreviewRoute.ts @@ -96,7 +96,7 @@ export function registerGamePreviewRoute(opts: { } const origin = requestOrigin(req, config); - const meta = buildPreview( + const meta = await buildPreview( gameID, origin, config.workerPath(gameID), diff --git a/src/server/RenderHtml.ts b/src/server/RenderHtml.ts index e3a939ce6..2b2b3db17 100644 --- a/src/server/RenderHtml.ts +++ b/src/server/RenderHtml.ts @@ -2,17 +2,11 @@ import ejs from "ejs"; import type { Response } from "express"; import fs from "fs/promises"; import { buildAssetUrl } from "../core/AssetUrls"; -import { - buildPublicAssetManifest, - getResourcesDir, -} from "./PublicAssetManifest"; +import { getRuntimeAssetManifest } from "./RuntimeAssetManifest"; export async function renderHtmlContent(htmlPath: string): Promise { const htmlContent = await fs.readFile(htmlPath, "utf-8"); - const assetManifest = - process.env.GAME_ENV === "prod" - ? buildPublicAssetManifest(getResourcesDir()) - : {}; + const assetManifest = await getRuntimeAssetManifest(); return ejs.render(htmlContent, { gitCommit: JSON.stringify(process.env.GIT_COMMIT ?? "undefined"), instanceId: JSON.stringify(process.env.INSTANCE_ID ?? "undefined"), diff --git a/src/server/RuntimeAssetManifest.ts b/src/server/RuntimeAssetManifest.ts new file mode 100644 index 000000000..812247889 --- /dev/null +++ b/src/server/RuntimeAssetManifest.ts @@ -0,0 +1,29 @@ +import fs from "fs/promises"; +import path from "path"; +import { fileURLToPath } from "url"; +import type { AssetManifest } from "../core/AssetUrls"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const staticDir = path.join(__dirname, "../../static"); +const manifestPath = path.join(staticDir, "_assets", "asset-manifest.json"); + +let manifestPromise: Promise | null = null; + +async function readRuntimeAssetManifest(): Promise { + const raw = await fs.readFile(manifestPath, "utf8"); + return JSON.parse(raw) as AssetManifest; +} + +export async function getRuntimeAssetManifest(): Promise { + if (process.env.GAME_ENV !== "prod") { + return {}; + } + + manifestPromise ??= readRuntimeAssetManifest(); + return manifestPromise; +} + +export function clearRuntimeAssetManifestCache(): void { + manifestPromise = null; +}