|
1 | 1 | import { ApiError, NetworkError, RateLimitError, TimeoutError } from './errors'; |
2 | 2 |
|
| 3 | +/** |
| 4 | + * Minimal fetch-like function signature covering only what the SDK uses. |
| 5 | + * |
| 6 | + * Defined locally so consumers without the DOM lib (e.g. Node-only projects |
| 7 | + * with `lib: ["ES2022"]` and older `@types/node`) don't pull `globalThis.fetch`, |
| 8 | + * `Response`, or `RequestInit` into their emitted `.d.ts` when they import |
| 9 | + * this SDK's types. |
| 10 | + * |
| 11 | + * At runtime the SDK still calls `globalThis.fetch` by default; this type is |
| 12 | + * purely a structural subset so any spec-compatible `fetch` implementation |
| 13 | + * (node's built-in, undici, whatwg-fetch, a user mock, etc.) satisfies it. |
| 14 | + */ |
| 15 | +export type FetchLike = ( |
| 16 | + input: string | URL, |
| 17 | + init?: { |
| 18 | + method?: string; |
| 19 | + headers?: Record<string, string>; |
| 20 | + signal?: AbortSignal; |
| 21 | + body?: string; |
| 22 | + }, |
| 23 | +) => Promise<FetchLikeResponse>; |
| 24 | + |
| 25 | +export interface FetchLikeResponse { |
| 26 | + ok: boolean; |
| 27 | + status: number; |
| 28 | + statusText: string; |
| 29 | + headers: { get(name: string): string | null }; |
| 30 | + json(): Promise<unknown>; |
| 31 | + text(): Promise<string>; |
| 32 | +} |
| 33 | + |
3 | 34 | /** |
4 | 35 | * Retry configuration for the {@link Transport}. |
5 | 36 | * |
@@ -29,7 +60,7 @@ export interface TransportOptions { |
29 | 60 | * initial attempt, so `{ max: 3 }` permits up to 4 total calls. |
30 | 61 | */ |
31 | 62 | retry: RetryConfig; |
32 | | - fetch: typeof globalThis.fetch; |
| 63 | + fetch: FetchLike; |
33 | 64 | sleep?: (ms: number) => Promise<void>; |
34 | 65 | } |
35 | 66 |
|
@@ -102,7 +133,7 @@ export class Transport { |
102 | 133 | const timer = setTimeout(() => { |
103 | 134 | controller.abort(); |
104 | 135 | }, this.opts.timeoutMs); |
105 | | - let response: Response; |
| 136 | + let response: FetchLikeResponse; |
106 | 137 | try { |
107 | 138 | response = await this.opts.fetch(url, { |
108 | 139 | method, |
@@ -166,7 +197,7 @@ export class Transport { |
166 | 197 | } |
167 | 198 | } |
168 | 199 |
|
169 | | - private async safeParseBody(response: Response): Promise<unknown> { |
| 200 | + private async safeParseBody(response: FetchLikeResponse): Promise<unknown> { |
170 | 201 | const ct = response.headers.get('content-type') ?? ''; |
171 | 202 | if (!ct.includes('application/json')) { |
172 | 203 | try { |
|
0 commit comments