bun-types 1.2.3-canary.20250216T140609 → 1.2.3-canary.20250217T140554

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/bun.d.ts CHANGED
@@ -465,192 +465,6 @@ declare module "bun" {
465
465
  }
466
466
  const TOML: TOML;
467
467
 
468
- type Serve<WebSocketDataType = undefined> =
469
- | ServeOptions
470
- | TLSServeOptions
471
- | UnixServeOptions
472
- | UnixTLSServeOptions
473
- | WebSocketServeOptions<WebSocketDataType>
474
- | TLSWebSocketServeOptions<WebSocketDataType>
475
- | UnixWebSocketServeOptions<WebSocketDataType>
476
- | UnixTLSWebSocketServeOptions<WebSocketDataType>;
477
-
478
- /**
479
- Bun.serve provides a high-performance HTTP server with built-in routing support.
480
- It enables both function-based and object-based route handlers with type-safe
481
- parameters and method-specific handling.
482
-
483
- @example Basic Usage
484
- ```ts
485
- Bun.serve({
486
- port: 3000,
487
- fetch(req) {
488
- return new Response("Hello World");
489
- }
490
- });
491
- ```
492
-
493
- @example Route-based Handlers
494
- ```ts
495
- Bun.serve({
496
- routes: {
497
- // Static responses
498
- "/": new Response("Home page"),
499
-
500
- // Function handlers with type-safe parameters
501
- "/users/:id": (req) => {
502
- // req.params.id is typed as string
503
- return new Response(`User ${req.params.id}`);
504
- },
505
-
506
- // Method-specific handlers
507
- "/api/posts": {
508
- GET: () => new Response("Get posts"),
509
- POST: async (req) => {
510
- const body = await req.json();
511
- return new Response("Created post");
512
- },
513
- DELETE: (req) => new Response("Deleted post")
514
- },
515
-
516
- // Wildcard routes
517
- "/static/*": (req) => {
518
- // Handle any path under /static/
519
- return new Response("Static file");
520
- },
521
-
522
- // Disable route (fall through to fetch handler)
523
- "/api/legacy": false
524
- },
525
-
526
- // Fallback handler for unmatched routes
527
- fetch(req) {
528
- return new Response("Not Found", { status: 404 });
529
- }
530
- });
531
- ```
532
-
533
- @example Path Parameters
534
- ```ts
535
- Bun.serve({
536
- routes: {
537
- // Single parameter
538
- "/users/:id": (req: BunRequest<"/users/:id">) => {
539
- return new Response(`User ID: ${req.params.id}`);
540
- },
541
-
542
- // Multiple parameters
543
- "/posts/:postId/comments/:commentId": (
544
- req: BunRequest<"/posts/:postId/comments/:commentId">
545
- ) => {
546
- return new Response(JSON.stringify(req.params));
547
- // Output: {"postId": "123", "commentId": "456"}
548
- }
549
- }
550
- });
551
- ```
552
-
553
- @example Route Precedence
554
- ```ts
555
- // Routes are matched in the following order:
556
- // 1. Exact static routes ("/about")
557
- // 2. Parameter routes ("/users/:id")
558
- // 3. Wildcard routes ("/api/*")
559
-
560
- Bun.serve({
561
- routes: {
562
- "/api/users": () => new Response("Users list"),
563
- "/api/users/:id": (req) => new Response(`User ${req.params.id}`),
564
- "/api/*": () => new Response("API catchall"),
565
- "/*": () => new Response("Root catchall")
566
- }
567
- });
568
- ```
569
-
570
- @example Error Handling
571
- ```ts
572
- Bun.serve({
573
- routes: {
574
- "/error": () => {
575
- throw new Error("Something went wrong");
576
- }
577
- },
578
- error(error) {
579
- // Custom error handler
580
- console.error(error);
581
- return new Response(`Error: ${error.message}`, {
582
- status: 500
583
- });
584
- }
585
- });
586
- ```
587
-
588
- @example Server Lifecycle
589
- ```ts
590
- const server = Bun.serve({
591
- // Server config...
592
- });
593
-
594
- // Update routes at runtime
595
- server.reload({
596
- routes: {
597
- "/": () => new Response("Updated route")
598
- }
599
- });
600
-
601
- // Stop the server
602
- server.stop();
603
- ```
604
-
605
- @example Development Mode
606
- ```ts
607
- Bun.serve({
608
- development: true, // Enable hot reloading
609
- routes: {
610
- // Routes will auto-reload on changes
611
- }
612
- });
613
- ```
614
-
615
- @example Type-Safe Request Handling
616
- ```ts
617
- type Post = {
618
- id: string;
619
- title: string;
620
- };
621
-
622
- Bun.serve({
623
- routes: {
624
- "/api/posts/:id": async (
625
- req: BunRequest<"/api/posts/:id">
626
- ) => {
627
- if (req.method === "POST") {
628
- const body: Post = await req.json();
629
- return Response.json(body);
630
- }
631
- return new Response("Method not allowed", {
632
- status: 405
633
- });
634
- }
635
- }
636
- });
637
- ```
638
- @param options - Server configuration options
639
- @param options.routes - Route definitions mapping paths to handlers
640
- */
641
- function serve<
642
- T,
643
- R extends { [K in keyof R]: RouterTypes.RouteValue<K & string> },
644
- >(
645
- options: Serve<T> & {
646
- routes?: R;
647
- /**
648
- * @deprecated Use {@link routes} instead in new code
649
- */
650
- static?: R;
651
- },
652
- ): Server;
653
-
654
468
  /**
655
469
  * Synchronously resolve a `moduleId` as though it were imported from `parent`
656
470
  *
@@ -4450,7 +4264,32 @@ declare module "bun" {
4450
4264
  *
4451
4265
  * Passing other options such as `port` or `hostname` won't do anything.
4452
4266
  */
