refactor(web): split lib/api.ts god module into per-domain files #1157

Merged
reviewer merged 1 commit from code-lead/1148 into main 2026-05-14 17:45:30 +00:00
Collaborator

Closes #1148.

Summary

Decomposes the 2419-line apps/web/src/lib/api.ts into 22 focused modules under apps/web/src/lib/api/. Every public symbol is re-exported through api/index.ts, so the 67 existing call sites keep using import { ... } from "@/lib/api" unchanged — no signature changes, no per-domain import migration in scope.

Domain map

File Domain
client Shared HTTP helpers (jsonFetch, localizedApiError, putJson)
tasks History + pause / resume / fork / steer / cancel / redispatch / sweep / artifact pins
queue, storage Fleet rollups
agents Instance CRUD + lifecycle + provider chain control + model catalogue
agent-types Type CRUD + identity / container / routing + AT-7 revision restore
agent-config-fleet Fleet compose + splitter (fetchAgentConfig / putAgentConfig)
agent-config Generic kind/scope artifacts + revisions
agent-tokens Per-instance Forgejo token override
agent-skills Skill library + per-type / per-instance CRUD
agent-sessions Per-(agent, provider) SDK session keys
pipeline, issue-deps, watchdog Pipeline + DAG + watchdog
settings /settings (billing / pipeline / caveman)
secrets Encrypted secrets + access log
forges, watched-repos Per-forge OAuth + active-forge picker + watched repo CRUD
service-config Sub-resources + speech
catalog Recommended catalog + onboarding reset
label-catalog Label catalog CRUD
usage Per-agent + per-issue token rollups

Test plan

  • just qa — typecheck + biome + drizzle/paraglide/i18n/flow checks all green
  • bun run test in apps/web — 1137 tests still pass
  • No call-site changes outside lib/api/

🤖 Generated with Claude Code

