0
# Instance Management
1
2
Create and extend ky instances with custom defaults for different API endpoints or configurations. This enables reusable configuration patterns and API-specific client creation.
3
4
## Capabilities
5
6
### Create Instance
7
8
Create a new ky instance with completely new defaults, independent of the parent instance.
9
10
```typescript { .api }
11
/**
12
* Create a new Ky instance with complete new defaults
13
* @param defaultOptions - Default options for the new instance
14
* @returns New KyInstance with the specified defaults
15
*/
16
function create(defaultOptions?: Options): KyInstance;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import ky from "ky";
23
24
// Create API-specific instance
25
const apiClient = ky.create({
26
prefixUrl: "https://api.example.com",
27
headers: {
28
"Authorization": "Bearer token123",
29
"Content-Type": "application/json"
30
},
31
timeout: 10000,
32
retry: 3
33
});
34
35
// Use the configured instance
36
const users = await apiClient.get("users").json();
37
const user = await apiClient.post("users", {
38
json: { name: "Alice", email: "alice@example.com" }
39
}).json();
40
41
// Create instance with custom retry logic
42
const robustClient = ky.create({
43
retry: {
44
limit: 5,
45
methods: ["get", "post", "put"],
46
statusCodes: [408, 413, 429, 500, 502, 503, 504],
47
delay: (attemptCount) => Math.min(1000 * (2 ** attemptCount), 30000)
48
},
49
timeout: 30000
50
});
51
52
// Create instance with custom JSON handling
53
const customJsonClient = ky.create({
54
parseJson: (text) => {
55
// Custom JSON parsing logic
56
return JSON.parse(text, (key, value) => {
57
if (key.endsWith("_date")) {
58
return new Date(value);
59
}
60
return value;
61
});
62
},
63
stringifyJson: (data) => {
64
// Custom JSON stringification
65
return JSON.stringify(data, (key, value) => {
66
if (value instanceof Date) {
67
return value.toISOString();
68
}
69
return value;
70
});
71
}
72
});
73
```
74
75
### Extend Instance
76
77
Create a new ky instance that inherits defaults from its parent and overrides or adds specific options.
78
79
```typescript { .api }
80
/**
81
* Create a new Ky instance with some defaults overridden with your own
82
* Inherits defaults from its parent, unlike create() which starts fresh
83
* @param defaultOptions - Options to override/add, or function receiving parent options
84
* @returns New KyInstance extending the parent instance
85
*/
86
function extend(defaultOptions: Options | ((parentOptions: Options) => Options)): KyInstance;
87
```
88
89
**Usage Examples:**
90
91
```typescript
92
import ky from "ky";
93
94
// Create base API client
95
const apiClient = ky.create({
96
prefixUrl: "https://api.example.com",
97
headers: { "Authorization": "Bearer token123" },
98
timeout: 10000
99
});
100
101
// Extend with additional headers
102
const adminClient = apiClient.extend({
103
headers: { "X-Admin-Access": "true" },
104
timeout: 15000 // Override parent timeout
105
});
106
107
// Extend with function for dynamic configuration
108
const versionedClient = apiClient.extend((options) => ({
109
prefixUrl: `${options.prefixUrl}/v2`,
110
headers: {
111
...options.headers,
112
"API-Version": "2.0"
113
}
114
}));
115
116
// Create specialized clients from base
117
const usersClient = apiClient.extend({
118
prefixUrl: "https://api.example.com/users",
119
hooks: {
120
beforeRequest: [
121
(request) => {
122
request.headers.set("X-Resource", "users");
123
}
124
]
125
}
126
});
127
128
const filesClient = apiClient.extend({
129
prefixUrl: "https://api.example.com/files",
130
timeout: 60000, // Longer timeout for file operations
131
onUploadProgress: (progress) => {
132
console.log(`Upload: ${Math.round(progress.percent * 100)}%`);
133
}
134
});
135
136
// Chain extensions for complex inheritance
137
const devUsersClient = usersClient.extend({
138
prefixUrl: "https://dev-api.example.com/users",
139
headers: { "X-Environment": "development" }
140
});
141
```
142
143
### Instance with Hooks
144
145
Create instances with pre-configured hooks for common patterns like authentication, logging, or error handling.
146
147
**Usage Examples:**
148
149
```typescript
150
import ky from "ky";
151
152
// Instance with authentication refresh
153
const authClient = ky.create({
154
prefixUrl: "https://api.example.com",
155
hooks: {
156
beforeRequest: [
157
(request) => {
158
const token = localStorage.getItem("token");
159
if (token) {
160
request.headers.set("Authorization", `Bearer ${token}`);
161
}
162
}
163
],
164
beforeRetry: [
165
async ({ request, options, error, retryCount }) => {
166
if (error instanceof HTTPError && error.response.status === 401) {
167
// Refresh token and retry
168
const newToken = await refreshAuthToken();
169
request.headers.set("Authorization", `Bearer ${newToken}`);
170
}
171
}
172
]
173
}
174
});
175
176
// Instance with logging
177
const loggedClient = ky.create({
178
hooks: {
179
beforeRequest: [
180
(request) => {
181
console.log(`→ ${request.method} ${request.url}`);
182
}
183
],
184
afterResponse: [
185
(request, options, response) => {
186
console.log(`← ${response.status} ${request.method} ${request.url}`);
187
}
188
]
189
}
190
});
191
192
// Instance with error transformation
193
const errorClient = ky.create({
194
hooks: {
195
beforeError: [
196
(error) => {
197
if (error.response) {
198
// Add custom error information
199
error.name = "APIError";
200
error.message = `API Error: ${error.response.status} ${error.response.statusText}`;
201
}
202
return error;
203
}
204
]
205
}
206
});
207
```
208
209
### Environment-Specific Instances
210
211
Create instances optimized for different environments or API versions.
212
213
**Usage Examples:**
214
215
```typescript
216
import ky from "ky";
217
218
// Development instance with verbose logging
219
const devClient = ky.create({
220
prefixUrl: "https://dev-api.example.com",
221
timeout: 30000,
222
retry: { limit: 1 }, // Fail fast in development
223
hooks: {
224
beforeRequest: [(request) => console.log("DEV:", request.method, request.url)],
225
beforeError: [(error) => { console.error("DEV ERROR:", error); return error; }]
226
}
227
});
228
229
// Production instance with robust retry
230
const prodClient = ky.create({
231
prefixUrl: "https://api.example.com",
232
timeout: 10000,
233
retry: {
234
limit: 3,
235
methods: ["get", "put", "head", "delete"],
236
statusCodes: [408, 413, 429, 500, 502, 503, 504]
237
},
238
throwHttpErrors: true
239
});
240
241
// Testing instance with mocked responses
242
const testClient = ky.create({
243
hooks: {
244
beforeRequest: [
245
(request) => {
246
// Return mock response for testing
247
if (request.url.includes("/users/123")) {
248
return new Response(JSON.stringify({ id: 123, name: "Test User" }), {
249
status: 200,
250
headers: { "Content-Type": "application/json" }
251
});
252
}
253
}
254
]
255
}
256
});
257
```
258
259
## Types
260
261
```typescript { .api }
262
interface KyInstance {
263
<T>(url: Input, options?: Options): ResponsePromise<T>;
264
get: <T>(url: Input, options?: Options) => ResponsePromise<T>;
265
post: <T>(url: Input, options?: Options) => ResponsePromise<T>;
266
put: <T>(url: Input, options?: Options) => ResponsePromise<T>;
267
patch: <T>(url: Input, options?: Options) => ResponsePromise<T>;
268
delete: <T>(url: Input, options?: Options) => ResponsePromise<T>;
269
head: (url: Input, options?: Options) => ResponsePromise;
270
create: (defaultOptions?: Options) => KyInstance;
271
extend: (defaultOptions: Options | ((parentOptions: Options) => Options)) => KyInstance;
272
readonly stop: typeof stop;
273
}
274
275
type Input = string | URL | Request;
276
277
interface Options extends KyOptions, RequestInit {
278
method?: LiteralUnion<HttpMethod, string>;
279
headers?: KyHeadersInit;
280
}
281
```