0
# ofetch
1
2
ofetch is a universal HTTP fetch library that works seamlessly across Node.js, browsers, and web workers. It enhances the standard fetch API with intelligent response parsing, comprehensive error handling with retry logic, request/response interceptor support, and TypeScript-first design with cross-environment compatibility.
3
4
## Package Information
5
6
- **Package Name**: ofetch
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install ofetch`
10
11
## Core Imports
12
13
```typescript
14
import { ofetch, $fetch } from "ofetch";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { ofetch, $fetch } = require("ofetch");
21
```
22
23
For Node.js optimized version (conditional exports):
24
25
```typescript
26
// Uses Node.js-specific optimizations automatically
27
import { ofetch } from "ofetch";
28
29
// Explicit Node.js imports (same API, Node.js optimizations)
30
import { ofetch, createNodeFetch } from "ofetch/node";
31
```
32
33
## Basic Usage
34
35
```typescript
36
import { ofetch } from "ofetch";
37
38
// Simple GET request with automatic JSON parsing
39
const data = await ofetch("https://api.example.com/users");
40
41
// POST request with JSON body
42
const newUser = await ofetch("https://api.example.com/users", {
43
method: "POST",
44
body: { name: "John", email: "john@example.com" }
45
});
46
47
// Configure base URL and default options
48
const api = ofetch.create({
49
baseURL: "https://api.example.com",
50
headers: { "Authorization": "Bearer token" }
51
});
52
53
const users = await api("/users");
54
```
55
56
## Architecture
57
58
ofetch is built around several key components:
59
60
- **Universal Fetch**: Conditional exports provide platform-specific optimizations while maintaining consistent API
61
- **Enhanced Response Handling**: Automatic content-type detection and parsing using destr library
62
- **Error Management**: Rich error objects with request/response context and automatic retry logic
63
- **Interceptor System**: Lifecycle hooks for request/response modification and logging
64
- **Type Safety**: Full TypeScript support with generic response types and comprehensive type definitions
65
- **Configuration System**: Flexible options merging with support for instance creation and global defaults
66
67
## Capabilities
68
69
### Core Fetch Operations
70
71
Primary fetch functionality with enhanced features like automatic JSON parsing, intelligent error handling, and cross-environment compatibility.
72
73
```typescript { .api }
74
interface $Fetch {
75
<T = any, R extends ResponseType = "json">(
76
request: FetchRequest,
77
options?: FetchOptions<R>
78
): Promise<MappedResponseType<R, T>>;
79
raw<T = any, R extends ResponseType = "json">(
80
request: FetchRequest,
81
options?: FetchOptions<R>
82
): Promise<FetchResponse<MappedResponseType<R, T>>>;
83
native: Fetch;
84
create(defaults: FetchOptions, globalOptions?: CreateFetchOptions): $Fetch;
85
}
86
```
87
88
[Core Operations](./core-operations.md)
89
90
### Configuration and Instance Management
91
92
Create customized fetch instances with default options, base URLs, and platform-specific settings.
93
94
```typescript { .api }
95
function createFetch(globalOptions?: CreateFetchOptions): $Fetch;
96
97
interface CreateFetchOptions {
98
defaults?: FetchOptions;
99
fetch?: Fetch;
100
Headers?: typeof Headers;
101
AbortController?: typeof AbortController;
102
}
103
```
104
105
[Configuration](./configuration.md)
106
107
### Request and Response Interceptors
108
109
Lifecycle hooks for modifying requests, handling responses, and implementing custom logic during the fetch process.
110
111
```typescript { .api }
112
interface FetchHooks<T = any, R extends ResponseType = ResponseType> {
113
onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>;
114
onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & { error: Error }>>;
115
onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & { response: FetchResponse<T> }>>;
116
onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & { response: FetchResponse<T> }>>;
117
}
118
119
type MaybeArray<T> = T | T[];
120
type MaybePromise<T> = T | Promise<T>;
121
type FetchHook<C extends FetchContext = FetchContext> = (
122
context: C
123
) => MaybePromise<void>;
124
```
125
126
[Interceptors](./interceptors.md)
127
128
### Error Handling and Retry Logic
129
130
Enhanced error objects with request/response context, automatic retry for specific status codes, and configurable retry strategies.
131
132
```typescript { .api }
133
class FetchError<T = any> extends Error implements IFetchError<T> {
134
request?: FetchRequest;
135
options?: FetchOptions;
136
response?: FetchResponse<T>;
137
data?: T;
138
status?: number;
139
statusText?: string;
140
statusCode?: number;
141
statusMessage?: string;
142
}
143
```
144
145
[Error Handling](./error-handling.md)
146
147
### Utility Functions
148
149
Low-level utility functions for request processing, response type detection, and option merging used internally and available for custom implementations.
150
151
```typescript { .api }
152
function isPayloadMethod(method?: string): boolean;
153
function isJSONSerializable(value: any): boolean;
154
function detectResponseType(contentType?: string): ResponseType;
155
function resolveFetchOptions<R extends ResponseType, T>(
156
request: FetchRequest,
157
input: FetchOptions<R, T> | undefined,
158
defaults: FetchOptions<R, T> | undefined,
159
Headers: typeof globalThis.Headers
160
): ResolvedFetchOptions<R, T>;
161
function callHooks<C extends FetchContext>(
162
context: C,
163
hooks: FetchHook<C> | FetchHook<C>[] | undefined
164
): Promise<void>;
165
function createNodeFetch(): typeof globalThis.fetch;
166
```
167
168
[Utilities](./utilities.md)
169
170
## Core Types
171
172
```typescript { .api }
173
type ResponseType = "json" | "text" | "blob" | "arrayBuffer" | "stream";
174
175
type FetchRequest = RequestInfo;
176
177
interface FetchOptions<R extends ResponseType = ResponseType, T = any>
178
extends Omit<RequestInit, "body">, FetchHooks<T, R> {
179
baseURL?: string;
180
body?: RequestInit["body"] | Record<string, any>;
181
ignoreResponseError?: boolean;
182
params?: Record<string, any>;
183
query?: Record<string, any>;
184
parseResponse?: (responseText: string) => any;
185
responseType?: R;
186
duplex?: "half" | undefined;
187
dispatcher?: InstanceType<typeof import("undici").Dispatcher>;
188
agent?: unknown;
189
timeout?: number;
190
retry?: number | false;
191
retryDelay?: number | ((context: FetchContext<T, R>) => number);
192
retryStatusCodes?: number[];
193
}
194
195
interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any>
196
extends FetchOptions<R, T> {
197
headers: Headers;
198
}
199
200
interface FetchResponse<T> extends Response {
201
_data?: T;
202
}
203
204
interface FetchContext<T = any, R extends ResponseType = ResponseType> {
205
request: FetchRequest;
206
options: ResolvedFetchOptions<R>;
207
response?: FetchResponse<T>;
208
error?: Error;
209
}
210
211
type MappedResponseType<R extends ResponseType, JsonType = any> =
212
R extends keyof ResponseMap ? ResponseMap[R] : JsonType;
213
214
interface ResponseMap {
215
blob: Blob;
216
text: string;
217
arrayBuffer: ArrayBuffer;
218
stream: ReadableStream<Uint8Array>;
219
}
220
221
interface SearchParameters {
222
[key: string]: any;
223
}
224
225
type Fetch = typeof globalThis.fetch;
226
227
type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">;
228
229
interface IFetchError<T = any> extends Error {
230
request?: FetchRequest;
231
options?: FetchOptions;
232
response?: FetchResponse<T>;
233
data?: T;
234
status?: number;
235
statusText?: string;
236
statusCode?: number;
237
statusMessage?: string;
238
}
239
```