4453
- reload(options: Serve): void;
4267
+ reload<T, R extends { [K in keyof R]: RouterTypes.RouteValue<K & string> }>(
4268
+ options: (
4269
+ | (Omit<ServeOptions, "fetch"> & {
4270
+ routes: R;
4271
+ fetch?: (
4272
+ this: Server,
4273
+ request: Request,
4274
+ server: Server,
4275
+ ) => Response | Promise<Response>;
4276
+ })
4277
+ | (Omit<ServeOptions, "routes"> & {
4278
+ routes?: never;
4279
+ fetch: (
4280
+ this: Server,
4281
+ request: Request,
4282
+ server: Server,
4283
+ ) => Response | Promise<Response>;
4284
+ })
4285
+ | WebSocketServeOptions<T>
4286
+ ) & {
4287
+ /**
4288
+ * @deprecated Use `routes` instead in new code. This will continue to work for awhile though.
4289
+ */
4290
+ static?: R;
4291
+ },
4292
+ ): Server;
4454
4293
 
4455
4294
  /**
4456
4295
  * Mock the fetch handler for a running server.
@@ -4648,6 +4487,209 @@ declare module "bun" {
4648
4487
  readonly id: string;
4649
4488
  }
4650
4489
 
4490
+ type Serve<WebSocketDataType = undefined> =
4491
+ | ServeOptions
4492
+ | TLSServeOptions
4493
+ | UnixServeOptions
4494
+ | UnixTLSServeOptions
4495
+ | WebSocketServeOptions<WebSocketDataType>
4496
+ | TLSWebSocketServeOptions<WebSocketDataType>
4497
+ | UnixWebSocketServeOptions<WebSocketDataType>
4498
+ | UnixTLSWebSocketServeOptions<WebSocketDataType>;
4499
+
4500
+ /**
4501
+ Bun.serve provides a high-performance HTTP server with built-in routing support.
4502
+ It enables both function-based and object-based route handlers with type-safe
4503
+ parameters and method-specific handling.
4504
+
4505
+ @example Basic Usage
4506
+ ```ts
4507
+ Bun.serve({
4508
+ port: 3000,
4509
+ fetch(req) {
4510
+ return new Response("Hello World");
4511
+ }
4512
+ });
4513
+ ```
4514
+
4515
+ @example Route-based Handlers
4516
+ ```ts
4517
+ Bun.serve({
4518
+ routes: {
4519
+ // Static responses
4520
+ "/": new Response("Home page"),
4521
+
4522
+ // Function handlers with type-safe parameters
4523
+ "/users/:id": (req) => {
4524
+ // req.params.id is typed as string
4525
+ return new Response(`User ${req.params.id}`);
4526
+ },
4527
+
4528
+ // Method-specific handlers
4529
+ "/api/posts": {
4530
+ GET: () => new Response("Get posts"),
4531
+ POST: async (req) => {
4532
+ const body = await req.json();
4533
+ return new Response("Created post");
4534
+ },
4535
+ DELETE: (req) => new Response("Deleted post")
4536
+ },
4537
+
4538
+ // Wildcard routes
4539
+ "/static/*": (req) => {
4540
+ // Handle any path under /static/
4541
+ return new Response("Static file");
4542
+ },
4543
+
4544
+ // Disable route (fall through to fetch handler)
4545
+ "/api/legacy": false
4546
+ },
4547
+
4548
+ // Fallback handler for unmatched routes
4549
+ fetch(req) {
4550
+ return new Response("Not Found", { status: 404 });
4551
+ }
4552
+ });
4553
+ ```
4554
+
4555
+ @example Path Parameters
4556
+ ```ts
4557
+ Bun.serve({
4558
+ routes: {
4559
+ // Single parameter
4560
+ "/users/:id": (req: BunRequest<"/users/:id">) => {
4561
+ return new Response(`User ID: ${req.params.id}`);
4562
+ },
4563
+
4564
+ // Multiple parameters
4565
+ "/posts/:postId/comments/:commentId": (
4566
+ req: BunRequest<"/posts/:postId/comments/:commentId">
4567
+ ) => {
4568
+ return new Response(JSON.stringify(req.params));
4569
+ // Output: {"postId": "123", "commentId": "456"}
4570
+ }
4571
+ }
4572
+ });
4573
+ ```
4574
+
4575
+ @example Route Precedence
4576
+ ```ts
4577
+ // Routes are matched in the following order:
4578
+ // 1. Exact static routes ("/about")
4579
+ // 2. Parameter routes ("/users/:id")
4580
+ // 3. Wildcard routes ("/api/*")
4581
+
4582
+ Bun.serve({
4583
+ routes: {
4584
+ "/api/users": () => new Response("Users list"),
4585
+ "/api/users/:id": (req) => new Response(`User ${req.params.id}`),
4586
+ "/api/*": () => new Response("API catchall"),
4587
+ "/*": () => new Response("Root catchall")
4588
+ }
4589
+ });
4590
+ ```
4591
+
4592
+ @example Error Handling
4593
+ ```ts
4594
+ Bun.serve({
4595
+ routes: {
4596
+ "/error": () => {
4597
+ throw new Error("Something went wrong");
4598
+ }
4599
+ },
4600
+ error(error) {
4601
+ // Custom error handler
4602
+ console.error(error);
4603
+ return new Response(`Error: ${error.message}`, {
4604
+ status: 500
4605
+ });
4606
+ }
4607
+ });
4608
+ ```
4609
+
4610
+ @example Server Lifecycle
4611
+ ```ts
4612
+ const server = Bun.serve({
4613
+ // Server config...
4614
+ });
4615
+
4616
+ // Update routes at runtime
4617
+ server.reload({
4618
+ routes: {
4619
+ "/": () => new Response("Updated route")
4620
+ }
4621
+ });
4622
+
4623
+ // Stop the server
4624
+ server.stop();
4625
+ ```
4626
+
4627
+ @example Development Mode
4628
+ ```ts
4629
+ Bun.serve({
4630
+ development: true, // Enable hot reloading
4631
+ routes: {
4632
+ // Routes will auto-reload on changes
4633
+ }
4634
+ });
4635
+ ```
4636
+
4637
+ @example Type-Safe Request Handling
4638
+ ```ts
4639
+ type Post = {
4640
+ id: string;
4641
+ title: string;
4642
+ };
4643
+
4644
+ Bun.serve({
4645
+ routes: {
4646
+ "/api/posts/:id": async (
4647
+ req: BunRequest<"/api/posts/:id">
4648
+ ) => {
4649
+ if (req.method === "POST") {
4650
+ const body: Post = await req.json();
4651
+ return Response.json(body);
4652
+ }
4653
+ return new Response("Method not allowed", {
4654
+ status: 405
4655
+ });
4656
+ }
4657
+ }
4658
+ });
4659
+ ```
4660
+ @param options - Server configuration options
4661
+ @param options.routes - Route definitions mapping paths to handlers
4662
+ */
4663
+ function serve<
4664
+ T,
4665
+ R extends { [K in keyof R]: RouterTypes.RouteValue<K & string> },
4666
+ >(
4667
+ options: (
4668
+ | (Omit<ServeOptions, "fetch"> & {
4669
+ routes: R;
4670
+ fetch?: (
4671
+ this: Server,
4672
+ request: Request,
4673
+ server: Server,
4674
+ ) => Response | Promise<Response>;
4675
+ })
4676
+ | (Omit<ServeOptions, "routes"> & {
4677
+ routes?: never;
4678
+ fetch: (
4679
+ this: Server,
4680
+ request: Request,
4681
+ server: Server,
4682
+ ) => Response | Promise<Response>;
4683
+ })
4684
+ | WebSocketServeOptions<T>
4685
+ ) & {
4686
+ /**
4687
+ * @deprecated Use `routes` instead in new code. This will continue to work for awhile though.
4688
+ */
4689
+ static?: R;
4690
+ },
4691
+ ): Server;
4692
+
4651
4693
  /**
4652
4694
  * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files.
4653
4695
  *
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.3-canary.20250216T140609
340
+ [fetch] > User-Agent: Bun/1.2.3-canary.20250217T140554
341
341
  [fetch] > Accept: */*
