* Create HTTPError from fetch Response
(response: Response, endpoint: string)
| 139 | * Create HTTPError from fetch Response |
| 140 | */ |
| 141 | static async fromResponse(response: Response, endpoint: string): Promise<HTTPError> { |
| 142 | const status = response.status |
| 143 | const config = HTTPError.getErrorConfig(status) |
| 144 | const isDevelopment = process.env.NODE_ENV === 'development' |
| 145 | |
| 146 | // Try to extract error details from response body |
| 147 | let responseBody: unknown |
| 148 | try { |
| 149 | responseBody = await response.json() |
| 150 | } catch { |
| 151 | // Response body is not JSON - ignore |
| 152 | } |
| 153 | let serverMessage = |
| 154 | typeof (responseBody as any)?.error === 'string' ? (responseBody as any).error : |
| 155 | typeof (responseBody as any)?.message === 'string' ? (responseBody as any).message : |
| 156 | typeof (responseBody as any)?.detail === 'string' ? (responseBody as any).detail : |
| 157 | '' |
| 158 | try { |
| 159 | serverMessage = JSON.parse(serverMessage)?.error || serverMessage |
| 160 | } catch {} |
| 161 | |
| 162 | return new HTTPError({ |
| 163 | ...config, |
| 164 | message: serverMessage || config.message, |
| 165 | userMessage: serverMessage || config.userMessage, |
| 166 | statusCode: status, |
| 167 | technicalDetails: isDevelopment |
| 168 | ? { |
| 169 | status, |
| 170 | statusText: response.statusText, |
| 171 | ...(responseBody ? { response: JSON.stringify(responseBody).slice(0, 200) } : {}), |
| 172 | } |
| 173 | : undefined, |
| 174 | }) |
| 175 | } |
| 176 | |
| 177 | /** |
| 178 | * Map HTTP status codes to error configurations |
no test coverage detected