Skip to content

Commit f761eac

Browse files
committed
fix(webapp): catalogs live in their own IO-free module
Reading them off the registry dragged the loaders (and so env.server and the engine singleton) into the pure renderer and its unit test. The catalogs-by-value map now imports only the per-report messages files.
1 parent 13d48b3 commit f761eac

3 files changed

Lines changed: 16 additions & 19 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Catalogs by value, in a module that imports ONLY the per-report `*-messages`
3+
* files — no loaders, no IO. Presentation stays decoupled from the data layer,
4+
* and a value import can't be tree-shaken away.
5+
*/
6+
import { healthMessages } from "./health/health-messages";
7+
import { type ReportMessages } from "./report-messages";
8+
9+
export const REPORT_MESSAGE_CATALOGS: Record<string, ReportMessages> = {
10+
health: healthMessages,
11+
};

apps/webapp/app/presenters/v3/reports/report-messages.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* No report vocabulary here — that would re-couple the renderer to a specific report.
66
*/
77

8-
import { REPORT_REGISTRY } from "./report-registry";
8+
import { REPORT_MESSAGE_CATALOGS } from "./report-message-catalogs";
99
import { type ReasonCode, type Severity } from "./report-view-model";
1010

1111
/**
@@ -23,14 +23,11 @@ export type ReportMessages = {
2323
actionMessage(code: ReasonCode): string;
2424
};
2525

26-
/**
27-
* Look up a report's catalog by `vm.title`. Catalogs live as values on the
28-
* report registry entries — there is deliberately no register-at-import-time
29-
* step: a side-effect registration is exactly what the production bundle
30-
* tree-shakes away under `"sideEffects": false`.
31-
*/
26+
/** Look up a report's catalog by `vm.title`. Catalogs are values, never
27+
* registered at import time — side-effect registration is what the production
28+
* bundle tree-shakes away. */
3229
export function reportMessages(title: string): ReportMessages {
33-
const messages = REPORT_REGISTRY[title]?.messages;
30+
const messages = REPORT_MESSAGE_CATALOGS[title];
3431
if (!messages) {
3532
throw new Error(`report-messages: no catalog registered for report "${title}"`);
3633
}

apps/webapp/app/presenters/v3/reports/report-registry.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,11 @@
1010
import { type AuthenticatedEnvironment } from "~/services/apiAuth.server";
1111
import { interpret as interpretHealth } from "./health/health";
1212
import { loadHealthInput } from "./health/health-data";
13-
import { healthMessages } from "./health/health-messages";
14-
import { type ReportMessages } from "./report-messages";
1513
import { type ReportViewModel } from "./report-view-model";
1614

1715
export type ReportLoader<TInput> = {
1816
load: (env: AuthenticatedEnvironment, period: string) => Promise<TInput>;
1917
interpret: (input: TInput) => ReportViewModel;
20-
/**
21-
* The report's message catalog, carried BY VALUE on the registry entry. It
22-
* used to be registered as a side effect of importing the catalog module —
23-
* which the production SSR bundle tree-shook away (`"sideEffects": false`),
24-
* leaving `GET /api/v1/reports/health` throwing "no catalog registered".
25-
* A value on the entry cannot be dropped.
26-
*/
27-
messages: ReportMessages;
2818
};
2919

3020
function defineReport<TInput>(loader: ReportLoader<TInput>): ReportLoader<unknown> {
@@ -35,7 +25,6 @@ export const REPORT_REGISTRY: Record<string, ReportLoader<unknown>> = {
3525
health: defineReport({
3626
load: (env, period) => loadHealthInput(env, period),
3727
interpret: interpretHealth,
38-
messages: healthMessages,
3928
}),
4029
};
4130

0 commit comments

Comments
 (0)