bun-types 1.2.9-canary.20250406T140639 → 1.2.9-canary.20250408T140629

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/api/fetch.md CHANGED
@@ -337,7 +337,7 @@ This will print the request and response headers to your terminal:
337
337
  ```sh
338
338
  [fetch] > HTTP/1.1 GET http://example.com/
339
339
  [fetch] > Connection: keep-alive
340
- [fetch] > User-Agent: Bun/1.2.9-canary.20250406T140639
340
+ [fetch] > User-Agent: Bun/1.2.9-canary.20250408T140629
341
341
  [fetch] > Accept: */*
342
342
  [fetch] > Host: example.com
343
343
  [fetch] > Accept-Encoding: gzip, deflate, br
@@ -0,0 +1,514 @@
1
+ Bun provides native bindings for working with Redis databases with a modern, Promise-based API. The interface is designed to be simple and performant, with built-in connection management, fully typed responses, and TLS support. **New in Bun v1.2.9**
2
+
3
+ ```ts
4
+ import { redis } from "bun";
5
+
6
+ // Set a key
7
+ await redis.set("greeting", "Hello from Bun!");
8
+
9
+ // Get a key
10
+ const greeting = await redis.get("greeting");
11
+ console.log(greeting); // "Hello from Bun!"
12
+
13
+ // Increment a counter
14
+ await redis.set("counter", 0);
15
+ await redis.incr("counter");
16
+
17
+ // Check if a key exists
18
+ const exists = await redis.exists("greeting");
19
+
20
+ // Delete a key
21
+ await redis.del("greeting");
22
+ ```
23
+
24
+ {% features title="Features" %}
25
+
26
+ {% icon size=20 name="Bolt" /%} Fast native implementation using Zig and JavaScriptCore
27
+
28
+ {% icon size=20 name="Link" /%} Automatic pipelining for better performance
29
+
30
+ {% icon size=20 name="EthernetPort" /%} Auto-reconnect with exponential backoff
31
+
32
+ {% icon size=20 name="Omega" /%} Support for RESP3 protocol
33
+
34
+ {% icon size=20 name="Lock" /%} TLS support
35
+
36
+ {% icon size=20 name="Clock" /%} Connection management with configurable timeouts
37
+
38
+ {% icon size=20 name="IndentDecrease" /%} Offline command queue
39
+
40
+ {% icon size=20 name="Settings" /%} Automatic configuration with environment variables
41
+
42
+ {% icon size=20 name="Hash" /%} Support for hash, set, and other Redis data structures
43
+
44
+ {% /features %}
45
+
46
+ ## Getting Started
47
+
48
+ To use the Redis client, you first need to create a connection:
49
+
50
+ ```ts
51
+ import { redis, RedisClient } from "bun";
52
+
53
+ // Using the default client (reads connection info from environment)
54
+ // process.env.REDIS_URL is used by default
55
+ await redis.set("hello", "world");
56
+ const result = await redis.get("hello");
57
+
58
+ // Creating a custom client
59
+ const client = new RedisClient("redis://username:password@localhost:6379");
60
+ await client.set("counter", "0");
61
+ await client.incr("counter");
62
+ ```
63
+
64
+ By default, the client reads connection information from the following environment variables (in order of precedence):
65
+
66
+ - `REDIS_URL`
67
+ - If not set, defaults to `"redis://localhost:6379"`
68
+
69
+ ### Connection Lifecycle
70
+
71
+ The Redis client automatically handles connections in the background:
72
+
73
+ ```ts
74
+ // No connection is made until a command is executed
75
+ const client = new RedisClient();
76
+
77
+ // First command initiates the connection
78
+ await client.set("key", "value");
79
+
80
+ // Connection remains open for subsequent commands
81
+ await client.get("key");
82
+
83
+ // Explicitly close the connection when done
84
+ client.disconnect();
85
+ ```
86
+
87
+ You can also manually control the connection lifecycle:
88
+
89
+ ```ts
90
+ const client = new RedisClient();
91
+
92
+ // Explicitly connect
93
+ await client.connect();
94
+
95
+ // Run commands
96
+ await client.set("key", "value");
97
+
98
+ // Disconnect when done
99
+ client.disconnect();
100
+ ```
101
+
102
+ ## Basic Operations
103
+
104
+ ### String Operations
105
+
106
+ ```ts
107
+ // Set a key
108
+ await redis.set("user:1:name", "Alice");
109
+
110
+ // Get a key
111
+ const name = await redis.get("user:1:name");
112
+
113
+ // Delete a key
114
+ await redis.del("user:1:name");
115
+
116
+ // Check if a key exists
117
+ const exists = await redis.exists("user:1:name");
118
+
119
+ // Set expiration (in seconds)
120
+ await redis.set("session:123", "active");
121
+ await redis.expire("session:123", 3600); // expires in 1 hour
122
+
123
+ // Get time to live (in seconds)
124
+ const ttl = await redis.ttl("session:123");
125
+ ```
126
+
127
+ ### Numeric Operations
128
+
129
+ ```ts
130
+ // Set initial value
131
+ await redis.set("counter", "0");
132
+
133
+ // Increment by 1
134
+ await redis.incr("counter");
135
+
136
+ // Decrement by 1
137
+ await redis.decr("counter");
138
+ ```
139
+
140
+ ### Hash Operations
141
+
142
+ ```ts
143
+ // Set multiple fields in a hash
144
+ await redis.hmset("user:123", [
145
+ "name",
146
+ "Alice",
147
+ "email",
148
+ "alice@example.com",
149
+ "active",
150
+ "true",
151
+ ]);
152
+
153
+ // Get multiple fields from a hash
154
+ const userFields = await redis.hmget("user:123", ["name", "email"]);
155
+ console.log(userFields); // ["Alice", "alice@example.com"]
156
+
157
+ // Increment a numeric field in a hash
158
+ await redis.hincrby("user:123", "visits", 1);
159
+
160
+ // Increment a float field in a hash
161
+ await redis.hincrbyfloat("user:123", "score", 1.5);
162
+ ```
163
+
164
+ ### Set Operations
165
+
166
+ ```ts
167
+ // Add member to set
168
+ await redis.sadd("tags", "javascript");
169
+
170
+ // Remove member from set
171
+ await redis.srem("tags", "javascript");
172
+
173
+ // Check if member exists in set
174
+ const isMember = await redis.sismember("tags", "javascript");
175
+
176
+ // Get all members of a set
177
+ const allTags = await redis.smembers("tags");
178
+
179
+ // Get a random member
180
+ const randomTag = await redis.srandmember("tags");
181
+
182
+ // Pop (remove and return) a random member
183
+ const poppedTag = await redis.spop("tags");
184
+ ```
185
+
186
+ ## Advanced Usage
187
+
188
+ ### Command Execution and Pipelining
189
+
190
+ The client automatically pipelines commands, improving performance by sending multiple commands in a batch and processing responses as they arrive.
191
+
192
+ ```ts
193
+ // Commands are automatically pipelined by default
194
+ const [infoResult, listResult] = await Promise.all([
195
+ redis.get("user:1:name"),
196
+ redis.get("user:2:email"),
197
+ ]);
198
+ ```
199
+
200
+ To disable automatic pipelining, you can set the `enableAutoPipelining` option to `false`:
201
+
202
+ ```ts
203
+ const client = new RedisClient("redis://localhost:6379", {
204
+ enableAutoPipelining: false,
205
+ });
206
+ ```
207
+
208
+ ### Raw Commands
209
+
210
+ When you need to use commands that don't have convenience methods, you can use the `send` method:
211
+
212
+ ```ts
213
+ // Run any Redis command
214
+ const info = await redis.send("INFO", []);
215
+
216
+ // LPUSH to a list
217
+ await redis.send("LPUSH", ["mylist", "value1", "value2"]);
218
+
219
+ // Get list range
220
+ const list = await redis.send("LRANGE", ["mylist", "0", "-1"]);
221
+ ```
222
+
223
+ The `send` method allows you to use any Redis command, even ones that don't have dedicated methods in the client. The first argument is the command name, and the second argument is an array of string arguments.
224
+
225
+ ### Connection Events
226
+
227
+ You can register handlers for connection events:
228
+
229
+ ```ts
230
+ const client = new RedisClient();
231
+
232
+ // Called when successfully connected to Redis server
233
+ client.onconnect = () => {
234
+ console.log("Connected to Redis server");
235
+ };
236
+
237
+ // Called when disconnected from Redis server
238
+ client.onclose = error => {
239
+ console.error("Disconnected from Redis server:", error);
240
+ };
241
+
242
+ // Manually connect/disconnect
243
+ await client.connect();
244
+ client.disconnect();
245
+ ```
246
+
247
+ ### Connection Status and Monitoring
248
+
249
+ ```ts
250
+ // Check if connected
251
+ console.log(client.connected); // boolean indicating connection status
252
+
253
+ // Check amount of data buffered (in bytes)
254
+ console.log(client.bufferedAmount);
255
+ ```
256
+
257
+ ### Type Conversion
258
+
259
+ The Redis client handles automatic type conversion for Redis responses:
260
+
261
+ - Integer responses are returned as JavaScript numbers
262
+ - Bulk strings are returned as JavaScript strings
263
+ - Simple strings are returned as JavaScript strings
264
+ - Null bulk strings are returned as `null`
265
+ - Array responses are returned as JavaScript arrays
266
+ - Error responses throw JavaScript errors with appropriate error codes
267
+ - Boolean responses (RESP3) are returned as JavaScript booleans
268
+ - Map responses (RESP3) are returned as JavaScript objects
269
+ - Set responses (RESP3) are returned as JavaScript arrays
270
+
271
+ Special handling for specific commands:
272
+
273
+ - `EXISTS` returns a boolean instead of a number (1 becomes true, 0 becomes false)
274
+ - `SISMEMBER` returns a boolean (1 becomes true, 0 becomes false)
275
+
276
+ The following commands disable automatic pipelining:
277
+
278
+ - `AUTH`
279
+ - `INFO`
280
+ - `QUIT`
281
+ - `EXEC`
282
+ - `MULTI`
283
+ - `WATCH`
284
+ - `SCRIPT`
285
+ - `SELECT`
286
+ - `CLUSTER`
287
+ - `DISCARD`
288
+ - `UNWATCH`
289
+ - `PIPELINE`
290
+ - `SUBSCRIBE`
291
+ - `UNSUBSCRIBE`
292
+ - `UNPSUBSCRIBE`
293
+
294
+ ## Connection Options
295
+
296
+ When creating a client, you can pass various options to configure the connection:
297
+
298
+ ```ts
299
+ const client = new RedisClient("redis://localhost:6379", {
300
+ // Connection timeout in milliseconds (default: 10000)
301
+ connectionTimeout: 5000,
302
+
303
+ // Idle timeout in milliseconds (default: 0 = no timeout)
304
+ idleTimeout: 30000,
305
+
306
+ // Whether to automatically reconnect on disconnection (default: true)
307
+ autoReconnect: true,
308
+
309
+ // Maximum number of reconnection attempts (default: 10)
310
+ maxRetries: 10,
311
+
312
+ // Whether to queue commands when disconnected (default: true)
313
+ enableOfflineQueue: true,
314
+
315
+ // Whether to automatically pipeline commands (default: true)
316
+ enableAutoPipelining: true,
317
+
318
+ // TLS options (default: false)
319
+ tls: true,
320
+ // Alternatively, provide custom TLS config:
321
+ // tls: {
322
+ // rejectUnauthorized: true,
323
+ // ca: "path/to/ca.pem",
324
+ // cert: "path/to/cert.pem",
325
+ // key: "path/to/key.pem",
326
+ // }
327
+ });
328
+ ```
329
+
330
+ ### Reconnection Behavior
331
+
332
+ When a connection is lost, the client automatically attempts to reconnect with exponential backoff:
333
+
334
+ 1. The client starts with a small delay (50ms) and doubles it with each attempt
335
+ 2. Reconnection delay is capped at 2000ms (2 seconds)
336
+ 3. The client attempts to reconnect up to `maxRetries` times (default: 10)
337
+ 4. Commands executed during disconnection are:
338
+ - Queued if `enableOfflineQueue` is true (default)
339
+ - Rejected immediately if `enableOfflineQueue` is false
340
+
341
+ ## Supported URL Formats
342
+
343
+ The Redis client supports various URL formats:
344
+
345
+ ```ts
346
+ // Standard Redis URL
347
+ new RedisClient("redis://localhost:6379");
348
+ new RedisClient("redis://localhost:6379");
349
+
350
+ // With authentication
351
+ new RedisClient("redis://username:password@localhost:6379");
352
+
353
+ // With database number
354
+ new RedisClient("redis://localhost:6379/0");
355
+
356
+ // TLS connections
357
+ new RedisClient("rediss://localhost:6379");
358
+ new RedisClient("rediss://localhost:6379");
359
+ new RedisClient("redis+tls://localhost:6379");
360
+ new RedisClient("redis+tls://localhost:6379");
361
+
362
+ // Unix socket connections
363
+ new RedisClient("redis+unix:///path/to/socket");
364
+ new RedisClient("redis+unix:///path/to/socket");
365
+
366
+ // TLS over Unix socket
367
+ new RedisClient("redis+tls+unix:///path/to/socket");
368
+ new RedisClient("redis+tls+unix:///path/to/socket");
369
+ ```
370
+
371
+ ## Error Handling
372
+
373
+ The Redis client throws typed errors for different scenarios:
374
+
375
+ ```ts
376
+ try {
377
+ await redis.get("non-existent-key");
378
+ } catch (error) {
379
+ if (error.code === "ERR_REDIS_CONNECTION_CLOSED") {
380
+ console.error("Connection to Redis server was closed");
381
+ } else if (error.code === "ERR_REDIS_AUTHENTICATION_FAILED") {
382
+ console.error("Authentication failed");
383
+ } else {
384
+ console.error("Unexpected error:", error);
385
+ }
386
+ }
387
+ ```
388
+
389
+ Common error codes:
390
+
391
+ - `ERR_REDIS_CONNECTION_CLOSED` - Connection to the server was closed
392
+ - `ERR_REDIS_AUTHENTICATION_FAILED` - Failed to authenticate with the server
393
+ - `ERR_REDIS_INVALID_RESPONSE` - Received an invalid response from the server
394
+
395
+ ## Example Use Cases
396
+
397
+ ### Caching
398
+
399
+ ```ts
400
+ async function getUserWithCache(userId) {
401
+ const cacheKey = `user:${userId}`;
402
+
403
+ // Try to get from cache first
404
+ const cachedUser = await redis.get(cacheKey);
405
+ if (cachedUser) {
406
+ return JSON.parse(cachedUser);
407
+ }
408
+
409
+ // Not in cache, fetch from database
410
+ const user = await database.getUser(userId);
411
+
412
+ // Store in cache for 1 hour
413
+ await redis.set(cacheKey, JSON.stringify(user));
414
+ await redis.expire(cacheKey, 3600);
415
+
416
+ return user;
417
+ }
418
+ ```
419
+
420
+ ### Rate Limiting
421
+
422
+ ```ts
423
+ async function rateLimit(ip, limit = 100, windowSecs = 3600) {
424
+ const key = `ratelimit:${ip}`;
425
+
426
+ // Increment counter
427
+ const count = await redis.incr(key);
428
+
429
+ // Set expiry if this is the first request in window
430
+ if (count === 1) {
431
+ await redis.expire(key, windowSecs);
432
+ }
433
+
434
+ // Check if limit exceeded
435
+ return {
436
+ limited: count > limit,
437
+ remaining: Math.max(0, limit - count),
438
+ };
439
+ }
440
+ ```
441
+
442
+ ### Session Storage
443
+
444
+ ```ts
445
+ async function createSession(userId, data) {
446
+ const sessionId = crypto.randomUUID();
447
+ const key = `session:${sessionId}`;
448
+
449
+ // Store session with expiration
450
+ await redis.hmset(key, [
451
+ "userId",
452
+ userId.toString(),
453
+ "created",
454
+ Date.now().toString(),
455
+ "data",
456
+ JSON.stringify(data),
457
+ ]);
458
+ await redis.expire(key, 86400); // 24 hours
459
+
460
+ return sessionId;
461
+ }
462
+
463
+ async function getSession(sessionId) {
464
+ const key = `session:${sessionId}`;
465
+
466
+ // Get session data
467
+ const exists = await redis.exists(key);
468
+ if (!exists) return null;
469
+
470
+ const [userId, created, data] = await redis.hmget(key, [
471
+ "userId",
472
+ "created",
473
+ "data",
474
+ ]);
475
+
476
+ return {
477
+ userId: Number(userId),
478
+ created: Number(created),
479
+ data: JSON.parse(data),
480
+ };
481
+ }
482
+ ```
483
+
484
+ ## Implementation Notes
485
+
486
+ Bun's Redis client is implemented in Zig and uses the Redis Serialization Protocol (RESP3). It manages connections efficiently and provides automatic reconnection with exponential backoff.
487
+
488
+ The client supports pipelining commands, meaning multiple commands can be sent without waiting for the replies to previous commands. This significantly improves performance when sending multiple commands in succession.
489
+
490
+ ### RESP3 Protocol Support
491
+
492
+ Bun's Redis client uses the newer RESP3 protocol by default, which provides more data types and features compared to RESP2:
493
+
494
+ - Better error handling with typed errors
495
+ - Native Boolean responses
496
+ - Map/Dictionary responses (key-value objects)
497
+ - Set responses
498
+ - Double (floating point) values
499
+ - BigNumber support for large integer values
500
+
501
+ When connecting to Redis servers using older versions that don't support RESP3, the client automatically fallbacks to compatible modes.
502
+
503
+ ## Limitations and Future Plans
504
+
505
+ Current limitations of the Redis client we are planning to address in future versions:
506
+
507
+ - [ ] No dedicated API for pub/sub functionality (though you can use the raw command API)
508
+ - [ ] Transactions (MULTI/EXEC) must be done through raw commands for now
509
+ - [ ] Streams are supported but without dedicated methods
510
+
511
+ Unsupported features:
512
+
513
+ - Redis Sentinel
514
+ - Redis Cluster
package/docs/api/spawn.md CHANGED
@@ -120,7 +120,7 @@ You can read results from the subprocess via the `stdout` and `stderr` propertie
120
120
  ```ts
