@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.
@@ -0,0 +1,44 @@
1
+ import { Server, ServerWebSocket } from 'bun';
2
+ import { BaseWsInstance } from '@nestjs/websockets';
3
+ import { WsData, WsOptions } from './bun.internal.types.js';
4
+ import { BunServerInstance } from './bun.server-instance.js';
5
+ /**
6
+ * Bun HTTP server placeholder used before the actual server instance is created.
7
+ * This class provides compatibility methods expected by NestJS framework.
8
+ *
9
+ * There's limitation in Bun where we can't create the server instance without
10
+ * listening on a port right away. This placeholder allows us to defer
11
+ * the server creation until NestJS calls the listen method.
12
+ */
13
+ export declare class BunPreflightHttpServer implements BaseWsInstance {
14
+ private readonly serverInstance;
15
+ constructor(serverInstance: BunServerInstance);
16
+ on(event: string, callback: Function): void;
17
+ /**
18
+ * NestJS compatibility methods
19
+ * Nest use this to listen for "error" events during HTTP server initialization
20
+ */
21
+ once(): void;
22
+ /**
23
+ * NestJS compatibility methods
24
+ * Nest use this to remove "error" event listeners during HTTP server cleanup
25
+ */
26
+ removeListener(): void;
27
+ /**
28
+ * NestJS compatibility methods
29
+ */
30
+ stop(force?: boolean): Promise<void>;
31
+ address(): {
32
+ address: string;
33
+ port: number;
34
+ };
35
+ setWsOptions(options: WsOptions): void;
36
+ registerWsOpenHandler(handler: (ws: ServerWebSocket<unknown>) => void): void;
37
+ registerWsMessageHandler(handler: (ws: ServerWebSocket<unknown>, message: WsData, server: Server<unknown>) => void): void;
38
+ registerWsCloseHandler(handler: (ws: ServerWebSocket<unknown>, code: number, reason: string) => void): void;
39
+ getBunServer(): Server<unknown> | null;
40
+ /**
41
+ * Proxy method for WebSocket server close
42
+ */
43
+ close(): Promise<void>;
44
+ }
@@ -39,6 +39,9 @@ export declare class BunRequest {
39
39
  */
40
40
  get socket(): {
41
41
  encrypted: boolean;
42
+ setKeepAlive: () => void;
43
+ setNoDelay: () => void;
44
+ setTimeout: () => void;
42
45
  };
43
46
  /**
44
47
  * Gets the URL path and query string of the request.
@@ -235,7 +238,7 @@ export declare class BunRequest {
235
238
  * console.log(user); // { id: 1, name: 'John' }
236
239
  * ```
237
240
  */
238
- get(key: string): unknown;
241
+ get<T>(key: string): T | undefined;
239
242
  /**
240
243
  * Sets a custom setting/property in the request.
241
244
  * Useful for passing data between middleware and handlers.
@@ -358,5 +361,42 @@ export declare class BunRequest {
358
361
  * ```
359
362
  */
360
363
  clone(): BunRequest;
364
+ /**
365
+ * Stub method for Node.js EventEmitter compatibility.
366
+ * This is a no-op method provided for compatibility with Node.js HTTP request objects.
367
+ * Required for SSE and other streaming scenarios where NestJS listens for request events.
368
+ *
369
+ * @param event - The event name
370
+ * @param listener - The event listener function
371
+ * @returns This request object for chaining
372
+ */
373
+ on(event: string, listener: (...args: unknown[]) => void): this;
374
+ /**
375
+ * Stub method for Node.js EventEmitter compatibility.
376
+ * This is a no-op method provided for compatibility with Node.js HTTP request objects.
377
+ *
378
+ * @param event - The event name
379
+ * @param listener - The event listener function
380
+ * @returns This request object for chaining
381
+ */
382
+ once(event: string, listener: (...args: unknown[]) => void): this;
383
+ /**
384
+ * Stub method for Node.js EventEmitter compatibility.
385
+ * This is a no-op method provided for compatibility with Node.js HTTP request objects.
386
+ *
387
+ * @param event - The event name
388
+ * @param listener - The event listener function
389
+ * @returns This request object for chaining
390
+ */
391
+ off(event: string, listener: (...args: unknown[]) => void): this;
392
+ /**
393
+ * Stub method for Node.js EventEmitter compatibility.
394
+ * This is a no-op method provided for compatibility with Node.js HTTP request objects.
395
+ *
396
+ * @param event - The event name
397
+ * @param args - Event arguments
398
+ * @returns True to indicate the event was handled
399
+ */
400
+ emit(event: string, ...args: unknown[]): boolean;
361
401
  }
362
402
  export {};
