(
url: string,
params: Record<string, string>,
deviceHeaders?: DeviceHeaders | undefined,
options?: { timeoutMs?: number; signal?: AbortSignal },
)
| 57 | const DEFAULT_HTTP_TIMEOUT_MS = 30_000; |
| 58 | |
| 59 | async function postForm( |
| 60 | url: string, |
| 61 | params: Record<string, string>, |
| 62 | deviceHeaders?: DeviceHeaders | undefined, |
| 63 | options?: { timeoutMs?: number; signal?: AbortSignal }, |
| 64 | ): Promise<{ status: number; data: Record<string, unknown> }> { |
| 65 | const timeoutMs = options?.timeoutMs ?? DEFAULT_HTTP_TIMEOUT_MS; |
| 66 | const body = new URLSearchParams(params).toString(); |
| 67 | // Compose a timeout signal with the optional caller signal. |
| 68 | const signals: AbortSignal[] = [AbortSignal.timeout(timeoutMs)]; |
| 69 | if (options?.signal !== undefined) signals.push(options.signal); |
| 70 | const signal = AbortSignal.any(signals); |
| 71 | let response: Response; |
| 72 | try { |
| 73 | response = await fetch(url, { |
| 74 | method: 'POST', |
| 75 | headers: { |
| 76 | ...deviceHeaders, |
| 77 | 'Content-Type': 'application/x-www-form-urlencoded', |
| 78 | Accept: 'application/json', |
| 79 | }, |
| 80 | body, |
| 81 | signal, |
| 82 | }); |
| 83 | } catch (error) { |
| 84 | throw new OAuthConnectionError( |
| 85 | `OAuth request to ${url} failed: ${error instanceof Error ? error.message : String(error)}`, |
| 86 | ); |
| 87 | } |
| 88 | const status = response.status; |
| 89 | let data: Record<string, unknown> = {}; |
| 90 | try { |
| 91 | const parsed: unknown = await response.json(); |
| 92 | if (isRecord(parsed)) data = parsed; |
| 93 | } catch { |
| 94 | // Non-JSON response — leave data empty; caller interprets by status. |
| 95 | } |
| 96 | return { status, data }; |
| 97 | } |
| 98 | |
| 99 | // ── requestDeviceAuthorization ──────────────────────────────────────── |
| 100 |
no test coverage detected