121
121
  const proc = Bun.spawn(["bun", "--version"]);
122
122
  const text = await new Response(proc.stdout).text();
123
- console.log(text); // => "1.2.9-canary.20250406T140639"
123
+ console.log(text); // => "1.2.9-canary.20250408T140629"
124
124
  ```
125
125
 
126
126
  Configure the output stream by passing one of the following values to `stdout/stderr`:
@@ -7,7 +7,7 @@ Use `bun publish` to publish a package to the npm registry.
7
7
  $ bun publish
8
8
 
9
9
  ## Output
10
- bun publish v1.2.9-canary.20250406T140639 (ca7428e9)
10
+ bun publish v1.2.9-canary.20250408T140629 (ca7428e9)
11
11
 
12
12
  packed 203B package.json
13
13
  packed 224B README.md
@@ -9,7 +9,7 @@ $ bunx nuxi init my-nuxt-app
9
9
  ✔ Which package manager would you like to use?
10
10
  bun
11
11
  ◐ Installing dependencies...
12
- bun install v1.2.9-canary.20250406T140639 (16b4bf34)
12
+ bun install v1.2.9-canary.20250408T140629 (16b4bf34)
13
13
  + @nuxt/devtools@0.8.2
14
14
  + nuxt@3.7.0
15
15
  785 packages installed [2.67s]
@@ -16,7 +16,7 @@ This will add the package to `peerDependencies` in `package.json`.
16
16
  ```json-diff
