or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-operations.mderror-handling.mdindex.mdinterceptors.mdutilities.md

utilities.mddocs/

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.