(
endpoint: string,
options: CloudAPIRequestOptions & {
parseResponse?: (data: unknown) => T
} = {},
)
| 23 | } |
| 24 | |
| 25 | private async request<T>( |
| 26 | endpoint: string, |
| 27 | options: CloudAPIRequestOptions & { |
| 28 | parseResponse?: (data: unknown) => T |
| 29 | } = {}, |
| 30 | ): Promise<T> { |
| 31 | const { timeout = 30_000, parseResponse, headers = {}, ...fetchOptions } = options |
| 32 | |
| 33 | const sessionToken = this.authService.getSessionToken() |
| 34 | |
| 35 | if (!sessionToken) { |
| 36 | throw new AuthenticationError() |
| 37 | } |
| 38 | |
| 39 | const url = `${this.baseUrl}${endpoint}` |
| 40 | |
| 41 | const requestHeaders = { |
| 42 | "Content-Type": "application/json", |
| 43 | Authorization: `Bearer ${sessionToken}`, |
| 44 | "User-Agent": getUserAgent(), |
| 45 | ...headers, |
| 46 | } |
| 47 | |
| 48 | try { |
| 49 | const response = await fetch(url, { |
| 50 | ...fetchOptions, |
| 51 | headers: requestHeaders, |
| 52 | signal: AbortSignal.timeout(timeout), |
| 53 | }) |
| 54 | |
| 55 | if (!response.ok) { |
| 56 | await this.handleErrorResponse(response, endpoint) |
| 57 | } |
| 58 | |
| 59 | const data = await response.json() |
| 60 | |
| 61 | if (parseResponse) { |
| 62 | return parseResponse(data) |
| 63 | } |
| 64 | |
| 65 | return data as T |
| 66 | } catch (error) { |
| 67 | if (error instanceof TypeError && error.message.includes("fetch")) { |
| 68 | throw new NetworkError(`Network error while calling ${endpoint}`) |
| 69 | } |
| 70 | |
| 71 | if (error instanceof CloudAPIError) { |
| 72 | throw error |
| 73 | } |
| 74 | |
| 75 | if (error instanceof Error && error.name === "AbortError") { |
| 76 | throw new CloudAPIError(`Request to ${endpoint} timed out`, undefined, undefined) |
| 77 | } |
| 78 | |
| 79 | throw new CloudAPIError( |
| 80 | `Unexpected error while calling ${endpoint}: ${error instanceof Error ? error.message : String(error)}`, |
| 81 | ) |
| 82 | } |
no test coverage detected