Skip to content

refactor(dashboard): extract formatters → src/lib/format.ts#30

Merged
esengine merged 1 commit into
mainfrom
refactor/dashboard-extract-formatters
May 1, 2026
Merged

refactor(dashboard): extract formatters → src/lib/format.ts#30
esengine merged 1 commit into
mainfrom
refactor/dashboard-extract-formatters

Conversation

@esengine

@esengine esengine commented May 1, 2026

Copy link
Copy Markdown
Owner

Why

First real TS module extraction after the build-infra PR (#29). Validates that the new pipeline (tsup bundle, dashboard/src/lib/, layered imports) actually works for code that ships, not just on paper.

The five formatters (fmtUsd, fmtPct, fmtNum, fmtBytes, fmtRelativeTime) are the lowest-blast-radius slice in the entire god file:

  • Pure functions, no DOM, no Preact, no buses, no API.
  • Used by ~6 panels (Overview, Usage, Sessions, Plans, System, diff blocks) — extraction proves the import path resolves into multiple call-sites.
  • Together, ~35 LoC. If something breaks in this PR, the surface to debug is tiny.

Closes part of #28 (Stage 1 PR 1.0b).

Changes

  • dashboard/src/lib/format.ts (new) — five typed exports. Inputs are number | null | undefined (or string | number | null | undefined for fmtRelativeTime); return type narrows to string. Bodies are byte-equivalent to the originals.
  • dashboard/app.js — drops the inline definitions, imports from ./src/lib/format. File-header comment shrunk from a 4-line essay to one line and corrected (no longer claims "no build step").
  • tests/dashboard-format.test.ts (new) — 17 cases covering the null/undefined branches, locale separators, byte-unit boundaries, and the time-band edges (just-now / m / h / d / fallback ISO). Mocks Date.now() for deterministic relative-time tests.

Bundle verification

Built locally; dashboard/dist/app.js contains exactly one copy of each function (esbuild inlines the lib module), CDN imports stay external as before. Bundle size unchanged within rounding.

Test plan

  • npm run build — bundles cleanly, format functions inlined, CDN imports preserved.
  • npm run typecheck — both root + dashboard projects clean.
  • npm run lint — clean (6 pre-existing warnings unrelated).
  • npm test — 1682/1682 (was 1665; +17 from the new test file).
  • Manual: open the dashboard locally, confirm Overview / Usage / Sessions panels still format numbers/cost/time correctly.

What's next

Once this lands, Stage 2 (drop the editor surface, ~−500 LoC) and Stage 3 (extract api(), usePoll, buses, error boundary, markdown) start in order. Each panel migration in Stage 4 will follow the same shape this PR established.

First real TS module after the build-infra PR. Moves the five pure
helpers (fmtUsd, fmtPct, fmtNum, fmtBytes, fmtRelativeTime) out of
the 4768-line god file and into a typed leaf module. They had no
dependencies and ~6 panel call-sites, so this validates the
extraction pattern without touching state, polling, or buses.

- dashboard/src/lib/format.ts (new) — five exports, fully typed.
- dashboard/app.js — drops 35 lines of inline definitions, imports
  from "./src/lib/format". File-header comment shrunk to one line
  and corrected (no longer claims "no build step").
- tests/dashboard-format.test.ts (new) — 17 cases covering the
  null/undefined branches, locale separators, byte-unit boundaries,
  and the time-band edges; mocks Date.now where needed.

Bundle output verified: format functions appear once each in
dashboard/dist/app.js, CDN imports stay external. 1682/1682 tests
pass (was 1665; +17 from this PR).
@esengine esengine added the enhancement New feature or request label May 1, 2026
@esengine esengine merged commit c770550 into main May 1, 2026
2 checks passed
@esengine esengine deleted the refactor/dashboard-extract-formatters branch May 1, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant