or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mderrors.mdhooks.mdhttp-methods.mdindex.mdinstances.mdresponses.mdretry.md
tile.json

configuration.mddocs/

0

# Configuration Options

1

2

Comprehensive options for customizing request behavior including JSON handling, URL manipulation, timeouts, progress tracking, and fetch customization.

3

4

## Capabilities

5

6

### JSON Options

7

8

Configure how JSON data is handled in requests and responses.

9

10

```typescript { .api }

11

interface JsonOptions {

12

/** Shortcut for sending JSON data in request body */

13

json?: unknown;

14

/** Custom JSON parsing function for responses */

15

parseJson?: (text: string) => unknown;

16

/** Custom JSON stringification function for requests */

17

stringifyJson?: (data: unknown) => string;

18

}

19

```

20

21

**Usage Examples:**

22

23

```typescript

24

import ky from "ky";

25

26

// Send JSON data

27

const user = await ky.post("https://api.example.com/users", {

28

json: { name: "Alice", email: "alice@example.com", age: 30 }

29

}).json();

30

31

// Custom JSON parsing with date handling

32

const client = ky.create({

33

parseJson: (text) => {

34

return JSON.parse(text, (key, value) => {

35

if (key.endsWith("_at") || key.endsWith("Date")) {

36

return new Date(value);

37

}

38

return value;

39

});

40

}

41

});

42

43

// Custom JSON stringification with BigInt support

44

const bigIntClient = ky.create({

45

stringifyJson: (data) => {

46

return JSON.stringify(data, (key, value) => {

47

if (typeof value === "bigint") {

48

return value.toString();

49

}

50

return value;

51

});

52

}

53

});

54

55

// Safe JSON parsing with error handling

56

const safeClient = ky.create({

57

parseJson: (text) => {

58

try {

59

return JSON.parse(text);

60

} catch (error) {

61

console.error("JSON parse error:", error);

62

return { error: "Invalid JSON response" };

63

}

64

}

65

});

66

```

67

68

### URL and Search Parameters

69

70

Configure URL prefixes and search parameters for requests.

71

72

```typescript { .api }

73

interface UrlOptions {

74

/** URL prefix to prepend to requests */

75

prefixUrl?: URL | string;

76

/** Search parameters to include in request URL */

77

searchParams?: SearchParamsOption;

78

}

79

80

type SearchParamsInit = string | string[][] | Record<string, string> | URLSearchParams | undefined;

81

82

type SearchParamsOption =

83

| SearchParamsInit

84

| Record<string, string | number | boolean | undefined>

85

| Array<Array<string | number | boolean>>;

86

```

87

88

**Usage Examples:**

89

90

```typescript

91

import ky from "ky";

92

93

// API client with base URL

94

const apiClient = ky.create({

95

prefixUrl: "https://api.example.com/v1"

96

});

97

98

// All requests use the prefix

99

const users = await apiClient.get("users").json(); // GET https://api.example.com/v1/users

100

const user = await apiClient.get("users/123").json(); // GET https://api.example.com/v1/users/123

101

102

// Search parameters as object

103

const filteredData = await ky.get("https://api.example.com/data", {

104

searchParams: {

105

category: "electronics",

106

minPrice: 100,

107

maxPrice: 500,

108

inStock: true,

109

tags: undefined // Will be filtered out

110

}

111

}).json();

112

113

// Search parameters as URLSearchParams

114

const params = new URLSearchParams();

115

params.append("sort", "name");

116

params.append("sort", "date");

117

params.append("limit", "20");

118

119

const sortedData = await ky.get("https://api.example.com/items", {

120

searchParams: params

121

}).json();

122

123

// Search parameters as array

124

const complexParams = await ky.get("https://api.example.com/search", {

125

searchParams: [

126

["query", "javascript"],

127

["category", "programming"],

128

["category", "web"],

129

["format", "json"]

130

]

131

}).json();

132

```

133

134

### Timeout Configuration

135

136

Configure request timeouts to prevent hanging requests.

137

138

```typescript { .api }

139

interface TimeoutOptions {

140

/** Timeout in milliseconds, or false to disable */

141

timeout?: number | false;

142

}

143

```

144

145

**Usage Examples:**

146

147

```typescript

148

import ky from "ky";

149

150

// Global timeout for all requests

151

const fastClient = ky.create({

152

timeout: 5000 // 5 seconds

153

});

154

155

// Per-request timeout

156

const quickData = await ky.get("https://api.example.com/quick", {

157

timeout: 2000 // 2 seconds

158

}).json();

159

160

// Long timeout for slow operations

161

const largeFile = await ky.get("https://api.example.com/export", {

162

timeout: 60000 // 60 seconds

163

}).arrayBuffer();

164

165

// Disable timeout for streaming operations

166

const stream = await ky.get("https://api.example.com/stream", {

167

timeout: false

168

});

169

170

// Environment-specific timeouts

171

const timeoutClient = ky.create({

172

timeout: process.env.NODE_ENV === "development" ? 30000 : 10000

173

});

174

```

175

176

### Error Handling Configuration

177

178

Configure how HTTP errors are handled.

179

180

```typescript { .api }

181

interface ErrorOptions {

182

/** Whether to throw HTTPError for non-2xx status codes */

183

throwHttpErrors?: boolean;

184

}

185

```

186

187

**Usage Examples:**

188

189

```typescript

190

import ky from "ky";

191

192

// Disable automatic error throwing

193

const response = await ky.get("https://api.example.com/might-fail", {

194

throwHttpErrors: false

195

});

196

197

if (response.ok) {

198

const data = await response.json();

199

console.log("Success:", data);

200

} else {

201

console.log("Failed with status:", response.status);

202

}

203

204

// Client that never throws HTTP errors

205

const tolerantClient = ky.create({

206

throwHttpErrors: false

207

});

208

209

// Handle errors manually

210

const result = await tolerantClient.get("https://api.example.com/data");

211

if (result.status === 404) {

212

console.log("Resource not found");

213

} else if (result.status >= 500) {

214

console.log("Server error");

215

} else if (result.ok) {

216

const data = await result.json();

217

console.log("Data:", data);

218

}

219

```

220

221

### Progress Tracking

222

223

Track upload and download progress for large requests.

224

225

```typescript { .api }

226

interface ProgressOptions {

227

/** Download progress handler */

228

onDownloadProgress?: (progress: Progress, chunk: Uint8Array) => void;

229

/** Upload progress handler */

230

onUploadProgress?: (progress: Progress, chunk: Uint8Array) => void;

231

}

232

233

interface Progress {

234

/** Progress as decimal (0.0 to 1.0) */

235

percent: number;

236

/** Bytes transferred so far */

237

transferredBytes: number;

238

/** Total bytes (0 if unknown) */

239

totalBytes: number;

240

}

241

```

242

243

**Usage Examples:**

244

245

```typescript

246

import ky from "ky";

247

248

// Download progress tracking

249

const fileData = await ky.get("https://api.example.com/large-file.zip", {

250

onDownloadProgress: (progress, chunk) => {

251

const percentage = Math.round(progress.percent * 100);

252

console.log(`Download: ${percentage}% (${progress.transferredBytes}/${progress.totalBytes} bytes)`);

253

254

// Update progress bar

255

updateProgressBar(percentage);

256

}

257

}).arrayBuffer();

258

259

// Upload progress tracking

260

const formData = new FormData();

261

formData.append("file", largeFile);

262

263

const uploadResult = await ky.post("https://api.example.com/upload", {

264

body: formData,

265

onUploadProgress: (progress, chunk) => {

266

const percentage = Math.round(progress.percent * 100);

267

console.log(`Upload: ${percentage}% (${progress.transferredBytes}/${progress.totalBytes} bytes)`);

268

269

// Show upload status

270

setUploadStatus(`Uploading... ${percentage}%`);

271

}

272

}).json();

273

274

// Combined progress tracking

275

const processLargeFile = async () => {

276

const result = await ky.post("https://api.example.com/process", {

277

json: { fileUrl: "https://example.com/input.dat" },

278

onUploadProgress: (progress) => {

279

console.log(`Sending request: ${Math.round(progress.percent * 100)}%`);

280

},

281

onDownloadProgress: (progress) => {

282

console.log(`Receiving response: ${Math.round(progress.percent * 100)}%`);

283

}

284

}).json();

285

286

return result;

287

};

288

```

289

290

### Custom Fetch Implementation

291

292

Provide a custom fetch implementation for advanced use cases.

293

294

```typescript { .api }

295

interface FetchOptions {

296

/** Custom fetch implementation */

297

fetch?: (input: Input, init?: RequestInit) => Promise<Response>;

298

}

299

```

300

301

**Usage Examples:**

302

303

```typescript

304

import ky from "ky";

305

306

// Use custom fetch with additional features

307

const customClient = ky.create({

308

fetch: async (input, init) => {

309

// Add request logging

310

console.log(`Fetching: ${init?.method || "GET"} ${input}`);

311

312

// Use native fetch with modifications

313

const response = await fetch(input, {

314

...init,

315

// Add custom headers

316

headers: {

317

...init?.headers,

318

"X-Custom-Client": "ky-enhanced"

319

}

320

});

321

322

// Add response logging

323

console.log(`Response: ${response.status} ${input}`);

324

325

return response;

326

}

327

});

328

329

// Node.js with undici or node-fetch

330

import { fetch } from "undici";

331

332

const nodeClient = ky.create({

333

fetch: fetch as any

334

});

335

336

// Mock fetch for testing

337

const mockClient = ky.create({

338

fetch: async (input, init) => {

339

const url = input.toString();

340

341

if (url.includes("/users")) {

342

return new Response(JSON.stringify([

343

{ id: 1, name: "Alice" },

344

{ id: 2, name: "Bob" }

345

]), {

346

status: 200,

347

headers: { "Content-Type": "application/json" }

348

});

349

}

350

351

return new Response("Not found", { status: 404 });

352

}

353

});

354

```

355

356

## Complete Options Interface

357

358

```typescript { .api }

359

interface Options extends KyOptions, RequestInit {

360

method?: LiteralUnion<HttpMethod, string>;

361

headers?: KyHeadersInit;

362

}

363

364

interface KyOptions {

365

json?: unknown;

366

parseJson?: (text: string) => unknown;

367

stringifyJson?: (data: unknown) => string;

368

searchParams?: SearchParamsOption;

369

prefixUrl?: URL | string;

370

retry?: RetryOptions | number;

371

timeout?: number | false;

372

throwHttpErrors?: boolean;

373

onDownloadProgress?: (progress: Progress, chunk: Uint8Array) => void;

374

onUploadProgress?: (progress: Progress, chunk: Uint8Array) => void;

375

fetch?: (input: Input, init?: RequestInit) => Promise<Response>;

376

hooks?: Hooks;

377

}

378

379

type KyHeadersInit = NonNullable<RequestInit['headers']> | Record<string, string | undefined>;

380

381

type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>);

382

383

type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete';

384

```