bun-types 1.2.1-canary.20250127T140607 → 1.2.1-canary.20250128T140616

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
@@ -195,7 +195,7 @@ This will print the request and response headers to your terminal:
195
195
  ```sh
196
196
  [fetch] > HTTP/1.1 GET http://example.com/
197
197
  [fetch] > Connection: keep-alive
198
- [fetch] > User-Agent: Bun/1.2.1-canary.20250127T140607
198
+ [fetch] > User-Agent: Bun/1.2.1-canary.20250128T140616
199
199
  [fetch] > Accept: */*
200
200
  [fetch] > Host: example.com
201
201
  [fetch] > Accept-Encoding: gzip, deflate, br
package/docs/api/http.md CHANGED
@@ -513,6 +513,241 @@ Bun.serve({
513
513
  });
514
514
  ```
515
515
 
516
+ ## Server Lifecycle Methods
517
+
518
+ ### server.stop() - Stop the server
519
+
520
+ To stop the server from accepting new connections:
521
+
522
+ ```ts
523
+ const server = Bun.serve({
524
+ fetch(req) {
525
+ return new Response("Hello!");
526
+ },
527
+ });
528
+
529
+ // Gracefully stop the server (waits for in-flight requests)
530
+ await server.stop();
531
+
532
+ // Force stop and close all active connections
533
+ await server.stop(true);
534
+ ```
535
+
536
+ By default, `stop()` allows in-flight requests and WebSocket connections to complete. Pass `true` to immediately terminate all connections.
537
+
538
+ ### server.ref() and server.unref() - Process lifecycle control
539
+
540
+ Control whether the server keeps the Bun process alive:
541
+
542
+ ```ts
543
+ // Don't keep process alive if server is the only thing running
544
+ server.unref();
545
+
546
+ // Restore default behavior - keep process alive
547
+ server.ref();
548
+ ```
549
+
550
+ ### server.reload() - Hot reload handlers
551
+
552
+ Update the server's handlers without restarting:
553
+
554
+ ```ts
555
+ const server = Bun.serve({
556
+ static: {
557
+ "/api/version": Response.json({ version: "v1" }),
558
+ },
559
+ fetch(req) {
560
+ return new Response("v1");
561
+ },
562
+ });
563
+
564
+ // Update to new handler
565
+ server.reload({
566
+ static: {
567
+ "/api/version": Response.json({ version: "v2" }),
568
+ },
569
+ fetch(req) {
570
+ return new Response("v2");
571
+ },
572
+ });
573
+ ```
574
+
575
+ This is useful for development and hot reloading. Only `fetch`, `error`, and `static` handlers can be updated.
576
+
577
+ ## Per-Request Controls
578
+
579
+ <!-- ### server.abort(Request) - Abort requests
580
+
581
+ The `server.abort(request: Request)` method:
582
+
583
+ - Returns `true` if request was aborted, `false` if already aborted/completed
584
+ - Triggers the request's `AbortSignal`
585
+ - Cancels any attached `ReadableStream`
586
+ - Rejects any pending body promises (like `.text()`)
587
+
588
+ ```ts
589
+ const server = Bun.serve({
590
+ fetch(req, server) {
591
+ // abort if the url contains "slow"
592
+ if (req.url.includes("slow")) {
593
+ server.abort(req);
594
+
595
+ // When aborted, the server will not error due to the lack of a `Response` object
596
+ // If you return a `Response` anyway, it will be ignored.
597
+ return;
598
+ }
599
+
600
+ return new Response("Processing...");
601
+ },
602
+ });
603
+ ``` -->
604
+
605
+ ### server.timeout(Request, seconds) - Custom request timeouts
606
+
607
+ Set a custom idle timeout for individual requests:
608
+
609
+ ```ts
610
+ const server = Bun.serve({
611
+ fetch(req, server) {
612
+ // Set 60 second timeout for this request
613
+ server.timeout(req, 60);
614
+
615
+ // Long operation
616
+ await someSlowOperation();
617
+
618
+ return new Response("Done!");
619
+ },
620
+ });
621
+ ```
622
+
623
+ Pass `0` to disable the timeout for a request.
624
+
625
+ ### server.requestIP(Request) - Get client information
626
+
627
+ Get client IP and port information:
628
+
629
+ ```ts
630
+ const server = Bun.serve({
631
+ fetch(req, server) {
632
+ const address = server.requestIP(req);
633
+ if (address) {
634
+ return new Response(
635
+ `Client IP: ${address.address}, Port: ${address.port}`,
636
+ );
637
+ }
638
+ return new Response("Unknown client");
639
+ },
640
+ });
641
+ ```
642
+
643
+ Returns `null` for closed requests or Unix domain sockets.
644
+
645
+ ## Server Metrics
646
+
647
+ ### server.pendingRequests and server.pendingWebSockets
648
+
649
+ Monitor server activity with built-in counters:
650
+
651
+ ```ts
652
+ const server = Bun.serve({
653
+ fetch(req, server) {
654
+ return new Response(
655
+ `Active requests: ${server.pendingRequests}\n` +
656
+ `Active WebSockets: ${server.pendingWebSockets}`,
657
+ );
658
+ },
659
+ });
660
+ ```
661
+
662
+ ### server.subscriberCount(topic) - WebSocket subscribers
663
+
664
+ Get count of subscribers for a WebSocket topic:
665
+
666
+ ```ts
667
+ const server = Bun.serve({
668
+ fetch(req, server) {
669
+ const chatUsers = server.subscriberCount("chat");
670
+ return new Response(`${chatUsers} users in chat`);
671
+ },
672
+ websocket: {
673
+ message(ws) {
674
+ ws.subscribe("chat");
675
+ },
676
+ },
677
+ });
678
+ ```
679
+
680
+ ## WebSocket Configuration
681
+
682
+ ### server.publish(topic, data, compress) - WebSocket Message Publishing
683
+
684
+ The server can publish messages to all WebSocket clients subscribed to a topic:
685
+
686
+ ```ts
687
+ const server = Bun.serve({
688
+ websocket: {
689
+ message(ws) {
690
+ // Publish to all "chat" subscribers
691
+ server.publish("chat", "Hello everyone!");
692
+ },
693
+ },
694
+
695
+ fetch(req) {
696
+ // ...
697
+ },
698
+ });
699
+ ```
700
+
701
+ The `publish()` method returns:
702
+
703
+ - Number of bytes sent if successful
704
+ - `0` if the message was dropped
705
+ - `-1` if backpressure was applied
706
+
707
+ ### WebSocket Handler Options
708
+
709
+ When configuring WebSockets, several advanced options are available through the `websocket` handler:
710
+
711
+ ```ts
712
+ Bun.serve({
713
+ websocket: {
714
+ // Maximum message size (in bytes)
715
+ maxPayloadLength: 64 * 1024,
716
+
717
+ // Backpressure limit before messages are dropped
718
+ backpressureLimit: 1024 * 1024,
719
+
720
+ // Close connection if backpressure limit is hit
721
+ closeOnBackpressureLimit: true,
722
+
723
+ // Handler called when backpressure is relieved
724
+ drain(ws) {
725
+ console.log("Backpressure relieved");
726
+ },
727
+
728
+ // Enable per-message deflate compression
729
+ perMessageDeflate: {
730
+ compress: true,
731
+ decompress: true,
732
+ },
733
+
734
+ // Send ping frames to keep connection alive
735
+ sendPings: true,
736
+
737
+ // Handlers for ping/pong frames
738
+ ping(ws, data) {
739
+ console.log("Received ping");
740
+ },
741
+ pong(ws, data) {
742
+ console.log("Received pong");
743
+ },
744
+
745
+ // Whether server receives its own published messages
746
+ publishToSelf: false,
747
+ },
748
+ });
749
+ ```
750
+
516
751
  ## Benchmarks