342
342
  [fetch] > Host: example.com
343
343
  [fetch] > Accept-Encoding: gzip, deflate, br
package/docs/api/http.md CHANGED
@@ -8,130 +8,158 @@ To start a high-performance HTTP server with a clean API, the recommended approa
8
8
 
9
9
  ## `Bun.serve()`
10
10
 
11
- Start an HTTP server in Bun with `Bun.serve`.
11
+ Use `Bun.serve` to start an HTTP server in Bun.
12
12
 
13
13
  ```ts
14
14
  Bun.serve({
15
- fetch(req) {
16
- return new Response("Bun!");
17
- },
18
- });
19
- ```
15
+ // `routes` requires Bun v1.2.3+
16
+ routes: {
17
+ // Static routes
18
+ "/api/status": new Response("OK"),
19
+
20
+ // Dynamic routes
21
+ "/users/:id": req => {
22
+ return new Response(`Hello User ${req.params.id}!`);
23
+ },
20
24
 
21
- ### `fetch` request handler
25
+ // Per-HTTP method handlers
26
+ "/api/posts": {
27
+ GET: () => new Response("List posts"),
28
+ POST: async req => {
29
+ const body = await req.json();
30
+ return Response.json({ created: true, ...body });
31
+ },
32
+ },
22
33
 
23
- The `fetch` handler handles incoming requests. It receives a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object and returns a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) or `Promise<Response>`.
34
+ // Wildcard route for all routes that start with "/api/" and aren't otherwise matched
35
+ "/api/*": Response.json({ message: "Not found" }, { status: 404 }),
24
36
 
25
- ```ts
26
- Bun.serve({
37
+ // Redirect from /blog/hello to /blog/hello/world
38
+ "/blog/hello": Response.redirect("/blog/hello/world"),
39
+
40
+ // Serve a file by buffering it in memory
41
+ "/favicon.ico": new Response(await Bun.file("./favicon.ico").bytes(), {
42
+ headers: {
43
+ "Content-Type": "image/x-icon",
44
+ },
45
+ }),
46
+ },
47
+
48
+ // (optional) fallback for unmatched routes:
49
+ // Required if Bun's version < 1.2.3
27
50
  fetch(req) {
28
- const url = new URL(req.url);
29
- if (url.pathname === "/") return new Response("Home page!");
30
- if (url.pathname === "/blog") return new Response("Blog!");
31
- return new Response("404!");
51
+ return new Response("Not Found", { status: 404 });
32
52
  },
33
53
  });
34
54
  ```
35
55
 
36
- The `fetch` handler supports async/await:
56
+ ### Routing
57
+
58
+ Routes in `Bun.serve()` receive a `BunRequest` (which extends [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)) and return a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) or `Promise<Response>`. This makes it easier to use the same code for both sending & receiving HTTP requests.
37
59
 
38
60
  ```ts
39
- import { sleep, serve } from "bun";
40
- serve({
41
- async fetch(req) {
42
- const start = performance.now();
43
- await sleep(10);
44
- const end = performance.now();
45
- return new Response(`Slept for ${end - start}ms`);
46
- },
47
- });
61
+ // Simplified for brevity
62
+ interface BunRequest<T extends string> extends Request {
63
+ params: Record<T, string>;
64
+ }
48
65
  ```
49
66
 
50
- Promise-based responses are also supported:
67
+ #### Async/await in routes
68
+
69
+ You can use async/await in route handlers to return a `Promise<Response>`.
51
70
 
52
71
  ```ts
53
- Bun.serve({
54
- fetch(req) {
55
- // Forward the request to another server.
56
- return fetch("https://example.com");
72
+ import { sql, serve } from "bun";
73
+
74
+ serve({
75
+ port: 3001,
76
+ routes: {
77
+ "/api/version": async () => {
78
+ const [version] = await sql`SELECT version()`;
79
+ return Response.json(version);
80
+ },
57
81
  },
58
82
  });
59
83
  ```
60
84
 
61
- You can also access the `Server` object from the `fetch` handler. It's the second argument passed to the `fetch` function.
85
+ #### Promise in routes
86
+
87
+ You can also return a `Promise<Response>` from a route handler.
62
88
 
63
89
  ```ts
64
- // `server` is passed in as the second argument to `fetch`.
65
- const server = Bun.serve({
66
- fetch(req, server) {
67
- const ip = server.requestIP(req);
68
- return new Response(`Your IP is ${ip}`);
90
+ import { sql, serve } from "bun";
91
+
92
+ serve({
93
+ routes: {
94
+ "/api/version": () => {
95
+ return new Promise(resolve => {
96
+ setTimeout(async () => {
97
+ const [version] = await sql`SELECT version()`;
98
+ resolve(Response.json(version));
99
+ }, 100);
100
+ });
101
+ },
69
102
  },
70
103
  });
71
104
  ```
72
105
 
73
- ### Static routes
106
+ #### Type-safe route parameters
74
107
 
75
- Use the `static` option to serve static `Response` objects by route.
108
+ TypeScript parses route parameters when passed as a string literal, so that your editor will show autocomplete when accessing `request.params`.
76
109
 
77
110
  ```ts
78
- // Bun v1.1.27+ required
79
- Bun.serve({
80
- static: {
81
- // health-check endpoint
82
- "/api/health-check": new Response("All good!"),
111
+ import type { BunRequest } from "bun";
83
112
 
84
- // redirect from /old-link to /new-link
85
- "/old-link": Response.redirect("/new-link", 301),
86
-
87
- // serve static text
88
- "/": new Response("Hello World"),
89
-
90
- // serve a file by buffering it in memory
91
- "/index.html": new Response(await Bun.file("./index.html").bytes(), {
92
- headers: {
93
- "Content-Type": "text/html",
94
- },
95
- }),
96
- "/favicon.ico": new Response(await Bun.file("./favicon.ico").bytes(), {
97
- headers: {
98
- "Content-Type": "image/x-icon",
99
- },
100
- }),
101
-
102
- // serve JSON
103
- "/api/version.json": Response.json({ version: "1.0.0" }),
104
- },
113
+ Bun.serve({
114
+ routes: {
115
+ // TypeScript knows the shape of params when passed as a string literal
116
+ "/orgs/:orgId/repos/:repoId": req => {
117
+ const { orgId, repoId } = req.params;
118
+ return Response.json({ orgId, repoId });
119
+ },
105
120
 
106
- fetch(req) {
107
- return new Response("404!");
121
+ "/orgs/:orgId/repos/:repoId/settings": (
122
+ // optional: you can explicitly pass a type to BunRequest:
123
+ req: BunRequest<"/orgs/:orgId/repos/:repoId/settings">,
124
+ ) => {
125
+ const { orgId, repoId } = req.params;
126
+ return Response.json({ orgId, repoId });
127
+ },
108
128
  },
109
129
  });
110
130
  ```
111
131
 
112
- Static routes support headers, status code, and other `Response` options.
132
+ Percent-encoded route parameter values are automatically decoded. Unicode characters are supported. Invalid unicode is replaced with the unicode replacement character `&0xFFFD;`.
133
+
134
+ ### Static responses
135
+
136
+ Routes can also be `Response` objects (without the handler function). Bun.serve() optimizes it for zero-allocation dispatch - perfect for health checks, redirects, and fixed content:
113
137
 
114
138
  ```ts
115
139
  Bun.serve({
116
- static: {
117
- "/api/time": new Response(new Date().toISOString(), {
140
+ routes: {
141
+ // Health checks
142
+ "/health": new Response("OK"),
143
+ "/ready": new Response("Ready", {
118
144
  headers: {
119
- "X-Custom-Header": "Bun!",
145
+ // Pass custom headers
146
+ "X-Ready": "1",
120
147
  },
121
148
  }),
122
- },
123
149
 
124
- fetch(req) {
125
- return new Response("404!");
150
+ // Redirects
151
+ "/blog": Response.redirect("https://bun.sh/blog"),
152
+
153
+ // API responses
154
+ "/api/config": Response.json({
155
+ version: "1.0.0",
156
+ env: "production",
157
+ }),
126
158
  },
127
159
  });
128
160
  ```
129
161
 
130
- Static routes can serve Response bodies faster than `fetch` handlers because they don't create `Request` objects, they don't create `AbortSignal`, they don't create additional `Response` objects. The only per-request memory allocation is the TCP/TLS socket data needed for each request.
131
-
132
- {% note %}
133
- `static` is experimental
134
- {% /note %}
162
+ Static responses do not allocate additional memory after initialization. You can generally expect at least a 15% performance improvement over manually returning a `Response` object.
135
163
 
136
164
  Static route responses are cached for the lifetime of the server object. To reload static routes, call `server.reload(options)`.
137
165
 
@@ -160,7 +188,7 @@ setInterval(() => {
160
188
  }, 1000);
161
189
  ```
162
190
 
163
- Reloading static routes only impact the next request. In-flight requests continue to use the old static routes. After in-flight requests to old static routes are finished, the old static routes are freed from memory.
191
+ Reloading routes only impact the next request. In-flight requests continue to use the old routes. After in-flight requests to old routes are finished, the old routes are freed from memory.
164
192
 
165
193
  To simplify error handling, static routes do not support streaming response bodies from `ReadableStream` or an `AsyncIterator`. Fortunately, you can still buffer the response in memory first:
166
194
 
@@ -180,6 +208,270 @@ const server = Bun.serve({
180
208
  });
181
209
  ```
182
210
 