Closes #1148. ## Summary Decomposes the 2419-line `apps/web/src/lib/api.ts` into 22 focused modules under `apps/web/src/lib/api/`. Every public symbol is re-exported through `api/index.ts`, so the 67 existing call sites keep using `import { ... } from "@/lib/api"` unchanged — no signature changes, no per-domain import migration in scope. ## Domain map | File | Domain | |---|---| | `client` | Shared HTTP helpers (`jsonFetch`, `localizedApiError`, `putJson`) | | `tasks` | History + pause / resume / fork / steer / cancel / redispatch / sweep / artifact pins | | `queue`, `storage` | Fleet rollups | | `agents` | Instance CRUD + lifecycle + provider chain control + model catalogue | | `agent-types` | Type CRUD + identity / container / routing + AT-7 revision restore | | `agent-config-fleet` | Fleet compose + splitter (`fetchAgentConfig` / `putAgentConfig`) | | `agent-config` | Generic kind/scope artifacts + revisions | | `agent-tokens` | Per-instance Forgejo token override | | `agent-skills` | Skill library + per-type / per-instance CRUD | | `agent-sessions` | Per-(agent, provider) SDK session keys | | `pipeline`, `issue-deps`, `watchdog` | Pipeline + DAG + watchdog | | `settings` | `/settings` (billing / pipeline / caveman) | | `secrets` | Encrypted secrets + access log | | `forges`, `watched-repos` | Per-forge OAuth + active-forge picker + watched repo CRUD | | `service-config` | Sub-resources + speech | | `catalog` | Recommended catalog + onboarding reset | | `label-catalog` | Label catalog CRUD | | `usage` | Per-agent + per-issue token rollups | ## Test plan - [x] `just qa` — typecheck + biome + drizzle/paraglide/i18n/flow checks all green - [x] `bun run test` in `apps/web` — 1137 tests still pass - [x] No call-site changes outside `lib/api/` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
refactor(web): split lib/api.ts god module into per-domain files (#1148)
All checks were successful
qa / dockerfile (pull_request) Successful in 11s
qa / db-schema (pull_request) Successful in 13s
qa / sql-layer-check (pull_request) Successful in 14s
qa / i18n-string-check (pull_request) Successful in 15s
qa / qa-1 (pull_request) Successful in 2m25s
qa / qa (pull_request) Successful in 0s
b041c2358e
Decomposes the 2419-line `apps/web/src/lib/api.ts` into 22 focused
modules under `apps/web/src/lib/api/`:

  - `client`              — shared `jsonFetch`, `localizedApiError`, `putJson`
  - `tasks`               — history + pause / resume / fork / steer / cancel /
                            redispatch / sweep / artifact pins
  - `queue`, `storage`    — fleet rollups
  - `agents`              — instance CRUD + lifecycle + provider chain control
                            + model catalogue
  - `agent-types`         — type CRUD + identity / container / routing + AT-7
                            revision restore
  - `agent-config-fleet`  — fleet compose + splitter (`fetchAgentConfig` /
                            `putAgentConfig`)
  - `agent-config`        — generic kind/scope artifacts + revisions
  - `agent-tokens`        — per-instance Forgejo token override
  - `agent-skills`        — skill library + per-type / per-instance CRUD
  - `agent-sessions`      — per-(agent, provider) SDK session keys
  - `pipeline`, `issue-deps`, `watchdog`
  - `settings`            — `/settings` (billing / pipeline / caveman)
  - `secrets`             — encrypted secrets + access log
  - `forges`, `watched-repos`
  - `service-config`      — sub-resources + speech
  - `catalog`             — recommended catalog + onboarding reset
  - `label-catalog`
  - `usage`               — per-agent + per-issue token rollups

`api/index.ts` re-exports every public symbol so existing
`import { ... } from "@/lib/api"` call sites (67 files) keep working
unchanged. No function signatures changed; no call-site edits.

`just qa` passes (typecheck + biome + drizzle / paraglide / i18n / flow
checks). All 1137 web tests still pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
reviewer approved these changes 2026-05-14 17:45:23 +00:00
reviewer left a comment

Review: refactor(web): split lib/api.ts god module into per-domain files

Reviewed the full diff (5261 lines, 24 files). This is a well-executed, purely structural refactor — no logic changes.


What I verified

Export surface completeness — scripted a comparison of all exported symbols from the old api.ts against the union of new domain modules + index.ts. Result: 194 old exports vs 193 new domain-file exports, difference of 3 (AgentProvider, FailoverTrigger, ProviderChainEntry) that appear "missing" only because my line-by-line scan missed the multi-line export type { … } from "@claude-hooks/shared" block in index.ts. All three are present there.

No export name conflictsexport * chaining in a barrel is only safe if no two modules export the same name. Checked all 22 domain files: zero conflicts.

No call-site changes — the PR claims 67 call sites are unchanged. Confirmed: every file in the diff lives under apps/web/src/lib/api/. Nothing outside that directory was touched.

New public symbolslocalizedApiError and putJson are now exported from client.ts and partly re-exported through the barrel. Both were private helpers in the old file. putJson is deliberately not re-exported from index.ts (only the internal jsonFetch / localizedApiError path is), matching the original visibility.

Module boundaries — every domain file imports only from ./client or @claude-hooks/shared. No cross-domain imports, no circular dependency risk.

CI: green. Tests: 1137 pass per PR description.


Code quality

  • JSDoc header in each file clearly maps the module to its endpoint group — good.
  • client.ts is a clean shared-HTTP layer; no business logic bled into it.
  • The barrel comment explaining why localizedApiError is re-exported (downstream board.ts / architect.ts / flows-api.ts) is useful context.

Minor observations (non-blocking)

  • putJson is exported from client.ts but not surfaced through index.ts. Any future caller outside lib/api/ would need to import from @/lib/api/client directly. That's intentional given the original private visibility, but worth a short internal note if someone expects it to be barrel-accessible.
  • The PR description domain table omits ./client as a standalone row — minor doc gap, trivially fixable later.

Overall: clean, safe, well-scoped. No behaviour changes. Approving and merging.

## Review: `refactor(web): split lib/api.ts god module into per-domain files` Reviewed the full diff (5261 lines, 24 files). This is a well-executed, purely structural refactor — no logic changes. --- ### What I verified **Export surface completeness** — scripted a comparison of all exported symbols from the old `api.ts` against the union of new domain modules + `index.ts`. Result: 194 old exports vs 193 new domain-file exports, difference of 3 (`AgentProvider`, `FailoverTrigger`, `ProviderChainEntry`) that appear "missing" only because my line-by-line scan missed the multi-line `export type { … } from "@claude-hooks/shared"` block in `index.ts`. All three are present there. ✅ **No export name conflicts** — `export *` chaining in a barrel is only safe if no two modules export the same name. Checked all 22 domain files: zero conflicts. ✅ **No call-site changes** — the PR claims 67 call sites are unchanged. Confirmed: every file in the diff lives under `apps/web/src/lib/api/`. Nothing outside that directory was touched. ✅ **New public symbols** — `localizedApiError` and `putJson` are now exported from `client.ts` and partly re-exported through the barrel. Both were private helpers in the old file. `putJson` is deliberately *not* re-exported from `index.ts` (only the internal `jsonFetch` / `localizedApiError` path is), matching the original visibility. ✅ **Module boundaries** — every domain file imports only from `./client` or `@claude-hooks/shared`. No cross-domain imports, no circular dependency risk. ✅ **CI**: green. **Tests**: 1137 pass per PR description. --- ### Code quality - JSDoc header in each file clearly maps the module to its endpoint group — good. - `client.ts` is a clean shared-HTTP layer; no business logic bled into it. - The barrel comment explaining why `localizedApiError` is re-exported (downstream `board.ts` / `architect.ts` / `flows-api.ts`) is useful context. --- ### Minor observations (non-blocking) - `putJson` is exported from `client.ts` but not surfaced through `index.ts`. Any future caller outside `lib/api/` would need to import from `@/lib/api/client` directly. That's intentional given the original private visibility, but worth a short internal note if someone expects it to be barrel-accessible. - The PR description domain table omits `./client` as a standalone row — minor doc gap, trivially fixable later. --- Overall: clean, safe, well-scoped. No behaviour changes. Approving and merging.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/agent-hooks!1157
No description provided.