17
17
  {
18
18
  "peerDependencies": {
19
- + "@types/bun": "^1.2.9-canary.20250406T140639"
19
+ + "@types/bun": "^1.2.9-canary.20250408T140629"
20
20
  }
21
21
  }
22
22
  ```
@@ -28,7 +28,7 @@ Running `bun install` will install peer dependencies by default, unless marked o
28
28
  ```json-diff
29
29
  {
30
30
  "peerDependencies": {
31
- "@types/bun": "^1.2.9-canary.20250406T140639"
31
+ "@types/bun": "^1.2.9-canary.20250408T140629"
32
32
  },
33
33
  "peerDependenciesMeta": {
34
34
  + "@types/bun": {
@@ -97,7 +97,7 @@ $ bun update
97
97
  $ bun update @types/bun --latest
98
98
 
99
99
  # Update a dependency to a specific version
100
- $ bun update @types/bun@1.2.9-canary.20250406T140639
100
+ $ bun update @types/bun@1.2.9-canary.20250408T140629
101
101
 
102
102
  # Update all dependencies to the latest versions
103
103
  $ bun update --latest
@@ -21,7 +21,7 @@ Here's what the output of a typical test run looks like. In this case, there are
21
21
 
22
22
  ```sh
23
23
  $ bun test
24
- bun test v1.2.9-canary.20250406T140639 (9c68abdb)
24
+ bun test v1.2.9-canary.20250408T140629 (9c68abdb)
25
25
 
26
26
  test.test.js:
27
27
  ✓ add [0.87ms]
@@ -47,7 +47,7 @@ To only run certain test files, pass a positional argument to `bun test`. The ru
47
47
 
48
48
  ```sh
49
49
  $ bun test test3
50
- bun test v1.2.9-canary.20250406T140639 (9c68abdb)
50
+ bun test v1.2.9-canary.20250408T140629 (9c68abdb)
51
51
 
52
52
  test3.test.js:
53
53
  ✓ add [1.40ms]
@@ -85,7 +85,7 @@ Adding `-t add` will only run tests with "add" in the name. This works with test
85
85
 
86
86
  ```sh
87
87
  $ bun test -t add
88
- bun test v1.2.9-canary.20250406T140639 (9c68abdb)
88
+ bun test v1.2.9-canary.20250408T140629 (9c68abdb)
89
89
 
90
90
  test.test.js:
91
91
  ✓ add [1.79ms]
@@ -18,7 +18,7 @@ The first time this test is executed, Bun will evaluate the value passed into `e
18
18
 
19
19
  ```sh
20
20
  $ bun test test/snap
21
- bun test v1.2.9-canary.20250406T140639 (9c68abdb)
21
+ bun test v1.2.9-canary.20250408T140629 (9c68abdb)
22
22
 
23
23
  test/snap.test.ts:
24
24
  ✓ snapshot [1.48ms]
@@ -61,7 +61,7 @@ Later, when this test file is executed again, Bun will read the snapshot file an
61
61
 
62
62
  ```sh
63
63
  $ bun test
64
- bun test v1.2.9-canary.20250406T140639 (9c68abdb)
64
+ bun test v1.2.9-canary.20250408T140629 (9c68abdb)
65
65
 
66
66
  test/snap.test.ts:
67
67
  ✓ snapshot [1.05ms]
@@ -78,7 +78,7 @@ To update snapshots, use the `--update-snapshots` flag.
78
78
 
79
79
  ```sh
80
80
  $ bun test --update-snapshots
81
- bun test v1.2.9-canary.20250406T140639 (9c68abdb)
81
+ bun test v1.2.9-canary.20250408T140629 (9c68abdb)
82
82
 
83
83
  test/snap.test.ts:
84
84
  ✓ snapshot [0.86ms]
@@ -29,7 +29,7 @@ To regenerate snapshots, use the `--update-snapshots` flag.
29
29
 
30
30
  ```sh
31
31
  $ bun test --update-snapshots
32
- bun test v1.2.9-canary.20250406T140639 (9c68abdb)
32
+ bun test v1.2.9-canary.20250408T140629 (9c68abdb)
33
33
 
34
34
  test/snap.test.ts:
35
35
  ✓ snapshot [0.86ms]
@@ -5,7 +5,7 @@ name: Get the current Bun version
5
5
  Get the current version of Bun in a semver format.
6
6
 
7
7
  ```ts#index.ts
8
- Bun.version; // => "1.2.9-canary.20250406T140639"
8
+ Bun.version; // => "1.2.9-canary.20250408T140629"
9
9
  ```
10
10
 
11
11
  ---
@@ -14,7 +14,7 @@ Kernel version 5.6 or higher is strongly recommended, but the minimum is 5.1. Us
14
14
  ```bash#macOS/Linux_(curl)
15
15
  $ curl -fsSL https://bun.sh/install | bash # for macOS, Linux, and WSL
16
16
  # to install a specific version
17
- $ curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.9-canary.20250406T140639"
17
+ $ curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.9-canary.20250408T140629"
18
18
  ```
19
19
 
20
20
  ```bash#npm
@@ -189,10 +189,10 @@ Since Bun is a single binary, you can install older versions of Bun by re-runnin
189
189
 
190
190
  ### Installing a specific version of Bun on Linux/Mac
191
191
 
192
- To install a specific version of Bun, you can pass the git tag of the version you want to install to the install script, such as `bun-v1.2.0` or `bun-v1.2.9-canary.20250406T140639`.
192
+ To install a specific version of Bun, you can pass the git tag of the version you want to install to the install script, such as `bun-v1.2.0` or `bun-v1.2.9-canary.20250408T140629`.
193
193
 
194
194
  ```sh
195
- $ curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.9-canary.20250406T140639"
195
+ $ curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.9-canary.20250408T140629"
196
196
  ```
197
197
 
198
198
  ### Installing a specific version of Bun on Windows
@@ -201,7 +201,7 @@ On Windows, you can install a specific version of Bun by passing the version num
201
201
 
202
202
  ```sh
203
203
  # PowerShell:
204
- $ iex "& {$(irm https://bun.sh/install.ps1)} -Version 1.2.9-canary.20250406T140639"
204
+ $ iex "& {$(irm https://bun.sh/install.ps1)} -Version 1.2.9-canary.20250408T140629"
205
205
  ```
206
206
 
207
207
  ## Downloading Bun binaries directly
@@ -124,11 +124,11 @@ await fetch("https://example.com", {
124
124
  This prints the `fetch` request as a single-line `curl` command to let you copy-paste into your terminal to replicate the request.
125
125
 
126
126
  ```sh
127
- [fetch] $ curl --http1.1 "https://example.com/" -X POST -H "content-type: application/json" -H "Connection: keep-alive" -H "User-Agent: Bun/1.2.9-canary.20250406T140639" -H "Accept: */*" -H "Host: example.com" -H "Accept-Encoding: gzip, deflate, br" --compressed -H "Content-Length: 13" --data-raw "{\"foo\":\"bar\"}"
127
+ [fetch] $ curl --http1.1 "https://example.com/" -X POST -H "content-type: application/json" -H "Connection: keep-alive" -H "User-Agent: Bun/1.2.9-canary.20250408T140629" -H "Accept: */*" -H "Host: example.com" -H "Accept-Encoding: gzip, deflate, br" --compressed -H "Content-Length: 13" --data-raw "{\"foo\":\"bar\"}"
128
128
  [fetch] > HTTP/1.1 POST https://example.com/
129
129
  [fetch] > content-type: application/json
130
130
  [fetch] > Connection: keep-alive
131
- [fetch] > User-Agent: Bun/1.2.9-canary.20250406T140639
131
+ [fetch] > User-Agent: Bun/1.2.9-canary.20250408T140629
132
132
  [fetch] > Accept: */*
133
133
  [fetch] > Host: example.com
134
134
  [fetch] > Accept-Encoding: gzip, deflate, br
@@ -170,7 +170,7 @@ This prints the following to the console:
170
170
  [fetch] > HTTP/1.1 POST https://example.com/
171
171
  [fetch] > content-type: application/json
172
172
  [fetch] > Connection: keep-alive
173
- [fetch] > User-Agent: Bun/1.2.9-canary.20250406T140639
173
+ [fetch] > User-Agent: Bun/1.2.9-canary.20250408T140629
174
174
  [fetch] > Accept: */*
175
175
  [fetch] > Host: example.com
176
176
  [fetch] > Accept-Encoding: gzip, deflate, br
package/docs/test/dom.md CHANGED
@@ -55,7 +55,7 @@ Let's run this test with `bun test`:
55
55
 
56
56
  ```bash
57
57
  $ bun test
58
- bun test v1.2.9-canary.20250406T140639
58
+ bun test v1.2.9-canary.20250408T140629
59
59
 
60
60
  dom.test.ts:
61
61
  ✓ dom test [0.82ms]
package/extensions.d.ts CHANGED
@@ -23,9 +23,3 @@ declare module "*.html" {
23
23
  var contents: any;
24
24
  export = contents;
25
25
  }
26
-
27
- declare module "*.svg" {
28
- // Bun 1.2.3 added support for frontend dev server
29
- var content: `${string}.svg`;
30
- export = content;
31
- }
package/index.d.ts CHANGED
@@ -18,7 +18,7 @@
18
18
  /// <reference path="./wasm.d.ts" />
19
19
  /// <reference path="./overrides.d.ts" />
20
20
  /// <reference path="./deprecated.d.ts" />
21
-
21
+ /// <reference path="./redis.d.ts" />
22
22
  /// <reference path="./bun.ns.d.ts" />
23
23
 
24
24
  // @ts-ignore Must disable this so it doesn't conflict with the DOM onmessage type, but still
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.2.9-canary.20250406T140639",
2
+ "version": "1.2.9-canary.20250408T140629",
3
3
  "name": "bun-types",
4
4
  "license": "MIT",
5
5
  "types": "./index.d.ts",
package/redis.d.ts ADDED
@@ -0,0 +1,497 @@
1
+ declare module "bun" {
2
+ export interface RedisOptions {
3
+ /**
4
+ * URL to connect to, defaults to "redis://localhost:6379"
5
+ * Supported protocols: redis://, rediss://, redis+unix://, redis+tls://
6
+ */
7
+ url?: string;
8
+
9
+ /**
10
+ * Connection timeout in milliseconds
11
+ * @default 10000
12
+ */
13
+ connectionTimeout?: number;
14
+
15
+ /**
16
+ * Idle timeout in milliseconds
17
+ * @default 0 (no timeout)
18
+ */
19
+ idleTimeout?: number;
20
+
21
+ /**
22
+ * Whether to automatically reconnect
23
+ * @default true
24
+ */
25
+ autoReconnect?: boolean;
26
+
27
+ /**
28
+ * Maximum number of reconnection attempts
29
+ * @default 10
30
+ */
31
+ maxRetries?: number;
32
+
33
+ /**
34
+ * Whether to queue commands when disconnected
35
+ * @default true
36
+ */
37
+ enableOfflineQueue?: boolean;
38
+
39
+ /**
40
+ * TLS options
41
+ * Can be a boolean or an object with TLS options
42
+ */
43
+ tls?:
44
+ | boolean
45
+ | {
46
+ key?: string | Buffer;
47
+ cert?: string | Buffer;
48
+ ca?: string | Buffer | Array<string | Buffer>;
49
+ rejectUnauthorized?: boolean;
50
+ };
51
+
52
+ /**
53
+ * Whether to enable auto-pipelining
54
+ * @default true
55
+ */
56
+ enableAutoPipelining?: boolean;
57
+ }
58
+
59
+ export class RedisClient {
60
+ /**
61
+ * Creates a new Redis client
62
+ * @param url URL to connect to, defaults to process.env.VALKEY_URL, process.env.REDIS_URL, or "valkey://localhost:6379"
63
+ * @param options Additional options
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * const valkey = new RedisClient();
68
+ *
69
+ * await valkey.set("hello", "world");
70
+ *
71
+ * console.log(await valkey.get("hello"));
72
+ * ```
73
+ */
74
+ constructor(url?: string, options?: RedisOptions);
75
+
76
+ /**
77
+ * Whether the client is connected to the Redis server
78
+ */
79
+ readonly connected: boolean;
80
+
81
+ /**
82
+ * Amount of data buffered in bytes
83
+ */
84
+ readonly bufferedAmount: number;
85
+
86
+ /**
87
+ * Callback fired when the client connects to the Redis server
88
+ */
89
+ onconnect: ((this: RedisClient) => void) | null;
90
+
91
+ /**
92
+ * Callback fired when the client disconnects from the Redis server
93
+ * @param error The error that caused the disconnection
94
+ */
95
+ onclose: ((this: RedisClient, error: Error) => void) | null;
96
+
97
+ /**
98
+ * Connect to the Redis server
99
+ * @returns A promise that resolves when connected
100
+ */
101
+ connect(): Promise<void>;
102
+
103
+ /**
104
+ * Disconnect from the Redis server
105
+ */
106
+ disconnect(): void;
107
+
108
+ /**
109
+ * Send a raw command to the Redis server
110
+ * @param command The command to send
111
+ * @param args The arguments to the command
112
+ * @returns A promise that resolves with the command result
113
+ */
114
+ send(command: string, args: string[]): Promise<any>;
115
+
116
+ /**
117
+ * Get the value of a key
118
+ * @param key The key to get
119
+ * @returns Promise that resolves with the key's value, or null if the key doesn't exist
120
+ */
121
+ get(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
122
+
123
+ /**
124
+ * Set the value of a key
125
+ * @param key The key to set
126
+ * @param value The value to set
127
+ * @returns Promise that resolves with "OK" on success
128
+ */
129
+ set(key: string | NodeJS.TypedArray | Blob, value: string | NodeJS.TypedArray | Blob): Promise<"OK">;
130
+
131
+ /**
132
+ * Delete a key
133
+ * @param key The key to delete
134
+ * @returns Promise that resolves with the number of keys removed
135
+ */
136
+ del(key: string | NodeJS.TypedArray | Blob): Promise<number>;
137
+
138
+ /**
139
+ * Increment the integer value of a key by one
140
+ * @param key The key to increment
141
+ * @returns Promise that resolves with the new value
142
+ */
143
+ incr(key: string | NodeJS.TypedArray | Blob): Promise<number>;
144
+
145
+ /**
146
+ * Decrement the integer value of a key by one
147
+ * @param key The key to decrement
148
+ * @returns Promise that resolves with the new value
149
+ */
150
+ decr(key: string | NodeJS.TypedArray | Blob): Promise<number>;
151
+
152
+ /**
153
+ * Determine if a key exists
154
+ * @param key The key to check
155
+ * @returns Promise that resolves with true if the key exists, false otherwise
156
+ */
157
+ exists(key: string | NodeJS.TypedArray | Blob): Promise<boolean>;
158
+
159
+ /**
160
+ * Set a key's time to live in seconds
161
+ * @param key The key to set the expiration for
162
+ * @param seconds The number of seconds until expiration
163
+ * @returns Promise that resolves with 1 if the timeout was set, 0 if not
164
+ */
165
+ expire(key: string | NodeJS.TypedArray | Blob, seconds: number): Promise<number>;
166
+
167
+ /**
168
+ * Get the time to live for a key in seconds
169
+ * @param key The key to get the TTL for
170
+ * @returns Promise that resolves with the TTL, -1 if no expiry, or -2 if key doesn't exist
171
+ */
172
+ ttl(key: string | NodeJS.TypedArray | Blob): Promise<number>;
173
+
174
+ /**
175
+ * Set multiple hash fields to multiple values
176
+ * @param key The hash key
177
+ * @param fieldValues An array of alternating field names and values
178
+ * @returns Promise that resolves with "OK" on success
179
+ */
180
+ hmset(key: string | NodeJS.TypedArray | Blob, fieldValues: string[]): Promise<string>;
181
+
182
+ /**
183
+ * Get the values of all the given hash fields
184
+ * @param key The hash key
185
+ * @param fields The fields to get
186
+ * @returns Promise that resolves with an array of values
187
+ */
188
+ hmget(key: string | NodeJS.TypedArray | Blob, fields: string[]): Promise<Array<string | null>>;
189
+
190
+ /**
191
+ * Check if a value is a member of a set
192
+ * @param key The set key
193
+ * @param member The member to check
194
+ * @returns Promise that resolves with true if the member exists, false otherwise
195
+ */
196
+ sismember(key: string | NodeJS.TypedArray | Blob, member: string): Promise<boolean>;
197
+
198
+ /**
199
+ * Add a member to a set
200
+ * @param key The set key
201
+ * @param member The member to add
202
+ * @returns Promise that resolves with 1 if the member was added, 0 if it already existed
203
+ */
204
+ sadd(key: string | NodeJS.TypedArray | Blob, member: string): Promise<number>;
205
+
206
+ /**
207
+ * Remove a member from a set
208
+ * @param key The set key
209
+ * @param member The member to remove
210
+ * @returns Promise that resolves with 1 if the member was removed, 0 if it didn't exist
211
+ */
212
+ srem(key: string | NodeJS.TypedArray | Blob, member: string): Promise<number>;
213
+
214
+ /**
215
+ * Get all the members in a set
216
+ * @param key The set key
217
+ * @returns Promise that resolves with an array of all members
218
+ */
219
+ smembers(key: string | NodeJS.TypedArray | Blob): Promise<string[]>;
220
+
221
+ /**
222
+ * Get a random member from a set
223
+ * @param key The set key
224
+ * @returns Promise that resolves with a random member, or null if the set is empty
225
+ */
226
+ srandmember(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
227
+
228
+ /**
229
+ * Remove and return a random member from a set
230
+ * @param key The set key
231
+ * @returns Promise that resolves with the removed member, or null if the set is empty
232
+ */
233
+ spop(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
234
+
235
+ /**
236
+ * Increment the integer value of a hash field by the given number
237
+ * @param key The hash key
238
+ * @param field The field to increment
239
+ * @param increment The amount to increment by
240
+ * @returns Promise that resolves with the new value
241
+ */
242
+ hincrby(key: string | NodeJS.TypedArray | Blob, field: string, increment: string | number): Promise<number>;
243
+
244
+ /**
245
+ * Increment the float value of a hash field by the given amount
246
+ * @param key The hash key
247
+ * @param field The field to increment
248
+ * @param increment The amount to increment by
249
+ * @returns Promise that resolves with the new value as a string
250
+ */
251
+ hincrbyfloat(key: string | NodeJS.TypedArray | Blob, field: string, increment: string | number): Promise<string>;
252
+
253
+ /**
254
+ * Get all the fields and values in a hash
255
+ * @param key The hash key
256
+ * @returns Promise that resolves with an object containing all fields and values
257
+ */
258
+ hgetall(key: string | NodeJS.TypedArray | Blob): Promise<Record<string, string> | null>;
259
+
260
+ /**
261
+ * Get all field names in a hash
262
+ * @param key The hash key
263
+ * @returns Promise that resolves with an array of field names
264
+ */
265
+ hkeys(key: string | NodeJS.TypedArray | Blob): Promise<string[]>;
266
+
267
+ /**
268
+ * Get the number of fields in a hash
269
+ * @param key The hash key
270
+ * @returns Promise that resolves with the number of fields
271
+ */
272
+ hlen(key: string | NodeJS.TypedArray | Blob): Promise<number>;
273
+
274
+ /**
275
+ * Get all values in a hash
276
+ * @param key The hash key
277
+ * @returns Promise that resolves with an array of values
278
+ */
279
+ hvals(key: string | NodeJS.TypedArray | Blob): Promise<string[]>;
280
+
281
+ /**
282
+ * Find all keys matching the given pattern
283
+ * @param pattern The pattern to match
284
+ * @returns Promise that resolves with an array of matching keys
285
+ */
286
+ keys(pattern: string): Promise<string[]>;
287
+
288
+ /**
289
+ * Get the length of a list
290
+ * @param key The list key
291
+ * @returns Promise that resolves with the length of the list
292
+ */
293
+ llen(key: string | NodeJS.TypedArray | Blob): Promise<number>;
294
+
295
+ /**
296
+ * Remove and get the first element in a list
297
+ * @param key The list key
298
+ * @returns Promise that resolves with the first element, or null if the list is empty
299
+ */
300
+ lpop(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
301
+
302
+ /**
303
+ * Remove the expiration from a key
304
+ * @param key The key to persist
305
+ * @returns Promise that resolves with 1 if the timeout was removed, 0 if the key doesn't exist or has no timeout
306
+ */
307
+ persist(key: string | NodeJS.TypedArray | Blob): Promise<number>;
308
+
309
+ /**
310
+ * Get the expiration time of a key as a UNIX timestamp in milliseconds
311
+ * @param key The key to check
312
+ * @returns Promise that resolves with the timestamp, or -1 if the key has no expiration, or -2 if the key doesn't exist
313
+ */
314
+ pexpiretime(key: string | NodeJS.TypedArray | Blob): Promise<number>;
315
+
316
+ /**
317
+ * Get the time to live for a key in milliseconds
318
+ * @param key The key to check
319
+ * @returns Promise that resolves with the TTL in milliseconds, or -1 if the key has no expiration, or -2 if the key doesn't exist
320
+ */
321
+ pttl(key: string | NodeJS.TypedArray | Blob): Promise<number>;
322
+
323
+ /**
324
+ * Remove and get the last element in a list
325
+ * @param key The list key
326
+ * @returns Promise that resolves with the last element, or null if the list is empty
327
+ */
328
+ rpop(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
329
+
330
+ /**
331
+ * Get the number of members in a set
332
+ * @param key The set key
333
+ * @returns Promise that resolves with the cardinality (number of elements) of the set
334
+ */
335
+ scard(key: string | NodeJS.TypedArray | Blob): Promise<number>;
336
+
337
+ /**
338
+ * Get the length of the value stored in a key
339
+ * @param key The key to check
340
+ * @returns Promise that resolves with the length of the string value, or 0 if the key doesn't exist
341
+ */
342
+ strlen(key: string | NodeJS.TypedArray | Blob): Promise<number>;
343
+
344
+ /**
345
+ * Get the number of members in a sorted set
346
+ * @param key The sorted set key
347
+ * @returns Promise that resolves with the cardinality (number of elements) of the sorted set
348
+ */
349
+ zcard(key: string | NodeJS.TypedArray | Blob): Promise<number>;
350
+
351
+ /**
352
+ * Remove and return members with the highest scores in a sorted set
353
+ * @param key The sorted set key
354
+ * @returns Promise that resolves with the removed member and its score, or null if the set is empty
355
+ */
356
+ zpopmax(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
357
+
358
+ /**
359
+ * Remove and return members with the lowest scores in a sorted set
360
+ * @param key The sorted set key
361
+ * @returns Promise that resolves with the removed member and its score, or null if the set is empty
362
+ */
363
+ zpopmin(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
364
+
365
+ /**
366
+ * Get one or multiple random members from a sorted set
367
+ * @param key The sorted set key
368
+ * @returns Promise that resolves with a random member, or null if the set is empty
369
+ */
370
+ zrandmember(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
371
+
372
+ /**
373
+ * Append a value to a key
374
+ * @param key The key to append to
375
+ * @param value The value to append
376
+ * @returns Promise that resolves with the length of the string after the append operation
377
+ */
378
+ append(key: string | NodeJS.TypedArray | Blob, value: string | NodeJS.TypedArray | Blob): Promise<number>;
379
+
380
+ /**
381
+ * Set the value of a key and return its old value
382
+ * @param key The key to set
383
+ * @param value The value to set
384
+ * @returns Promise that resolves with the old value, or null if the key didn't exist
385
+ */
386
+ getset(key: string | NodeJS.TypedArray | Blob, value: string | NodeJS.TypedArray | Blob): Promise<string | null>;
387
+
388
+ /**
389
+ * Prepend one or multiple values to a list
390
+ * @param key The list key
391
+ * @param value The value to prepend
392
+ * @returns Promise that resolves with the length of the list after the push operation
393
+ */
394
+ lpush(key: string | NodeJS.TypedArray | Blob, value: string | NodeJS.TypedArray | Blob): Promise<number>;
395
+
396
+ /**
397
+ * Prepend a value to a list, only if the list exists
398
+ * @param key The list key
399
+ * @param value The value to prepend
400
+ * @returns Promise that resolves with the length of the list after the push operation, or 0 if the list doesn't exist
401
+ */
402
+ lpushx(key: string | NodeJS.TypedArray | Blob, value: string | NodeJS.TypedArray | Blob): Promise<number>;
403
+
404
+ /**
405
+ * Add one or more members to a HyperLogLog
406
+ * @param key The HyperLogLog key
407
+ * @param element The element to add
408
+ * @returns Promise that resolves with 1 if the HyperLogLog was altered, 0 otherwise
409
+ */
410
+ pfadd(key: string | NodeJS.TypedArray | Blob, element: string): Promise<number>;
411
+
412
+ /**
413
+ * Append one or multiple values to a list
414
+ * @param key The list key
415
+ * @param value The value to append
416
+ * @returns Promise that resolves with the length of the list after the push operation
417
+ */
418
+ rpush(key: string | NodeJS.TypedArray | Blob, value: string | NodeJS.TypedArray | Blob): Promise<number>;
419
+
420
+ /**
421
+ * Append a value to a list, only if the list exists
422
+ * @param key The list key
423
+ * @param value The value to append
424
+ * @returns Promise that resolves with the length of the list after the push operation, or 0 if the list doesn't exist
425
+ */
426
+ rpushx(key: string | NodeJS.TypedArray | Blob, value: string | NodeJS.TypedArray | Blob): Promise<number>;
427
+
428
+ /**
429
+ * Set the value of a key, only if the key does not exist
430
+ * @param key The key to set
431
+ * @param value The value to set
432
+ * @returns Promise that resolves with 1 if the key was set, 0 if the key was not set
433
+ */
434
+ setnx(key: string | NodeJS.TypedArray | Blob, value: string | NodeJS.TypedArray | Blob): Promise<number>;
435
+
436
+ /**
437
+ * Get the score associated with the given member in a sorted set
438
+ * @param key The sorted set key
439
+ * @param member The member to get the score for
440
+ * @returns Promise that resolves with the score of the member as a string, or null if the member or key doesn't exist
441
+ */
442
+ zscore(key: string | NodeJS.TypedArray | Blob, member: string): Promise<string | null>;
443
+
444
+ /**
445
+ * Get the values of all specified keys
446
+ * @param keys The keys to get
447
+ * @returns Promise that resolves with an array of values, with null for keys that don't exist
448
+ */
449
+ mget(...keys: (string | NodeJS.TypedArray | Blob)[]): Promise<(string | null)[]>;
450
+
451
+ /**
452
+ * Count the number of set bits (population counting) in a string
453
+ * @param key The key to count bits in
454
+ * @returns Promise that resolves with the number of bits set to 1
455
+ */
456
+ bitcount(key: string | NodeJS.TypedArray | Blob): Promise<number>;
457
+
458
+ /**
459
+ * Return a serialized version of the value stored at the specified key
460
+ * @param key The key to dump
461
+ * @returns Promise that resolves with the serialized value, or null if the key doesn't exist
462
+ */
463
+ dump(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
464
+
465
+ /**
466
+ * Get the expiration time of a key as a UNIX timestamp in seconds
467
+ * @param key The key to check
468
+ * @returns Promise that resolves with the timestamp, or -1 if the key has no expiration, or -2 if the key doesn't exist
469
+ */
470
+ expiretime(key: string | NodeJS.TypedArray | Blob): Promise<number>;
471
+
472
+ /**
473
+ * Get the value of a key and delete the key
474
+ * @param key The key to get and delete
475
+ * @returns Promise that resolves with the value of the key, or null if the key doesn't exist
476
+ */
477
+ getdel(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
478
+
479
+ /**
480
+ * Get the value of a key and optionally set its expiration
481
+ * @param key The key to get
482
+ * @returns Promise that resolves with the value of the key, or null if the key doesn't exist
483
+ */
484
+ getex(key: string | NodeJS.TypedArray | Blob): Promise<string | null>;
485
+ }
486
+
487
+ /**
488
+ * Default Redis client
489
+ *
490
+ * Connection information populated from one of, in order of preference:
491
+ * - `process.env.VALKEY_URL`
492
+ * - `process.env.REDIS_URL`
493
+ * - `"valkey://localhost:6379"`
494
+ *
495
+ */
496
+ export const redis: RedisClient;
497
+ }