@krisanalfa/bunest-adapter 0.0.1 → 0.3.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 +479 -16
- package/dist/bun.adapter.d.ts +24 -4
- package/dist/bun.preflight-http-server.d.ts +62 -0
- package/dist/bun.request.d.ts +26 -3
- package/dist/bun.response.d.ts +102 -2
- package/dist/bun.ws-adapter.d.ts +48 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +566 -72
- package/dist/index.js.map +10 -8
- package/dist/internal.types.d.ts +8 -0
- package/package.json +9 -6
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Server, ServerWebSocket } from 'bun';
|
|
2
|
+
import { BaseWsInstance } from '@nestjs/websockets';
|
|
3
|
+
import { ServerOptions, WsOptions } from './internal.types.js';
|
|
4
|
+
interface BunHttpAdapter {
|
|
5
|
+
setWsOptions(options: WsOptions): void;
|
|
6
|
+
getBunHttpServerInstance(): Server<unknown>;
|
|
7
|
+
getWsHandlers(): {
|
|
8
|
+
onOpen: ((ws: ServerWebSocket<unknown>) => void) | undefined;
|
|
9
|
+
onMessage: ((ws: ServerWebSocket<unknown>, message: string | ArrayBuffer | Buffer | Buffer[], server: Server<unknown>) => void) | undefined;
|
|
10
|
+
onClose: ((ws: ServerWebSocket<unknown>, code: number, reason: string) => void) | undefined;
|
|
11
|
+
};
|
|
12
|
+
getBunServerOptions(): Pick<ServerOptions, 'port' | 'hostname'>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Bun HTTP server placeholder used before the actual server instance is created.
|
|
16
|
+
* This class provides compatibility methods expected by NestJS framework.
|
|
17
|
+
*
|
|
18
|
+
* There's limitation in Bun where we can't create the server instance without
|
|
19
|
+
* listening on a port right away. This placeholder allows us to defer
|
|
20
|
+
* the server creation until NestJS calls the listen method.
|
|
21
|
+
*/
|
|
22
|
+
export declare class BunPreflightHttpServer implements BaseWsInstance {
|
|
23
|
+
private readonly adapter;
|
|
24
|
+
constructor(adapter: BunHttpAdapter);
|
|
25
|
+
on(event: string, callback: Function): void;
|
|
26
|
+
/**
|
|
27
|
+
* NestJS compatibility methods
|
|
28
|
+
* Nest use this to listen for "error" events during HTTP server initialization
|
|
29
|
+
*/
|
|
30
|
+
once(): void;
|
|
31
|
+
/**
|
|
32
|
+
* NestJS compatibility methods
|
|
33
|
+
* Nest use this to remove "error" event listeners during HTTP server cleanup
|
|
34
|
+
*/
|
|
35
|
+
removeListener(): void;
|
|
36
|
+
/**
|
|
37
|
+
* NestJS compatibility methods
|
|
38
|
+
*/
|
|
39
|
+
stop(force?: boolean): Promise<void>;
|
|
40
|
+
address(): {
|
|
41
|
+
address: "0.0.0.0" | "127.0.0.1" | "localhost" | (string & {});
|
|
42
|
+
port: string | number;
|
|
43
|
+
} | {
|
|
44
|
+
address: string | undefined;
|
|
45
|
+
port: number | undefined;
|
|
46
|
+
};
|
|
47
|
+
setWsOptions(options: WsOptions): void;
|
|
48
|
+
registerWsOpenHandler(handler: (ws: ServerWebSocket<unknown>) => void): void;
|
|
49
|
+
registerWsMessageHandler(handler: (ws: ServerWebSocket<unknown>, message: string | ArrayBuffer | Buffer | Buffer[], server: Server<unknown>) => void): void;
|
|
50
|
+
registerWsCloseHandler(handler: (ws: ServerWebSocket<unknown>, code: number, reason: string) => void): void;
|
|
51
|
+
getWsHandlers(): {
|
|
52
|
+
onOpen: ((ws: ServerWebSocket<unknown>) => void) | undefined;
|
|
53
|
+
onMessage: ((ws: ServerWebSocket<unknown>, message: string | ArrayBuffer | Buffer | Buffer[], server: Server<unknown>) => void) | undefined;
|
|
54
|
+
onClose: ((ws: ServerWebSocket<unknown>, code: number, reason: string) => void) | undefined;
|
|
55
|
+
};
|
|
56
|
+
getBunServer(): Server<unknown>;
|
|
57
|
+
/**
|
|
58
|
+
* Proxy method for WebSocket server close
|
|
59
|
+
*/
|
|
60
|
+
close(): Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
export {};
|
package/dist/bun.request.d.ts
CHANGED
|
@@ -32,15 +32,38 @@ export declare class BunRequest {
|
|
|
32
32
|
readonly params: Record<string, string>;
|
|
33
33
|
constructor(nativeRequest: NativeRequest);
|
|
34
34
|
/**
|
|
35
|
-
* Gets
|
|
35
|
+
* Gets a mock socket object for compatibility with Node.js middleware.
|
|
36
|
+
* Some middleware (like Better Auth) check req.socket.encrypted to determine if the connection is HTTPS.
|
|
36
37
|
*
|
|
37
|
-
* @returns
|
|
38
|
+
* @returns A mock socket object with encrypted property
|
|
39
|
+
*/
|
|
40
|
+
get socket(): {
|
|
41
|
+
encrypted: boolean;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Gets the URL path and query string of the request.
|
|
45
|
+
* Returns the pathname + search params for Node.js/Express compatibility.
|
|
46
|
+
* For the full URL including protocol and host, use the original() method to access the native request.
|
|
47
|
+
*
|
|
48
|
+
* @returns The URL path and query string (e.g., "/api/users?page=1")
|
|
38
49
|
* @example
|
|
39
50
|
* ```typescript
|
|
40
|
-
* const url = request.url; // "
|
|
51
|
+
* const url = request.url; // "/api/users?page=1"
|
|
52
|
+
* // For full URL: request.original().url // "http://localhost:3000/api/users?page=1"
|
|
41
53
|
* ```
|
|
42
54
|
*/
|
|
43
55
|
get url(): string;
|
|
56
|
+
/**
|
|
57
|
+
* Gets the original native Bun request object.
|
|
58
|
+
*
|
|
59
|
+
* @returns The underlying Bun request
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const nativeReq = request.original();
|
|
63
|
+
* console.log(nativeReq.url); // Full URL with protocol and host
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
original(): NativeRequest;
|
|
44
67
|
/**
|
|
45
68
|
* Gets the pathname portion of the URL.
|
|
46
69
|
* Uses lazy parsing for optimal performance - the pathname is only extracted when first accessed.
|
package/dist/bun.response.d.ts
CHANGED
|
@@ -17,10 +17,12 @@ export declare class BunResponse {
|
|
|
17
17
|
private resolve;
|
|
18
18
|
private readonly response;
|
|
19
19
|
private readonly cookieMap;
|
|
20
|
-
private
|
|
20
|
+
private static readonly textDecoder;
|
|
21
|
+
private headers;
|
|
21
22
|
private statusCode;
|
|
22
23
|
private ended;
|
|
23
|
-
private
|
|
24
|
+
private cookieHeaders;
|
|
25
|
+
private chunks;
|
|
24
26
|
constructor();
|
|
25
27
|
private get headersMap();
|
|
26
28
|
/**
|
|
@@ -99,6 +101,7 @@ export declare class BunResponse {
|
|
|
99
101
|
* Ends the response and sends the body to the client.
|
|
100
102
|
* Automatically handles JSON serialization, streams, and binary data.
|
|
101
103
|
* Can only be called once per response.
|
|
104
|
+
* If write() was called before end(), accumulated chunks will be sent.
|
|
102
105
|
*
|
|
103
106
|
* @param body - The response body (JSON, string, Uint8Array, StreamableFile, or undefined)
|
|
104
107
|
* @example
|
|
@@ -117,9 +120,24 @@ export declare class BunResponse {
|
|
|
117
120
|
* // Send file stream
|
|
118
121
|
* const file = new StreamableFile(stream);
|
|
119
122
|
* response.end(file);
|
|
123
|
+
*
|
|
124
|
+
* // Send accumulated chunks from write() calls
|
|
125
|
+
* response.write('Hello ');
|
|
126
|
+
* response.write('World');
|
|
127
|
+
* response.end('!'); // Sends "Hello World!"
|
|
120
128
|
* ```
|
|
121
129
|
*/
|
|
122
130
|
end(body?: unknown): void;
|
|
131
|
+
/**
|
|
132
|
+
* Applies cookie headers to the response.
|
|
133
|
+
* According to RFC 6265, each cookie must be sent as a separate Set-Cookie header.
|
|
134
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
|
|
135
|
+
*/
|
|
136
|
+
private applyCookieHeaders;
|
|
137
|
+
private sendResponse;
|
|
138
|
+
private combineChunks;
|
|
139
|
+
private combineAsString;
|
|
140
|
+
private combineAsBinary;
|
|
123
141
|
/**
|
|
124
142
|
* Sets a response header.
|
|
125
143
|
* Header names are automatically normalized to lowercase.
|
|
@@ -134,6 +152,88 @@ export declare class BunResponse {
|
|
|
134
152
|
* ```
|
|
135
153
|
*/
|
|
136
154
|
setHeader(name: string, value: string): void;
|
|
155
|
+
/**
|
|
156
|
+
* Writes the response status and headers (Node.js compatibility method).
|
|
157
|
+
* This method is provided for compatibility with Node.js HTTP response objects.
|
|
158
|
+
*
|
|
159
|
+
* @param statusCode - The HTTP status code
|
|
160
|
+
* @param headers - Optional headers to set
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* response.writeHead(200, { 'Content-Type': 'application/json' });
|
|
164
|
+
* response.writeHead(404);
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
writeHead(statusCode: number, headers?: Record<string, string>): void;
|
|
168
|
+
/**
|
|
169
|
+
* Stub method for Node.js EventEmitter compatibility.
|
|
170
|
+
* This is a no-op method provided for compatibility with Node.js HTTP response objects.
|
|
171
|
+
* Some middleware may try to listen for events like 'close' on the response object.
|
|
172
|
+
*
|
|
173
|
+
* @param event - The event name
|
|
174
|
+
* @param listener - The event listener function
|
|
175
|
+
* @returns This response object for chaining
|
|
176
|
+
*/
|
|
177
|
+
on(event: string, listener: (...args: unknown[]) => void): this;
|
|
178
|
+
/**
|
|
179
|
+
* Stub method for Node.js EventEmitter compatibility.
|
|
180
|
+
* This is a no-op method provided for compatibility with Node.js HTTP response objects.
|
|
181
|
+
*
|
|
182
|
+
* @param event - The event name
|
|
183
|
+
* @param listener - The event listener function
|
|
184
|
+
* @returns This response object for chaining
|
|
185
|
+
*/
|
|
186
|
+
off(event: string, listener: (...args: unknown[]) => void): this;
|
|
187
|
+
/**
|
|
188
|
+
* Property for Node.js HTTP response compatibility.
|
|
189
|
+
* Always returns false since Bun responses don't have a destroyed state.
|
|
190
|
+
*/
|
|
191
|
+
readonly destroyed = false;
|
|
192
|
+
/**
|
|
193
|
+
* Stub method for Node.js HTTP response compatibility.
|
|
194
|
+
* This is a no-op method provided for compatibility with Node.js HTTP response objects.
|
|
195
|
+
*
|
|
196
|
+
* @param error - Optional error
|
|
197
|
+
*/
|
|
198
|
+
destroy(error?: Error): void;
|
|
199
|
+
/**
|
|
200
|
+
* Stub method for Node.js EventEmitter compatibility.
|
|
201
|
+
* This is a no-op method provided for compatibility with Node.js HTTP response objects.
|
|
202
|
+
*
|
|
203
|
+
* @param event - The event name
|
|
204
|
+
* @param listener - The event listener function
|
|
205
|
+
* @returns This response object for chaining
|
|
206
|
+
*/
|
|
207
|
+
once(event: string, listener: (...args: unknown[]) => void): this;
|
|
208
|
+
/**
|
|
209
|
+
* Stub method for Node.js HTTP response compatibility.
|
|
210
|
+
* This method writes data to the response stream.
|
|
211
|
+
* Data is accumulated in a buffer until end() is called.
|
|
212
|
+
* Mimics Node.js behavior where write() can be called multiple times.
|
|
213
|
+
*
|
|
214
|
+
* @param chunk - The data to write (string, Uint8Array, or other types that can be stringified)
|
|
215
|
+
* @returns true if the chunk was successfully buffered, false if the response has already ended
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* // Write string chunks
|
|
219
|
+
* response.write('Hello ');
|
|
220
|
+
* response.write('World');
|
|
221
|
+
* response.end('!'); // Sends "Hello World!"
|
|
222
|
+
*
|
|
223
|
+
* // Write binary chunks
|
|
224
|
+
* const chunk1 = new Uint8Array([1, 2, 3]);
|
|
225
|
+
* const chunk2 = new Uint8Array([4, 5, 6]);
|
|
226
|
+
* response.write(chunk1);
|
|
227
|
+
* response.write(chunk2);
|
|
228
|
+
* response.end(); // Sends combined binary data
|
|
229
|
+
*
|
|
230
|
+
* // Mixed usage (converts to string)
|
|
231
|
+
* response.write('Status: ');
|
|
232
|
+
* response.write(200);
|
|
233
|
+
* response.end(); // Sends "Status: 200"
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
write(chunk: unknown): boolean;
|
|
137
237
|
/**
|
|
138
238
|
* Gets the value of a response header.
|
|
139
239
|
* Header lookup is case-insensitive.
|
|
@@ -0,0 +1,48 @@
|
|
|
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 { BunPreflightHttpServer } from './bun.preflight-http-server.js';
|
|
6
|
+
import { WsOptions } from './internal.types.js';
|
|
7
|
+
export type WsData = string | Buffer | ArrayBuffer | Buffer[];
|
|
8
|
+
export type WsMessageParser<TData = unknown> = (data: WsData) => WsParsedData<TData>;
|
|
9
|
+
export interface WsParsedData<TData = unknown> {
|
|
10
|
+
event: string;
|
|
11
|
+
data: TData;
|
|
12
|
+
}
|
|
13
|
+
export interface BunWsAdapterOptions extends WsOptions {
|
|
14
|
+
messageParser?: WsMessageParser;
|
|
15
|
+
}
|
|
16
|
+
/** Internal data stored on each WebSocket connection - must match bun.adapter.ts */
|
|
17
|
+
interface BunWsClientData {
|
|
18
|
+
/** Called when a message is received - matches bun.adapter.ts onMessageInternal */
|
|
19
|
+
onMessageInternal?: (message: WsData) => void;
|
|
20
|
+
/** Called when the connection closes - matches bun.adapter.ts onCloseInternal */
|
|
21
|
+
onCloseInternal?: () => void;
|
|
22
|
+
/** Called by NestJS for disconnect handling */
|
|
23
|
+
onDisconnect?: (ws: ServerWebSocket<unknown>) => void;
|
|
24
|
+
}
|
|
25
|
+
type BunWsClient = ServerWebSocket<BunWsClientData> & BaseWsInstance;
|
|
26
|
+
/**
|
|
27
|
+
* High-performance WebSocket adapter for Bun runtime with NestJS.
|
|
28
|
+
*/
|
|
29
|
+
export declare class BunWsAdapter extends AbstractWsAdapter<BunPreflightHttpServer, BunWsClient> {
|
|
30
|
+
private readonly logger;
|
|
31
|
+
private readonly nestApp;
|
|
32
|
+
private messageParser;
|
|
33
|
+
private onOpenHandler?;
|
|
34
|
+
private globalHandlersInitialized;
|
|
35
|
+
constructor(appOrHttpServer?: INestApplicationContext | object);
|
|
36
|
+
create(_port: number, options?: BunWsAdapterOptions): BunPreflightHttpServer;
|
|
37
|
+
private extractWsOptions;
|
|
38
|
+
close(server: BunPreflightHttpServer): Promise<void>;
|
|
39
|
+
bindClientConnect(server: BunPreflightHttpServer, callback: (client: BunWsClient) => void): void;
|
|
40
|
+
bindClientDisconnect(client: BunWsClient, callback: (client: BunWsClient) => void): void;
|
|
41
|
+
bindMessageHandlers(client: BunWsClient, handlers: MessageMappingProperties[], transform: (data: unknown) => Observable<unknown>): void;
|
|
42
|
+
private initializeGlobalHandlers;
|
|
43
|
+
private buildHandlerMap;
|
|
44
|
+
private processMessage;
|
|
45
|
+
private sendResponse;
|
|
46
|
+
private cleanupClient;
|
|
47
|
+
}
|
|
48
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
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 './internal.types.js';
|
|
6
|
+
export * from './bun.preflight-http-server.js';
|
|
7
|
+
export * from './bun.ws-adapter.js';
|