Establishes the server-TypeScript foundation and migrates utils/money →
utils/money.mts with branded Cents/Dollars (mirroring the client), so the
cents↔dollars boundary — the origin of the reconciliation bug class — is a
compile error for any typed server caller.
Approach (no build step): Node 25 runs .ts natively (type-stripping).
Migrated modules use the explicit-ESM .mts extension (the project is
"type":"commonjs", which disables .ts ESM auto-detection) and are required
from the CJS callers via Node's require(esm) — verified working. Infra:
tsconfig.server.json (allowJs + checkJs:false → incremental like the
client), npm run typecheck:server, check:server extended to .mts, wired
into ci. 28 require sites repointed to money.mts.
typecheck:server clean; full server suite 225 + e2e probe 17/17 green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
getTracker ran a payments query per bill plus computeAmountSuggestion per bill
(up to 12 queries each: 6 months x 2) inside bills.map — ~70-450 queries for a
35-bill account per load. Now one query fetches all cycle payments (grouped in
JS per bill range) and two compute all amount suggestions
(computeAmountSuggestionsBatch). Behavior-preserving.
Test: tests/amountSuggestionService.test.js pins batch == per-bill output.
Co-Authored-By: Claude Opus 4.8 <[email protected]>