517
752
 
518
753
  Below are Bun and Node.js implementations of a simple HTTP server that responds `Bun!` to each incoming `Request`.
@@ -561,100 +796,174 @@ The `Bun.serve` server can handle roughly 2.5x more requests per second than Nod
561
796
  {% details summary="See TypeScript definitions" %}
562
797
 
563
798
  ```ts
564
- interface Bun {
565
- serve(options: {
566
- development?: boolean;
567
- error?: (
568
- request: ErrorLike,
569
- ) => Response | Promise<Response> | undefined | Promise<undefined>;
570
- fetch(request: Request, server: Server): Response | Promise<Response>;
571
- hostname?: string;
572
- id?: string | null;
573
- maxRequestBodySize?: number;
574
- port?: string | number;
575
- reusePort?: boolean;
576
- tls?: TLSOptions | Array<TLSOptions>;
577
- unix: string;
578
- websocket: WebSocketHandler<WebSocketDataType>;
579
- }): Server;
580
- }
799
+ interface Server extends Disposable {
800
+ /**
801
+ * Stop the server from accepting new connections.
802
+ * @param closeActiveConnections If true, immediately terminates all connections
803
+ * @returns Promise that resolves when the server has stopped
804
+ */
805
+ stop(closeActiveConnections?: boolean): Promise<void>;
806
+
807
+ /**
808
+ * Update handlers without restarting the server.
809
+ * Only fetch and error handlers can be updated.
810
+ */
811
+ reload(options: Serve): void;
581
812
 
582
- interface TLSOptions {
583
- ca?: string | Buffer | BunFile | Array<string | Buffer | BunFile> | undefined;
584
- cert?:
585
- | string
586
- | Buffer
587
- | BunFile
588
- | Array<string | Buffer | BunFile>
589
- | undefined;
590
- dhParamsFile?: string;
591
- key?:
592
- | string
593
- | Buffer
594
- | BunFile
595
- | Array<string | Buffer | BunFile>
596
- | undefined;
597
- lowMemoryMode?: boolean;
598
- passphrase?: string;
599
- secureOptions?: number | undefined;
600
- serverName?: string;
813
+ /**
814
+ * Make a request to the running server.
815
+ * Useful for testing or internal routing.
816
+ */
817
+ fetch(request: Request | string): Response | Promise<Response>;
818
+
819
+ /**
820
+ * Upgrade an HTTP request to a WebSocket connection.
821
+ * @returns true if upgrade successful, false if failed
822
+ */
823
+ upgrade<T = undefined>(
824
+ request: Request,
825
+ options?: {
826
+ headers?: Bun.HeadersInit;
827
+ data?: T;
828
+ },
829
+ ): boolean;
830
+
831
+ /**
832
+ * Publish a message to all WebSocket clients subscribed to a topic.
833
+ * @returns Bytes sent, 0 if dropped, -1 if backpressure applied
834
+ */
835
+ publish(
836
+ topic: string,
837
+ data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
838
+ compress?: boolean,
839
+ ): ServerWebSocketSendStatus;
840
+
841
+ /**
842
+ * Get count of WebSocket clients subscribed to a topic.
843
+ */
844
+ subscriberCount(topic: string): number;
845
+
846
+ /**
847
+ * Get client IP address and port.
848
+ * @returns null for closed requests or Unix sockets
849
+ */
850
+ requestIP(request: Request): SocketAddress | null;
851
+
852
+ /**
853
+ * Set custom idle timeout for a request.
854
+ * @param seconds Timeout in seconds, 0 to disable
855
+ */
856
+ timeout(request: Request, seconds: number): void;
857
+
858
+ /**
859
+ * Keep process alive while server is running.
860
+ */
861
+ ref(): void;
862
+
863
+ /**
864
+ * Allow process to exit if server is only thing running.
865
+ */
866
+ unref(): void;
867
+
868
+ /** Number of in-flight HTTP requests */
869
+ readonly pendingRequests: number;
870
+
871
+ /** Number of active WebSocket connections */
872
+ readonly pendingWebSockets: number;
873
+
874
+ /** Server URL including protocol, hostname and port */
875
+ readonly url: URL;
876
+
877
+ /** Port server is listening on */
878
+ readonly port: number;
879
+
880
+ /** Hostname server is bound to */
881
+ readonly hostname: string;
882
+
883
+ /** Whether server is in development mode */
884
+ readonly development: boolean;
885
+
886
+ /** Server instance identifier */
887
+ readonly id: string;
601
888
  }
602
889
 
603
890
  interface WebSocketHandler<T = undefined> {
891
+ /** Maximum WebSocket message size in bytes */
892
+ maxPayloadLength?: number;
893
+
894
+ /** Bytes of queued messages before applying backpressure */
604
895
  backpressureLimit?: number;
605
- close?(
606
- ws: ServerWebSocket<T>,
607
- code: number,
608
- reason: string,
609
- ): void | Promise<void>;
896
+
897
+ /** Whether to close connection when backpressure limit hit */
610
898
  closeOnBackpressureLimit?: boolean;
899
+
900
+ /** Called when backpressure is relieved */
611
901
  drain?(ws: ServerWebSocket<T>): void | Promise<void>;
902
+
903
+ /** Seconds before idle timeout */
612
904
  idleTimeout?: number;
613
- maxPayloadLength?: number;
614
- message(
615
- ws: ServerWebSocket<T>,
616
- message: string | Buffer,
617
- ): void | Promise<void>;
618
- open?(ws: ServerWebSocket<T>): void | Promise<void>;
905
+
906
+ /** Enable per-message deflate compression */
619
907
  perMessageDeflate?:
620
908
  | boolean
621
909
  | {
622
910
  compress?: WebSocketCompressor | boolean;
623
911
  decompress?: WebSocketCompressor | boolean;
624
912
  };
913
+
914
+ /** Send ping frames to keep connection alive */
915
+ sendPings?: boolean;
916
+
917
+ /** Whether server receives its own published messages */
918
+ publishToSelf?: boolean;
919
+
920
+ /** Called when connection opened */
921
+ open?(ws: ServerWebSocket<T>): void | Promise<void>;
922
+
923
+ /** Called when message received */
924
+ message(
925
+ ws: ServerWebSocket<T>,
926
+ message: string | Buffer,
927
+ ): void | Promise<void>;
928
+
929
+ /** Called when connection closed */
930
+ close?(
931
+ ws: ServerWebSocket<T>,
932
+ code: number,
933
+ reason: string,
934
+ ): void | Promise<void>;
935
+
936
+ /** Called when ping frame received */
625
937
  ping?(ws: ServerWebSocket<T>, data: Buffer): void | Promise<void>;
938
+
939
+ /** Called when pong frame received */
626
940
  pong?(ws: ServerWebSocket<T>, data: Buffer): void | Promise<void>;
627
- publishToSelf?: boolean;
628
- sendPings?: boolean;
629
941
  }
630
942
 
631
- interface Server {
632
- fetch(request: Request | string): Response | Promise<Response>;
633
- publish(
634
- compress?: boolean,
635
- data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
636
- topic: string,
637
- ): ServerWebSocketSendStatus;
638
- ref(): void;
639
- reload(options: Serve): void;
640
- requestIP(request: Request): SocketAddress | null;
641
- stop(closeActiveConnections?: boolean): void;
642
- unref(): void;
643
- upgrade<T = undefined>(
644
- options?: {
645
- data?: T;
646
- headers?: Bun.HeadersInit;
647
- },
648
- request: Request,
649
- ): boolean;
943
+ interface TLSOptions {
944
+ /** Certificate authority chain */
945
+ ca?: string | Buffer | BunFile | Array<string | Buffer | BunFile>;
650
946
 
651
- readonly development: boolean;
652
- readonly hostname: string;
653
- readonly id: string;
654
- readonly pendingRequests: number;
655
- readonly pendingWebSockets: number;
656
- readonly port: number;
657
- readonly url: URL;
947
+ /** Server certificate */
948
+ cert?: string | Buffer | BunFile | Array<string | Buffer | BunFile>;
949
+
950
+ /** Path to DH parameters file */
951
+ dhParamsFile?: string;
952
+
953
+ /** Private key */
954
+ key?: string | Buffer | BunFile | Array<string | Buffer | BunFile>;
955
+
956
+ /** Reduce TLS memory usage */
957
+ lowMemoryMode?: boolean;
958
+
959
+ /** Private key passphrase */
960
+ passphrase?: string;
961
+
962
+ /** OpenSSL options flags */
963
+ secureOptions?: number;
964
+
965
+ /** Server name for SNI */
966
+ serverName?: string;
658
967
  }
659
968
  ```
