@krisanalfa/bunest-adapter 0.1.0 → 0.4.0

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/README.md CHANGED
@@ -2,6 +2,48 @@
2
2
 
3
3
  This project provides a native Bun adapter for NestJS, allowing developers to leverage the performance benefits of the Bun runtime while using the powerful features of the NestJS framework.
4
4
 
5
+ ## Table of Contents
6
+
7
+ - [Features](#features)
8
+ - [Native Bun adapter for NestJS](#native-bun-adapter-for-nestjs)
9
+ - [Full NestJS Feature Support](#full-nestjs-feature-support)
10
+ - [Controllers & HTTP Methods](#controllers--http-methods)
11
+ - [Middleware](#middleware)
12
+ - [Guards](#guards)
13
+ - [Interceptors](#interceptors)
14
+ - [Exception Filters](#exception-filters)
15
+ - [Validation](#validation)
16
+ - [File Uploads](#file-uploads)
17
+ - [Streaming Responses](#streaming-responses)
18
+ - [Server-Sent Events (SSE)](#server-sent-events-sse)
19
+ - [Versioning](#versioning)
20
+ - [CORS](#cors)
21
+ - [Cookies](#cookies)
22
+ - [Popular Express Middleware](#popular-express-middleware)
23
+ - [Bun File API Support](#bun-file-api-support)
24
+ - [BunFileInterceptor](#bunfileinterceptor)
25
+ - [WebSocket Support](#websocket-support)
26
+ - [Basic WebSocket Gateway](#basic-websocket-gateway)
27
+ - [WebSocket with Guards](#websocket-with-guards)
28
+ - [WebSocket with Pipes](#websocket-with-pipes)
29
+ - [WebSocket with Exception Filters](#websocket-with-exception-filters)
30
+ - [Broadcasting Messages](#broadcasting-messages)
31
+ - [Secure WebSocket (WSS)](#secure-websocket-wss)
32
+ - [Limitations](#limitations)
33
+ - [HTTPS](#https)
34
+ - [Code Quality](#code-quality)
35
+ - [Request / Response Objects](#request--response-objects)
36
+ - [BunRequest](#bunrequest)
37
+ - [BunResponse](#bunresponse)
38
+ - [Benchmark Results](#benchmark-results)
39
+ - [HTTP Benchmark](#http-benchmark)
40
+ - [WebSocket Benchmark](#websocket-benchmark)
41
+ - [Running HTTP Benchmark](#running-http-benchmark)
42
+ - [Running WebSocket Benchmark](#running-websocket-benchmark)
43
+ - [Contributing](#contributing)
44
+ - [Future Plans](#future-plans)
45
+ - [License](#license)
46
+
5
47
  ## Features
6
48
 
7
49
  ### Native Bun adapter for NestJS
@@ -334,6 +376,67 @@ class FilesController {
334
376
  }
335
377
  ```
336
378
 
379
+ #### Server-Sent Events (SSE)
380
+
381
+ Full support for [Server-Sent Events](https://docs.nestjs.com/techniques/server-sent-events) using the `@Sse()` decorator. SSE allows servers to push real-time updates to clients over HTTP:
382
+
383
+ ```ts
384
+ import { Controller, Sse, MessageEvent } from '@nestjs/common';
385
+ import { Observable, interval, map } from 'rxjs';
386
+
387
+ @Controller()
388
+ class EventsController {
389
+ @Sse('/sse')
390
+ sendEvents(): Observable<MessageEvent> {
391
+ return interval(1000).pipe(
392
+ map(num => ({
393
+ data: `SSE message ${num.toString()}`,
394
+ })),
395
+ );
396
+ }
397
+ }
398
+ ```
399
+
400
+ **Client Connection Example:**
401
+
402
+ ```ts
403
+ const eventSource = new EventSource('http://localhost:3000/sse');
404
+
405
+ eventSource.onopen = () => {
406
+ console.log('SSE connection opened');
407
+ };
408
+
409
+ eventSource.onmessage = (event) => {
410
+ console.log('Received:', event.data); // "SSE message 0", "SSE message 1", etc.
411
+ };
412
+
413
+ eventSource.onerror = (error) => {
414
+ console.error('SSE error:', error);
415
+ eventSource.close();
416
+ };
417
+
418
+ // Close the connection when done
419
+ // eventSource.close();
420
+ ```
421
+
422
+ **For HTTPS/Secure Connections:**
423
+
424
+ ```ts
425
+ import { EventSource } from 'eventsource'; // npm package for Node.js
426
+
427
+ const eventSource = new EventSource('https://localhost:3000/sse', {
428
+ fetch: (url, init) => fetch(url, {
429
+ ...init,
430
+ tls: { rejectUnauthorized: false }, // For self-signed certificates
431
+ }),
432
+ });
433
+
434
+ eventSource.onmessage = (event) => {
435
+ console.log('Received:', event.data);
436
+ };
437
+ ```
438
+
439
+
337
440
  #### Versioning
338
441
 
339
442
  Full API [versioning](https://docs.nestjs.com/techniques/versioning) support (URI, Header, Media Type, Custom):
@@ -442,6 +545,343 @@ Tested and working with:
442
545
  - `cors` - CORS handling
443
546
  - And most other Express-compatible middleware
444
547
 
548
+ ### WebSocket Support
549
+
550
+ The Bun adapter provides full WebSocket support using Bun's native WebSocket implementation. The `BunWsAdapter` enables real-time, bidirectional communication between clients and servers with excellent performance.
551
+
552
+ #### Basic WebSocket Gateway
553
+
554
+ Create WebSocket gateways using NestJS decorators:
555
+
556
+ ```ts
557
+ import { BunWsAdapter, BunAdapter } from "@krisanalfa/bunest-adapter";
558
+ import {
559
+ WebSocketGateway,
560
+ SubscribeMessage,
561
+ MessageBody,
562
+ OnGatewayConnection,
563
+ OnGatewayDisconnect,
564
+ ConnectedSocket,
565
+ } from "@nestjs/websockets";
566
+ import { ServerWebSocket } from "bun";
567
+
568
+ @WebSocketGateway({ cors: true })
569
+ class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
570
+ handleConnection(client: ServerWebSocket) {
571
+ client.send(JSON.stringify({ event: "welcome", data: "Welcome!" }));
572
+ }
573
+
574
+ handleDisconnect(client: ServerWebSocket) {
575
+ console.log("Client disconnected");
576
+ }
577
+
578
+ @SubscribeMessage("message")
579
+ handleMessage(@MessageBody() data: string) {
580
+ return {
581
+ event: "message",
582
+ data: `Received: ${data}`,
583
+ };
584
+ }
585
+ }
586
+
587
+ // Enable WebSocket support in your application
588
+ const app = await NestFactory.create(AppModule, new BunAdapter());
589
+ app.useWebSocketAdapter(new BunWsAdapter(app));
590
+ await app.listen(3000);
591
+ ```
592
+
593
+ Connect from the client:
594
+
595
+ ```ts
596
+ const socket = new WebSocket("ws://localhost:3000");
597
+
598
+ socket.onopen = () => {
599
+ socket.send(JSON.stringify({ event: "message", data: "Hello!" }));
600
+ };
601
+
602
+ socket.onmessage = (event) => {
603
+ const data = JSON.parse(event.data);
604
+ console.log(data); // { event: 'message', data: 'Received: Hello!' }
605
+ };
606
+ ```
607
+
608
+ #### WebSocket with Guards
609
+
610
+ Protect WebSocket endpoints with guards:
611
+
612
+ ```ts
613
+ import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
614
+ import { WsException } from "@nestjs/websockets";
615
+
616
+ @Injectable()
617
+ class WsAuthGuard implements CanActivate {
618
+ canActivate(context: ExecutionContext): boolean {
619
+ const data = context.switchToWs().getData<{ token?: string }>();
620
+
621
+ if (data.token !== "valid-token") {
622
+ throw new WsException("Unauthorized");
623
+ }
624
+
625
+ return true;
626
+ }
627
+ }
628
+
629
+ @WebSocketGateway()
630
+ @UseGuards(WsAuthGuard)
631
+ class ProtectedGateway {
632
+ @SubscribeMessage("protected")
633
+ handleProtected(@MessageBody() data: { message: string }) {
634
+ return {
635
+ event: "protected",
636
+ data: `Protected message: ${data.message}`,
637
+ };
638
+ }
639
+ }
640
+ ```
641
+
642
+ #### WebSocket with Pipes
643
+
644
+ Validate WebSocket messages using pipes:
645
+
646
+ ```ts
647
+ import { UsePipes, ValidationPipe } from "@nestjs/common";
648
+ import { IsString, IsNotEmpty, MinLength } from "class-validator";
649
+
650
+ class CreateMessageDto {
651
+ @IsString()
652
+ @IsNotEmpty()
653
+ @MinLength(3)
654
+ text!: string;
655
+ }
656
+
657
+ @WebSocketGateway()
658
+ @UsePipes(
659
+ new ValidationPipe({
660
+ exceptionFactory: (errors) => new WsException(errors),
661
+ }),
662
+ )
663
+ class ValidationGateway {
664
+ @SubscribeMessage("createMessage")
665
+ handleCreateMessage(@MessageBody() dto: CreateMessageDto) {
666
+ return {
667
+ event: "messageCreated",
668
+ data: dto.text,
669
+ };
670
+ }
671
+ }
672
+ ```
673
+
674
+ #### WebSocket with Exception Filters
675
+
676
+ Handle WebSocket exceptions with custom filters:
677
+
678
+ ```ts
679
+ import { Catch, ArgumentsHost, WsExceptionFilter } from "@nestjs/common";
680
+ import { WsException } from "@nestjs/websockets";
681
+ import { ServerWebSocket } from "bun";
682
+
683
+ @Catch(WsException)
684
+ class WsExceptionsFilter implements WsExceptionFilter {
685
+ catch(exception: WsException, host: ArgumentsHost) {
686
+ const client = host.switchToWs().getClient<ServerWebSocket>();
687
+ const error = exception.getError();
688
+ const details = typeof error === "object" ? error : { message: error };
689
+
690
+ client.send(
691
+ JSON.stringify({
692
+ event: "error",
693
+ data: {
694
+ message: "An error occurred",
695
+ details,
696
+ },
697
+ }),
698
+ );
699
+ }
700
+ }
701
+
702
+ @WebSocketGateway()
703
+ @UseFilters(WsExceptionsFilter)
704
+ class ErrorHandlingGateway {
705
+ @SubscribeMessage("risky")
706
+ handleRisky(@MessageBody() data: { shouldFail: boolean }) {
707
+ if (data.shouldFail) {
708
+ throw new WsException("Something went wrong");
709
+ }
710
+ return { event: "success", data: "OK" };
711
+ }
712
+ }
713
+ ```
714
+
715
+ #### Broadcasting Messages
716
+
717
+ Broadcast messages to all connected clients using Bun's publish/subscribe system:
718
+
719
+ ```ts
720
+ import {
721
+ WebSocketGateway,
722
+ WebSocketServer,
723
+ SubscribeMessage,
724
+ MessageBody,
725
+ ConnectedSocket,
726
+ OnGatewayConnection,
727
+ } from "@nestjs/websockets";
728
+ import { ServerWebSocket } from "bun";
729
+ import { BunPreflightHttpServer } from "@krisanalfa/bunest-adapter";
730
+
731
+ @Injectable() // Mandatory to be able to inject `BunPreflightHttpServer`
732
+ @WebSocketGateway()
733
+ class BroadcastGateway implements OnGatewayConnection {
734
+ @WebSocketServer()
735
+ server!: BunPreflightHttpServer; // Inject BunPreflightHttpServer
736
+
737
+ private readonly roomName = "global-room";
738
+
739
+ handleConnection(client: ServerWebSocket) {
740
+ // Subscribe client to room
741
+ client.subscribe(this.roomName);
742
+ }
743
+
744
+ @SubscribeMessage("broadcast")
745
+ handleBroadcast(
746
+ @MessageBody() message: string,
747
+ @ConnectedSocket() socket: ServerWebSocket,
748
+ ) {
749
+ // Get subscriber count
750
+ const count = this.server.getBunServer().subscriberCount(this.roomName);
751
+
752
+ // Publish to all subscribers in the room
753
+ socket.publishText(
754
+ this.roomName,
755
+ JSON.stringify({
756
+ event: "broadcast",
757
+ data: message,
758
+ subscribers: count,
759
+ }),
760
+ );
761
+ }
762
+ }
763
+ ```
764
+
765
+ **Key Features:**
766
+
767
+ - **Native Performance** - Uses Bun's native WebSocket implementation for maximum speed
768
+ - **NestJS Integration** - Full support for decorators, guards, pipes, and exception filters
769
+ - **Pub/Sub Support** - Built-in support for broadcasting messages to multiple clients
770
+ - **CORS Configuration** - Easy CORS setup for WebSocket connections
771
+ - **HTTP + WebSocket** - Run both HTTP and WebSocket servers on the same port
772
+
773
+ #### Secure WebSocket (WSS)
774
+
775
+ The Bun adapter supports secure WebSocket connections (WSS) using TLS/SSL certificates. You can configure WSS in two ways:
776
+
777
+ **Using BunAdapter constructor options:**
778
+
779
+ ```ts
780
+ import { BunAdapter, BunWsAdapter } from "@krisanalfa/bunest-adapter";
781
+ import { NestFactory } from "@nestjs/core";
782
+
783
+ const app = await NestFactory.create(
784
+ AppModule,
785
+ new BunAdapter({
786
+ tls: {
787
+ cert: Bun.file("/path/to/cert.pem"),
788
+ key: Bun.file("/path/to/key.pem"),
789
+ },
790
+ }),
791
+ );
792
+
793
+ app.useWebSocketAdapter(new BunWsAdapter(app));
794
+ await app.listen(3000);
795
+
796
+ // Clients connect using wss:// protocol
797
+ // const ws = new WebSocket('wss://localhost:3000');
798
+ ```
799
+
800
+ **Using NestFactory.create httpsOptions:**
801
+
802
+ ```ts
803
+ import { BunAdapter, BunWsAdapter } from "@krisanalfa/bunest-adapter";
804
+ import { NestFactory } from "@nestjs/core";
805
+
806
+ const app = await NestFactory.create(AppModule, new BunAdapter(), {
807
+ httpsOptions: {
808
+ cert: Bun.file("/path/to/cert.pem"),
809
+ key: Bun.file("/path/to/key.pem"),
810
+ },
811
+ });
812
+
813
+ app.useWebSocketAdapter(new BunWsAdapter(app));
814
+ await app.listen(3000);
815
+ ```
816
+
817
+ **Unix Socket Support with WSS:**
818
+
819
+ You can also run secure WebSocket servers over Unix sockets:
820
+
821
+ ```ts
822
+ import { BunAdapter, BunWsAdapter } from "@krisanalfa/bunest-adapter";
823
+ import { NestFactory } from "@nestjs/core";
824
+
825
+ const app = await NestFactory.create(
826
+ AppModule,
827
+ new BunAdapter({
828
+ tls: {
829
+ cert: Bun.file("/path/to/cert.pem"),
830
+ key: Bun.file("/path/to/key.pem"),
831
+ },
832
+ }),
833
+ );
834
+
835
+ app.useWebSocketAdapter(new BunWsAdapter(app));
836
+ await app.listen("/tmp/secure-nestjs.sock");
837
+
838
+ // Or use abstract namespace socket on Linux
839
+ await app.listen("\0secure-nestjs-socket");
840
+ ```
841
+
842
+ **Client Connection Example:**
843
+
844
+ ```ts
845
+ // For development with self-signed certificates
846
+ const ws = new WebSocket("wss://localhost:3000", {
847
+ tls: { rejectUnauthorized: false },
848
+ });
849
+
850
+ ws.onopen = () => {
851
+ console.log("Connected to secure WebSocket");
852
+ ws.send(JSON.stringify({ event: "message", data: "Hello WSS!" }));
853
+ };
854
+
855
+ ws.onmessage = (event) => {
856
+ const data = JSON.parse(event.data);
857
+ console.log("Received:", data);
858
+ };
859
+ ```
860
+
861
+ **Important Notes:**
862
+
863
+ - WSS automatically uses the same port as your HTTPS server
864
+ - The `wss://` protocol is used instead of `ws://` for secure connections
865
+ - For production, use properly signed certificates from a trusted Certificate Authority
866
+ - For development, you can use self-signed certificates with `rejectUnauthorized: false` on the client
867
+
868
+ #### Limitations
869
+
870
+ **Port Configuration:** The WebSocket server port will always be the same as the Bun HTTP server port. In standard NestJS, you can configure different ports via the `@WebSocketGateway` decorator's `port` option (see [NestJS WebSocket documentation](https://docs.nestjs.com/websockets/gateways#overview)), but with the Bun adapter, WebSocket connections must use the same port as your HTTP server. This is due to Bun's unified server architecture where HTTP and WebSocket upgrades are handled by the same server instance.
871
+
872
+ ```ts
873
+ // This port option is ignored with BunWsAdapter
874
+ @WebSocketGateway({ port: 8080 }) // ⚠️ Port option has no effect
875
+ class ChatGateway {
876
+ // Gateway will use the same port as app.listen()
877
+ }
878
+
879
+ // WebSocket will be available on the same port as HTTP
880
+ const app = await NestFactory.create(AppModule, new BunAdapter());
881
+ app.useWebSocketAdapter(new BunWsAdapter(app));
882
+ await app.listen(3000); // Both HTTP and WebSocket use port 3000
883
+ ```
884
+
445
885
  ### Bun File API Support
446
886
 
447
887
  This package provides first-class support for Bun's native [`BunFile`](https://bun.com/docs/runtime/file-io) API, enabling seamless file uploads and downloads using Bun's efficient file handling capabilities.
@@ -550,7 +990,7 @@ The Bun adapter is developed with high code quality standards, including:
550
990
  - Strict TypeScript typings
551
991
  - Strict linting rules (ESLint)
552
992
  - Comprehensive unit and integration tests
553
- - Coverage reports (>98% line coverage, >85% function coverage)
993
+ - Coverage reports (>97% line coverage, >85% function coverage)
554
994
 
555
995
  ## Request / Response Objects
556
996
 
@@ -853,38 +1293,102 @@ class HybridController {
853
1293
 
854
1294
  ## Benchmark Results
855
1295
 
856
- Tested on MacOS Sequoia (15.6.1), Apple M1 Max (64GB RAM), Bun 1.3.5, Node.js 20.10.0
1296
+ Tested on MacOS Sequoia (15.6.1), Apple M1 Max (64GB RAM), Bun 1.3.5, Node.js 20.10.0.
1297
+
1298
+ ### HTTP Benchmark
1299
+
1300
+ HTTP benchmarks run using [`oha`](https://github.com/hatoo/oha) tool with the following command:
1301
+
1302
+ ```
1303
+ oha -c 125 -n 1000000 --no-tui "http://127.0.0.1:3000/"
1304
+ ```
857
1305
 
858
1306
  | Configuration | Requests/sec | Compared to Pure Bun |
859
1307
  | --------------------------------------------------------------------------------- | -----------: | -------------------: |
860
1308
  | Pure Bun | 80,742.72 | 100.00% |
861
- | Nest + Bun + Native Bun Adapter | 69,665.59 | 86.32% |
1309
+ | Nest + Bun + Native Bun Adapter | 70,234.76 | 86.98% |
862
1310
  | Nest + Bun + Express Adapter | 43,375.97 | 53.72% |
863
1311
  | Nest + Bun + [Hono Adapter](https://www.npmjs.com/package/@kiyasov/platform-hono) | 19,194.78 | 23.77% |
864
1312
  | Nest + Node + Express | 14,019.88 | 17.36% |
865
1313
 
866
1314
  > **Pure Bun** is the fastest at **80,743 req/s**. **Nest + Bun + Native Bun Adapter** achieves **~86%** of Pure Bun's performance while providing full NestJS features, and is **~5x faster** than Nest + Node + Express. Compared to Bun with Express adapter, the native Bun adapter is **~1.6x faster**.
867
1315
 
868
- ### Running Benchmarks
1316
+ Bonus if you use Unix sockets:
1317
+ ```
1318
+ Summary:
1319
+ Success rate: 100.00%
1320
+ Total: 8298.2243 ms
1321
+ Slowest: 5.2326 ms
1322
+ Fastest: 0.2857 ms
1323
+ Average: 1.0361 ms
1324
+ Requests/sec: 120507.7092
1325
+
1326
+ Total data: 21.93 MiB
1327
+ Size/request: 23 B
1328
+ Size/sec: 2.64 MiB
1329
+ ```
1330
+
1331
+ As you can see, using Unix sockets boosts the performance further to **120,508 req/s**, which is **~1.5x faster** than TCP. Since Bun `fetch` supports Unix sockets, you can leverage this for inter-process communication on the same machine.
1332
+
1333
+ ### WebSocket Benchmark
1334
+
1335
+ WebSocket benchmarks run using the custom benchmark script in `benchmarks/ws.benchmark.ts`.
1336
+
1337
+ | Configuration | Messages/sec | Compared to Pure Bun |
1338
+ | ---------------------------------- | -----------: | -------------------: |
1339
+ | Pure Bun WebSocket | 817,594.60 | 100.00% |
1340
+ | Nest + Bun + BunWsAdapter | 764,962.70 | 93.56% |
1341
+ | Nest + Bun + WebSocketAdapter (ws) | 299,161.50 | 36.59% |
1342
+
1343
+ > **Pure Bun WebSocket** achieves **817,595 msg/s**. **Nest + Bun + BunWsAdapter** achieves **~94%** of Pure Bun's performance, and is **~2.6x faster** than using the standard WebSocketAdapter with `ws` library.
1344
+
1345
+ ### Running HTTP Benchmark
869
1346
 
870
1347
  This project includes benchmark configurations in the `benchmarks` directory.
871
- To run the specific server benchmark, you can use predefined scripts in `package.json`. For example:
1348
+ To run the specific HTTP server benchmark, you can use predefined scripts in `package.json`:
872
1349
 
873
1350
  ```bash
874
1351
  # Running native bun server benchmark
875
- bun run native
1352
+ bun run http:native
876
1353
 
877
1354
  # Running NestJS with Bun adapter benchmark
878
- bun run bun
1355
+ bun run http:bun
879
1356
 
880
1357
  # Running NestJS with Hono adapter benchmark
881
- bun run hono
1358
+ bun run http:hono
882
1359
 
883
1360
  # Running NestJS with Express adapter benchmark
884
- bun run express
1361
+ bun run http:express
885
1362
 
886
1363
  # Running NestJS with Node and Express benchmark
887
- bun run node
1364
+ bun run http:node
1365
+ ```
1366
+
1367
+ Then run the benchmark using [`oha`](https://github.com/hatoo/oha):
1368
+
1369
+ ```bash
1370
+ oha -c 125 -n 1000000 --no-tui "http://127.0.0.1:3000/"
1371
+ ```
1372
+
1373
+ ### Running WebSocket Benchmark
1374
+
1375
+ To run WebSocket benchmarks, first start the WebSocket server:
1376
+
1377
+ ```bash
1378
+ # Running native bun websocket benchmark
1379
+ bun run ws:native
1380
+
1381
+ # Running NestJS with BunWsAdapter websocket benchmark
1382
+ bun run ws:bun
1383
+
1384
+ # Running NestJS with WebSocketAdapter (ws) websocket benchmark
1385
+ bun run ws:ws
1386
+ ```
1387
+
1388
+ Then run the benchmark script:
1389
+
1390
+ ```bash
1391
+ bun benchmarks/ws.benchmark.ts
888
1392
  ```
889
1393
 
890
1394
  All benchmarks use port `3000` by default. You can adjust the port in the respective benchmark files if needed.
@@ -895,9 +1399,8 @@ Contributions are welcome! Please open issues or submit pull requests for bug fi
895
1399
 
896
1400
  ## Future Plans
897
1401
 
898
- - Support for WebSocket integration with Bun
899
1402
  - Enhanced trusted proxy configuration for host header handling
900
- - Additional performance optimizations and benchmarks
1403
+ - Improved documentation and examples
901
1404
  - Release automation via CI/CD pipelines
902
1405
 
903
1406
  ## License
@@ -1,58 +1,24 @@
1
1
  import { CorsOptions, CorsOptionsDelegate } from '@nestjs/common/interfaces/external/cors-options.interface.js';
2
2
  import { ErrorHandler, RequestHandler } from '@nestjs/common/interfaces/index.js';
3
3
  import { NestApplicationOptions, RequestMethod, VersioningOptions } from '@nestjs/common';
4
- import { Serve, Server } from 'bun';
4
+ import { Server } from 'bun';
5
5
  import { AbstractHttpAdapter } from '@nestjs/core';
6
6
  import { VersionValue } from '@nestjs/common/interfaces/version-options.interface.js';
7
+ import { BunWsClientData, ServerOptions } from './bun.internal.types.js';
8
+ import { BunPreflightHttpServer } from './bun.preflight-http-server.js';
7
9
  import { BunRequest } from './bun.request.js';
8
10
  import { BunResponse } from './bun.response.js';
11
+ import { BunServerInstance } from './bun.server-instance.js';
9
12
  export declare class BunAdapter extends AbstractHttpAdapter<Server<unknown>, BunRequest, BunResponse> {
10
- private bunServeOptions;
13
+ protected bunServeOptions: ServerOptions<BunWsClientData>;
11
14
  private readonly logger;
12
- private readonly middlewareEngine;
13
- private useVersioning;
14
- private readonly routes;
15
- private readonly routeHandlers;
16
- private notFoundHandler;
17
- constructor(bunServeOptions?: Pick<Serve.Options<unknown>, 'development' | 'maxRequestBodySize' | 'idleTimeout' | 'id' | 'tls'>);
18
- use(middleware: RequestHandler<BunRequest, BunResponse>): void;
19
- get(handler: RequestHandler<BunRequest, BunResponse>): void;
20
- get(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
21
- post(handler: RequestHandler<BunRequest, BunResponse>): void;
22
- post(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
23
- put(handler: RequestHandler<BunRequest, BunResponse>): void;
24
- put(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
25
- patch(handler: RequestHandler<BunRequest, BunResponse>): void;
26
- patch(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
27
- delete(handler: RequestHandler<BunRequest, BunResponse>): void;
28
- delete(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
29
- head(handler: RequestHandler<BunRequest, BunResponse>): void;
30
- head(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
31
- options(handler: RequestHandler<BunRequest, BunResponse>): void;
32
- options(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
33
- all(handler: RequestHandler<BunRequest, BunResponse>): void;
34
- all(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
35
- propfind(handler: RequestHandler<BunRequest, BunResponse>): void;
36
- propfind(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
37
- proppatch(handler: RequestHandler<BunRequest, BunResponse>): void;
38
- proppatch(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
39
- mkcol(handler: RequestHandler<BunRequest, BunResponse>): void;
40
- mkcol(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
41
- copy(handler: RequestHandler<BunRequest, BunResponse>): void;
42
- copy(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
43
- move(handler: RequestHandler<BunRequest, BunResponse>): void;
44
- move(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
45
- lock(handler: RequestHandler<BunRequest, BunResponse>): void;
46
- lock(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
47
- unlock(handler: RequestHandler<BunRequest, BunResponse>): void;
48
- unlock(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
49
- search(handler: RequestHandler<BunRequest, BunResponse>): void;
50
- search(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void;
15
+ protected instance: BunServerInstance;
16
+ constructor(bunServeOptions?: ServerOptions<BunWsClientData>);
51
17
  useStaticAssets(...args: unknown[]): void;
52
18
  setViewEngine(engine: string): void;
53
19
  render(response: unknown, view: string, options: unknown): void;
54
20
  close(): Promise<void>;
55
- initHttpServer(options: NestApplicationOptions): void;
21
+ initHttpServer(options: NestApplicationOptions): BunPreflightHttpServer;
56
22
  getRequestHostname(request: BunRequest): string;
57
23
  getRequestMethod(request: BunRequest): string;
58
24
  getRequestUrl(request: BunRequest): string;
@@ -84,10 +50,5 @@ export declare class BunAdapter extends AbstractHttpAdapter<Server<unknown>, Bun
84
50
  * @param callback Optional callback to invoke once the server is listening.
85
51
  */
86
52
  listen(port: string | number, hostname: string, callback?: () => void): void;
87
- private delegateRouteHandler;
88
- private createVersioningHandlers;
89
- private executeHandlerChain;
90
- private createChainedHandlerForVersioningResolution;
91
- private mapRequestMethodToString;
92
- private parseRouteHandler;
53
+ private configureTls;
93
54
  }
@@ -0,0 +1,22 @@
1
+ import { CorsOptionsDelegate, CorsOptions as NestCorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface.js';
2
+ import { Serve, Server, ServerWebSocket, WebSocketHandler } from 'bun';
3
+ import { BunRequest } from './bun.request.js';
4
+ export interface WsOptions extends Pick<WebSocketHandler<unknown>, 'maxPayloadLength' | 'idleTimeout' | 'backpressureLimit' | 'closeOnBackpressureLimit' | 'sendPings' | 'publishToSelf' | 'perMessageDeflate'> {
5
+ cors?: true | NestCorsOptions | CorsOptionsDelegate<BunRequest>;
6
+ clientDataFactory?: (req: BunRequest) => unknown;
7
+ }
8
+ export type ServerOptions<TWebSocketData = unknown> = Pick<Serve.Options<TWebSocketData>, 'development' | 'maxRequestBodySize' | 'idleTimeout' | 'id' | 'tls' | 'websocket' | 'port' | 'hostname'>;
9
+ export type WsData = string | Buffer | ArrayBuffer | Buffer[];
10
+ export interface WsHandlers {
11
+ onOpen: ((ws: ServerWebSocket<unknown>) => void) | undefined;
12
+ onMessage: ((ws: ServerWebSocket<unknown>, message: WsData, server: Server<unknown>) => void) | undefined;
13
+ onClose: ((ws: ServerWebSocket<unknown>, code: number, reason: string) => void) | undefined;
14
+ }
15
+ export interface BunWsClientData {
16
+ /** Called when a message is received - matches bun.adapter.ts onMessageInternal */
17
+ onMessageInternal?: (message: WsData) => void;
18
+ /** Called when the connection closes - matches bun.adapter.ts onCloseInternal */
19
+ onCloseInternal?: () => void;
20
+ /** Called by NestJS for disconnect handling */
21
+ onDisconnect?: (ws: ServerWebSocket<unknown>) => void;
22
+ }