Summary
There are two parallel client modules — the Node axios client (src/utils/hevyClient.ts) and the Worker native-fetch Kubb wrapper (src/utils/hevyClientKubb.ts, 472 LOC) — plus observability/enrichment layers (hevy-client-observability.ts, observability-wrapper.ts, safe-error-diagnostic.ts, hevy-http-error.ts). Tool code depends on a concrete client rather than an interface, so runtime choice is spread across the edges instead of isolated at one seam.
Files
src/utils/hevyClient.ts, hevyClientKubb.ts
src/utils/hevy-client-observability.ts, observability-wrapper.ts, safe-error-diagnostic.ts, hevy-http-error.ts
src/shared-server.ts (consumer), src/tools/* (callers)
Proposed approach
- Name the client as an interface (
HevyClient) with method signatures tools already rely on.
- Node and Worker become two adapters behind that interface. The in-memory fake used by
tests/integration/mocked/ becomes a first-class test adapter.
- Move observability/enrichment into the adapter construction, not into every call site.
Constraints
- Must remain safe for both Node.js and Cloudflare Workers (no Node built-ins in the Worker adapter).
shared-server.ts already accepts a hevyClient override — preserve that injection point.
- Do not edit generated client code (
src/generated/); adapters wrap it.
Acceptance
- Tool code depends on the
HevyClient interface, not a concrete module.
- Node, Worker, and test adapters swap behind the seam; tests use the test adapter.
npm run check:types and all suites (mocked, worker, live) pass.
Notes
Speculative — only worth it once candidates 2–4 land and the seam is clearer. Two adapters (Node + Worker) justify the seam; a test adapter makes it real.
See architecture review candidate 6.
Summary
There are two parallel client modules — the Node axios client (
src/utils/hevyClient.ts) and the Worker native-fetch Kubb wrapper (src/utils/hevyClientKubb.ts, 472 LOC) — plus observability/enrichment layers (hevy-client-observability.ts,observability-wrapper.ts,safe-error-diagnostic.ts,hevy-http-error.ts). Tool code depends on a concrete client rather than an interface, so runtime choice is spread across the edges instead of isolated at one seam.Files
src/utils/hevyClient.ts,hevyClientKubb.tssrc/utils/hevy-client-observability.ts,observability-wrapper.ts,safe-error-diagnostic.ts,hevy-http-error.tssrc/shared-server.ts(consumer),src/tools/*(callers)Proposed approach
HevyClient) with method signatures tools already rely on.tests/integration/mocked/becomes a first-class test adapter.Constraints
shared-server.tsalready accepts ahevyClientoverride — preserve that injection point.src/generated/); adapters wrap it.Acceptance
HevyClientinterface, not a concrete module.npm run check:typesand all suites (mocked, worker, live) pass.Notes
Speculative — only worth it once candidates 2–4 land and the seam is clearer. Two adapters (Node + Worker) justify the seam; a test adapter makes it real.
See architecture review candidate 6.