@@ -18,11 +18,18 @@ export declare class BunResponse {
18
18
  private readonly response;
19
19
  private readonly cookieMap;
20
20
  private static readonly textDecoder;
21
+ /**
22
+ * Property for Node.js Writable stream compatibility.
23
+ * Indicates this object can be written to.
24
+ */
25
+ readonly writable = true;
21
26
  private headers;
22
27
  private statusCode;
23
28
  private ended;
24
29
  private cookieHeaders;
25
30
  private chunks;
31
+ private streamWriter;
32
+ private textEncoder;
26
33
  constructor();
27
34
  private get headersMap();
28
35
  /**
@@ -205,6 +212,21 @@ export declare class BunResponse {
205
212
  * @returns This response object for chaining
206
213
  */
207
214
  once(event: string, listener: (...args: unknown[]) => void): this;
215
+ /**
216
+ * Stub method for Node.js EventEmitter compatibility.
217
+ * This is a no-op method provided for compatibility with Node.js streams and HTTP response objects.
218
+ * Required when streams are piped to the response object (e.g., for SSE).
219
+ *
220
+ * @param event - The event name
221
+ * @param args - Event arguments
222
+ * @returns True to indicate the event was handled
223
+ */
224
+ emit(event: string, ...args: unknown[]): boolean;
225
+ /**
226
+ * Property for Node.js Writable stream compatibility.
227
+ * Indicates whether the stream has ended.
228
+ */
229
+ get writableEnded(): boolean;
208
230
  /**
209
231
  * Stub method for Node.js HTTP response compatibility.
210
232
  * This method writes data to the response stream.
@@ -234,6 +256,12 @@ export declare class BunResponse {
234
256
  * ```
235
257
  */
236
258
  write(chunk: unknown): boolean;
259
+ /**
260
+ * Initializes streaming mode by creating a TransformStream and resolving the response.
261
+ * This is used for SSE and other streaming scenarios where data needs to be sent
262
+ * before end() is called.
263
+ */
264
+ private initializeStreamingMode;
237
265
  /**
238
266
  * Gets the value of a response header.
239
267
  * Header lookup is case-insensitive.
@@ -0,0 +1,131 @@
1
+ import { CorsOptions, CorsOptionsDelegate } from '@nestjs/common/interfaces/external/cors-options.interface.js';
2
+ import { RequestMethod } from '@nestjs/common';
3
+ import { Server, ServerWebSocket } from 'bun';
4
+ import { RequestHandler } from '@nestjs/common/interfaces/index.js';
5
+ import { BunWsClientData, ServerOptions, WsData, WsOptions } from './bun.internal.types.js';
6
+ import { BunMiddlewareEngine } from './bun.middleware-engine.js';
7
+ import { BunRequest } from './bun.request.js';
8
+ import { BunResponse } from './bun.response.js';
9
+ /**
10
+ * BunServerInstance is the actual server instance that handles route registrations,
11
+ * WebSocket functionalities, and the listen method. This class is passed to
12
+ * AbstractHttpAdapter.setInstance() and implements the methods that NestJS expects
13
+ * from an HTTP server instance (similar to Express app or Fastify instance).
14
+ */
15
+ export declare class BunServerInstance {
16
+ private readonly bunServeOptions;
17
+ private readonly logger;
18
+ private readonly middlewareEngine;
19
+ private useVersioning;
20
+ private readonly routes;
21
+ private readonly routeHandlers;
22
+ private notFoundHandler;
23
+ private readonly wsHandlers;
24
+ private readonly wsMiddlewareEngine;
25
+ private wsOptions;
26
+ private useWs;
27
+ private useWsCors;
28
+ private httpServer;
29
+ constructor(bunServeOptions: ServerOptions<BunWsClientData>);
30
+ use(maybePath: string | RequestHandler<BunRequest, BunResponse>, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
31
+ private createHttpMethodHandler;
32
+ get(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
33
+ post(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
34
+ put(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
35
+ patch(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
36
+ delete(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
37
+ head(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
38
+ options(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
39
+ private createUnsupportedMethod;
40
+ all(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
41
+ propfind(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
42
+ proppatch(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
43
+ mkcol(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
44
+ copy(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
45
+ move(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
46
+ lock(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
47
+ unlock(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
48
+ search(pathOrHandler: unknown, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void;
49
+ /**
50
+ * Start listening on the specified port and hostname.
51
+ * @param port The port number or Unix socket path to listen on.
52
+ * @param hostnameOrCallback The hostname to bind to or the callback function.
53
+ * @param maybeCallback Optional callback to invoke once the server is listening.
54
+ */
55
+ listen(port: string | number, hostnameOrCallback?: string | (() => void), maybeCallback?: () => void): Server<unknown>;
56
+ /**
57
+ * NestJS compatibility methods - stop the server
58
+ */
59
+ stop(force?: boolean): Promise<void>;
60
+ /**
61
+ * Get the address of the server
62
+ */
63
+ address(): {
64
+ address: string;
65
+ port: number;
66
+ };
67
+ /**
68
+ * Set WebSocket options
69
+ */
70
+ setWsOptions(options: WsOptions): void;
71
+ /**
72
+ * Register WebSocket open handler
73
+ */
74
+ registerWsOpenHandler(handler: (ws: ServerWebSocket<unknown>) => void): void;
75
+ /**
76
+ * Register WebSocket message handler
77
+ */
78
+ registerWsMessageHandler(handler: (ws: ServerWebSocket<unknown>, message: WsData, server: Server<unknown>) => void): void;
79
+ /**
80
+ * Register WebSocket close handler
81
+ */
82
+ registerWsCloseHandler(handler: (ws: ServerWebSocket<unknown>, code: number, reason: string) => void): void;
83
+ /**
84
+ * Get the underlying Bun server
85
+ */
86
+ getBunServer(): Server<unknown> | null;
87
+ /**
88
+ * Proxy method for WebSocket server close (BaseWsInstance)
89
+ */
90
+ close(): Promise<void>;
91
+ /**
92
+ * Get the middleware engine
93
+ */
94
+ getMiddlewareEngine(): BunMiddlewareEngine;
95
+ /**
96
+ * Set the not found handler
97
+ */
98
+ setNotFoundHandler(handler: RequestHandler<BunRequest, BunResponse>): void;
99
+ /**
100
+ * Enable versioning support
101
+ */
102
+ setUseVersioning(value: boolean): void;
103
+ /**
104
+ * Register body parser middleware
105
+ */
106
+ registerParserMiddleware(prefix?: string, rawBody?: boolean): void;
107
+ /**
108
+ * Create middleware factory for NestJS
109
+ */
110
+ createMiddlewareFactory(requestMethod: RequestMethod): (path: string, callback: Function) => void;
111
+ /**
112
+ * Enable CORS middleware
113
+ */
114
+ enableCors(corsOptions?: CorsOptions | CorsOptionsDelegate<BunRequest>, prefix?: string): void;
115
+ private static isNumericPort;
116
+ private static omitKeys;
117
+ private isWebSocketUpgradeRequest;
118
+ private provideCorsHeaders;
119
+ private upgradeWebSocket;
120
+ private setupWebSocketIfNeeded;
121
+ private createServer;
122
+ private delegateRouteHandler;
123
+ private ensureRouteExists;
124
+ private prepareRequestHandler;
125
+ private createRouteFetchHandler;
126
+ private createVersioningHandlers;
127
+ private executeHandlerChain;
128
+ private createChainedHandlerForVersioningResolution;
129
+ private mapRequestMethodToString;
130
+ private parseRouteHandler;
131
+ }
@@ -0,0 +1,38 @@
1
+ import { AbstractWsAdapter, BaseWsInstance, MessageMappingProperties } from '@nestjs/websockets';
2
+ import { Observable } from 'rxjs';
3
+ import { INestApplicationContext } from '@nestjs/common';
4
+ import { ServerWebSocket } from 'bun';
5
+ import { BunWsClientData, WsData, WsOptions } from './bun.internal.types.js';
6
+ import { BunPreflightHttpServer } from './bun.preflight-http-server.js';
7
+ export type WsMessageParser<TData = unknown> = (data: WsData) => WsParsedData<TData>;
8
+ export interface WsParsedData<TData = unknown> {
9
+ event: string;
10
+ data: TData;
11
+ }
12
+ export interface BunWsAdapterOptions extends WsOptions {
13
+ messageParser?: WsMessageParser;
14
+ }
15
+ type BunWsClient = ServerWebSocket<BunWsClientData> & BaseWsInstance;
16
+ /**
17
+ * High-performance WebSocket adapter for Bun runtime with NestJS.
18
+ */
19
+ export declare class BunWsAdapter extends AbstractWsAdapter<BunPreflightHttpServer, BunWsClient> {
20
+ private readonly logger;
21
+ private readonly nestApp;
22
+ private messageParser;
23
+ private onOpenHandler?;
24
+ private globalHandlersInitialized;
25
+ constructor(appOrHttpServer?: INestApplicationContext | object);
26
+ create(_port: number, options?: BunWsAdapterOptions): BunPreflightHttpServer;
27
+ private extractWsOptions;
28
+ close(server: BunPreflightHttpServer): Promise<void>;
29
+ bindClientConnect(server: BunPreflightHttpServer, callback: (client: BunWsClient) => void): void;
30
+ bindClientDisconnect(client: BunWsClient, callback: (client: BunWsClient) => void): void;
31
+ bindMessageHandlers(client: BunWsClient, handlers: MessageMappingProperties[], transform: (data: unknown) => Observable<unknown>): void;
32
+ private initializeGlobalHandlers;
33
+ private buildHandlerMap;
34
+ private processMessage;
35
+ private sendResponse;
36
+ private cleanupClient;
37
+ }
38
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
- export { BunAdapter } from './bun.adapter.js';
2
- export { BunRequest } from './bun.request.js';
3
- export { BunResponse } from './bun.response.js';
4
- export { BunFileInterceptor } from './bun.file.interceptor.js';
1
+ export * from './bun.adapter.js';
2
+ export * from './bun.request.js';
3
+ export * from './bun.response.js';
4
+ export * from './bun.file.interceptor.js';
5
+ export * from './bun.internal.types.js';
6
+ export * from './bun.preflight-http-server.js';
7
+ export * from './bun.server-instance.js';
8
+ export * from './bun.ws-adapter.js';