bun-types 1.2.24-canary.20251006T140715 → 1.2.24-canary.20251007T140703
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 +65 -1514
- package/bun.ns.d.ts +0 -2
- package/deprecated.d.ts +5 -0
- package/docs/api/fetch.md +1 -1
- package/docs/api/spawn.md +1 -1
- package/docs/api/websockets.md +9 -3
- package/docs/cli/pm.md +1 -1
- package/docs/cli/publish.md +1 -1
- package/docs/guides/ecosystem/nuxt.md +1 -1
- package/docs/guides/install/add-peer.md +2 -2
- package/docs/guides/install/from-npm-install-to-bun-install.md +1 -1
- package/docs/guides/test/run-tests.md +3 -3
- package/docs/guides/test/snapshot.md +3 -3
- package/docs/guides/test/update-snapshots.md +1 -1
- package/docs/guides/util/version.md +1 -1
- package/docs/guides/websocket/context.md +8 -3
- package/docs/guides/websocket/pubsub.md +4 -1
- package/docs/guides/websocket/simple.md +1 -1
- package/docs/installation.md +4 -4
- package/docs/runtime/bunfig.md +40 -0
- package/docs/runtime/debugger.md +3 -3
- package/docs/test/dom.md +1 -1
- package/globals.d.ts +64 -12
- package/index.d.ts +1 -0
- package/package.json +1 -1
- package/serve.d.ts +1272 -0
package/serve.d.ts
ADDED
|
@@ -0,0 +1,1272 @@
|
|
|
1
|
+
declare module "bun" {
|
|
2
|
+
/**
|
|
3
|
+
* A status that represents the outcome of a sent message.
|
|
4
|
+
*
|
|
5
|
+
* - if **0**, the message was **dropped**.
|
|
6
|
+
* - if **-1**, there is **backpressure** of messages.
|
|
7
|
+
* - if **>0**, it represents the **number of bytes sent**.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```js
|
|
11
|
+
* const status = ws.send("Hello!");
|
|
12
|
+
* if (status === 0) {
|
|
13
|
+
* console.log("Message was dropped");
|
|
14
|
+
* } else if (status === -1) {
|
|
15
|
+
* console.log("Backpressure was applied");
|
|
16
|
+
* } else {
|
|
17
|
+
* console.log(`Success! Sent ${status} bytes`);
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
type ServerWebSocketSendStatus = number;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A state that represents if a WebSocket is connected.
|
|
25
|
+
*
|
|
26
|
+
* - `WebSocket.CONNECTING` is `0`, the connection is pending.
|
|
27
|
+
* - `WebSocket.OPEN` is `1`, the connection is established and `send()` is possible.
|
|
28
|
+
* - `WebSocket.CLOSING` is `2`, the connection is closing.
|
|
29
|
+
* - `WebSocket.CLOSED` is `3`, the connection is closed or couldn't be opened.
|
|
30
|
+
*
|
|
31
|
+
* @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
|
|
32
|
+
*/
|
|
33
|
+
type WebSocketReadyState = 0 | 1 | 2 | 3;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A fast WebSocket designed for servers.
|
|
37
|
+
*
|
|
38
|
+
* Features:
|
|
39
|
+
* - **Message compression** - Messages can be compressed
|
|
40
|
+
* - **Backpressure** - If the client is not ready to receive data, the server will tell you.
|
|
41
|
+
* - **Dropped messages** - If the client cannot receive data, the server will tell you.
|
|
42
|
+
* - **Topics** - Messages can be {@link ServerWebSocket.publish}ed to a specific topic and the client can {@link ServerWebSocket.subscribe} to topics
|
|
43
|
+
*
|
|
44
|
+
* This is slightly different than the browser {@link WebSocket} which Bun supports for clients.
|
|
45
|
+
*
|
|
46
|
+
* Powered by [uWebSockets](https://github.com/uNetworking/uWebSockets).
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* Bun.serve({
|
|
51
|
+
* websocket: {
|
|
52
|
+
* open(ws) {
|
|
53
|
+
* console.log("Connected", ws.remoteAddress);
|
|
54
|
+
* },
|
|
55
|
+
* message(ws, data) {
|
|
56
|
+
* console.log("Received", data);
|
|
57
|
+
* ws.send(data);
|
|
58
|
+
* },
|
|
59
|
+
* close(ws, code, reason) {
|
|
60
|
+
* console.log("Disconnected", code, reason);
|
|
61
|
+
* },
|
|
62
|
+
* }
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
interface ServerWebSocket<T = undefined> {
|
|
67
|
+
/**
|
|
68
|
+
* Sends a message to the client.
|
|
69
|
+
*
|
|
70
|
+
* @param data The data to send.
|
|
71
|
+
* @param compress Should the data be compressed? If the client does not support compression, this is ignored.
|
|
72
|
+
* @example
|
|
73
|
+
* ws.send("Hello!");
|
|
74
|
+
* ws.send("Compress this.", true);
|
|
75
|
+
* ws.send(new Uint8Array([1, 2, 3, 4]));
|
|
76
|
+
*/
|
|
77
|
+
send(data: string | BufferSource, compress?: boolean): ServerWebSocketSendStatus;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Sends a text message to the client.
|
|
81
|
+
*
|
|
82
|
+
* @param data The data to send.
|
|
83
|
+
* @param compress Should the data be compressed? If the client does not support compression, this is ignored.
|
|
84
|
+
* @example
|
|
85
|
+
* ws.send("Hello!");
|
|
86
|
+
* ws.send("Compress this.", true);
|
|
87
|
+
*/
|
|
88
|
+
sendText(data: string, compress?: boolean): ServerWebSocketSendStatus;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Sends a binary message to the client.
|
|
92
|
+
*
|
|
93
|
+
* @param data The data to send.
|
|
94
|
+
* @param compress Should the data be compressed? If the client does not support compression, this is ignored.
|
|
95
|
+
* @example
|
|
96
|
+
* ws.send(new TextEncoder().encode("Hello!"));
|
|
97
|
+
* ws.send(new Uint8Array([1, 2, 3, 4]), true);
|
|
98
|
+
*/
|
|
99
|
+
sendBinary(data: BufferSource, compress?: boolean): ServerWebSocketSendStatus;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Closes the connection.
|
|
103
|
+
*
|
|
104
|
+
* Here is a list of close codes:
|
|
105
|
+
* - `1000` means "normal closure" **(default)**
|
|
106
|
+
* - `1009` means a message was too big and was rejected
|
|
107
|
+
* - `1011` means the server encountered an error
|
|
108
|
+
* - `1012` means the server is restarting
|
|
109
|
+
* - `1013` means the server is too busy or the client is rate-limited
|
|
110
|
+
* - `4000` through `4999` are reserved for applications (you can use it!)
|
|
111
|
+
*
|
|
112
|
+
* To close the connection abruptly, use `terminate()`.
|
|
113
|
+
*
|
|
114
|
+
* @param code The close code to send
|
|
115
|
+
* @param reason The close reason to send
|
|
116
|
+
*/
|
|
117
|
+
close(code?: number, reason?: string): void;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Abruptly close the connection.
|
|
121
|
+
*
|
|
122
|
+
* To gracefully close the connection, use `close()`.
|
|
123
|
+
*/
|
|
124
|
+
terminate(): void;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Sends a ping.
|
|
128
|
+
*
|
|
129
|
+
* @param data The data to send
|
|
130
|
+
*/
|
|
131
|
+
ping(data?: string | BufferSource): ServerWebSocketSendStatus;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Sends a pong.
|
|
135
|
+
*
|
|
136
|
+
* @param data The data to send
|
|
137
|
+
*/
|
|
138
|
+
pong(data?: string | BufferSource): ServerWebSocketSendStatus;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Sends a message to subscribers of the topic.
|
|
142
|
+
*
|
|
143
|
+
* @param topic The topic name.
|
|
144
|
+
* @param data The data to send.
|
|
145
|
+
* @param compress Should the data be compressed? If the client does not support compression, this is ignored.
|
|
146
|
+
* @example
|
|
147
|
+
* ws.publish("chat", "Hello!");
|
|
148
|
+
* ws.publish("chat", "Compress this.", true);
|
|
149
|
+
* ws.publish("chat", new Uint8Array([1, 2, 3, 4]));
|
|
150
|
+
*/
|
|
151
|
+
publish(topic: string, data: string | BufferSource, compress?: boolean): ServerWebSocketSendStatus;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Sends a text message to subscribers of the topic.
|
|
155
|
+
*
|
|
156
|
+
* @param topic The topic name.
|
|
157
|
+
* @param data The data to send.
|
|
158
|
+
* @param compress Should the data be compressed? If the client does not support compression, this is ignored.
|
|
159
|
+
* @example
|
|
160
|
+
* ws.publish("chat", "Hello!");
|
|
161
|
+
* ws.publish("chat", "Compress this.", true);
|
|
162
|
+
*/
|
|
163
|
+
publishText(topic: string, data: string, compress?: boolean): ServerWebSocketSendStatus;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Sends a binary message to subscribers of the topic.
|
|
167
|
+
*
|
|
168
|
+
* @param topic The topic name.
|
|
169
|
+
* @param data The data to send.
|
|
170
|
+
* @param compress Should the data be compressed? If the client does not support compression, this is ignored.
|
|
171
|
+
* @example
|
|
172
|
+
* ws.publish("chat", new TextEncoder().encode("Hello!"));
|
|
173
|
+
* ws.publish("chat", new Uint8Array([1, 2, 3, 4]), true);
|
|
174
|
+
*/
|
|
175
|
+
publishBinary(topic: string, data: BufferSource, compress?: boolean): ServerWebSocketSendStatus;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Subscribes a client to the topic.
|
|
179
|
+
*
|
|
180
|
+
* @param topic The topic name.
|
|
181
|
+
* @example
|
|
182
|
+
* ws.subscribe("chat");
|
|
183
|
+
*/
|
|
184
|
+
subscribe(topic: string): void;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Unsubscribes a client to the topic.
|
|
188
|
+
*
|
|
189
|
+
* @param topic The topic name.
|
|
190
|
+
* @example
|
|
191
|
+
* ws.unsubscribe("chat");
|
|
192
|
+
*/
|
|
193
|
+
unsubscribe(topic: string): void;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Is the client subscribed to a topic?
|
|
197
|
+
*
|
|
198
|
+
* @param topic The topic name.
|
|
199
|
+
* @example
|
|
200
|
+
* ws.subscribe("chat");
|
|
201
|
+
* console.log(ws.isSubscribed("chat")); // true
|
|
202
|
+
*/
|
|
203
|
+
isSubscribed(topic: string): boolean;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Batches `send()` and `publish()` operations, which makes it faster to send data.
|
|
207
|
+
*
|
|
208
|
+
* The `message`, `open`, and `drain` callbacks are automatically corked, so
|
|
209
|
+
* you only need to call this if you are sending messages outside of those
|
|
210
|
+
* callbacks or in async functions.
|
|
211
|
+
*
|
|
212
|
+
* @param callback The callback to run.
|
|
213
|
+
* @example
|
|
214
|
+
* ws.cork((ctx) => {
|
|
215
|
+
* ctx.send("These messages");
|
|
216
|
+
* ctx.sendText("are sent");
|
|
217
|
+
* ctx.sendBinary(new TextEncoder().encode("together!"));
|
|
218
|
+
* });
|
|
219
|
+
*/
|
|
220
|
+
cork<T = unknown>(callback: (ws: ServerWebSocket<T>) => T): T;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The IP address of the client.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* console.log(socket.remoteAddress); // "127.0.0.1"
|
|
227
|
+
*/
|
|
228
|
+
readonly remoteAddress: string;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* The ready state of the client.
|
|
232
|
+
*
|
|
233
|
+
* - if `0`, the client is connecting.
|
|
234
|
+
* - if `1`, the client is connected.
|
|
235
|
+
* - if `2`, the client is closing.
|
|
236
|
+
* - if `3`, the client is closed.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* console.log(socket.readyState); // 1
|
|
240
|
+
*/
|
|
241
|
+
readonly readyState: WebSocketReadyState;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Sets how binary data is returned in events.
|
|
245
|
+
*
|
|
246
|
+
* - if `nodebuffer`, binary data is returned as `Buffer` objects. **(default)**
|
|
247
|
+
* - if `arraybuffer`, binary data is returned as `ArrayBuffer` objects.
|
|
248
|
+
* - if `uint8array`, binary data is returned as `Uint8Array` objects.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* let ws: WebSocket;
|
|
252
|
+
* ws.binaryType = "uint8array";
|
|
253
|
+
* ws.addEventListener("message", ({ data }) => {
|
|
254
|
+
* console.log(data instanceof Uint8Array); // true
|
|
255
|
+
* });
|
|
256
|
+
*/
|
|
257
|
+
binaryType?: "nodebuffer" | "arraybuffer" | "uint8array";
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Custom data that you can assign to a client, can be read and written at any time.
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* import { serve } from "bun";
|
|
264
|
+
*
|
|
265
|
+
* serve({
|
|
266
|
+
* fetch(request, server) {
|
|
267
|
+
* const data = {
|
|
268
|
+
* accessToken: request.headers.get("Authorization"),
|
|
269
|
+
* };
|
|
270
|
+
* if (server.upgrade(request, { data })) {
|
|
271
|
+
* return;
|
|
272
|
+
* }
|
|
273
|
+
* return new Response();
|
|
274
|
+
* },
|
|
275
|
+
* websocket: {
|
|
276
|
+
* open(ws) {
|
|
277
|
+
* console.log(ws.data.accessToken);
|
|
278
|
+
* }
|
|
279
|
+
* }
|
|
280
|
+
* });
|
|
281
|
+
*/
|
|
282
|
+
data: T;
|
|
283
|
+
|
|
284
|
+
getBufferedAmount(): number;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Compression options for WebSocket messages.
|
|
289
|
+
*/
|
|
290
|
+
type WebSocketCompressor =
|
|
291
|
+
| "disable"
|
|
292
|
+
| "shared"
|
|
293
|
+
| "dedicated"
|
|
294
|
+
| "3KB"
|
|
295
|
+
| "4KB"
|
|
296
|
+
| "8KB"
|
|
297
|
+
| "16KB"
|
|
298
|
+
| "32KB"
|
|
299
|
+
| "64KB"
|
|
300
|
+
| "128KB"
|
|
301
|
+
| "256KB";
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Create a server-side {@link ServerWebSocket} handler for use with {@link Bun.serve}
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```ts
|
|
308
|
+
* import { websocket, serve } from "bun";
|
|
309
|
+
*
|
|
310
|
+
* serve<{name: string}>({
|
|
311
|
+
* port: 3000,
|
|
312
|
+
* websocket: {
|
|
313
|
+
* open: (ws) => {
|
|
314
|
+
* console.log("Client connected");
|
|
315
|
+
* },
|
|
316
|
+
* message: (ws, message) => {
|
|
317
|
+
* console.log(`${ws.data.name}: ${message}`);
|
|
318
|
+
* },
|
|
319
|
+
* close: (ws) => {
|
|
320
|
+
* console.log("Client disconnected");
|
|
321
|
+
* },
|
|
322
|
+
* },
|
|
323
|
+
*
|
|
324
|
+
* fetch(req, server) {
|
|
325
|
+
* const url = new URL(req.url);
|
|
326
|
+
* if (url.pathname === "/chat") {
|
|
327
|
+
* const upgraded = server.upgrade(req, {
|
|
328
|
+
* data: {
|
|
329
|
+
* name: new URL(req.url).searchParams.get("name"),
|
|
330
|
+
* },
|
|
331
|
+
* });
|
|
332
|
+
* if (!upgraded) {
|
|
333
|
+
* return new Response("Upgrade failed", { status: 400 });
|
|
334
|
+
* }
|
|
335
|
+
* return;
|
|
336
|
+
* }
|
|
337
|
+
* return new Response("Hello World");
|
|
338
|
+
* },
|
|
339
|
+
* });
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
interface WebSocketHandler<T> {
|
|
343
|
+
/**
|
|
344
|
+
* Specify the type for the {@link ServerWebSocket.data} property on
|
|
345
|
+
* connecting websocket clients. You can pass this value when you make a
|
|
346
|
+
* call to {@link Server.upgrade}.
|
|
347
|
+
*
|
|
348
|
+
* This pattern exists in Bun due to a [TypeScript limitation (#26242)](https://github.com/microsoft/TypeScript/issues/26242)
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```ts
|
|
352
|
+
* Bun.serve({
|
|
353
|
+
* websocket: {
|
|
354
|
+
* data: {} as { name: string }, // ← Specify the type of `ws.data` like this
|
|
355
|
+
* message: (ws, message) => console.log(ws.data.name, 'says:', message);
|
|
356
|
+
* },
|
|
357
|
+
* // ...
|
|
358
|
+
* });
|
|
359
|
+
* ```
|
|
360
|
+
*/
|
|
361
|
+
data?: T;
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Called when the server receives an incoming message.
|
|
365
|
+
*
|
|
366
|
+
* If the message is not a `string`, its type is based on the value of `binaryType`.
|
|
367
|
+
* - if `nodebuffer`, then the message is a `Buffer`.
|
|
368
|
+
* - if `arraybuffer`, then the message is an `ArrayBuffer`.
|
|
369
|
+
* - if `uint8array`, then the message is a `Uint8Array`.
|
|
370
|
+
*
|
|
371
|
+
* @param ws The websocket that sent the message
|
|
372
|
+
* @param message The message received
|
|
373
|
+
*/
|
|
374
|
+
message(ws: ServerWebSocket<T>, message: string | Buffer<ArrayBuffer>): void | Promise<void>;
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Called when a connection is opened.
|
|
378
|
+
*
|
|
379
|
+
* @param ws The websocket that was opened
|
|
380
|
+
*/
|
|
381
|
+
open?(ws: ServerWebSocket<T>): void | Promise<void>;
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Called when a connection was previously under backpressure,
|
|
385
|
+
* meaning it had too many queued messages, but is now ready to receive more data.
|
|
386
|
+
*
|
|
387
|
+
* @param ws The websocket that is ready for more data
|
|
388
|
+
*/
|
|
389
|
+
drain?(ws: ServerWebSocket<T>): void | Promise<void>;
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Called when a connection is closed.
|
|
393
|
+
*
|
|
394
|
+
* @param ws The websocket that was closed
|
|
395
|
+
* @param code The close code
|
|
396
|
+
* @param reason The close reason
|
|
397
|
+
*/
|
|
398
|
+
close?(ws: ServerWebSocket<T>, code: number, reason: string): void | Promise<void>;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Called when a ping is sent.
|
|
402
|
+
*
|
|
403
|
+
* @param ws The websocket that received the ping
|
|
404
|
+
* @param data The data sent with the ping
|
|
405
|
+
*/
|
|
406
|
+
ping?(ws: ServerWebSocket<T>, data: Buffer): void | Promise<void>;
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Called when a pong is received.
|
|
410
|
+
*
|
|
411
|
+
* @param ws The websocket that received the ping
|
|
412
|
+
* @param data The data sent with the ping
|
|
413
|
+
*/
|
|
414
|
+
pong?(ws: ServerWebSocket<T>, data: Buffer): void | Promise<void>;
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Sets the maximum size of messages in bytes.
|
|
418
|
+
*
|
|
419
|
+
* Default is 16 MB, or `1024 * 1024 * 16` in bytes.
|
|
420
|
+
*/
|
|
421
|
+
maxPayloadLength?: number;
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Sets the maximum number of bytes that can be buffered on a single connection.
|
|
425
|
+
*
|
|
426
|
+
* Default is 16 MB, or `1024 * 1024 * 16` in bytes.
|
|
427
|
+
*/
|
|
428
|
+
backpressureLimit?: number;
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Sets if the connection should be closed if `backpressureLimit` is reached.
|
|
432
|
+
*
|
|
433
|
+
* @default false
|
|
434
|
+
*/
|
|
435
|
+
closeOnBackpressureLimit?: boolean;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Sets the the number of seconds to wait before timing out a connection
|
|
439
|
+
* due to no messages or pings.
|
|
440
|
+
*
|
|
441
|
+
* @default 120
|
|
442
|
+
*/
|
|
443
|
+
idleTimeout?: number;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Should `ws.publish()` also send a message to `ws` (itself), if it is subscribed?
|
|
447
|
+
*
|
|
448
|
+
* @default false
|
|
449
|
+
*/
|
|
450
|
+
publishToSelf?: boolean;
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Should the server automatically send and respond to pings to clients?
|
|
454
|
+
*
|
|
455
|
+
* @default true
|
|
456
|
+
*/
|
|
457
|
+
sendPings?: boolean;
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Sets the compression level for messages, for clients that supports it. By default, compression is disabled.
|
|
461
|
+
*
|
|
462
|
+
* @default false
|
|
463
|
+
*/
|
|
464
|
+
perMessageDeflate?:
|
|
465
|
+
| boolean
|
|
466
|
+
| {
|
|
467
|
+
/**
|
|
468
|
+
* Sets the compression level.
|
|
469
|
+
*/
|
|
470
|
+
compress?: WebSocketCompressor | boolean;
|
|
471
|
+
/**
|
|
472
|
+
* Sets the decompression level.
|
|
473
|
+
*/
|
|
474
|
+
decompress?: WebSocketCompressor | boolean;
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
namespace Serve {
|
|
479
|
+
type ExtractRouteParams<T> = T extends `${string}:${infer Param}/${infer Rest}`
|
|
480
|
+
? { [K in Param]: string } & ExtractRouteParams<Rest>
|
|
481
|
+
: T extends `${string}:${infer Param}`
|
|
482
|
+
? { [K in Param]: string }
|
|
483
|
+
: T extends `${string}*`
|
|
484
|
+
? {}
|
|
485
|
+
: {};
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Development configuration for {@link Bun.serve}
|
|
489
|
+
*/
|
|
490
|
+
type Development =
|
|
491
|
+
| boolean
|
|
492
|
+
| {
|
|
493
|
+
/**
|
|
494
|
+
* Enable Hot Module Replacement for routes (including React Fast Refresh, if React is in use)
|
|
495
|
+
*
|
|
496
|
+
* @default true if process.env.NODE_ENV !== 'production'
|
|
497
|
+
*
|
|
498
|
+
*/
|
|
499
|
+
hmr?: boolean;
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Enable console log streaming from browser to server
|
|
503
|
+
* @default false
|
|
504
|
+
*/
|
|
505
|
+
console?: boolean;
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Enable automatic workspace folders for Chrome DevTools
|
|
509
|
+
*
|
|
510
|
+
* This lets you persistently edit files in the browser. It works by adding the following route to the server:
|
|
511
|
+
* `/.well-known/appspecific/com.chrome.devtools.json`
|
|
512
|
+
*
|
|
513
|
+
* The response is a JSON object with the following shape:
|
|
514
|
+
* ```json
|
|
515
|
+
* {
|
|
516
|
+
* "workspace": {
|
|
517
|
+
* "root": "<cwd>",
|
|
518
|
+
* "uuid": "<uuid>"
|
|
519
|
+
* }
|
|
520
|
+
* }
|
|
521
|
+
* ```
|
|
522
|
+
*
|
|
523
|
+
* The `root` field is the current working directory of the server.
|
|
524
|
+
* The `"uuid"` field is a hash of the file that started the server and a hash of the current working directory.
|
|
525
|
+
*
|
|
526
|
+
* For security reasons, if the remote socket address is not from localhost, 127.0.0.1, or ::1, the request is ignored.
|
|
527
|
+
* @default true
|
|
528
|
+
*/
|
|
529
|
+
chromeDevToolsAutomaticWorkspaceFolders?: boolean;
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
|
|
533
|
+
|
|
534
|
+
type Handler<Req extends Request, S, Res> = (request: Req, server: S) => MaybePromise<Res>;
|
|
535
|
+
|
|
536
|
+
type BaseRouteValue = Response | false | HTMLBundle | BunFile;
|
|
537
|
+
|
|
538
|
+
type Routes<WebSocketData, R extends string> = {
|
|
539
|
+
[Path in R]:
|
|
540
|
+
| BaseRouteValue
|
|
541
|
+
| Handler<BunRequest<Path>, Server<WebSocketData>, Response>
|
|
542
|
+
| Partial<Record<HTTPMethod, Handler<BunRequest<Path>, Server<WebSocketData>, Response>>>;
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
type RoutesWithUpgrade<WebSocketData, R extends string> = {
|
|
546
|
+
[Path in R]:
|
|
547
|
+
| BaseRouteValue
|
|
548
|
+
| Handler<BunRequest<Path>, Server<WebSocketData>, Response | undefined | void>
|
|
549
|
+
| Partial<Record<HTTPMethod, Handler<BunRequest<Path>, Server<WebSocketData>, Response | undefined | void>>>;
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
type FetchOrRoutes<WebSocketData, R extends string> =
|
|
553
|
+
| {
|
|
554
|
+
/**
|
|
555
|
+
* Handle HTTP requests
|
|
556
|
+
*
|
|
557
|
+
* Respond to {@link Request} objects with a {@link Response} object.
|
|
558
|
+
*/
|
|
559
|
+
fetch?(this: Server<WebSocketData>, req: Request, server: Server<WebSocketData>): MaybePromise<Response>;
|
|
560
|
+
|
|
561
|
+
routes: Routes<WebSocketData, R>;
|
|
562
|
+
}
|
|
563
|
+
| {
|
|
564
|
+
/**
|
|
565
|
+
* Handle HTTP requests
|
|
566
|
+
*
|
|
567
|
+
* Respond to {@link Request} objects with a {@link Response} object.
|
|
568
|
+
*/
|
|
569
|
+
fetch(this: Server<WebSocketData>, req: Request, server: Server<WebSocketData>): MaybePromise<Response>;
|
|
570
|
+
|
|
571
|
+
routes?: Routes<WebSocketData, R>;
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
type FetchOrRoutesWithWebSocket<WebSocketData, R extends string> = {
|
|
575
|
+
/**
|
|
576
|
+
* Enable websockets with {@link Bun.serve}
|
|
577
|
+
*
|
|
578
|
+
* Upgrade a {@link Request} to a {@link ServerWebSocket} via {@link Server.upgrade}
|
|
579
|
+
*
|
|
580
|
+
* Pass `data` in {@link Server.upgrade} to attach data to the {@link ServerWebSocket.data} property
|
|
581
|
+
*
|
|
582
|
+
* @example
|
|
583
|
+
* ```js
|
|
584
|
+
* const server: Bun.Server = Bun.serve({
|
|
585
|
+
* websocket: {
|
|
586
|
+
* open: (ws) => {
|
|
587
|
+
* console.log("Client connected");
|
|
588
|
+
* },
|
|
589
|
+
* message: (ws, message) => {
|
|
590
|
+
* console.log("Client sent message", message);
|
|
591
|
+
* },
|
|
592
|
+
* close: (ws) => {
|
|
593
|
+
* console.log("Client disconnected");
|
|
594
|
+
* },
|
|
595
|
+
* },
|
|
596
|
+
* fetch(req, server) {
|
|
597
|
+
* const url = new URL(req.url);
|
|
598
|
+
* if (url.pathname === "/chat") {
|
|
599
|
+
* const upgraded = server.upgrade(req);
|
|
600
|
+
* if (!upgraded) {
|
|
601
|
+
* return new Response("Upgrade failed", { status: 400 });
|
|
602
|
+
* }
|
|
603
|
+
* }
|
|
604
|
+
* return new Response("Hello World");
|
|
605
|
+
* },
|
|
606
|
+
* });
|
|
607
|
+
* ```
|
|
608
|
+
*/
|
|
609
|
+
websocket: WebSocketHandler<WebSocketData>;
|
|
610
|
+
} & (
|
|
611
|
+
| {
|
|
612
|
+
/**
|
|
613
|
+
* Handle HTTP requests, or call {@link Server.upgrade} and return early
|
|
614
|
+
*
|
|
615
|
+
* Respond to {@link Request} objects with a {@link Response} object.
|
|
616
|
+
*/
|
|
617
|
+
fetch?(
|
|
618
|
+
this: Server<WebSocketData>,
|
|
619
|
+
req: Request,
|
|
620
|
+
server: Server<WebSocketData>,
|
|
621
|
+
): MaybePromise<Response | void | undefined>;
|
|
622
|
+
|
|
623
|
+
routes: RoutesWithUpgrade<WebSocketData, R>;
|
|
624
|
+
}
|
|
625
|
+
| {
|
|
626
|
+
/**
|
|
627
|
+
* Handle HTTP requests, or call {@link Server.upgrade} and return early
|
|
628
|
+
*
|
|
629
|
+
* Respond to {@link Request} objects with a {@link Response} object.
|
|
630
|
+
*/
|
|
631
|
+
fetch(
|
|
632
|
+
this: Server<WebSocketData>,
|
|
633
|
+
req: Request,
|
|
634
|
+
server: Server<WebSocketData>,
|
|
635
|
+
): MaybePromise<Response | void | undefined>;
|
|
636
|
+
|
|
637
|
+
routes?: RoutesWithUpgrade<WebSocketData, R>;
|
|
638
|
+
}
|
|
639
|
+
);
|
|
640
|
+
|
|
641
|
+
interface BaseServeOptions<WebSocketData> {
|
|
642
|
+
/**
|
|
643
|
+
* Set options for using TLS with this server
|
|
644
|
+
*
|
|
645
|
+
* @example
|
|
646
|
+
* ```ts
|
|
647
|
+
* const server = Bun.serve({
|
|
648
|
+
* fetch: request => new Response("Welcome to Bun!"),
|
|
649
|
+
* tls: {
|
|
650
|
+
* cert: Bun.file("cert.pem"),
|
|
651
|
+
* key: Bun.file("key.pem"),
|
|
652
|
+
* ca: [Bun.file("ca1.pem"), Bun.file("ca2.pem")],
|
|
653
|
+
* },
|
|
654
|
+
* });
|
|
655
|
+
* ```
|
|
656
|
+
*/
|
|
657
|
+
tls?: TLSOptions | TLSOptions[];
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* What is the maximum size of a request body? (in bytes)
|
|
661
|
+
* @default 1024 * 1024 * 128 // 128MB
|
|
662
|
+
*/
|
|
663
|
+
maxRequestBodySize?: number;
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Render contextual errors? This enables bun's error page
|
|
667
|
+
* @default process.env.NODE_ENV !== 'production'
|
|
668
|
+
*/
|
|
669
|
+
development?: Development;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Callback called when an error is thrown during request handling
|
|
673
|
+
* @param error The error that was thrown
|
|
674
|
+
* @returns A response to send to the client
|
|
675
|
+
*
|
|
676
|
+
* @example
|
|
677
|
+
* ```ts
|
|
678
|
+
* error: (error) => {
|
|
679
|
+
* return new Response("Internal Server Error", { status: 500 });
|
|
680
|
+
* }
|
|
681
|
+
* ```
|
|
682
|
+
*/
|
|
683
|
+
error?: (this: Server<WebSocketData>, error: ErrorLike) => Response | Promise<Response> | void | Promise<void>;
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* Uniquely identify a server instance with an ID
|
|
687
|
+
*
|
|
688
|
+
* ---
|
|
689
|
+
*
|
|
690
|
+
* **When bun is started with the `--hot` flag**:
|
|
691
|
+
*
|
|
692
|
+
* This string will be used to hot reload the server without interrupting
|
|
693
|
+
* pending requests or websockets. If not provided, a value will be
|
|
694
|
+
* generated. To disable hot reloading, set this value to `null`.
|
|
695
|
+
*
|
|
696
|
+
* **When bun is not started with the `--hot` flag**:
|
|
697
|
+
*
|
|
698
|
+
* This string will currently do nothing. But in the future it could be useful for logs or metrics.
|
|
699
|
+
*/
|
|
700
|
+
id?: string | null;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
interface HostnamePortServeOptions<WebSocketData> extends BaseServeOptions<WebSocketData> {
|
|
704
|
+
/**
|
|
705
|
+
* What hostname should the server listen on?
|
|
706
|
+
*
|
|
707
|
+
* @default
|
|
708
|
+
* ```js
|
|
709
|
+
* "0.0.0.0" // listen on all interfaces
|
|
710
|
+
* ```
|
|
711
|
+
* @example
|
|
712
|
+
* ```js
|
|
713
|
+
* "127.0.0.1" // Only listen locally
|
|
714
|
+
* ```
|
|
715
|
+
* @example
|
|
716
|
+
* ```js
|
|
717
|
+
* "remix.run" // Only listen on remix.run
|
|
718
|
+
* ````
|
|
719
|
+
*
|
|
720
|
+
* note: hostname should not include a {@link port}
|
|
721
|
+
*/
|
|
722
|
+
hostname?: "0.0.0.0" | "127.0.0.1" | "localhost" | (string & {});
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* What port should the server listen on?
|
|
726
|
+
* @default process.env.PORT || "3000"
|
|
727
|
+
*/
|
|
728
|
+
port?: string | number;
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Whether the `SO_REUSEPORT` flag should be set.
|
|
732
|
+
*
|
|
733
|
+
* This allows multiple processes to bind to the same port, which is useful for load balancing.
|
|
734
|
+
*
|
|
735
|
+
* @default false
|
|
736
|
+
*/
|
|
737
|
+
reusePort?: boolean;
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Whether the `IPV6_V6ONLY` flag should be set.
|
|
741
|
+
* @default false
|
|
742
|
+
*/
|
|
743
|
+
ipv6Only?: boolean;
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* Sets the the number of seconds to wait before timing out a connection
|
|
747
|
+
* due to inactivity.
|
|
748
|
+
*
|
|
749
|
+
* @default 10
|
|
750
|
+
*/
|
|
751
|
+
idleTimeout?: number;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
interface UnixServeOptions<WebSocketData> extends BaseServeOptions<WebSocketData> {
|
|
755
|
+
/**
|
|
756
|
+
* If set, the HTTP server will listen on a unix socket instead of a port.
|
|
757
|
+
* (Cannot be used with hostname+port)
|
|
758
|
+
*/
|
|
759
|
+
unix?: string;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* The type of options that can be passed to {@link serve}, with support for
|
|
764
|
+
* `routes` and a safer requirement for `fetch`
|
|
765
|
+
*
|
|
766
|
+
* @example
|
|
767
|
+
* ```ts
|
|
768
|
+
* export default {
|
|
769
|
+
* fetch: req => Response.json(req.url),
|
|
770
|
+
*
|
|
771
|
+
* websocket: {
|
|
772
|
+
* message(ws) {
|
|
773
|
+
* ws.data.name; // string
|
|
774
|
+
* },
|
|
775
|
+
* },
|
|
776
|
+
* } satisfies Bun.Serve.Options<{ name: string }>;
|
|
777
|
+
* ```
|
|
778
|
+
*/
|
|
779
|
+
type Options<WebSocketData, R extends string = never> = Bun.__internal.XOR<
|
|
780
|
+
HostnamePortServeOptions<WebSocketData>,
|
|
781
|
+
UnixServeOptions<WebSocketData>
|
|
782
|
+
> &
|
|
783
|
+
Bun.__internal.XOR<FetchOrRoutes<WebSocketData, R>, FetchOrRoutesWithWebSocket<WebSocketData, R>>;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
interface BunRequest<T extends string = string> extends Request {
|
|
787
|
+
readonly params: {
|
|
788
|
+
[Key in keyof Serve.ExtractRouteParams<T>]: Serve.ExtractRouteParams<T>[Key];
|
|
789
|
+
} & {};
|
|
790
|
+
readonly cookies: CookieMap;
|
|
791
|
+
clone(): BunRequest<T>;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* HTTP & HTTPS Server
|
|
796
|
+
*
|
|
797
|
+
* To start the server, see {@link serve}
|
|
798
|
+
*
|
|
799
|
+
* For performance, Bun pre-allocates most of the data for 2048 concurrent requests.
|
|
800
|
+
* That means starting a new server allocates about 500 KB of memory. Try to
|
|
801
|
+
* avoid starting and stopping the server often (unless it's a new instance of bun).
|
|
802
|
+
*
|
|
803
|
+
* Powered by a fork of [uWebSockets](https://github.com/uNetworking/uWebSockets). Thank you \@alexhultman.
|
|
804
|
+
*/
|
|
805
|
+
interface Server<WebSocketData> extends Disposable {
|
|
806
|
+
/**
|
|
807
|
+
* Stop listening to prevent new connections from being accepted.
|
|
808
|
+
*
|
|
809
|
+
* By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops.
|
|
810
|
+
*
|
|
811
|
+
* @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections.
|
|
812
|
+
* @default false
|
|
813
|
+
*/
|
|
814
|
+
stop(closeActiveConnections?: boolean): Promise<void>;
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Update the `fetch` and `error` handlers without restarting the server.
|
|
818
|
+
*
|
|
819
|
+
* This is useful if you want to change the behavior of your server without
|
|
820
|
+
* restarting it or for hot reloading.
|
|
821
|
+
*
|
|
822
|
+
* @example
|
|
823
|
+
*
|
|
824
|
+
* ```js
|
|
825
|
+
* // create the server
|
|
826
|
+
* const server = Bun.serve({
|
|
827
|
+
* fetch(request) {
|
|
828
|
+
* return new Response("Hello World v1")
|
|
829
|
+
* }
|
|
830
|
+
* });
|
|
831
|
+
*
|
|
832
|
+
* // Update the server to return a different response
|
|
833
|
+
* server.reload({
|
|
834
|
+
* fetch(request) {
|
|
835
|
+
* return new Response("Hello World v2")
|
|
836
|
+
* }
|
|
837
|
+
* });
|
|
838
|
+
* ```
|
|
839
|
+
*
|
|
840
|
+
* Passing other options such as `port` or `hostname` won't do anything.
|
|
841
|
+
*/
|
|
842
|
+
reload<R extends string>(options: Serve.Options<WebSocketData, R>): Server<WebSocketData>;
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Mock the fetch handler for a running server.
|
|
846
|
+
*
|
|
847
|
+
* This feature is not fully implemented yet. It doesn't normalize URLs
|
|
848
|
+
* consistently in all cases and it doesn't yet call the `error` handler
|
|
849
|
+
* consistently. This needs to be fixed
|
|
850
|
+
*/
|
|
851
|
+
fetch(request: Request | string): Response | Promise<Response>;
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* Upgrade a {@link Request} to a {@link ServerWebSocket}
|
|
855
|
+
*
|
|
856
|
+
* @param request The {@link Request} to upgrade
|
|
857
|
+
* @param options Pass headers or attach data to the {@link ServerWebSocket}
|
|
858
|
+
*
|
|
859
|
+
* @returns `true` if the upgrade was successful and `false` if it failed
|
|
860
|
+
*
|
|
861
|
+
* @example
|
|
862
|
+
* ```js
|
|
863
|
+
* import { serve } from "bun";
|
|
864
|
+
* const server: Bun.Server<{ user: string }> = serve({
|
|
865
|
+
* websocket: {
|
|
866
|
+
* open: (ws) => {
|
|
867
|
+
* console.log("Client connected");
|
|
868
|
+
* },
|
|
869
|
+
* message: (ws, message) => {
|
|
870
|
+
* console.log("Client sent message", message);
|
|
871
|
+
* },
|
|
872
|
+
* close: (ws) => {
|
|
873
|
+
* console.log("Client disconnected");
|
|
874
|
+
* },
|
|
875
|
+
* },
|
|
876
|
+
* fetch(req, server) {
|
|
877
|
+
* const url = new URL(req.url);
|
|
878
|
+
* if (url.pathname === "/chat") {
|
|
879
|
+
* const upgraded = server.upgrade(req, {
|
|
880
|
+
* data: {user: "John Doe"}
|
|
881
|
+
* });
|
|
882
|
+
* if (!upgraded) {
|
|
883
|
+
* return new Response("Upgrade failed", { status: 400 });
|
|
884
|
+
* }
|
|
885
|
+
* }
|
|
886
|
+
* return new Response("Hello World");
|
|
887
|
+
* },
|
|
888
|
+
* });
|
|
889
|
+
* ```
|
|
890
|
+
*
|
|
891
|
+
* What you pass to `data` is available on the {@link ServerWebSocket.data} property
|
|
892
|
+
*/
|
|
893
|
+
upgrade(
|
|
894
|
+
request: Request,
|
|
895
|
+
...options: [WebSocketData] extends [undefined]
|
|
896
|
+
? [
|
|
897
|
+
options?: {
|
|
898
|
+
/**
|
|
899
|
+
*/
|
|
900
|
+
headers?: HeadersInit;
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* Data to store on the WebSocket instance
|
|
904
|
+
*
|
|
905
|
+
* ---
|
|
906
|
+
*
|
|
907
|
+
* **Surprised this line is erroring?**
|
|
908
|
+
*
|
|
909
|
+
* Tell TypeScript about the WebSocket data by using `Bun.Server<MyWebSocketData>`
|
|
910
|
+
*
|
|
911
|
+
* ```ts
|
|
912
|
+
* const server: Bun.Server<MyWebSocketData> = Bun.serve({
|
|
913
|
+
* fetch: (req, server) => {
|
|
914
|
+
* const didUpgrade = server.upgrade(req, {
|
|
915
|
+
* data: { ... }, // Works now!
|
|
916
|
+
* });
|
|
917
|
+
* },
|
|
918
|
+
* });
|
|
919
|
+
* ```
|
|
920
|
+
*/
|
|
921
|
+
data?: undefined;
|
|
922
|
+
},
|
|
923
|
+
]
|
|
924
|
+
: [
|
|
925
|
+
options: {
|
|
926
|
+
/**
|
|
927
|
+
* Send any additional headers while upgrading, like cookies
|
|
928
|
+
*/
|
|
929
|
+
headers?: HeadersInit;
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Data to store on the WebSocket instance
|
|
933
|
+
*/
|
|
934
|
+
data: WebSocketData;
|
|
935
|
+
},
|
|
936
|
+
]
|
|
937
|
+
): boolean;
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Send a message to all connected {@link ServerWebSocket} subscribed to a topic
|
|
941
|
+
*
|
|
942
|
+
* @param topic The topic to publish to
|
|
943
|
+
* @param data The data to send
|
|
944
|
+
* @param compress Should the data be compressed? Ignored if the client does not support compression.
|
|
945
|
+
*
|
|
946
|
+
* @returns 0 if the message was dropped, -1 if backpressure was applied, or the number of bytes sent.
|
|
947
|
+
*
|
|
948
|
+
* @example
|
|
949
|
+
*
|
|
950
|
+
* ```js
|
|
951
|
+
* server.publish("chat", "Hello World");
|
|
952
|
+
* ```
|
|
953
|
+
*
|
|
954
|
+
* @example
|
|
955
|
+
* ```js
|
|
956
|
+
* server.publish("chat", new Uint8Array([1, 2, 3, 4]));
|
|
957
|
+
* ```
|
|
958
|
+
*
|
|
959
|
+
* @example
|
|
960
|
+
* ```js
|
|
961
|
+
* server.publish("chat", new ArrayBuffer(4), true);
|
|
962
|
+
* ```
|
|
963
|
+
*
|
|
964
|
+
* @example
|
|
965
|
+
* ```js
|
|
966
|
+
* server.publish("chat", new DataView(new ArrayBuffer(4)));
|
|
967
|
+
* ```
|
|
968
|
+
*/
|
|
969
|
+
publish(
|
|
970
|
+
topic: string,
|
|
971
|
+
data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
|
|
972
|
+
compress?: boolean,
|
|
973
|
+
): ServerWebSocketSendStatus;
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
* A count of connections subscribed to a given topic
|
|
977
|
+
*
|
|
978
|
+
* This operation will loop through each topic internally to get the count.
|
|
979
|
+
*
|
|
980
|
+
* @param topic the websocket topic to check how many subscribers are connected to
|
|
981
|
+
* @returns the number of subscribers
|
|
982
|
+
*/
|
|
983
|
+
subscriberCount(topic: string): number;
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null.
|
|
987
|
+
*
|
|
988
|
+
* @example
|
|
989
|
+
* ```js
|
|
990
|
+
* export default {
|
|
991
|
+
* async fetch(request, server) {
|
|
992
|
+
* return new Response(server.requestIP(request));
|
|
993
|
+
* }
|
|
994
|
+
* }
|
|
995
|
+
* ```
|
|
996
|
+
*/
|
|
997
|
+
requestIP(request: Request): SocketAddress | null;
|
|
998
|
+
|
|
999
|
+
/**
|
|
1000
|
+
* Reset the idleTimeout of the given Request to the number in seconds. 0 means no timeout.
|
|
1001
|
+
*
|
|
1002
|
+
* @example
|
|
1003
|
+
* ```js
|
|
1004
|
+
* export default {
|
|
1005
|
+
* async fetch(request, server) {
|
|
1006
|
+
* server.timeout(request, 60);
|
|
1007
|
+
* await Bun.sleep(30000);
|
|
1008
|
+
* return new Response("30 seconds have passed");
|
|
1009
|
+
* }
|
|
1010
|
+
* }
|
|
1011
|
+
* ```
|
|
1012
|
+
*/
|
|
1013
|
+
timeout(request: Request, seconds: number): void;
|
|
1014
|
+
|
|
1015
|
+
/**
|
|
1016
|
+
* Undo a call to {@link Server.unref}
|
|
1017
|
+
*
|
|
1018
|
+
* If the Server has already been stopped, this does nothing.
|
|
1019
|
+
*
|
|
1020
|
+
* If {@link Server.ref} is called multiple times, this does nothing. Think of it as a boolean toggle.
|
|
1021
|
+
*/
|
|
1022
|
+
ref(): void;
|
|
1023
|
+
|
|
1024
|
+
/**
|
|
1025
|
+
* Don't keep the process alive if this server is the only thing left.
|
|
1026
|
+
* Active connections may continue to keep the process alive.
|
|
1027
|
+
*
|
|
1028
|
+
* By default, the server is ref'd.
|
|
1029
|
+
*
|
|
1030
|
+
* To prevent new connections from being accepted, use {@link Server.stop}
|
|
1031
|
+
*/
|
|
1032
|
+
unref(): void;
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* How many requests are in-flight right now?
|
|
1036
|
+
*/
|
|
1037
|
+
readonly pendingRequests: number;
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* How many {@link ServerWebSocket}s are in-flight right now?
|
|
1041
|
+
*/
|
|
1042
|
+
readonly pendingWebSockets: number;
|
|
1043
|
+
|
|
1044
|
+
readonly url: URL;
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* The port the server is listening on.
|
|
1048
|
+
*
|
|
1049
|
+
* This will be undefined when the server is listening on a unix socket.
|
|
1050
|
+
*
|
|
1051
|
+
* @example
|
|
1052
|
+
* ```js
|
|
1053
|
+
* 3000
|
|
1054
|
+
* ```
|
|
1055
|
+
*/
|
|
1056
|
+
readonly port: number | undefined;
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* The hostname the server is listening on. Does not include the port.
|
|
1060
|
+
*
|
|
1061
|
+
* This will be `undefined` when the server is listening on a unix socket.
|
|
1062
|
+
*
|
|
1063
|
+
* @example
|
|
1064
|
+
* ```js
|
|
1065
|
+
* "localhost"
|
|
1066
|
+
* ```
|
|
1067
|
+
*/
|
|
1068
|
+
readonly hostname: string | undefined;
|
|
1069
|
+
|
|
1070
|
+
/**
|
|
1071
|
+
* Is the server running in development mode?
|
|
1072
|
+
*
|
|
1073
|
+
* In development mode, `Bun.serve()` returns rendered error messages with
|
|
1074
|
+
* stack traces instead of a generic 500 error. This makes debugging easier,
|
|
1075
|
+
* but development mode shouldn't be used in production or you will risk
|
|
1076
|
+
* leaking sensitive information.
|
|
1077
|
+
*/
|
|
1078
|
+
readonly development: boolean;
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* An identifier of the server instance
|
|
1082
|
+
*
|
|
1083
|
+
* When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets.
|
|
1084
|
+
*
|
|
1085
|
+
* When bun is not started with the `--hot` flag, this ID is currently unused.
|
|
1086
|
+
*/
|
|
1087
|
+
readonly id: string;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* Bun.serve provides a high-performance HTTP server with built-in routing support.
|
|
1092
|
+
* It enables both function-based and object-based route handlers with type-safe
|
|
1093
|
+
* parameters and method-specific handling.
|
|
1094
|
+
*
|
|
1095
|
+
* @param options Server configuration options
|
|
1096
|
+
*
|
|
1097
|
+
* @example
|
|
1098
|
+
* **Basic Usage**
|
|
1099
|
+
*
|
|
1100
|
+
* ```ts
|
|
1101
|
+
* Bun.serve({
|
|
1102
|
+
* port: 3000,
|
|
1103
|
+
* fetch(req) {
|
|
1104
|
+
* return new Response("Hello World");
|
|
1105
|
+
* }
|
|
1106
|
+
* });
|
|
1107
|
+
* ```
|
|
1108
|
+
*
|
|
1109
|
+
* @example
|
|
1110
|
+
* **Route-based Handlers**
|
|
1111
|
+
*
|
|
1112
|
+
* ```ts
|
|
1113
|
+
* Bun.serve({
|
|
1114
|
+
* routes: {
|
|
1115
|
+
* // Static responses
|
|
1116
|
+
* "/": new Response("Home page"),
|
|
1117
|
+
*
|
|
1118
|
+
* // Function handlers with type-safe parameters
|
|
1119
|
+
* "/users/:id": (req) => {
|
|
1120
|
+
* // req.params.id is typed as string
|
|
1121
|
+
* return new Response(`User ${req.params.id}`);
|
|
1122
|
+
* },
|
|
1123
|
+
*
|
|
1124
|
+
* // Method-specific handlers
|
|
1125
|
+
* "/api/posts": {
|
|
1126
|
+
* GET: () => new Response("Get posts"),
|
|
1127
|
+
* POST: async (req) => {
|
|
1128
|
+
* const body = await req.json();
|
|
1129
|
+
* return new Response("Created post");
|
|
1130
|
+
* },
|
|
1131
|
+
* DELETE: (req) => new Response("Deleted post")
|
|
1132
|
+
* },
|
|
1133
|
+
*
|
|
1134
|
+
* // Wildcard routes
|
|
1135
|
+
* "/static/*": (req) => {
|
|
1136
|
+
* // Handle any path under /static/
|
|
1137
|
+
* return new Response("Static file");
|
|
1138
|
+
* },
|
|
1139
|
+
*
|
|
1140
|
+
* // Disable route (fall through to fetch handler)
|
|
1141
|
+
* "/api/legacy": false
|
|
1142
|
+
* },
|
|
1143
|
+
*
|
|
1144
|
+
* // Fallback handler for unmatched routes
|
|
1145
|
+
* fetch(req) {
|
|
1146
|
+
* return new Response("Not Found", { status: 404 });
|
|
1147
|
+
* }
|
|
1148
|
+
* });
|
|
1149
|
+
* ```
|
|
1150
|
+
*
|
|
1151
|
+
* @example
|
|
1152
|
+
* **Path Parameters**
|
|
1153
|
+
*
|
|
1154
|
+
* ```ts
|
|
1155
|
+
* Bun.serve({
|
|
1156
|
+
* routes: {
|
|
1157
|
+
* // Single parameter
|
|
1158
|
+
* "/users/:id": (req: BunRequest<"/users/:id">) => {
|
|
1159
|
+
* return new Response(`User ID: ${req.params.id}`);
|
|
1160
|
+
* },
|
|
1161
|
+
*
|
|
1162
|
+
* // Multiple parameters
|
|
1163
|
+
* "/posts/:postId/comments/:commentId": (
|
|
1164
|
+
* req: BunRequest<"/posts/:postId/comments/:commentId">
|
|
1165
|
+
* ) => {
|
|
1166
|
+
* return new Response(JSON.stringify(req.params));
|
|
1167
|
+
* // Output: {"postId": "123", "commentId": "456"}
|
|
1168
|
+
* }
|
|
1169
|
+
* }
|
|
1170
|
+
* });
|
|
1171
|
+
* ```
|
|
1172
|
+
*
|
|
1173
|
+
* @example
|
|
1174
|
+
* **Route Precedence**
|
|
1175
|
+
*
|
|
1176
|
+
* ```ts
|
|
1177
|
+
* // Routes are matched in the following order:
|
|
1178
|
+
* // 1. Exact static routes ("/about")
|
|
1179
|
+
* // 2. Parameter routes ("/users/:id")
|
|
1180
|
+
* // 3. Wildcard routes ("/api/*")
|
|
1181
|
+
*
|
|
1182
|
+
* Bun.serve({
|
|
1183
|
+
* routes: {
|
|
1184
|
+
* "/api/users": () => new Response("Users list"),
|
|
1185
|
+
* "/api/users/:id": (req) => new Response(`User ${req.params.id}`),
|
|
1186
|
+
* "/api/*": () => new Response("API catchall"),
|
|
1187
|
+
* "/*": () => new Response("Root catchall")
|
|
1188
|
+
* }
|
|
1189
|
+
* });
|
|
1190
|
+
* ```
|
|
1191
|
+
*
|
|
1192
|
+
* @example
|
|
1193
|
+
* **Error Handling**
|
|
1194
|
+
*
|
|
1195
|
+
* ```ts
|
|
1196
|
+
* Bun.serve({
|
|
1197
|
+
* routes: {
|
|
1198
|
+
* "/error": () => {
|
|
1199
|
+
* throw new Error("Something went wrong");
|
|
1200
|
+
* }
|
|
1201
|
+
* },
|
|
1202
|
+
* error(error) {
|
|
1203
|
+
* // Custom error handler
|
|
1204
|
+
* console.error(error);
|
|
1205
|
+
* return new Response(`Error: ${error.message}`, {
|
|
1206
|
+
* status: 500
|
|
1207
|
+
* });
|
|
1208
|
+
* }
|
|
1209
|
+
* });
|
|
1210
|
+
* ```
|
|
1211
|
+
*
|
|
1212
|
+
* @example
|
|
1213
|
+
* **Server Lifecycle**
|
|
1214
|
+
*
|
|
1215
|
+
* ```ts
|
|
1216
|
+
* const server = Bun.serve({
|
|
1217
|
+
* // Server config...
|
|
1218
|
+
* });
|
|
1219
|
+
*
|
|
1220
|
+
* // Update routes at runtime
|
|
1221
|
+
* server.reload({
|
|
1222
|
+
* routes: {
|
|
1223
|
+
* "/": () => new Response("Updated route")
|
|
1224
|
+
* }
|
|
1225
|
+
* });
|
|
1226
|
+
*
|
|
1227
|
+
* // Stop the server
|
|
1228
|
+
* server.stop();
|
|
1229
|
+
* ```
|
|
1230
|
+
*
|
|
1231
|
+
* @example
|
|
1232
|
+
* **Development Mode**
|
|
1233
|
+
*
|
|
1234
|
+
* ```ts
|
|
1235
|
+
* Bun.serve({
|
|
1236
|
+
* development: true, // Enable hot reloading
|
|
1237
|
+
* routes: {
|
|
1238
|
+
* // Routes will auto-reload on changes
|
|
1239
|
+
* }
|
|
1240
|
+
* });
|
|
1241
|
+
* ```
|
|
1242
|
+
*
|
|
1243
|
+
* @example
|
|
1244
|
+
* **Type-Safe Request Handling**
|
|
1245
|
+
*
|
|
1246
|
+
* ```ts
|
|
1247
|
+
* type Post = {
|
|
1248
|
+
* id: string;
|
|
1249
|
+
* title: string;
|
|
1250
|
+
* };
|
|
1251
|
+
*
|
|
1252
|
+
* Bun.serve({
|
|
1253
|
+
* routes: {
|
|
1254
|
+
* "/api/posts/:id": async (
|
|
1255
|
+
* req: BunRequest<"/api/posts/:id">
|
|
1256
|
+
* ) => {
|
|
1257
|
+
* if (req.method === "POST") {
|
|
1258
|
+
* const body: Post = await req.json();
|
|
1259
|
+
* return Response.json(body);
|
|
1260
|
+
* }
|
|
1261
|
+
* return new Response("Method not allowed", {
|
|
1262
|
+
* status: 405
|
|
1263
|
+
* });
|
|
1264
|
+
* }
|
|
1265
|
+
* }
|
|
1266
|
+
* });
|
|
1267
|
+
* ```
|
|
1268
|
+
*/
|
|
1269
|
+
function serve<WebSocketData = undefined, R extends string = string>(
|
|
1270
|
+
options: Serve.Options<WebSocketData, R>,
|
|
1271
|
+
): Server<WebSocketData>;
|
|
1272
|
+
}
|