211
+ ### Route precedence
212
+
213
+ Routes are matched in order of specificity:
214
+
215
+ 1. Exact routes (`/users/all`)
216
+ 2. Parameter routes (`/users/:id`)
217
+ 3. Wildcard routes (`/users/*`)
218
+ 4. Global catch-all (`/*`)
219
+
220
+ ```ts
221
+ Bun.serve({
222
+ routes: {
223
+ // Most specific first
224
+ "/api/users/me": () => new Response("Current user"),
225
+ "/api/users/:id": req => new Response(`User ${req.params.id}`),
226
+ "/api/*": () => new Response("API catch-all"),
227
+ "/*": () => new Response("Global catch-all"),
228
+ },
229
+ });
230
+ ```
231
+
232
+ ### Per-HTTP Method Routes
233
+
234
+ Route handlers can be specialized by HTTP method:
235
+
236
+ ```ts
237
+ Bun.serve({
238
+ routes: {
239
+ "/api/posts": {
240
+ // Different handlers per method
241
+ GET: () => new Response("List posts"),
242
+ POST: async req => {
243
+ const post = await req.json();
244
+ return Response.json({ id: crypto.randomUUID(), ...post });
245
+ },
246
+ PUT: async req => {
247
+ const updates = await req.json();
248
+ return Response.json({ updated: true, ...updates });
249
+ },
250
+ DELETE: () => new Response(null, { status: 204 }),
251
+ },
252
+ },
253
+ });
254
+ ```
255
+
256
+ You can pass any of the following methods:
257
+
258
+ | Method | Usecase example |
259
+ | --------- | ------------------------------- |
260
+ | `GET` | Fetch a resource |
261
+ | `HEAD` | Check if a resource exists |
262
+ | `OPTIONS` | Get allowed HTTP methods (CORS) |
263
+ | `DELETE` | Delete a resource |
264
+ | `PATCH` | Update a resource |
265
+ | `POST` | Create a resource |
266
+ | `PUT` | Update a resource |
267
+
268
+ When passing a function instead of an object, all methods will be handled by that function:
269
+
270
+ ```ts
271
+ const server = Bun.serve({
272
+ routes: {
273
+ "/api/version": () => Response.json({ version: "1.0.0" }),
274
+ },
275
+ });
276
+
277
+ await fetch(new URL("/api/version", server.url));
278
+ await fetch(new URL("/api/version", server.url), { method: "PUT" });
279
+ // ... etc
280
+ ```
281
+
282
+ ### Hot Route Reloading
283
+
284
+ Update routes without server restarts using `server.reload()`:
285
+
286
+ ```ts
287
+ const server = Bun.serve({
288
+ routes: {
289
+ "/api/version": () => Response.json({ version: "1.0.0" }),
290
+ },
291
+ });
292
+
293
+ // Deploy new routes without downtime
294
+ server.reload({
295
+ routes: {
296
+ "/api/version": () => Response.json({ version: "2.0.0" }),
297
+ },
298
+ });
299
+ ```
300
+
301
+ ### Error Handling
302
+
303
+ Bun provides structured error handling for routes:
304
+
305
+ ```ts
306
+ Bun.serve({
307
+ routes: {
308
+ // Errors are caught automatically
309
+ "/api/risky": () => {
310
+ throw new Error("Something went wrong");
311
+ },
312
+ },
313
+ // Global error handler
314
+ error(error) {
315
+ console.error(error);
316
+ return new Response(`Internal Error: ${error.message}`, {
317
+ status: 500,
318
+ headers: {
319
+ "Content-Type": "text/plain",
320
+ },
321
+ });
322
+ },
323
+ });
324
+ ```
325
+
326
+ ### HTML imports
327
+
328
+ To add a client-side single-page app, you can use an HTML import:
329
+
330
+ ```ts
331
+ import myReactSinglePageApp from "./index.html";
332
+
333
+ Bun.serve({
334
+ routes: {
335
+ "/": myReactSinglePageApp,
336
+ },
337
+ });
338
+ ```
339
+
340
+ HTML imports don't just serve HTML. It's a full-featured frontend bundler, transpiler, and toolkit built using Bun's [bundler](https://bun.sh/docs/bundler), JavaScript transpiler and CSS parser.
341
+
342
+ You can use this to build a full-featured frontend with React, TypeScript, Tailwind CSS, and more. Check out [/docs/bundler/fullstack](https://bun.sh/docs/bundler/fullstack) to learn more.
343
+
344
+ ### Practical example: REST API
345
+
346
+ Here's a basic database-backed REST API using Bun's router with zero dependencies:
347
+
348
+ {% codetabs %}
349
+
350
+ ```ts#server.ts
351
+ import type { Post } from "./types.ts";
352
+ import { Database } from "bun:sqlite";
353
+
354
+ const db = new Database("posts.db");
355
+ db.exec(`
356
+ CREATE TABLE IF NOT EXISTS posts (
357
+ id TEXT PRIMARY KEY,
358
+ title TEXT NOT NULL,
359
+ content TEXT NOT NULL,
360
+ created_at TEXT NOT NULL
361
+ )
362
+ `);
363
+
364
+ Bun.serve({
365
+ routes: {
366
+ // List posts
367
+ "/api/posts": {
368
+ GET: () => {
369
+ const posts = db.query("SELECT * FROM posts").all();
370
+ return Response.json(posts);
371
+ },
372
+
373
+ // Create post
374
+ POST: async req => {
375
+ const post: Omit<Post, "id" | "created_at"> = await req.json();
376
+ const id = crypto.randomUUID();
377
+
378
+ db.query(
379
+ `INSERT INTO posts (id, title, content, created_at)
380
+ VALUES (?, ?, ?, ?)`,
381
+ ).run(id, post.title, post.content, new Date().toISOString());
382
+
383
+ return Response.json({ id, ...post }, { status: 201 });
384
+ },
385
+ },
386
+
387
+ // Get post by ID
388
+ "/api/posts/:id": req => {
389
+ const post = db
390
+ .query("SELECT * FROM posts WHERE id = ?")
391
+ .get(req.params.id);
392
+
393
+ if (!post) {
394
+ return new Response("Not Found", { status: 404 });
395
+ }
396
+
397
+ return Response.json(post);
398
+ },
399
+ },
400
+
401
+ error(error) {
402
+ console.error(error);
403
+ return new Response("Internal Server Error", { status: 500 });
404
+ },
405
+ });
406
+ ```
407
+
408
+ ```ts#types.ts
409
+ export interface Post {
410
+ id: string;
411
+ title: string;
412
+ content: string;
413
+ created_at: string;
414
+ }
415
+ ```
416
+
417
+ {% /codetabs %}
418
+
419
+ ### Routing performance
420
+
421
+ `Bun.serve()`'s router builds on top uWebSocket's [tree-based approach](https://github.com/oven-sh/bun/blob/0d1a00fa0f7830f8ecd99c027fce8096c9d459b6/packages/bun-uws/src/HttpRouter.h#L57-L64) to add [SIMD-accelerated route parameter decoding](https://github.com/oven-sh/bun/blob/jarred/optional-fetch/src/bun.js/bindings/decodeURIComponentSIMD.cpp#L21-L271) and [JavaScriptCore structure caching](https://github.com/oven-sh/bun/blob/jarred/optional-fetch/src/bun.js/bindings/ServerRouteList.cpp#L100-L101) to push the performance limits of what modern hardware allows.
422
+
423
+ ### `fetch` request handler
424
+
425
+ The `fetch` handler handles incoming requests that weren't matched by any route. It receives a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object and returns a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) or [`Promise<Response>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
426
+
427
+ ```ts
428
+ Bun.serve({
429
+ fetch(req) {
430
+ const url = new URL(req.url);
431
+ if (url.pathname === "/") return new Response("Home page!");
432
+ if (url.pathname === "/blog") return new Response("Blog!");
433
+ return new Response("404!");
434
+ },
435
+ });
436
+ ```
437
+
438
+ The `fetch` handler supports async/await:
439
+
440
+ ```ts
441
+ import { sleep, serve } from "bun";
442
+ serve({
443
+ async fetch(req) {
444
+ const start = performance.now();
445
+ await sleep(10);
446
+ const end = performance.now();
447
+ return new Response(`Slept for ${end - start}ms`);
448
+ },
449
+ });
450
+ ```
451
+
452
+ Promise-based responses are also supported:
453
+
454
+ ```ts
455
+ Bun.serve({
456
+ fetch(req) {
457
+ // Forward the request to another server.
458
+ return fetch("https://example.com");
459
+ },
460
+ });
461
+ ```
462
+
463
+ You can also access the `Server` object from the `fetch` handler. It's the second argument passed to the `fetch` function.
464
+
465
+ ```ts
466
+ // `server` is passed in as the second argument to `fetch`.
467
+ const server = Bun.serve({
468
+ fetch(req, server) {
469
+ const ip = server.requestIP(req);
470
+ return new Response(`Your IP is ${ip}`);
471
+ },
472
+ });
473
+ ```
474
+
183
475
  ### Changing the `port` and `hostname`
184
476
 
185
477
  To configure which port and hostname the server will listen on, set `port` and `hostname` in the options object.
@@ -553,7 +845,7 @@ Update the server's handlers without restarting:
553
845
 
554
846
  ```ts
555
847
  const server = Bun.serve({
556
- static: {
848
+ routes: {
557
849
  "/api/version": Response.json({ version: "v1" }),
558
850
  },
559
851
  fetch(req) {
@@ -563,7 +855,7 @@ const server = Bun.serve({
563
855
 
564
856
  // Update to new handler
565
857
  server.reload({
566
- static: {
858
+ routes: {
567
859
  "/api/version": Response.json({ version: "v2" }),
568
860
  },
569
861
  fetch(req) {
@@ -572,7 +864,7 @@ server.reload({
572
864
  });
573
865
  ```
574
866
 
575
- This is useful for development and hot reloading. Only `fetch`, `error`, and `static` handlers can be updated.
867
+ This is useful for development and hot reloading. Only `fetch`, `error`, and `routes` can be updated.
576
868
 
577
869
  ## Per-Request Controls
578
870
 
package/docs/api/spawn.md CHANGED
@@ -110,7 +110,7 @@ You can read results from the subprocess via the `stdout` and `stderr` propertie
110
110
  ```ts
111
111
  const proc = Bun.spawn(["bun", "--version"]);
112
112
  const text = await new Response(proc.stdout).text();
113
- console.log(text); // => "1.2.3-canary.20250216T140609"
113
+ console.log(text); // => "1.2.3-canary.20250217T140554"
114
114
  ```
115
115
 
116
116
  Configure the output stream by passing one of the following values to `stdout/stderr`:
package/docs/api/sql.md CHANGED
@@ -185,11 +185,19 @@ Note that simple queries cannot use parameters (`${value}`). If you need paramet
185
185
 
186
186
  ### Unsafe Queries
187
187
 
188
- You can use the `sql.unsafe` function to execute raw SQL strings. Use this with caution, as it will not escape user input.
188
+ You can use the `sql.unsafe` function to execute raw SQL strings. Use this with caution, as it will not escape user input. Executing more than one command per query is allowed if no parameters are used.
189
189
 
190
190
  ```ts
191
+ // Multiple commands without parameters
192
+ const result = await sql.unsafe(`
193
+ SELECT ${userColumns} FROM users;
194
+ SELECT ${accountColumns} FROM accounts;
195
+ `);
196
+
197
+ // Using parameters (only one command is allowed)
191
198
  const result = await sql.unsafe(
192
- "SELECT " + columns + " FROM users WHERE id = " + id,
199
+ "SELECT " + dangerous + " FROM users WHERE id = $1",
200
+ [id],
193
201
  );
194
202
  ```
195
203
 
@@ -451,28 +459,29 @@ try {
451
459
 
452
460
  ## Prepared Statements
453
461
 
454
- By default, Bun's SQL client automatically creates prepared statements for queries where it can be inferred that the query is static. This provides better performance and security. However, you can disable prepared statements by setting `prepare: false` in the connection options:
462
+ By default, Bun's SQL client automatically creates named prepared statements for queries where it can be inferred that the query is static. This provides better performance. However, you can change this behavior by setting `prepare: false` in the connection options:
455
463
 
456
464
  ```ts
457
465
  const sql = new SQL({
458
466
  // ... other options ...
459
- prepare: false, // Disable prepared statements
467
+ prepare: false, // Disable persisting named prepared statements on the server
460
468
  });
461
469
  ```
462
470
 
463
- When prepared statements are disabled:
471
+ When `prepare: false` is set:
472
+
473
+ Queries are still executed using the "extended" protocol, but they are executed using [unnamed prepared statements](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY), an unnamed prepared statement lasts only until the next Parse statement specifying the unnamed statement as destination is issued.
464
474
 
465
- - Queries are executed using simple query protocol
466
- - Each query is sent to the server as a raw SQL string
467
- - Multiple statements can be executed in a single query (using `sql``.simple()`)
468
- - Parameter binding is still safe against SQL injection, but simple queries cannot include parameters
475
+ - Parameter binding is still safe against SQL injection
469
476
  - Each query is parsed and planned from scratch by the server
477
+ - Queries will not be [pipelined](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-PIPELINING)
470
478
 
471
- You might want to disable prepared statements when:
479
+ You might want to use `prepare: false` when:
472
480
 
473
481
  - Using PGBouncer in transaction mode (though since PGBouncer 1.21.0, protocol-level named prepared statements are supported when configured properly)
474
482
  - Debugging query execution plans
475
483
  - Working with dynamic SQL where query plans need to be regenerated frequently
484
+ - More than one command per query will not be supported (unless you use `sql``.simple()`)
476
485
 
477
486
  Note that disabling prepared statements may impact performance for queries that are executed frequently with different parameters, as the server needs to parse and plan each query from scratch.
478
487
 
@@ -3,26 +3,34 @@ Using `Bun.serve()`'s `routes` option, you can run your frontend and backend in
3
3
  To get started, import HTML files and pass them to the `routes` option in `Bun.serve()`.
4
4
 
5
5
  ```ts
6
+ import { sql, serve } from "bun";
6
7
  import dashboard from "./dashboard.html";
7
8
  import homepage from "./index.html";
8
9
 
9
- const server = Bun.serve({
10
- // Add HTML imports to `routes` (before Bun v1.2.3, this was called `static`)
10
+ const server = serve({
11
11
  routes: {
12
- // Bundle & route index.html to "/"
12
+ // ** HTML imports **
13
+ // Bundle & route index.html to "/". This uses HTMLRewriter to scan the HTML for `<script>` and `<link>` tags, run's Bun's JavaScript & CSS bundler on them, transpiles any TypeScript, JSX, and TSX, downlevels CSS with Bun's CSS parser and serves the result.
13
14
  "/": homepage,
14
15
  // Bundle & route dashboard.html to "/dashboard"
15
16
  "/dashboard": dashboard,
16
17
 
17
- // API endpoints:
18
- "/api/users": async req => {
19
- const users = await Bun.sql`SELECT * FROM users`;
20
- return Response.json(users);
18
+ // ** API endpoints ** (Bun v1.2.3+ required)
19
+ "/api/users": {
20
+ async GET(req) {
21
+ const users = await sql`SELECT * FROM users`;
22
+ return Response.json(users);
23
+ },
24
+ async POST(req) {
25
+ const { name, email } = await req.json();
26
+ const [user] =
27
+ await sql`INSERT INTO users (name, email) VALUES (${name}, ${email})`;
28
+ return Response.json(user);
29
+ },
21
30
  },
22
-
23
31
  "/api/users/:id": async req => {
24
32
  const { id } = req.params;
25
- const [user] = await Bun.sql`SELECT * FROM users WHERE id = ${id}`;
33
+ const [user] = await sql`SELECT * FROM users WHERE id = ${id}`;
26
34
  return Response.json(user);
27
35
  },
28
36
  },
@@ -32,11 +40,11 @@ const server = Bun.serve({
32
40
  // - Hot reloading (Bun v1.2.3+ required)
33
41
  development: true,
34
42
 
35
- // Handle API requests
36
- async fetch(req) {
37
- // Return 404 for unmatched routes
38
- return new Response("Not Found", { status: 404 });
39
- },
43
+ // Prior to v1.2.3, the `fetch` option was used to handle all API requests. It is now optional.
44
+ // async fetch(req) {
45
+ // // Return 404 for unmatched routes
46
+ // return new Response("Not Found", { status: 404 });
47
+ // },
40
48
  });
41
49
 
42
50
  console.log(`Listening on ${server.url}`);
@@ -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.3-canary.20250216T140609 (ca7428e9)
10
+ bun publish v1.2.3-canary.20250217T140554 (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.3-canary.20250216T140609 (16b4bf34)
12
+ bun install v1.2.3-canary.20250217T140554 (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.3-canary.20250216T140609"
19
+ + "@types/bun": "^1.2.3-canary.20250217T140554"
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.3-canary.20250216T140609"
31
+ "@types/bun": "^1.2.3-canary.20250217T140554"
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.3-canary.20250216T140609
100
+ $ bun update @types/bun@1.2.3-canary.20250217T140554
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.3-canary.20250216T140609 (9c68abdb)
24
+ bun test v1.2.3-canary.20250217T140554 (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.3-canary.20250216T140609 (9c68abdb)
50
+ bun test v1.2.3-canary.20250217T140554 (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.3-canary.20250216T140609 (9c68abdb)
88
+ bun test v1.2.3-canary.20250217T140554 (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.3-canary.20250216T140609 (9c68abdb)
21
+ bun test v1.2.3-canary.20250217T140554 (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.3-canary.20250216T140609 (9c68abdb)
64
+ bun test v1.2.3-canary.20250217T140554 (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.3-canary.20250216T140609 (9c68abdb)
81
+ bun test v1.2.3-canary.20250217T140554 (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.3-canary.20250216T140609 (9c68abdb)
32
+ bun test v1.2.3-canary.20250217T140554 (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.3-canary.20250216T140609"
8
+ Bun.version; // => "1.2.3-canary.20250217T140554"
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.3-canary.20250216T140609"
17
+ $ curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.3-canary.20250217T140554"
18
18
  ```
19
19
 
20
20
  ```bash#npm
@@ -188,10 +188,10 @@ Since Bun is a single binary, you can install older versions of Bun by re-runnin
188
188
 
189
189
  ### Installing a specific version of Bun on Linux/Mac
190
190
 
191
- 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.3-canary.20250216T140609`.
191
+ 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.3-canary.20250217T140554`.
192
192
 
193
193
  ```sh
194
- $ curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.3-canary.20250216T140609"
194
+ $ curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.3-canary.20250217T140554"
195
195
  ```
196
196
 
197
197
  ### Installing a specific version of Bun on Windows
@@ -200,7 +200,7 @@ On Windows, you can install a specific version of Bun by passing the version num
200
200
 
201
201
  ```sh
202
202
  # PowerShell:
203
- $ iex "& {$(irm https://bun.sh/install.ps1)} -Version 1.2.3-canary.20250216T140609"
203
+ $ iex "& {$(irm https://bun.sh/install.ps1)} -Version 1.2.3-canary.20250217T140554"
204
204
  ```
205
205
 
206
206
  ## 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.3-canary.20250216T140609" -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.3-canary.20250217T140554" -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.3-canary.20250216T140609
131
+ [fetch] > User-Agent: Bun/1.2.3-canary.20250217T140554
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.3-canary.20250216T140609
173
+ [fetch] > User-Agent: Bun/1.2.3-canary.20250217T140554
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.3-canary.20250216T140609
58
+ bun test v1.2.3-canary.20250217T140554
59
59
 
60
60
  dom.test.ts:
61
61
  ✓ dom test [0.82ms]
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.2.3-canary.20250216T140609",
2
+ "version": "1.2.3-canary.20250217T140554",
3
3
  "name": "bun-types",
4
4
  "license": "MIT",
5
5
  "main": "",