diff --git a/.server-changes/report-messages-not-treeshaken.md b/.server-changes/report-messages-not-treeshaken.md new file mode 100644 index 00000000000..b599e84f1ce --- /dev/null +++ b/.server-changes/report-messages-not-treeshaken.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: fix +--- + +Fix the health report failing with an internal error when requested through the API. diff --git a/apps/webapp/app/presenters/v3/reports/health/health-messages.ts b/apps/webapp/app/presenters/v3/reports/health/health-messages.ts index 888b2b54b73..2475118a685 100644 --- a/apps/webapp/app/presenters/v3/reports/health/health-messages.ts +++ b/apps/webapp/app/presenters/v3/reports/health/health-messages.ts @@ -8,7 +8,7 @@ * metrics / evidence — meaning lives here, numbers stay facts. */ -import { registerReportMessages, type ReportMessages } from "../report-messages"; +import { type ReportMessages } from "../report-messages"; import { type ReasonCode, type Severity } from "../report-view-model"; /** Metric id -> expanded display label. */ @@ -166,5 +166,3 @@ export const healthMessages: ReportMessages = { statementMessage, actionMessage: (code) => ACTIONS[code] ?? code, }; - -registerReportMessages("health", healthMessages); diff --git a/apps/webapp/app/presenters/v3/reports/health/health.ts b/apps/webapp/app/presenters/v3/reports/health/health.ts index 08beae3894c..fa56e7b630e 100644 --- a/apps/webapp/app/presenters/v3/reports/health/health.ts +++ b/apps/webapp/app/presenters/v3/reports/health/health.ts @@ -26,7 +26,6 @@ import { applyFlowPolicy, buildFlowRead, interpretFlow } from "./flow"; import { interpretLiveness } from "./liveness"; // Registers the "health" message catalog (side effect) so the renderer resolves this report's // codes. Kept here — the health report's entry module — so loading it always registers its prose. -import "./health-messages"; // Re-exported so the data layer + tests keep a single import path (`./health`). export { HEALTH_THRESHOLDS, isPendingIncreasing, type HealthInput } from "./health-core"; diff --git a/apps/webapp/app/presenters/v3/reports/report-message-catalogs.ts b/apps/webapp/app/presenters/v3/reports/report-message-catalogs.ts new file mode 100644 index 00000000000..eca36e7e95a --- /dev/null +++ b/apps/webapp/app/presenters/v3/reports/report-message-catalogs.ts @@ -0,0 +1,11 @@ +/** + * Catalogs by value, in a module that imports ONLY the per-report `*-messages` + * files — no loaders, no IO. Presentation stays decoupled from the data layer, + * and a value import can't be tree-shaken away. + */ +import { healthMessages } from "./health/health-messages"; +import { type ReportMessages } from "./report-messages"; + +export const REPORT_MESSAGE_CATALOGS: Record = { + health: healthMessages, +}; diff --git a/apps/webapp/app/presenters/v3/reports/report-messages.ts b/apps/webapp/app/presenters/v3/reports/report-messages.ts index 2d90ea016ed..1c549f78a1c 100644 --- a/apps/webapp/app/presenters/v3/reports/report-messages.ts +++ b/apps/webapp/app/presenters/v3/reports/report-messages.ts @@ -5,6 +5,7 @@ * No report vocabulary here — that would re-couple the renderer to a specific report. */ +import { REPORT_MESSAGE_CATALOGS } from "./report-message-catalogs"; import { type ReasonCode, type Severity } from "./report-view-model"; /** @@ -22,16 +23,11 @@ export type ReportMessages = { actionMessage(code: ReasonCode): string; }; -const catalogs = new Map(); - -/** Register a report's catalog under its title (e.g. "health"). Called for its side effect. */ -export function registerReportMessages(title: string, messages: ReportMessages): void { - catalogs.set(title, messages); -} - -/** Look up a report's catalog by `vm.title`. Throws if the report never registered one. */ +/** Look up a report's catalog by `vm.title`. Catalogs are values, never + * registered at import time — side-effect registration is what the production + * bundle tree-shakes away. */ export function reportMessages(title: string): ReportMessages { - const messages = catalogs.get(title); + const messages = REPORT_MESSAGE_CATALOGS[title]; if (!messages) { throw new Error(`report-messages: no catalog registered for report "${title}"`); }