660
969
 
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.1-canary.20250127T140607"
113
+ console.log(text); // => "1.2.1-canary.20250128T140616"
114
114
  ```
115
115
 
116
116
  Configure the output stream by passing one of the following values to `stdout/stderr`:
@@ -6,7 +6,7 @@ To get started, import your HTML files and pass them to the `static` option in `
6
6
  import dashboard from "./dashboard.html";
7
7
  import homepage from "./index.html";
8
8
 
9
- Bun.serve({
9
+ const server = Bun.serve({
10
10
  // Add HTML imports to `static`
11
11
  static: {
12
12
  // Bundle & route index.html to "/"
@@ -32,6 +32,8 @@ Bun.serve({
32
32
  return new Response("Not Found", { status: 404 });
33
33
  },
34
34
  });
35
+
36
+ console.log(`Listening on ${server.url}`)
35
37
  ```
36
38
 
37
39
  ```bash
@@ -107,7 +109,7 @@ To use React in your client-side code, import `react-dom/client` and render your
107
109
  {% codetabs %}
108
110
 
109
111
  ```ts#src/backend.ts
110
- import dashboard from "./public/dashboard.html";
112
+ import dashboard from "../public/dashboard.html";
111
113
  import { serve } from "bun";
112
114
 
113
115
  serve({
@@ -204,18 +206,19 @@ To configure plugins for `Bun.serve`, add a `plugins` array in the `[serve.stati
204
206
 
205
207
  ### Using TailwindCSS in HTML routes
206
208
 
207
- For example, enable TailwindCSS on your routes by adding add the `bun-plugin-tailwind` plugin:
209
+ For example, enable TailwindCSS on your routes by installing and adding the `bun-plugin-tailwind` plugin:
208
210
 
209
- ```toml
211
+ ```sh
212
+ $ bun add bun-plugin-tailwind
213
+ ```
214
+ ```toml#bunfig.toml
210
215
  [serve.static]
211
216
  plugins = ["bun-plugin-tailwind"]
212
-
213
217
  ```
214
218
 
215
219
  This will allow you to use TailwindCSS utility classes in your HTML and CSS files. All you need to do is import `tailwindcss` somewhere:
216
220
 
217
- ```html
218
- <!-- index.html -->
221
+ ```html#index.html
219
222
  <!doctype html>
220
223
  <html>
221
224
  <head>
@@ -230,14 +233,15 @@ This will allow you to use TailwindCSS utility classes in your HTML and CSS file
230
233
 
231
234
  Or in your CSS:
232
235
 
233
- ```css
234
- /* style.css */
236
+ ```css#style.css
235
237
  @import "tailwindcss";
236
238
  ```
237
239
 
240
+ ### Custom plugins
241
+
238
242
  Any JS file or module which exports a [valid bundler plugin object](https://bun.sh/docs/bundler/plugins#usage) (essentially an object with a `name` and `setup` field) can be placed inside the `plugins` array:
239
243
 
240
- ```toml
244
+ ```toml#bunfig.toml
241
245
  [serve.static]
242
246
  plugins = ["./my-plugin-implementation.ts"]
243
247
  ```
@@ -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.1-canary.20250127T140607 (ca7428e9)
10
+ bun publish v1.2.1-canary.20250128T140616 (ca7428e9)
11
11
 
12
12
  packed 203B package.json
13
13
  packed 224B README.md
@@ -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.1-canary.20250127T140607" -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.1-canary.20250128T140616" -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.1-canary.20250127T140607
131
+ [fetch] > User-Agent: Bun/1.2.1-canary.20250128T140616
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.1-canary.20250127T140607
173
+ [fetch] > User-Agent: Bun/1.2.1-canary.20250128T140616
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.1-canary.20250127T140607
58
+ bun test v1.2.1-canary.20250128T140616
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.1-canary.20250127T140607",
2
+ "version": "1.2.1-canary.20250128T140616",
3
3
  "name": "bun-types",
4
4
  "license": "MIT",
5
5
  "main": "",