Skip to content

refactor(web): extract duplicated fetchJson / error handling into shared lib #293

Description

@jerry609

Problem

PR #291 introduced friendly upstream error handling in the Research components, but the implementation was copy-pasted identically into 3 files:

  • web/src/components/research/ResearchDashboard.tsx
  • web/src/components/research/ResearchDiscoveryPage.tsx
  • web/src/components/research/ResearchPageNew.tsx

Duplicated code (3 copies each)

Item Lines per copy Total duplicated
type UpstreamErrorBody 4 lines 12 lines
function toFriendlyErrorMessage() ~25 lines ~75 lines
async function fetchJson<T>() ~12 lines ~36 lines

Additionally, `e instanceof Error ? e.message : String(e)` appears 47 times across the entire frontend codebase, scattered across:

  • ResearchDashboard (12x), ResearchPageNew (7x), ResearchDiscoveryPage (2x)
  • Settings page (5x), WorkspacePanel (11x), RunbookPanel (4x)
  • ScholarSubscriptionsPanel (4x), and others

Proposed fix

  1. Create web/src/lib/fetch.ts — shared module:

    export type UpstreamErrorBody = { detail?: string; error?: string }
    
    export function toFriendlyErrorMessage(status: number, rawText: string): string | null { ... }
    
    export async function fetchJson<T>(url: string, init?: RequestInit): Promise<T> { ... }
    
    export function getErrorMessage(e: unknown): string {
      return e instanceof Error ? e.message : String(e)
    }
  2. Update 3 Research components to import from shared lib, delete inline copies

  3. Optionally replace scattered inline error extraction with getErrorMessage(e) across all components (low priority, incremental)

Context

  • web/src/lib/api.ts already has postJson<T>() but returns null on error (different contract)
  • web/src/lib/dashboard-api.ts has fetchJsonOrNull<T>() — yet another variant
  • Long-term consider unifying all three fetch wrappers

Metadata

Metadata

Assignees

Labels

frontendFrontend/UI related work

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions