(path: string, options?: RequestInit)
| 42 | } |
| 43 | |
| 44 | private async fetch<T>(path: string, options?: RequestInit): Promise<T> { |
| 45 | const url = `${this.baseUrl}${path}`; |
| 46 | |
| 47 | const response = await fetch(url, { |
| 48 | headers: { |
| 49 | 'Content-Type': 'application/json', |
| 50 | ...options?.headers, |
| 51 | }, |
| 52 | ...options, |
| 53 | }); |
| 54 | |
| 55 | if (!response.ok) { |
| 56 | const error = await response.json().catch(() => ({ |
| 57 | error: { code: 'unknown', message: response.statusText } |
| 58 | })); |
| 59 | throw new Error(error.error?.message || 'Request failed'); |
| 60 | } |
| 61 | |
| 62 | const result: ApiResponse<T> = await response.json(); |
| 63 | |
| 64 | if (!result.success) { |
| 65 | throw new Error(result.error?.message || 'Request failed'); |
| 66 | } |
| 67 | |
| 68 | return result.data as T; |
| 69 | } |
| 70 | |
| 71 | private buildQueryString(params: object): string { |
| 72 | const searchParams = new URLSearchParams(); |
no outgoing calls
no test coverage detected