(
path: string,
init?: RequestInit,
attempt: number = 0,
overrideToken?: string | null
)
| 103 | } |
| 104 | |
| 105 | private async request<T>( |
| 106 | path: string, |
| 107 | init?: RequestInit, |
| 108 | attempt: number = 0, |
| 109 | overrideToken?: string | null |
| 110 | ): Promise<T> { |
| 111 | const headers = new Headers(init?.headers) |
| 112 | const liveToken = this.getToken ? this.getToken() : null |
| 113 | const authToken = overrideToken !== undefined |
| 114 | ? (overrideToken ?? (liveToken ?? this.token)) |
| 115 | : (liveToken ?? this.token) |
| 116 | if (authToken) { |
| 117 | headers.set('authorization', `Bearer ${authToken}`) |
| 118 | } |
| 119 | if (init?.body !== undefined && !headers.has('content-type')) { |
| 120 | headers.set('content-type', 'application/json') |
| 121 | } |
| 122 | |
| 123 | const res = await fetch(this.buildUrl(path), { |
| 124 | ...init, |
| 125 | headers |
| 126 | }) |
| 127 | |
| 128 | if (res.status === 401) { |
| 129 | if (attempt === 0 && this.onUnauthorized) { |
| 130 | const refreshed = await this.onUnauthorized() |
| 131 | if (refreshed) { |
| 132 | this.token = refreshed |
| 133 | return await this.request<T>(path, init, attempt + 1, refreshed) |
| 134 | } |
| 135 | } |
| 136 | throw new Error('Session expired. Please sign in again.') |
| 137 | } |
| 138 | |
| 139 | if (!res.ok) { |
| 140 | const body = await res.text().catch(() => '') |
| 141 | const code = parseErrorCode(body) |
| 142 | throw new ApiError( |
| 143 | `HTTP ${res.status} ${res.statusText}: ${body}`, |
| 144 | res.status, |
| 145 | code, |
| 146 | body || undefined |
| 147 | ) |
| 148 | } |
| 149 | |
| 150 | return await res.json() as T |
| 151 | } |
| 152 | |
| 153 | async authenticate(auth: { initData: string } | { accessToken: string }): Promise<AuthResponse> { |
| 154 | const res = await fetch(this.buildUrl('/api/auth'), { |
no test coverage detected