0
# Utility Functions
1
2
Low-level utility functions for request processing, response type detection, option merging, and hook execution used internally by ofetch and available for custom implementations.
3
4
## Capabilities
5
6
### Request Method Validation
7
8
Determines if an HTTP method typically includes a request payload/body.
9
10
```typescript { .api }
11
/**
12
* Check if HTTP method typically includes a request body
13
* @param method - HTTP method string (default: "GET")
14
* @returns True if method typically includes payload (PATCH, POST, PUT, DELETE)
15
*/
16
function isPayloadMethod(method?: string): boolean;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import { isPayloadMethod } from "ofetch";
23
24
console.log(isPayloadMethod("GET")); // false
25
console.log(isPayloadMethod("POST")); // true
26
console.log(isPayloadMethod("PUT")); // true
27
console.log(isPayloadMethod("DELETE")); // true
28
console.log(isPayloadMethod("PATCH")); // true
29
30
// Use in custom logic
31
function prepareRequest(method: string, data: any) {
32
if (isPayloadMethod(method) && data) {
33
return { method, body: JSON.stringify(data) };
34
}
35
return { method };
36
}
37
```
38
39
### JSON Serialization Check
40
41
Determines if a value can be safely JSON serialized.
42
43
```typescript { .api }
44
/**
45
* Check if a value can be JSON serialized
46
* @param value - Value to check for JSON serializability
47
* @returns True if value can be safely JSON stringified
48
*/
49
function isJSONSerializable(value: any): boolean;
50
```
51
52
**Usage Examples:**
53
54
```typescript
55
import { isJSONSerializable } from "ofetch";
56
57
// Primitive types
58
console.log(isJSONSerializable("string")); // true
59
console.log(isJSONSerializable(123)); // true
60
console.log(isJSONSerializable(true)); // true
61
console.log(isJSONSerializable(null)); // true
62
63
// Objects and arrays
64
console.log(isJSONSerializable({ key: "value" })); // true
65
console.log(isJSONSerializable([1, 2, 3])); // true
66
67
// Non-serializable types
68
console.log(isJSONSerializable(undefined)); // false
69
console.log(isJSONSerializable(() => {})); // false
70
console.log(isJSONSerializable(Symbol("test"))); // false
71
console.log(isJSONSerializable(new ArrayBuffer(8))); // false
72
73
// Objects with toJSON method
74
class CustomClass {
75
toJSON() { return { serialized: true }; }
76
}
77
console.log(isJSONSerializable(new CustomClass())); // true
78
79
// Use in request preparation
80
function prepareBody(data: any) {
81
if (isJSONSerializable(data)) {
82
return JSON.stringify(data);
83
}
84
return data; // Return as-is for FormData, Buffer, etc.
85
}
86
```
87
88
### Response Type Detection
89
90
Automatically detects the appropriate response type based on Content-Type header.
91
92
```typescript { .api }
93
/**
94
* Detect response type from Content-Type header
95
* @param contentType - Content-Type header value
96
* @returns Appropriate ResponseType for parsing
97
*/
98
function detectResponseType(contentType?: string): ResponseType;
99
100
type ResponseType = "json" | "text" | "blob" | "arrayBuffer" | "stream";
101
```
102
103
**Usage Examples:**
104
105
```typescript
106
import { detectResponseType } from "ofetch";
107
108
// JSON content types
109
console.log(detectResponseType("application/json")); // "json"
110
console.log(detectResponseType("application/json; charset=utf-8")); // "json"
111
console.log(detectResponseType("application/ld+json")); // "json"
112
113
// Text content types
114
console.log(detectResponseType("text/plain")); // "text"
115
console.log(detectResponseType("text/html")); // "text"
116
console.log(detectResponseType("application/xml")); // "text"
117
console.log(detectResponseType("image/svg+xml")); // "text"
118
119
// Binary content types
120
console.log(detectResponseType("image/png")); // "blob"
121
console.log(detectResponseType("application/pdf")); // "blob"
122
console.log(detectResponseType("video/mp4")); // "blob"
123
124
// Default behavior
125
console.log(detectResponseType("")); // "json"
126
console.log(detectResponseType(undefined)); // "json"
127
128
// Use in custom response handling
129
async function handleResponse(response: Response) {
130
const contentType = response.headers.get("content-type") || "";
131
const responseType = detectResponseType(contentType);
132
133
switch (responseType) {
134
case "json":
135
return await response.json();
136
case "text":
137
return await response.text();
138
case "blob":
139
return await response.blob();
140
default:
141
return await response.text();
142
}
143
}
144
```
145
146
### Options Resolution
147
148
Merges fetch options with defaults, handling headers and query parameters properly.
149
150
```typescript { .api }
151
/**
152
* Resolve and merge fetch options with defaults
153
* @param request - The fetch request (URL or Request object)
154
* @param input - Input fetch options
155
* @param defaults - Default fetch options
156
* @param Headers - Headers constructor
157
* @returns Merged and resolved fetch options
158
*/
159
function resolveFetchOptions<R extends ResponseType = ResponseType, T = any>(
160
request: FetchRequest,
161
input: FetchOptions<R, T> | undefined,
162
defaults: FetchOptions<R, T> | undefined,
163
Headers: typeof globalThis.Headers
164
): ResolvedFetchOptions<R, T>;
165
```
166
167
**Usage Examples:**
168
169
```typescript
170
import { resolveFetchOptions } from "ofetch";
171
172
// Merge options with defaults
173
const defaults = {
174
headers: { "Content-Type": "application/json" },
175
timeout: 5000,
176
query: { version: "v1" }
177
};
178
179
const input = {
180
headers: { "Authorization": "Bearer token" },
181
query: { filter: "active" }
182
};
183
184
const resolved = resolveFetchOptions(
185
"https://api.example.com/users",
186
input,
187
defaults,
188
Headers
189
);
190
191
console.log(resolved.headers.get("Content-Type")); // "application/json"
192
console.log(resolved.headers.get("Authorization")); // "Bearer token"
193
console.log(resolved.query); // { version: "v1", filter: "active" }
194
console.log(resolved.timeout); // 5000
195
196
// Use in custom fetch implementation
197
function customFetch(url: string, options?: any) {
198
const resolved = resolveFetchOptions(url, options, myDefaults, Headers);
199
return fetch(url, resolved);
200
}
201
```
202
203
### Hook Execution
204
205
Executes interceptor hooks in sequence, supporting both single hooks and arrays.
206
207
```typescript { .api }
208
/**
209
* Execute fetch hooks in sequence
210
* @param context - Fetch context containing request, options, response, error
211
* @param hooks - Single hook function or array of hook functions
212
* @returns Promise that resolves when all hooks complete
213
*/
214
async function callHooks<C extends FetchContext = FetchContext>(
215
context: C,
216
hooks: FetchHook<C> | FetchHook<C>[] | undefined
217
): Promise<void>;
218
219
type FetchHook<C extends FetchContext = FetchContext> = (
220
context: C
221
) => MaybePromise<void>;
222
223
type MaybePromise<T> = T | Promise<T>;
224
```
225
226
**Usage Examples:**
227
228
```typescript
229
import { callHooks } from "ofetch";
230
231
// Single hook
232
const singleHook = ({ options }: FetchContext) => {
233
options.headers.set("X-Custom", "value");
234
};
235
236
// Multiple hooks
237
const hooks = [
238
({ options }: FetchContext) => {
239
console.log("Hook 1");
240
options.headers.set("X-Hook1", "executed");
241
},
242
async ({ options }: FetchContext) => {
243
console.log("Hook 2");
244
const token = await getAuthToken();
245
options.headers.set("Authorization", `Bearer ${token}`);
246
}
247
];
248
249
// Execute hooks
250
const context = {
251
request: "https://api.example.com/data",
252
options: { headers: new Headers() },
253
response: undefined,
254
error: undefined
255
};
256
257
await callHooks(context, singleHook);
258
await callHooks(context, hooks);
259
260
// Use in custom interceptor system
261
class CustomFetcher {
262
private onRequestHooks: FetchHook[] = [];
263
264
addHook(hook: FetchHook) {
265
this.onRequestHooks.push(hook);
266
}
267
268
async fetch(url: string, options: any = {}) {
269
const context = { request: url, options: { ...options, headers: new Headers(options.headers) } };
270
271
// Execute all hooks
272
await callHooks(context, this.onRequestHooks);
273
274
return fetch(context.request, context.options);
275
}
276
}
277
```
278
279
### Node.js Fetch Creation
280
281
Creates a Node.js-optimized fetch function with optional keep-alive support.
282
283
```typescript { .api }
284
/**
285
* Create Node.js-specific fetch with keep-alive support
286
* Uses FETCH_KEEP_ALIVE environment variable to enable persistent connections
287
* @returns Fetch function with Node.js optimizations
288
*/
289
function createNodeFetch(): typeof globalThis.fetch;
290
```
291
292
**Usage Examples:**
293
294
```typescript
295
import { createNodeFetch } from "ofetch/node";
296
297
// Enable keep-alive via environment variable
298
process.env.FETCH_KEEP_ALIVE = "true";
299
const fetch = createNodeFetch();
300
301
// Use the Node.js optimized fetch
302
const response = await fetch("https://api.example.com/data");
303
304
// Without keep-alive (default)
305
process.env.FETCH_KEEP_ALIVE = "false";
306
const standardFetch = createNodeFetch();
307
308
// Use in custom ofetch instance
309
import { createFetch } from "ofetch";
310
const nodeFetch = createFetch({
311
fetch: createNodeFetch(),
312
defaults: { timeout: 10000 }
313
});
314
```
315
316
## Internal Constants and Patterns
317
318
The utilities module also defines several internal constants used for request processing:
319
320
```typescript { .api }
321
// HTTP methods that typically include request payloads
322
const payloadMethods = ["PATCH", "POST", "PUT", "DELETE"];
323
324
// Content types that should be parsed as text
325
const textTypes = [
326
"image/svg",
327
"application/xml",
328
"application/xhtml",
329
"application/html"
330
];
331
332
// Regular expression for JSON content type detection
333
const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;
334
```
335
336
These constants help ensure consistent behavior across different response types and request methods.