Skip to content

refactor(settings-panel): migrate 15 bare fetch to apiFetch#686

Open
jun261930-tech wants to merge 2 commits into
builderz-labs:mainfrom
jun261930-tech:migrate/settings-panel
Open

refactor(settings-panel): migrate 15 bare fetch to apiFetch#686
jun261930-tech wants to merge 2 commits into
builderz-labs:mainfrom
jun261930-tech:migrate/settings-panel

Conversation

@jun261930-tech
Copy link
Copy Markdown

Summary

Migrate src/components/panels/settings-panel.tsx (the largest single-file fetch hotspot, 15 bare fetch calls) to apiFetch<T>() from @/lib/api-client.

Calls Migrated (15 total)

Settings core (CRUD):

  • GET /api/settings (load) — keeps redirectOnUnauthenticated: false because the panel manually redirects to /login?next=%2Fsettings
  • PUT /api/settings (save changes)
  • DELETE /api/settings?key=… (reset to default, template literal)
  • POST /api/settings (hook profile selector)
  • PUT /api/settings (interface-mode switcher, fire-and-forget)

Coordinator routing preview (nested in fetchSettings):

  • GET /api/agents?limit=200
  • GET /api/sessions

API key management:

  • GET /api/tokens/rotate (info)
  • POST /api/tokens/rotate (rotate)

Hermes integration:

  • GET /api/hermes (status)
  • POST /api/hermes (install / uninstall hook)

Backups:

  • POST /api/backup (MC database)
  • POST /api/backup?target=gateway (gateway state)

Onboarding & OAuth:

  • POST /api/onboarding (replay reset)
  • POST /api/auth/google/disconnect (disconnect Google)

Migration Pattern

  • GET with auto-parse: apiFetch<T>(url)
  • POST/PUT/DELETE keeping res.ok semantics: apiFetch<Response>(url, { method, headers, body, raw: true })
  • Removed the verbose nested if (res.ok) { const data = await res.json() … } pattern where status code wasn't needed (tokens info, hermes status, agents/sessions)

Verification

  • pnpm typecheck → 0 error
  • pnpm lint → 0 error, 328 warnings (baseline 343 → 328, -15 matches migrated count)
  • vitest run src/lib/__tests__/api-client.test.ts → 8/8 pass

Why this matters

settings-panel.tsx was the single largest concentration of bare fetch (15 calls). After this PR it adopts the same global 401/403/5xx interceptor as cost-tracker, dashboard, chat, and panel-route, completing the P2 Top-5 hotspot migration.

Refs PR #681 (api-client base)
Closes: task-11 P2.5 (settings-panel hotspot)

P1 of MC code-quality plan (see PLAN.md / PR-api-client.md):

- src/lib/api-client.ts          (+120) ApiError + apiFetch<T> wrapper
- src/lib/__tests__/api-client.test.ts (+108) 8 vitest cases (200/401/403/500/network/loop/204/no-redirect)
- src/components/auth-expired-listener.tsx (+30) global mc:auth-expired -> /login redirect
- src/app/layout.tsx             (+2) register listener
- eslint.config.mjs              (+31) no-restricted-syntax warn for bare fetch('/api/...')

Quality gates passed:
- pnpm vitest run src/lib/__tests__/api-client.test.ts: 8/8 (2.5s)
- pnpm typecheck: 0 error
- pnpm lint: 0 error, 343 warn (~baseline 334 bare fetch + 9 pre-existing)

Out of scope: migrating existing 334 bare fetch sites (P2, separate PR).

P0 verification: playwright captured 19/19 /api/* returning 200 after login,
ruling out backend issue (cookie expired) — see p0-network-evidence.txt.
Migrate all fetch('/api/...') calls in settings-panel.tsx to apiFetch from
@/lib/api-client. Adopts the global 401/403/5xx interceptor for unified
auth-expired handling across the panel:

- fetchSettings (3 inner): /api/settings + /api/agents + /api/sessions
- fetchApiKeyInfo: /api/tokens/rotate (GET)
- handleRotateKey: /api/tokens/rotate (POST)
- fetchHermesStatus: /api/hermes (GET)
- handleSave: /api/settings (PUT)
- handleReset: /api/settings (DELETE template literal)
- MC backup, gateway backup: /api/backup (POST)
- Onboarding reset: /api/onboarding (POST)
- Hermes hook install/uninstall: /api/hermes (POST)
- Hook profile selector: /api/settings (POST)
- InterfaceModeSelector: /api/settings (PUT, fire-and-forget)
- AccountOAuthSection.handleDisconnect: /api/auth/google/disconnect (POST)

Pattern follows established conventions:
- GET with auto-parse: apiFetch<T>(url)
- POST/PUT/DELETE keeping res.ok semantics: apiFetch<Response>(url, {
  method, headers, body, raw: true })
- The /api/settings GET keeps redirectOnUnauthenticated: false because
  the panel manually issues window.location.assign('/login?next=…')

Verification:
- pnpm typecheck: 0 errors
- pnpm lint: 0 errors, 328 warnings (343 -> 328, -15 matches migrated count)
- api-client unit tests: 8/8 pass

Refs PR builderz-labs#681 (api-client base)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant