@krisanalfa/bunest-adapter 0.0.1 → 0.1.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 +44 -5
- package/dist/bun.request.d.ts +26 -3
- package/dist/bun.response.d.ts +102 -2
- package/dist/index.js +205 -20
- package/dist/index.js.map +6 -6
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -562,10 +562,10 @@ A high-performance request wrapper that provides lazy parsing and caching for op
|
|
|
562
562
|
|
|
563
563
|
#### Properties
|
|
564
564
|
|
|
565
|
-
- **`url`** - The
|
|
565
|
+
- **`url`** - The URL path and query string (e.g., "/api/users?page=1"). For the full URL including protocol and host, use `original().url`
|
|
566
566
|
- **`method`** - HTTP method (GET, POST, etc.)
|
|
567
567
|
- **`pathname`** - URL path (lazily parsed)
|
|
568
|
-
- **`hostname`** - Host name without port (lazily parsed)
|
|
568
|
+
- **`hostname`** - Host name without port (lazily parsed, respects X-Forwarded-Host header)
|
|
569
569
|
- **`query`** - Parsed query parameters (lazily parsed)
|
|
570
570
|
- **`headers`** - Request headers object with `.get()` method (lazily materialized)
|
|
571
571
|
- **`params`** - Route parameters from URL patterns
|
|
@@ -575,9 +575,11 @@ A high-performance request wrapper that provides lazy parsing and caching for op
|
|
|
575
575
|
- **`files`** - Multiple uploaded files (for multi-file uploads)
|
|
576
576
|
- **`signal`** - AbortSignal for request cancellation
|
|
577
577
|
- **`cookies`** - Cookie map for accessing request cookies
|
|
578
|
+
- **`socket`** - Mock socket object for Node.js compatibility (contains `encrypted` property)
|
|
578
579
|
|
|
579
580
|
#### Methods
|
|
580
581
|
|
|
582
|
+
- **`original()`** - Get the underlying native Bun request object
|
|
581
583
|
- **`get(key)`** - Get custom property stored in request
|
|
582
584
|
- **`set(key, value)`** - Set custom property in request (useful for middleware)
|
|
583
585
|
- **`json()`** - Parse body as JSON
|
|
@@ -603,7 +605,10 @@ class UsersController {
|
|
|
603
605
|
const auth = req.headers.get("authorization");
|
|
604
606
|
const contentType = req.headers["content-type"];
|
|
605
607
|
|
|
606
|
-
|
|
608
|
+
// Check if connection is secure
|
|
609
|
+
const isSecure = req.socket.encrypted;
|
|
610
|
+
|
|
611
|
+
return { page, limit, auth, isSecure };
|
|
607
612
|
}
|
|
608
613
|
|
|
609
614
|
@Post()
|
|
@@ -612,10 +617,14 @@ class UsersController {
|
|
|
612
617
|
console.log(req.body); // Same as dto
|
|
613
618
|
|
|
614
619
|
// Access request info
|
|
620
|
+
console.log(req.url); // "/users" (pathname + search)
|
|
615
621
|
console.log(req.pathname); // "/users"
|
|
616
622
|
console.log(req.hostname); // "localhost"
|
|
617
623
|
console.log(req.method); // "POST"
|
|
618
624
|
|
|
625
|
+
// Access native request for full URL
|
|
626
|
+
console.log(req.original().url); // "http://localhost:3000/users"
|
|
627
|
+
|
|
619
628
|
return { created: dto };
|
|
620
629
|
}
|
|
621
630
|
|
|
@@ -658,7 +667,7 @@ class ApiController {
|
|
|
658
667
|
|
|
659
668
|
### BunResponse
|
|
660
669
|
|
|
661
|
-
A high-performance response builder that provides methods to construct responses with headers, cookies, and various body types. Uses lazy initialization and optimized response building for maximum performance.
|
|
670
|
+
A high-performance response builder that provides methods to construct responses with headers, cookies, and various body types. Uses lazy initialization and optimized response building for maximum performance. Includes Node.js compatibility methods for seamless integration with existing middleware.
|
|
662
671
|
|
|
663
672
|
#### Methods
|
|
664
673
|
|
|
@@ -673,10 +682,22 @@ A high-performance response builder that provides methods to construct responses
|
|
|
673
682
|
- **`deleteCookie(name)`** - Delete a cookie by name
|
|
674
683
|
- **`deleteCookie(options)`** - Delete a cookie with path/domain options
|
|
675
684
|
- **`redirect(url, statusCode?)`** - Send redirect response (default 302)
|
|
676
|
-
- **`
|
|
685
|
+
- **`write(chunk)`** - Write data to response stream (Node.js compatibility). Chunks are accumulated until `end()` is called
|
|
686
|
+
- **`writeHead(statusCode, headers?)`** - Write status and headers (Node.js compatibility)
|
|
687
|
+
- **`end(body?)`** - End response and send body. Auto-handles JSON, streams, binary, [`BunFile`](https://bun.com/docs/runtime/file-io), and accumulated chunks from `write()` calls
|
|
677
688
|
- **`res()`** - Get the native Response promise
|
|
678
689
|
- **`isEnded()`** - Check if response has been ended
|
|
679
690
|
|
|
691
|
+
#### Node.js Compatibility Properties
|
|
692
|
+
|
|
693
|
+
For compatibility with Node.js HTTP response objects and EventEmitter-based middleware:
|
|
694
|
+
|
|
695
|
+
- **`destroyed`** - Always returns `false` (read-only property)
|
|
696
|
+
- **`on(event, listener)`** - No-op stub for EventEmitter compatibility
|
|
697
|
+
- **`off(event, listener)`** - No-op stub for EventEmitter compatibility
|
|
698
|
+
- **`once(event, listener)`** - No-op stub for EventEmitter compatibility
|
|
699
|
+
- **`destroy(error?)`** - No-op stub for Node.js compatibility
|
|
700
|
+
|
|
680
701
|
#### Usage Examples
|
|
681
702
|
|
|
682
703
|
**Setting status and headers:**
|
|
@@ -773,6 +794,23 @@ class FilesController {
|
|
|
773
794
|
sendBinary(@Res() res: BunResponse) {
|
|
774
795
|
const buffer = new Uint8Array([1, 2, 3, 4, 5]);
|
|
775
796
|
res.setHeader("Content-Type", "application/octet-stream");
|
|
797
|
+
|
|
798
|
+
@Get("chunked")
|
|
799
|
+
sendChunked(@Res() res: BunResponse) {
|
|
800
|
+
// Node.js-style chunked response
|
|
801
|
+
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
802
|
+
res.write("Hello ");
|
|
803
|
+
res.write("World");
|
|
804
|
+
res.end("!"); // Sends "Hello World!"
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
@Get("mixed-chunks")
|
|
808
|
+
sendMixedChunks(@Res() res: BunResponse) {
|
|
809
|
+
// Mix of strings and binary data
|
|
810
|
+
res.write("Status: ");
|
|
811
|
+
res.write(new Uint8Array([50, 48, 48])); // "200" in bytes
|
|
812
|
+
res.end(); // Chunks are combined and sent
|
|
813
|
+
}
|
|
776
814
|
res.end(buffer);
|
|
777
815
|
}
|
|
778
816
|
|
|
@@ -860,6 +898,7 @@ Contributions are welcome! Please open issues or submit pull requests for bug fi
|
|
|
860
898
|
- Support for WebSocket integration with Bun
|
|
861
899
|
- Enhanced trusted proxy configuration for host header handling
|
|
862
900
|
- Additional performance optimizations and benchmarks
|
|
901
|
+
- Release automation via CI/CD pipelines
|
|
863
902
|
|
|
864
903
|
## License
|
|
865
904
|
|
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.
|
package/dist/index.js
CHANGED
|
@@ -207,6 +207,57 @@ class BunMiddlewareEngine {
|
|
|
207
207
|
useNotFoundHandler(handler) {
|
|
208
208
|
this.notFoundHandler = handler;
|
|
209
209
|
}
|
|
210
|
+
findRouteHandler(method, path) {
|
|
211
|
+
const exactHandler = this.findExactRouteHandler(method, path);
|
|
212
|
+
if (exactHandler)
|
|
213
|
+
return exactHandler;
|
|
214
|
+
return this.findPrefixRouteHandler(method, path);
|
|
215
|
+
}
|
|
216
|
+
findExactRouteHandler(method, path) {
|
|
217
|
+
const exactKey = `${method}:${path}`;
|
|
218
|
+
const exactMiddleware = this.routeMiddleware.get(exactKey);
|
|
219
|
+
if (exactMiddleware && exactMiddleware.length > 0) {
|
|
220
|
+
return exactMiddleware[exactMiddleware.length - 1];
|
|
221
|
+
}
|
|
222
|
+
const allExactKey = `ALL:${path}`;
|
|
223
|
+
const allExactMiddleware = this.routeMiddleware.get(allExactKey);
|
|
224
|
+
if (allExactMiddleware && allExactMiddleware.length > 0) {
|
|
225
|
+
return allExactMiddleware[allExactMiddleware.length - 1];
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
findPrefixRouteHandler(method, path) {
|
|
230
|
+
const methodMap = this.routeMiddlewareByMethod.get(method);
|
|
231
|
+
const allMethodMap = this.routeMiddlewareByMethod.get("ALL");
|
|
232
|
+
if (!methodMap && !allMethodMap)
|
|
233
|
+
return null;
|
|
234
|
+
const mapsToCheck = [];
|
|
235
|
+
if (methodMap)
|
|
236
|
+
mapsToCheck.push(methodMap);
|
|
237
|
+
if (allMethodMap)
|
|
238
|
+
mapsToCheck.push(allMethodMap);
|
|
239
|
+
return this.findBestMatchInMaps(mapsToCheck, path);
|
|
240
|
+
}
|
|
241
|
+
findBestMatchInMaps(maps, path) {
|
|
242
|
+
let bestMatch = null;
|
|
243
|
+
let bestMatchLength = 0;
|
|
244
|
+
const pathLen = path.length;
|
|
245
|
+
for (const map of maps) {
|
|
246
|
+
for (const [keyPath, middleware] of map) {
|
|
247
|
+
if (middleware.length === 0 || keyPath.length <= bestMatchLength)
|
|
248
|
+
continue;
|
|
249
|
+
if (this.isPrefixMatch(path, pathLen, keyPath)) {
|
|
250
|
+
bestMatch = middleware[middleware.length - 1];
|
|
251
|
+
bestMatchLength = keyPath.length;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return bestMatch;
|
|
256
|
+
}
|
|
257
|
+
isPrefixMatch(path, pathLen, keyPath) {
|
|
258
|
+
const keyPathLen = keyPath.length;
|
|
259
|
+
return path === keyPath || pathLen > keyPathLen && path.charCodeAt(keyPathLen) === 47 && path.startsWith(keyPath);
|
|
260
|
+
}
|
|
210
261
|
async run(options) {
|
|
211
262
|
try {
|
|
212
263
|
const middlewares = this.getMiddlewareChain(options.method, options.path);
|
|
@@ -290,14 +341,17 @@ class BunMiddlewareEngine {
|
|
|
290
341
|
}
|
|
291
342
|
if (index === chainLength) {
|
|
292
343
|
index++;
|
|
293
|
-
|
|
344
|
+
if (!res.isEnded()) {
|
|
345
|
+
const result = requestHandler(req, res, next);
|
|
346
|
+
if (result instanceof Promise)
|
|
347
|
+
await result;
|
|
348
|
+
}
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (index > chainLength && !res.isEnded()) {
|
|
352
|
+
const result = this.notFoundHandler?.(req, res, noop);
|
|
294
353
|
if (result instanceof Promise)
|
|
295
354
|
await result;
|
|
296
|
-
if (index > chainLength) {
|
|
297
|
-
const result2 = this.notFoundHandler?.(req, res, noop);
|
|
298
|
-
if (result2 instanceof Promise)
|
|
299
|
-
await result2;
|
|
300
|
-
}
|
|
301
355
|
}
|
|
302
356
|
};
|
|
303
357
|
await next();
|
|
@@ -341,8 +395,16 @@ class BunRequest {
|
|
|
341
395
|
this.method = nativeRequest.method;
|
|
342
396
|
this.params = nativeRequest.params;
|
|
343
397
|
}
|
|
398
|
+
get socket() {
|
|
399
|
+
return {
|
|
400
|
+
encrypted: this._parsedUrl.protocol === "https:"
|
|
401
|
+
};
|
|
402
|
+
}
|
|
344
403
|
get url() {
|
|
345
|
-
return this.
|
|
404
|
+
return this._parsedUrl.pathname + this._parsedUrl.search;
|
|
405
|
+
}
|
|
406
|
+
original() {
|
|
407
|
+
return this.nativeRequest;
|
|
346
408
|
}
|
|
347
409
|
get pathname() {
|
|
348
410
|
return this._pathname ??= this._parsedUrl.pathname;
|
|
@@ -441,20 +503,22 @@ class BunResponse {
|
|
|
441
503
|
resolve;
|
|
442
504
|
response;
|
|
443
505
|
cookieMap = new CookieMap;
|
|
444
|
-
|
|
506
|
+
static textDecoder = new TextDecoder;
|
|
507
|
+
headers = null;
|
|
445
508
|
statusCode = 200;
|
|
446
509
|
ended = false;
|
|
447
|
-
|
|
510
|
+
cookieHeaders = null;
|
|
511
|
+
chunks = [];
|
|
448
512
|
constructor() {
|
|
449
513
|
this.response = new Promise((r) => {
|
|
450
514
|
this.resolve = r;
|
|
451
515
|
});
|
|
452
516
|
}
|
|
453
517
|
get headersMap() {
|
|
454
|
-
return this.
|
|
518
|
+
return this.headers ??= new Map;
|
|
455
519
|
}
|
|
456
520
|
cookie(...args) {
|
|
457
|
-
this.
|
|
521
|
+
this.cookieHeaders = null;
|
|
458
522
|
if (args.length === 1) {
|
|
459
523
|
this.cookieMap.set(args[0]);
|
|
460
524
|
} else {
|
|
@@ -478,10 +542,22 @@ class BunResponse {
|
|
|
478
542
|
if (this.ended)
|
|
479
543
|
return;
|
|
480
544
|
this.ended = true;
|
|
481
|
-
this.
|
|
482
|
-
if (this.
|
|
483
|
-
this.
|
|
545
|
+
this.applyCookieHeaders();
|
|
546
|
+
if (this.chunks.length > 0) {
|
|
547
|
+
const finalBody = this.combineChunks(body);
|
|
548
|
+
this.resolve(this.createResponse(finalBody));
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
this.sendResponse(body);
|
|
552
|
+
}
|
|
553
|
+
applyCookieHeaders() {
|
|
554
|
+
this.cookieHeaders ??= this.cookieMap.toSetCookieHeaders();
|
|
555
|
+
if (this.cookieHeaders.length > 0) {
|
|
556
|
+
this.setHeader("set-cookie", this.cookieHeaders.join(`
|
|
557
|
+
`));
|
|
484
558
|
}
|
|
559
|
+
}
|
|
560
|
+
sendResponse(body) {
|
|
485
561
|
if (body !== null && typeof body === "object") {
|
|
486
562
|
if (body instanceof Uint8Array || body instanceof Blob) {
|
|
487
563
|
this.resolve(this.createResponse(body));
|
|
@@ -500,11 +576,100 @@ class BunResponse {
|
|
|
500
576
|
}
|
|
501
577
|
this.resolve(this.buildJsonResponse(body));
|
|
502
578
|
}
|
|
579
|
+
combineChunks(finalChunk) {
|
|
580
|
+
const hasStrings = this.chunks.some((chunk) => typeof chunk === "string");
|
|
581
|
+
const finalIsString = typeof finalChunk === "string";
|
|
582
|
+
if (hasStrings || finalIsString) {
|
|
583
|
+
return this.combineAsString(finalChunk);
|
|
584
|
+
}
|
|
585
|
+
return this.combineAsBinary(finalChunk);
|
|
586
|
+
}
|
|
587
|
+
combineAsString(finalChunk) {
|
|
588
|
+
const decoder = BunResponse.textDecoder;
|
|
589
|
+
const parts = this.chunks.map((chunk) => typeof chunk === "string" ? chunk : decoder.decode(chunk));
|
|
590
|
+
if (finalChunk !== undefined && finalChunk !== null) {
|
|
591
|
+
if (typeof finalChunk === "string") {
|
|
592
|
+
parts.push(finalChunk);
|
|
593
|
+
} else if (finalChunk instanceof Uint8Array) {
|
|
594
|
+
parts.push(decoder.decode(finalChunk));
|
|
595
|
+
} else if (typeof finalChunk === "object") {
|
|
596
|
+
parts.push(JSON.stringify(finalChunk));
|
|
597
|
+
} else {
|
|
598
|
+
parts.push(String(finalChunk));
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return parts.join("");
|
|
602
|
+
}
|
|
603
|
+
combineAsBinary(finalChunk) {
|
|
604
|
+
const binaryChunks = this.chunks;
|
|
605
|
+
let totalLength = 0;
|
|
606
|
+
for (const chunk of binaryChunks) {
|
|
607
|
+
totalLength += chunk.length;
|
|
608
|
+
}
|
|
609
|
+
if (finalChunk instanceof Uint8Array) {
|
|
610
|
+
totalLength += finalChunk.length;
|
|
611
|
+
}
|
|
612
|
+
const result = new Uint8Array(totalLength);
|
|
613
|
+
let offset = 0;
|
|
614
|
+
for (const chunk of binaryChunks) {
|
|
615
|
+
result.set(chunk, offset);
|
|
616
|
+
offset += chunk.length;
|
|
617
|
+
}
|
|
618
|
+
if (finalChunk instanceof Uint8Array) {
|
|
619
|
+
result.set(finalChunk, offset);
|
|
620
|
+
}
|
|
621
|
+
return result;
|
|
622
|
+
}
|
|
503
623
|
setHeader(name, value) {
|
|
504
624
|
this.headersMap.set(name.toLowerCase(), value);
|
|
505
625
|
}
|
|
626
|
+
writeHead(statusCode, headers) {
|
|
627
|
+
this.statusCode = statusCode;
|
|
628
|
+
if (headers) {
|
|
629
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
630
|
+
this.setHeader(name, value);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
on(event, listener) {
|
|
635
|
+
return this;
|
|
636
|
+
}
|
|
637
|
+
off(event, listener) {
|
|
638
|
+
return this;
|
|
639
|
+
}
|
|
640
|
+
destroyed = false;
|
|
641
|
+
destroy(error) {}
|
|
642
|
+
once(event, listener) {
|
|
643
|
+
return this;
|
|
644
|
+
}
|
|
645
|
+
write(chunk) {
|
|
646
|
+
if (this.ended) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
if (typeof chunk === "string") {
|
|
650
|
+
this.chunks.push(chunk);
|
|
651
|
+
return true;
|
|
652
|
+
}
|
|
653
|
+
if (chunk instanceof Uint8Array) {
|
|
654
|
+
this.chunks.push(chunk);
|
|
655
|
+
return true;
|
|
656
|
+
}
|
|
657
|
+
if (chunk instanceof Buffer) {
|
|
658
|
+
this.chunks.push(new Uint8Array(chunk));
|
|
659
|
+
return true;
|
|
660
|
+
}
|
|
661
|
+
if (chunk != null) {
|
|
662
|
+
if (typeof chunk === "object") {
|
|
663
|
+
this.chunks.push(JSON.stringify(chunk));
|
|
664
|
+
} else {
|
|
665
|
+
this.chunks.push(String(chunk));
|
|
666
|
+
}
|
|
667
|
+
return true;
|
|
668
|
+
}
|
|
669
|
+
return true;
|
|
670
|
+
}
|
|
506
671
|
getHeader(name) {
|
|
507
|
-
return this.
|
|
672
|
+
return this.headers?.get(name.toLowerCase()) ?? null;
|
|
508
673
|
}
|
|
509
674
|
appendHeader(name, value) {
|
|
510
675
|
const key = name.toLowerCase();
|
|
@@ -513,7 +678,7 @@ class BunResponse {
|
|
|
513
678
|
headers.set(key, existing ? `${existing}, ${value}` : value);
|
|
514
679
|
}
|
|
515
680
|
removeHeader(name) {
|
|
516
|
-
this.
|
|
681
|
+
this.headers?.delete(name.toLowerCase());
|
|
517
682
|
}
|
|
518
683
|
setStatus(code) {
|
|
519
684
|
this.statusCode = code;
|
|
@@ -542,7 +707,7 @@ class BunResponse {
|
|
|
542
707
|
return this.createResponse(body.getStream());
|
|
543
708
|
}
|
|
544
709
|
buildJsonResponse(body) {
|
|
545
|
-
const headers = this.
|
|
710
|
+
const headers = this.headers;
|
|
546
711
|
if (headers === null || headers.size === 0) {
|
|
547
712
|
return Response.json(body, { status: this.statusCode });
|
|
548
713
|
}
|
|
@@ -555,7 +720,7 @@ class BunResponse {
|
|
|
555
720
|
});
|
|
556
721
|
}
|
|
557
722
|
createResponse(body) {
|
|
558
|
-
const headers = this.
|
|
723
|
+
const headers = this.headers;
|
|
559
724
|
if (headers === null || headers.size === 0) {
|
|
560
725
|
return new Response(body, { status: this.statusCode });
|
|
561
726
|
}
|
|
@@ -767,6 +932,25 @@ class BunAdapter extends AbstractHttpAdapter {
|
|
|
767
932
|
}) {
|
|
768
933
|
super();
|
|
769
934
|
this.bunServeOptions = bunServeOptions;
|
|
935
|
+
this.setInstance({
|
|
936
|
+
use: (maybePath, maybeHandler) => {
|
|
937
|
+
if (typeof maybePath === "string") {
|
|
938
|
+
let path = maybePath;
|
|
939
|
+
const handler = maybeHandler;
|
|
940
|
+
if (!handler) {
|
|
941
|
+
throw new Error("Handler must be provided when path is a string.");
|
|
942
|
+
}
|
|
943
|
+
if (path.includes("/*")) {
|
|
944
|
+
path = path.substring(0, path.indexOf("/*"));
|
|
945
|
+
}
|
|
946
|
+
this.logger.log(`Registering middleware for path: ${path}`);
|
|
947
|
+
this.middlewareEngine.useRoute("ALL", path, handler);
|
|
948
|
+
} else {
|
|
949
|
+
const handler = maybePath;
|
|
950
|
+
this.middlewareEngine.useGlobal(handler);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
});
|
|
770
954
|
}
|
|
771
955
|
use(middleware) {
|
|
772
956
|
this.middlewareEngine.useGlobal(middleware);
|
|
@@ -938,12 +1122,13 @@ class BunAdapter extends AbstractHttpAdapter {
|
|
|
938
1122
|
const fetch = async (request) => {
|
|
939
1123
|
const bunRequest = new BunRequest(request);
|
|
940
1124
|
const bunResponse = new BunResponse;
|
|
1125
|
+
const routeHandler = middlewareEngine.findRouteHandler(bunRequest.method, bunRequest.pathname) ?? notFoundHandler;
|
|
941
1126
|
await middlewareEngine.run({
|
|
942
1127
|
req: bunRequest,
|
|
943
1128
|
res: bunResponse,
|
|
944
1129
|
method: bunRequest.method,
|
|
945
1130
|
path: bunRequest.pathname,
|
|
946
|
-
requestHandler:
|
|
1131
|
+
requestHandler: routeHandler
|
|
947
1132
|
});
|
|
948
1133
|
return bunResponse.res();
|
|
949
1134
|
};
|
|
@@ -1085,5 +1270,5 @@ export {
|
|
|
1085
1270
|
BunAdapter
|
|
1086
1271
|
};
|
|
1087
1272
|
|
|
1088
|
-
//# debugId=
|
|
1273
|
+
//# debugId=43ACC6E0AFE16AD764756E2164756E21
|
|
1089
1274
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../lib/bun.adapter.ts", "../lib/bun.body-parser.middleware.ts", "../lib/bun.cors.middleware.ts", "../lib/bun.middleware-engine.ts", "../lib/bun.request.ts", "../lib/bun.response.ts", "../lib/bun.version-filter.middleware.ts", "../lib/bun.file.interceptor.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import {\n CorsOptions,\n CorsOptionsDelegate,\n} from '@nestjs/common/interfaces/external/cors-options.interface.js'\nimport {\n ErrorHandler,\n RequestHandler,\n} from '@nestjs/common/interfaces/index.js'\nimport {\n Logger,\n NestApplicationOptions,\n RequestMethod,\n VersioningOptions,\n} from '@nestjs/common'\nimport { BunRequest as NativeRequest, Serve, Server, randomUUIDv7 } from 'bun'\nimport { AbstractHttpAdapter } from '@nestjs/core'\nimport { VersionValue } from '@nestjs/common/interfaces/version-options.interface.js'\n\nimport { BunBodyParserMiddleware } from './bun.body-parser.middleware.js'\nimport { BunCorsMiddleware } from './bun.cors.middleware.js'\nimport { BunMiddlewareEngine } from './bun.middleware-engine.js'\nimport { BunRequest } from './bun.request.js'\nimport { BunResponse } from './bun.response.js'\nimport { BunVersionFilterMiddleware } from './bun.version-filter.middleware.js'\n\n// Static method map - use direct string lookup for hot path\nconst REQUEST_METHOD_STRINGS: readonly string[] = [\n 'GET', // 0\n 'POST', // 1\n 'PUT', // 2\n 'DELETE', // 3\n 'PATCH', // 4\n 'ALL', // 5\n 'OPTIONS', // 6\n 'HEAD', // 7\n 'SEARCH', // 8\n 'PROPFIND', // 9\n 'PROPPATCH', // 10\n 'MKCOL', // 11\n 'COPY', // 12\n 'MOVE', // 13\n 'LOCK', // 14\n 'UNLOCK', // 15\n]\n\ntype PathHandler = Partial<\n Record<\n Serve.HTTPMethod,\n Serve.Handler<NativeRequest, Server<unknown>, Response> | Response\n >\n>\n\nexport class BunAdapter extends AbstractHttpAdapter<\n Server<unknown>,\n BunRequest,\n BunResponse\n> {\n private readonly logger: Logger = new Logger('BunAdapter', { timestamp: true })\n private readonly middlewareEngine = new BunMiddlewareEngine()\n private useVersioning = false\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n private readonly routes: Record<string, PathHandler> = Object.create(null) // Use null prototype for faster lookup\n\n // Store multiple handlers per route/method for version chaining\n private readonly routeHandlers = new Map<\n string,\n RequestHandler<BunRequest, BunResponse>[]\n >()\n\n private notFoundHandler: RequestHandler<BunRequest, BunResponse> = (\n req,\n res,\n ) => {\n res.setStatus(404)\n res.end({ message: 'Not Found' })\n }\n\n constructor(private bunServeOptions: Pick<Serve.Options<unknown>, 'development' | 'maxRequestBodySize' | 'idleTimeout' | 'id' | 'tls'> = {\n development: false,\n id: randomUUIDv7(),\n }) {\n super()\n }\n\n use(middleware: RequestHandler<BunRequest, BunResponse>): void {\n this.middlewareEngine.useGlobal(middleware)\n }\n\n get(handler: RequestHandler<BunRequest, BunResponse>): void\n get(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n get(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('GET', path, handler)\n }\n\n post(handler: RequestHandler<BunRequest, BunResponse>): void\n post(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n post(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('POST', path, handler)\n }\n\n put(handler: RequestHandler<BunRequest, BunResponse>): void\n put(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n put(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('PUT', path, handler)\n }\n\n patch(handler: RequestHandler<BunRequest, BunResponse>): void\n patch(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n patch(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('PATCH', path, handler)\n }\n\n delete(handler: RequestHandler<BunRequest, BunResponse>): void\n delete(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n delete(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('DELETE', path, handler)\n }\n\n head(handler: RequestHandler<BunRequest, BunResponse>): void\n head(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n head(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('HEAD', path, handler)\n }\n\n options(handler: RequestHandler<BunRequest, BunResponse>): void\n options(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n options(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('OPTIONS', path, handler)\n }\n\n all(handler: RequestHandler<BunRequest, BunResponse>): void\n all(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n all(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n propfind(handler: RequestHandler<BunRequest, BunResponse>): void\n propfind(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n propfind(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n proppatch(handler: RequestHandler<BunRequest, BunResponse>): void\n proppatch(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n proppatch(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n mkcol(handler: RequestHandler<BunRequest, BunResponse>): void\n mkcol(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n mkcol(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n copy(handler: RequestHandler<BunRequest, BunResponse>): void\n copy(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n copy(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n move(handler: RequestHandler<BunRequest, BunResponse>): void\n move(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n move(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n lock(handler: RequestHandler<BunRequest, BunResponse>): void\n lock(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n lock(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n unlock(handler: RequestHandler<BunRequest, BunResponse>): void\n unlock(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n unlock(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n search(handler: RequestHandler<BunRequest, BunResponse>): void\n search(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n search(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n useStaticAssets(...args: unknown[]) {\n throw new Error('Not supported.')\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n setViewEngine(engine: string) {\n throw new Error('Not supported.')\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n render(response: unknown, view: string, options: unknown) {\n throw new Error('Not supported.')\n }\n\n async close() {\n await this.httpServer.stop()\n }\n\n initHttpServer(options: NestApplicationOptions) {\n // Set dummy server to satisfy AbstractHttpAdapter requirements\n this.setHttpServer({\n once: () => { /* noop: Nest use this to listen for \"error\" event */ },\n address: () => ({ address: '0.0.0.0', port: 0 }),\n removeListener: () => { /* noop: Nest may use this to remove \"error\" listener */ },\n stop: () => { /* noop */ },\n } as unknown as Server<unknown>)\n\n if (options.httpsOptions) {\n this.bunServeOptions.tls = {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n key: options.httpsOptions.key,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n cert: options.httpsOptions.cert,\n passphrase: options.httpsOptions.passphrase,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n ca: options.httpsOptions.ca,\n ciphers: options.httpsOptions.ciphers,\n secureOptions: options.httpsOptions.secureOptions,\n rejectUnauthorized: options.httpsOptions.rejectUnauthorized,\n requestCert: options.httpsOptions.requestCert,\n }\n }\n }\n\n getRequestHostname(request: BunRequest) {\n return request.hostname\n }\n\n getRequestMethod(request: BunRequest) {\n return request.method\n }\n\n getRequestUrl(request: BunRequest) {\n return request.pathname\n }\n\n status(response: BunResponse, statusCode: number) {\n response.setStatus(statusCode)\n }\n\n reply(response: BunResponse, body: unknown, statusCode?: number) {\n if (statusCode) {\n response.setStatus(statusCode)\n }\n\n response.end(body)\n }\n\n end(response: BunResponse, message?: string) {\n response.end(message)\n }\n\n redirect(response: BunResponse, statusCode: number, url: string) {\n response.redirect(url, statusCode)\n }\n\n setErrorHandler(\n handler: ErrorHandler<BunRequest, BunResponse>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n prefix?: string,\n ) {\n this.middlewareEngine.useErrorHandler(handler)\n }\n\n setNotFoundHandler(\n handler: RequestHandler<BunRequest, BunResponse>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n prefix?: string,\n ) {\n this.notFoundHandler = handler\n this.middlewareEngine.useNotFoundHandler(handler)\n }\n\n isHeadersSent(response: BunResponse): boolean {\n return response.isEnded()\n }\n\n getHeader(response: BunResponse, name: string): string | null {\n return response.getHeader(name)\n }\n\n setHeader(response: BunResponse, name: string, value: string) {\n response.setHeader(name, value)\n }\n\n appendHeader(response: BunResponse, name: string, value: string) {\n response.appendHeader(name, value)\n }\n\n registerParserMiddleware(prefix?: string, rawBody?: boolean) {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n this.logger.log(`Registering Body Parser Middleware with prefix: ${prefix || '/'} and rawBody: ${rawBody ? 'true' : 'false'}`)\n const bodyParser = new BunBodyParserMiddleware({ prefix, rawBody })\n this.middlewareEngine.useGlobal(bodyParser.run.bind(bodyParser))\n }\n\n enableCors(\n options?: CorsOptions | CorsOptionsDelegate<BunRequest>,\n prefix?: string,\n ) {\n this.logger.log(`Enabling CORS Middleware with prefix: ${prefix ?? '/'}`)\n const corsMiddleware = new BunCorsMiddleware({ corsOptions: options, prefix })\n this.middlewareEngine.useGlobal(corsMiddleware.run.bind(corsMiddleware))\n }\n\n createMiddlewareFactory(\n requestMethod: RequestMethod,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n ): (path: string, callback: Function) => void {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return (path: string, callback: Function) => {\n // Map RequestMethod enum to string method name\n const methodName = this.mapRequestMethodToString(requestMethod)\n\n // Handle wildcard routes (applies to all paths)\n // NestJS uses \"/*\" or \"*\" for wildcard routes\n if (path === '*' || path === '/*') {\n this.middlewareEngine.useWildcard(\n methodName,\n callback as RequestHandler<BunRequest, BunResponse>,\n )\n return\n }\n\n // Normalize path by removing trailing slash (except for root \"/\")\n const normalizedPath = path === '/' ? path : path.replace(/\\/$/, '')\n this.middlewareEngine.useRoute(\n methodName,\n normalizedPath,\n callback as RequestHandler<BunRequest, BunResponse>,\n )\n }\n }\n\n getType(): string {\n return 'bun'\n }\n\n applyVersionFilter(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n handler: Function,\n version: VersionValue,\n versioningOptions: VersioningOptions,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n ): (req: BunRequest, res: BunResponse, next: () => void) => Function {\n this.logger.log(`Applying Version Filter Middleware for version: ${JSON.stringify(version)}`)\n this.useVersioning = true\n return BunVersionFilterMiddleware.createFilter(\n handler as (req: BunRequest, res: BunResponse, next: () => void) => unknown,\n version,\n versioningOptions,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n ) as (req: BunRequest, res: BunResponse, next: () => void) => Function\n }\n\n /**\n * Start listening on the specified port and hostname.\n * @param port The port number or Unix socket path to listen on.\n * @param callback Optional callback to invoke once the server is listening.\n */\n listen(port: string | number, callback?: () => void): void\n /**\n * Start listening on the specified port and hostname.\n * @param port The port number or Unix socket path to listen on.\n * @param hostname The hostname to bind to.\n * @param callback Optional callback to invoke once the server is listening.\n */\n listen(port: string | number, hostname: string, callback?: () => void): void\n /**\n * Start listening on the specified port and hostname.\n * @param port The port number or Unix socket path to listen on.\n * @param hostnameOrCallback The hostname to bind to or the callback function.\n * @param maybeCallback Optional callback to invoke once the server is listening.\n */\n listen(\n port: string | number,\n hostnameOrCallback?: string | (() => void),\n maybeCallback?: () => void,\n ): void {\n const hostname\n = typeof hostnameOrCallback === 'string' ? hostnameOrCallback : 'localhost'\n const callback\n = typeof hostnameOrCallback === 'function'\n ? hostnameOrCallback\n : maybeCallback\n\n // Capture references for closure - avoid 'this' lookup in hot path\n const middlewareEngine = this.middlewareEngine\n const notFoundHandler = this.notFoundHandler\n\n const fetch = async (request: NativeRequest): Promise<Response> => {\n const bunRequest = new BunRequest(request)\n const bunResponse = new BunResponse()\n // Inline property access for hot path\n await middlewareEngine.run({\n req: bunRequest,\n res: bunResponse,\n method: bunRequest.method,\n path: bunRequest.pathname,\n requestHandler: notFoundHandler,\n })\n return bunResponse.res()\n }\n\n const omit = <T extends object, K extends keyof T>(\n obj: T,\n ...keys: K[]\n ): Omit<T, K> => {\n const result = { ...obj }\n for (const key of keys) {\n Reflect.deleteProperty(result, key)\n }\n return result\n }\n\n const server = typeof port === 'number' || !isNaN(Number(port))\n ? Bun.serve<unknown>({\n ...this.bunServeOptions,\n hostname,\n port,\n routes: this.routes,\n fetch,\n })\n : Bun.serve<unknown>({\n ...omit(this.bunServeOptions, 'idleTimeout'),\n unix: port,\n routes: this.routes,\n fetch,\n })\n\n if (typeof port === 'string' && isNaN(Number(port))) {\n this.logger.log(`Bun server listening on unix socket: ${port}`)\n }\n\n callback?.()\n\n // Add `address` method to match Node.js Server interface\n Object.defineProperty(server, 'address', {\n configurable: true,\n enumerable: true,\n get: () => ({ address: server.hostname, port: server.port }),\n })\n\n this.setHttpServer(server)\n }\n\n private delegateRouteHandler(\n method: Serve.HTTPMethod,\n path: string,\n handler: RequestHandler<BunRequest, BunResponse>,\n ): void {\n // Use null prototype object for route if not exists\n if (!(path in this.routes)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n this.routes[path] = Object.create(null)\n }\n\n const requestHandler = !this.useVersioning\n ? handler\n // Create handler that wraps array + fallback into a single callable\n // This avoids recreating the chained handler on every request\n : this.createChainedHandlerForVersioningResolution(\n this.createVersioningHandlers(method, path, handler),\n this.notFoundHandler,\n )\n\n this.routes[path][method] = async (request: NativeRequest): Promise<Response> => {\n const bunRequest = new BunRequest(request)\n const bunResponse = new BunResponse()\n\n await this.middlewareEngine.run({\n req: bunRequest,\n res: bunResponse,\n method,\n path,\n requestHandler,\n })\n\n return bunResponse.res()\n }\n }\n\n private createVersioningHandlers(\n method: Serve.HTTPMethod,\n path: string,\n handler: RequestHandler<BunRequest, BunResponse>,\n ) {\n // Store handler in the handlers array for chaining (versioning support)\n const routeKey = `${method}:${path}`\n let versioningHandlers = this.routeHandlers.get(routeKey)\n if (!versioningHandlers) {\n versioningHandlers = []\n this.routeHandlers.set(routeKey, versioningHandlers)\n }\n versioningHandlers.push(handler)\n\n return versioningHandlers\n }\n\n private async executeHandlerChain(\n handlers: RequestHandler<BunRequest, BunResponse>[],\n req: BunRequest,\n res: BunResponse,\n ): Promise<void> {\n const handlersLength = handlers.length\n let index = 0\n let shouldContinue = true\n\n while (shouldContinue && index < handlersLength && !res.isEnded()) {\n shouldContinue = false\n const currentIndex = index++\n const result = handlers[currentIndex](req, res, () => {\n shouldContinue = true\n }) as unknown\n if (result instanceof Promise) await result\n }\n }\n\n private createChainedHandlerForVersioningResolution(\n handlers: RequestHandler<BunRequest, BunResponse>[],\n notFoundHandler: RequestHandler<BunRequest, BunResponse>,\n ): RequestHandler<BunRequest, BunResponse> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return (async (req: BunRequest, res: BunResponse, next?: Function): Promise<void> => {\n // First pass: discovery for versioning\n await this.executeHandlerChain(handlers, req, res)\n\n // Check for custom versioning candidates\n if (!res.isEnded() && BunVersionFilterMiddleware.hasCustomVersioningCandidates(req)) {\n const bestVersion = BunVersionFilterMiddleware.selectBestCustomVersionCandidate(req)\n\n if (bestVersion) {\n BunVersionFilterMiddleware.setCustomVersioningExecutionPhase(req, bestVersion)\n await this.executeHandlerChain(handlers, req, res)\n }\n }\n\n // If still not handled, call not found handler\n if (!res.isEnded()) {\n notFoundHandler(req, res, next)\n }\n }) as RequestHandler<BunRequest, BunResponse>\n }\n\n private mapRequestMethodToString(requestMethod: RequestMethod): string {\n return REQUEST_METHOD_STRINGS[requestMethod] ?? 'ALL'\n }\n\n private parseRouteHandler(handler: RequestHandler<BunRequest, BunResponse>): {\n path: string\n handler: RequestHandler<BunRequest, BunResponse>\n }\n private parseRouteHandler(\n path: unknown,\n handler?: RequestHandler<BunRequest, BunResponse>,\n ): { path: string, handler: RequestHandler<BunRequest, BunResponse> }\n private parseRouteHandler(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): { path: string, handler: RequestHandler<BunRequest, BunResponse> } {\n const path = typeof pathOrHandler === 'string' ? pathOrHandler : '/'\n const handler\n = typeof pathOrHandler === 'function'\n ? (pathOrHandler as RequestHandler<BunRequest, BunResponse>)\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n : maybeHandler!\n return { path, handler }\n }\n}\n",
|
|
5
|
+
"import {\n CorsOptions,\n CorsOptionsDelegate,\n} from '@nestjs/common/interfaces/external/cors-options.interface.js'\nimport {\n ErrorHandler,\n RequestHandler,\n} from '@nestjs/common/interfaces/index.js'\nimport {\n Logger,\n NestApplicationOptions,\n RequestMethod,\n VersioningOptions,\n} from '@nestjs/common'\nimport { BunRequest as NativeRequest, Serve, Server, randomUUIDv7 } from 'bun'\nimport { AbstractHttpAdapter } from '@nestjs/core'\nimport { VersionValue } from '@nestjs/common/interfaces/version-options.interface.js'\n\nimport { BunBodyParserMiddleware } from './bun.body-parser.middleware.js'\nimport { BunCorsMiddleware } from './bun.cors.middleware.js'\nimport { BunMiddlewareEngine } from './bun.middleware-engine.js'\nimport { BunRequest } from './bun.request.js'\nimport { BunResponse } from './bun.response.js'\nimport { BunVersionFilterMiddleware } from './bun.version-filter.middleware.js'\n\n// Static method map - use direct string lookup for hot path\nconst REQUEST_METHOD_STRINGS: readonly string[] = [\n 'GET', // 0\n 'POST', // 1\n 'PUT', // 2\n 'DELETE', // 3\n 'PATCH', // 4\n 'ALL', // 5\n 'OPTIONS', // 6\n 'HEAD', // 7\n 'SEARCH', // 8\n 'PROPFIND', // 9\n 'PROPPATCH', // 10\n 'MKCOL', // 11\n 'COPY', // 12\n 'MOVE', // 13\n 'LOCK', // 14\n 'UNLOCK', // 15\n]\n\ntype PathHandler = Partial<\n Record<\n Serve.HTTPMethod,\n Serve.Handler<NativeRequest, Server<unknown>, Response> | Response\n >\n>\n\nexport class BunAdapter extends AbstractHttpAdapter<\n Server<unknown>,\n BunRequest,\n BunResponse\n> {\n private readonly logger: Logger = new Logger('BunAdapter', { timestamp: true })\n private readonly middlewareEngine = new BunMiddlewareEngine()\n private useVersioning = false\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n private readonly routes: Record<string, PathHandler> = Object.create(null) // Use null prototype for faster lookup\n\n // Store multiple handlers per route/method for version chaining\n private readonly routeHandlers = new Map<\n string,\n RequestHandler<BunRequest, BunResponse>[]\n >()\n\n private notFoundHandler: RequestHandler<BunRequest, BunResponse> = (\n req,\n res,\n ) => {\n res.setStatus(404)\n res.end({ message: 'Not Found' })\n }\n\n constructor(private bunServeOptions: Pick<Serve.Options<unknown>, 'development' | 'maxRequestBodySize' | 'idleTimeout' | 'id' | 'tls'> = {\n development: false,\n id: randomUUIDv7(),\n }) {\n super()\n this.setInstance({\n // Some libraries try to register middleware via `app.use(...)`\n use: (maybePath: string | RequestHandler<BunRequest, BunResponse>, maybeHandler?: RequestHandler<BunRequest, BunResponse>): void => {\n if (typeof maybePath === 'string') {\n let path = maybePath\n const handler = maybeHandler\n if (!handler) {\n throw new Error('Handler must be provided when path is a string.')\n }\n // Normalize wildcard patterns like /api/auth/* or /api/auth/*path\n // Strip trailing /* or /*anything to treat as prefix match\n if (path.includes('/*')) {\n path = path.substring(0, path.indexOf('/*'))\n }\n this.logger.log(`Registering middleware for path: ${path}`)\n this.middlewareEngine.useRoute('ALL', path, handler)\n }\n else {\n const handler = maybePath\n this.middlewareEngine.useGlobal(handler)\n }\n },\n })\n }\n\n use(middleware: RequestHandler<BunRequest, BunResponse>): void {\n this.middlewareEngine.useGlobal(middleware)\n }\n\n get(handler: RequestHandler<BunRequest, BunResponse>): void\n get(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n get(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('GET', path, handler)\n }\n\n post(handler: RequestHandler<BunRequest, BunResponse>): void\n post(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n post(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('POST', path, handler)\n }\n\n put(handler: RequestHandler<BunRequest, BunResponse>): void\n put(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n put(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('PUT', path, handler)\n }\n\n patch(handler: RequestHandler<BunRequest, BunResponse>): void\n patch(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n patch(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('PATCH', path, handler)\n }\n\n delete(handler: RequestHandler<BunRequest, BunResponse>): void\n delete(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n delete(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('DELETE', path, handler)\n }\n\n head(handler: RequestHandler<BunRequest, BunResponse>): void\n head(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n head(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('HEAD', path, handler)\n }\n\n options(handler: RequestHandler<BunRequest, BunResponse>): void\n options(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n options(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n const { path, handler } = this.parseRouteHandler(\n pathOrHandler,\n maybeHandler,\n )\n this.delegateRouteHandler('OPTIONS', path, handler)\n }\n\n all(handler: RequestHandler<BunRequest, BunResponse>): void\n all(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n all(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n propfind(handler: RequestHandler<BunRequest, BunResponse>): void\n propfind(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n propfind(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n proppatch(handler: RequestHandler<BunRequest, BunResponse>): void\n proppatch(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n proppatch(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n mkcol(handler: RequestHandler<BunRequest, BunResponse>): void\n mkcol(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n mkcol(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n copy(handler: RequestHandler<BunRequest, BunResponse>): void\n copy(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n copy(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n move(handler: RequestHandler<BunRequest, BunResponse>): void\n move(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n move(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n lock(handler: RequestHandler<BunRequest, BunResponse>): void\n lock(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n lock(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n unlock(handler: RequestHandler<BunRequest, BunResponse>): void\n unlock(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n unlock(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n search(handler: RequestHandler<BunRequest, BunResponse>): void\n search(path: unknown, handler: RequestHandler<BunRequest, BunResponse>): void\n search(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pathOrHandler: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): void {\n throw new Error('Not supported.')\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n useStaticAssets(...args: unknown[]) {\n throw new Error('Not supported.')\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n setViewEngine(engine: string) {\n throw new Error('Not supported.')\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n render(response: unknown, view: string, options: unknown) {\n throw new Error('Not supported.')\n }\n\n async close() {\n await this.httpServer.stop()\n }\n\n initHttpServer(options: NestApplicationOptions) {\n // Set dummy server to satisfy AbstractHttpAdapter requirements\n this.setHttpServer({\n once: () => { /* noop: Nest use this to listen for \"error\" event */ },\n address: () => ({ address: '0.0.0.0', port: 0 }),\n removeListener: () => { /* noop: Nest may use this to remove \"error\" listener */ },\n stop: () => { /* noop */ },\n } as unknown as Server<unknown>)\n\n if (options.httpsOptions) {\n this.bunServeOptions.tls = {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n key: options.httpsOptions.key,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n cert: options.httpsOptions.cert,\n passphrase: options.httpsOptions.passphrase,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n ca: options.httpsOptions.ca,\n ciphers: options.httpsOptions.ciphers,\n secureOptions: options.httpsOptions.secureOptions,\n rejectUnauthorized: options.httpsOptions.rejectUnauthorized,\n requestCert: options.httpsOptions.requestCert,\n }\n }\n }\n\n getRequestHostname(request: BunRequest) {\n return request.hostname\n }\n\n getRequestMethod(request: BunRequest) {\n return request.method\n }\n\n getRequestUrl(request: BunRequest) {\n return request.pathname\n }\n\n status(response: BunResponse, statusCode: number) {\n response.setStatus(statusCode)\n }\n\n reply(response: BunResponse, body: unknown, statusCode?: number) {\n if (statusCode) {\n response.setStatus(statusCode)\n }\n\n response.end(body)\n }\n\n end(response: BunResponse, message?: string) {\n response.end(message)\n }\n\n redirect(response: BunResponse, statusCode: number, url: string) {\n response.redirect(url, statusCode)\n }\n\n setErrorHandler(\n handler: ErrorHandler<BunRequest, BunResponse>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n prefix?: string,\n ) {\n this.middlewareEngine.useErrorHandler(handler)\n }\n\n setNotFoundHandler(\n handler: RequestHandler<BunRequest, BunResponse>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n prefix?: string,\n ) {\n this.notFoundHandler = handler\n this.middlewareEngine.useNotFoundHandler(handler)\n }\n\n isHeadersSent(response: BunResponse): boolean {\n return response.isEnded()\n }\n\n getHeader(response: BunResponse, name: string): string | null {\n return response.getHeader(name)\n }\n\n setHeader(response: BunResponse, name: string, value: string) {\n response.setHeader(name, value)\n }\n\n appendHeader(response: BunResponse, name: string, value: string) {\n response.appendHeader(name, value)\n }\n\n registerParserMiddleware(prefix?: string, rawBody?: boolean) {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n this.logger.log(`Registering Body Parser Middleware with prefix: ${prefix || '/'} and rawBody: ${rawBody ? 'true' : 'false'}`)\n const bodyParser = new BunBodyParserMiddleware({ prefix, rawBody })\n this.middlewareEngine.useGlobal(bodyParser.run.bind(bodyParser))\n }\n\n enableCors(\n options?: CorsOptions | CorsOptionsDelegate<BunRequest>,\n prefix?: string,\n ) {\n this.logger.log(`Enabling CORS Middleware with prefix: ${prefix ?? '/'}`)\n const corsMiddleware = new BunCorsMiddleware({ corsOptions: options, prefix })\n this.middlewareEngine.useGlobal(corsMiddleware.run.bind(corsMiddleware))\n }\n\n createMiddlewareFactory(\n requestMethod: RequestMethod,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n ): (path: string, callback: Function) => void {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return (path: string, callback: Function) => {\n // Map RequestMethod enum to string method name\n const methodName = this.mapRequestMethodToString(requestMethod)\n\n // Handle wildcard routes (applies to all paths)\n // NestJS uses \"/*\" or \"*\" for wildcard routes\n if (path === '*' || path === '/*') {\n this.middlewareEngine.useWildcard(\n methodName,\n callback as RequestHandler<BunRequest, BunResponse>,\n )\n return\n }\n\n // Normalize path by removing trailing slash (except for root \"/\")\n const normalizedPath = path === '/' ? path : path.replace(/\\/$/, '')\n this.middlewareEngine.useRoute(\n methodName,\n normalizedPath,\n callback as RequestHandler<BunRequest, BunResponse>,\n )\n }\n }\n\n getType(): string {\n return 'bun'\n }\n\n applyVersionFilter(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n handler: Function,\n version: VersionValue,\n versioningOptions: VersioningOptions,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n ): (req: BunRequest, res: BunResponse, next: () => void) => Function {\n this.logger.log(`Applying Version Filter Middleware for version: ${JSON.stringify(version)}`)\n this.useVersioning = true\n return BunVersionFilterMiddleware.createFilter(\n handler as (req: BunRequest, res: BunResponse, next: () => void) => unknown,\n version,\n versioningOptions,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n ) as (req: BunRequest, res: BunResponse, next: () => void) => Function\n }\n\n /**\n * Start listening on the specified port and hostname.\n * @param port The port number or Unix socket path to listen on.\n * @param callback Optional callback to invoke once the server is listening.\n */\n listen(port: string | number, callback?: () => void): void\n /**\n * Start listening on the specified port and hostname.\n * @param port The port number or Unix socket path to listen on.\n * @param hostname The hostname to bind to.\n * @param callback Optional callback to invoke once the server is listening.\n */\n listen(port: string | number, hostname: string, callback?: () => void): void\n /**\n * Start listening on the specified port and hostname.\n * @param port The port number or Unix socket path to listen on.\n * @param hostnameOrCallback The hostname to bind to or the callback function.\n * @param maybeCallback Optional callback to invoke once the server is listening.\n */\n listen(\n port: string | number,\n hostnameOrCallback?: string | (() => void),\n maybeCallback?: () => void,\n ): void {\n const hostname\n = typeof hostnameOrCallback === 'string' ? hostnameOrCallback : 'localhost'\n const callback\n = typeof hostnameOrCallback === 'function'\n ? hostnameOrCallback\n : maybeCallback\n\n // Capture references for closure - avoid 'this' lookup in hot path\n const middlewareEngine = this.middlewareEngine\n const notFoundHandler = this.notFoundHandler\n\n const fetch = async (request: NativeRequest): Promise<Response> => {\n const bunRequest = new BunRequest(request)\n const bunResponse = new BunResponse()\n // Find the actual route handler or fall back to notFoundHandler\n const routeHandler = middlewareEngine.findRouteHandler(bunRequest.method, bunRequest.pathname) ?? notFoundHandler\n // Inline property access for hot path\n await middlewareEngine.run({\n req: bunRequest,\n res: bunResponse,\n method: bunRequest.method,\n path: bunRequest.pathname,\n requestHandler: routeHandler,\n })\n return bunResponse.res()\n }\n\n const omit = <T extends object, K extends keyof T>(\n obj: T,\n ...keys: K[]\n ): Omit<T, K> => {\n const result = { ...obj }\n for (const key of keys) {\n Reflect.deleteProperty(result, key)\n }\n return result\n }\n\n const server = typeof port === 'number' || !isNaN(Number(port))\n ? Bun.serve<unknown>({\n ...this.bunServeOptions,\n hostname,\n port,\n routes: this.routes,\n fetch,\n })\n : Bun.serve<unknown>({\n ...omit(this.bunServeOptions, 'idleTimeout'),\n unix: port,\n routes: this.routes,\n fetch,\n })\n\n if (typeof port === 'string' && isNaN(Number(port))) {\n this.logger.log(`Bun server listening on unix socket: ${port}`)\n }\n\n callback?.()\n\n // Add `address` method to match Node.js Server interface\n Object.defineProperty(server, 'address', {\n configurable: true,\n enumerable: true,\n get: () => ({ address: server.hostname, port: server.port }),\n })\n\n this.setHttpServer(server)\n }\n\n private delegateRouteHandler(\n method: Serve.HTTPMethod,\n path: string,\n handler: RequestHandler<BunRequest, BunResponse>,\n ): void {\n // Use null prototype object for route if not exists\n if (!(path in this.routes)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n this.routes[path] = Object.create(null)\n }\n\n const requestHandler = !this.useVersioning\n ? handler\n // Create handler that wraps array + fallback into a single callable\n // This avoids recreating the chained handler on every request\n : this.createChainedHandlerForVersioningResolution(\n this.createVersioningHandlers(method, path, handler),\n this.notFoundHandler,\n )\n\n this.routes[path][method] = async (request: NativeRequest): Promise<Response> => {\n const bunRequest = new BunRequest(request)\n const bunResponse = new BunResponse()\n\n await this.middlewareEngine.run({\n req: bunRequest,\n res: bunResponse,\n method,\n path,\n requestHandler,\n })\n\n return bunResponse.res()\n }\n }\n\n private createVersioningHandlers(\n method: Serve.HTTPMethod,\n path: string,\n handler: RequestHandler<BunRequest, BunResponse>,\n ) {\n // Store handler in the handlers array for chaining (versioning support)\n const routeKey = `${method}:${path}`\n let versioningHandlers = this.routeHandlers.get(routeKey)\n if (!versioningHandlers) {\n versioningHandlers = []\n this.routeHandlers.set(routeKey, versioningHandlers)\n }\n versioningHandlers.push(handler)\n\n return versioningHandlers\n }\n\n private async executeHandlerChain(\n handlers: RequestHandler<BunRequest, BunResponse>[],\n req: BunRequest,\n res: BunResponse,\n ): Promise<void> {\n const handlersLength = handlers.length\n let index = 0\n let shouldContinue = true\n\n while (shouldContinue && index < handlersLength && !res.isEnded()) {\n shouldContinue = false\n const currentIndex = index++\n const result = handlers[currentIndex](req, res, () => {\n shouldContinue = true\n }) as unknown\n if (result instanceof Promise) await result\n }\n }\n\n private createChainedHandlerForVersioningResolution(\n handlers: RequestHandler<BunRequest, BunResponse>[],\n notFoundHandler: RequestHandler<BunRequest, BunResponse>,\n ): RequestHandler<BunRequest, BunResponse> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return (async (req: BunRequest, res: BunResponse, next?: Function): Promise<void> => {\n // First pass: discovery for versioning\n await this.executeHandlerChain(handlers, req, res)\n\n // Check for custom versioning candidates\n if (!res.isEnded() && BunVersionFilterMiddleware.hasCustomVersioningCandidates(req)) {\n const bestVersion = BunVersionFilterMiddleware.selectBestCustomVersionCandidate(req)\n\n if (bestVersion) {\n BunVersionFilterMiddleware.setCustomVersioningExecutionPhase(req, bestVersion)\n await this.executeHandlerChain(handlers, req, res)\n }\n }\n\n // If still not handled, call not found handler\n if (!res.isEnded()) {\n notFoundHandler(req, res, next)\n }\n }) as RequestHandler<BunRequest, BunResponse>\n }\n\n private mapRequestMethodToString(requestMethod: RequestMethod): string {\n return REQUEST_METHOD_STRINGS[requestMethod] ?? 'ALL'\n }\n\n private parseRouteHandler(handler: RequestHandler<BunRequest, BunResponse>): {\n path: string\n handler: RequestHandler<BunRequest, BunResponse>\n }\n private parseRouteHandler(\n path: unknown,\n handler?: RequestHandler<BunRequest, BunResponse>,\n ): { path: string, handler: RequestHandler<BunRequest, BunResponse> }\n private parseRouteHandler(\n pathOrHandler: unknown,\n maybeHandler?: RequestHandler<BunRequest, BunResponse>,\n ): { path: string, handler: RequestHandler<BunRequest, BunResponse> } {\n const path = typeof pathOrHandler === 'string' ? pathOrHandler : '/'\n const handler\n = typeof pathOrHandler === 'function'\n ? (pathOrHandler as RequestHandler<BunRequest, BunResponse>)\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n : maybeHandler!\n return { path, handler }\n }\n}\n",
|
|
6
6
|
"import { BunRequest } from './bun.request.js'\nimport { BunResponse } from './bun.response.js'\n\n// Pre-computed method codes for fast comparison\nconst GET_CODE = 'GET'.charCodeAt(0) // 71\nconst HEAD_CODE = 'HEAD'.charCodeAt(0) // 72\nconst DELETE_CODE = 'DELETE'.charCodeAt(0) // 68\nconst OPTIONS_CODE = 'OPTIONS'.charCodeAt(0) // 79\n\nexport class BunBodyParserMiddleware {\n private readonly prefix: string | null\n private readonly rawBody: boolean\n private readonly prefixLen: number\n\n constructor(options?: { prefix?: string, rawBody?: boolean }) {\n this.prefix = options?.prefix ?? null\n this.prefixLen = this.prefix?.length ?? 0\n this.rawBody = options?.rawBody ?? false\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n async run(req: BunRequest, res: BunResponse, next?: Function): Promise<void> {\n // Fast path: skip body parsing for methods that don't have body\n // Use charCodeAt for fast string comparison\n const methodFirstChar = req.method.charCodeAt(0)\n if (\n methodFirstChar === GET_CODE // Most common case first\n || methodFirstChar === HEAD_CODE\n || methodFirstChar === DELETE_CODE\n || methodFirstChar === OPTIONS_CODE\n ) {\n next?.()\n return\n }\n\n // Check prefix if specified\n if (this.prefix !== null) {\n const pathname = req.pathname\n if (pathname.length < this.prefixLen || !pathname.startsWith(this.prefix)) {\n next?.()\n return\n }\n }\n\n if (this.rawBody) {\n req.setRawBody(await req.arrayBuffer())\n }\n\n await this.parseRequestBody(req)\n next?.()\n }\n\n private async parseRequestBody(req: BunRequest): Promise<void> {\n const contentType = req.headers.get('content-type')\n if (!contentType) {\n return\n }\n\n // Use indexOf for faster content-type checking\n if (contentType.includes('application/json')) {\n req.setBody(await req.json())\n return\n }\n\n if (contentType.includes('text/') || contentType.includes('application/text')) {\n req.setBody(await req.text())\n return\n }\n\n if (contentType.includes('form')) {\n await this.parseFormData(req)\n }\n }\n\n private async parseFormData(req: BunRequest): Promise<void> {\n const formData = await req.formData()\n const body: Record<string, string | File> = Object.create(null) as Record<string, string | File>\n let files: File[] | null = null\n let firstFile: File | null = null\n\n for (const [key, value] of formData.entries()) {\n body[key] = value\n // Fast file detection using 'size' property check\n if (this.isFile(value)) {\n if (firstFile === null) {\n firstFile = value\n files = [value]\n }\n else {\n files?.push(value)\n }\n }\n }\n\n req.setBody(body)\n\n if (firstFile !== null) {\n req.setFile(firstFile)\n }\n\n if (files !== null) {\n req.setFiles(files)\n }\n }\n\n private isFile(value: unknown): value is File {\n return typeof value === 'object' && value !== null && 'size' in value && 'name' in value && 'type' in value\n }\n}\n",
|
|
7
7
|
"import {\n CorsOptionsDelegate,\n CorsOptions as NestCorsOptions,\n} from '@nestjs/common/interfaces/external/cors-options.interface.js'\nimport { IncomingMessage, ServerResponse } from 'node:http'\nimport cors, { CorsOptions } from 'cors'\n\nimport { BunRequest } from './bun.request.js'\nimport { BunResponse } from './bun.response.js'\n\ntype NextFunction = ((err?: Error) => void) | undefined\n\nexport class BunCorsMiddleware {\n private readonly options?: NestCorsOptions | CorsOptionsDelegate<BunRequest>\n private readonly prefix?: string\n\n constructor(options?: {\n corsOptions?: NestCorsOptions | CorsOptionsDelegate<BunRequest>\n prefix?: string\n }) {\n this.options = options?.corsOptions\n this.prefix = options?.prefix\n }\n\n async run(\n req: BunRequest,\n res: BunResponse,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n next: NextFunction | Function,\n ): Promise<void> {\n const nextFn = next as NextFunction\n\n if (this.prefix && !req.pathname.startsWith(this.prefix)) {\n return nextFn?.()\n }\n\n const corsOptions = await this.resolveCorsOptions(req)\n const { nodeReq, nodeRes, isEnded } = this.createNodeAdapters(req, res)\n\n cors(corsOptions)(nodeReq, nodeRes, (err?: Error) => {\n if (err) return nextFn?.(err)\n if (!isEnded()) nextFn?.()\n })\n }\n\n private async resolveCorsOptions(\n req: BunRequest,\n ): Promise<CorsOptions | undefined> {\n const options = this.options\n if (typeof options === 'function') {\n return new Promise((resolve, reject) => {\n options(req, (err: Error | null, opts: NestCorsOptions | undefined) => {\n if (err) reject(err)\n else resolve(opts as CorsOptions)\n })\n })\n }\n if (!options) return undefined\n return {\n origin: options.origin as CorsOptions['origin'],\n methods: options.methods,\n allowedHeaders: options.allowedHeaders,\n exposedHeaders: options.exposedHeaders,\n credentials: options.credentials,\n maxAge: options.maxAge,\n preflightContinue: options.preflightContinue,\n optionsSuccessStatus: options.optionsSuccessStatus,\n }\n }\n\n private createNodeAdapters(req: BunRequest, res: BunResponse) {\n const nodeReq = {\n method: req.method,\n headers: req.headers,\n url: req.pathname,\n } as unknown as IncomingMessage\n\n const nodeRes = {\n get statusCode() { return res.getStatus() },\n set statusCode(code: number) { res.setStatus(code) },\n setHeader: (key: string, value: string) => { res.setHeader(key, value) },\n end: (data?: unknown) => { res.end(data) },\n getHeader: (name: string) => res.getHeader(name),\n removeHeader: (name: string) => { res.removeHeader(name) },\n } as unknown as ServerResponse\n\n return { nodeReq, nodeRes, isEnded: () => res.isEnded() }\n }\n}\n",
|
|
8
|
-
"import { ErrorHandler, RequestHandler } from '@nestjs/common/interfaces/index.js'\nimport { ErrorLike } from 'bun'\n\nimport { BunRequest } from './bun.request.js'\nimport { BunResponse } from './bun.response.js'\n\ntype MiddlewareHandler = RequestHandler<BunRequest, BunResponse>\ninterface MiddlewareRunOptions {\n req: BunRequest\n res: BunResponse\n method: string\n path: string\n requestHandler: MiddlewareHandler\n}\n\n// Shared empty array to avoid allocations\nconst EMPTY_HANDLERS: readonly MiddlewareHandler[] = new Array<MiddlewareHandler>(0)\n\n// Reusable noop function for error handler\nconst noop = (): void => { /* noop */ }\n\nexport class BunMiddlewareEngine {\n private readonly globalMiddlewares: MiddlewareHandler[] = []\n private readonly routeMiddleware = new Map<string, MiddlewareHandler[]>()\n // Group route middleware by method for faster prefix matching\n private readonly routeMiddlewareByMethod = new Map<string, Map<string, MiddlewareHandler[]>>()\n private readonly wildcardMiddleware = new Map<string, MiddlewareHandler[]>()\n private readonly middlewareCache = new Map<string, MiddlewareHandler[]>()\n private errorHandler: ErrorHandler<BunRequest, BunResponse> | null = null\n private notFoundHandler: MiddlewareHandler | null = null\n\n useGlobal(middleware: MiddlewareHandler): void {\n this.globalMiddlewares.push(middleware)\n }\n\n useRoute(method: string, path: string, middleware: MiddlewareHandler): void {\n const key = `${method}:${path}`;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n (this.routeMiddleware.get(key) ?? (this.routeMiddleware.set(key, []).get(key)!)).push(middleware);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n (this.routeMiddlewareByMethod.get(method) ?? this.routeMiddlewareByMethod.set(method, new Map()).get(method)!)\n .set(path, ((this.routeMiddlewareByMethod.get(method)?.get(path)) ?? []))\n .get(path)!\n .push(middleware)\n }\n\n useWildcard(method: string, middleware: MiddlewareHandler): void {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n (this.wildcardMiddleware.get(method) ?? this.wildcardMiddleware.set(method, []).get(method)!).push(middleware)\n }\n\n useErrorHandler(handler: ErrorHandler<BunRequest, BunResponse>): void {\n this.errorHandler = handler\n }\n\n useNotFoundHandler(handler: MiddlewareHandler): void {\n this.notFoundHandler = handler\n }\n\n async run(options: MiddlewareRunOptions): Promise<BunResponse> {\n try {\n const middlewares = this.getMiddlewareChain(options.method, options.path)\n await this.executeChain(middlewares, options.requestHandler, options.req, options.res)\n return options.res\n }\n catch (error) {\n return this.handleError(error, options.req, options.res)\n }\n }\n\n private getMiddlewareChain(method: string, path: string): MiddlewareHandler[] {\n const cacheKey = `${method}:${path}`\n let cached = this.middlewareCache.get(cacheKey)\n if (cached !== undefined) return cached\n\n cached = this.buildMiddlewareChain(method, path, cacheKey)\n this.middlewareCache.set(cacheKey, cached)\n return cached\n }\n\n private buildMiddlewareChain(\n method: string,\n path: string,\n cacheKey: string,\n ): MiddlewareHandler[] {\n // Minimize array operations and allocations\n const global = this.globalMiddlewares\n const globalLen = global.length\n const wildcardAll = this.wildcardMiddleware.get('ALL')\n const wildcardMethod = this.wildcardMiddleware.get(method)\n const routeMiddleware = this.findRouteMiddleware(method, path, cacheKey)\n\n const wildcardAllLen = wildcardAll?.length ?? 0\n const wildcardMethodLen = wildcardMethod?.length ?? 0\n const routeLen = routeMiddleware.length\n\n const totalLen = globalLen + wildcardAllLen + wildcardMethodLen + routeLen\n if (totalLen === 0) return EMPTY_HANDLERS as MiddlewareHandler[]\n\n // Avoid iterator overhead from for...of loops\n const chain = new Array<MiddlewareHandler>(totalLen)\n let idx = 0\n\n // Global middlewares\n for (let i = 0; i < globalLen; i++) chain[idx++] = global[i]\n // Wildcard middlewares\n if (wildcardAll) for (let i = 0; i < wildcardAllLen; i++) chain[idx++] = wildcardAll[i]\n // Method-specific wildcard middlewares\n if (wildcardMethod) for (let i = 0; i < wildcardMethodLen; i++) chain[idx++] = wildcardMethod[i]\n // Route-specific middlewares\n for (let i = 0; i < routeLen; i++) chain[idx++] = routeMiddleware[i]\n\n return chain\n }\n\n private findRouteMiddleware(\n method: string,\n path: string,\n cacheKey: string,\n ): readonly MiddlewareHandler[] {\n const exactMiddleware = this.routeMiddleware.get(cacheKey)\n if (exactMiddleware !== undefined) return exactMiddleware\n return this.findBestPrefixMatch(method, path)\n }\n\n private findBestPrefixMatch(\n method: string,\n path: string,\n ): readonly MiddlewareHandler[] {\n const methodMap = this.routeMiddlewareByMethod.get(method)\n if (!methodMap) return EMPTY_HANDLERS\n\n let bestMatch: MiddlewareHandler[] | null = null\n let bestMatchLength = 0\n const pathLen = path.length\n\n for (const [keyPath, middleware] of methodMap) {\n const keyPathLen = keyPath.length\n if (keyPathLen <= bestMatchLength || middleware.length === 0) continue\n\n // Fast path check: exact match or prefix match with /\n if (path === keyPath || (pathLen > keyPathLen && path.charCodeAt(keyPathLen) === 47 /* '/' */ && path.startsWith(keyPath))) {\n bestMatch = middleware\n bestMatchLength = keyPathLen\n }\n }\n\n return bestMatch ?? EMPTY_HANDLERS\n }\n\n private async executeChain(\n chain: MiddlewareHandler[],\n requestHandler: MiddlewareHandler,\n req: BunRequest,\n res: BunResponse,\n ): Promise<void> {\n const chainLength = chain.length\n let index = 0\n\n const next = async (err?: ErrorLike): Promise<void> => {\n if (err) throw err\n\n // Process middleware chain\n if (index < chainLength) {\n const handler = chain[index++]\n const result = handler(req, res, next) as unknown\n if (result instanceof Promise) await result\n return\n }\n\n // Process request handler at the end\n if (index === chainLength) {\n index++\n const result = requestHandler(req, res, next) as unknown\n
|
|
9
|
-
"/* eslint-disable sonarjs/no-nested-assignment */\nimport { CookieMap, BunRequest as NativeRequest } from 'bun'\nimport { ParsedQs, parse } from 'qs'\n\n// Optimized headers type - use native Headers for hot-path .get()\ntype HeadersProxy = Record<string, string> & {\n get: (key: string) => string | null\n}\n\n// Pre-allocated empty object for Object.create(null) pattern\nconst NULL_PROTO = Object.getPrototypeOf(Object.create(null)) as object\n\n/**\n * A high-performance request wrapper for Bun's native request object.\n * Provides lazy parsing and caching for optimal performance in NestJS applications.\n *\n * @example\n * ```typescript\n * const bunRequest = new BunRequest(nativeRequest);\n * const pathname = bunRequest.pathname; // Lazily parsed\n * const query = bunRequest.query; // Parsed only when accessed\n * ```\n */\nexport class BunRequest {\n private _nativeHeaders: Headers\n private _headers: HeadersProxy | null = null\n private _hostname: string | null = null\n private _pathname: string | null = null\n private _query: ParsedQs | null = null\n private _body: unknown = null\n private _rawBody: ArrayBuffer | null = null\n private _file: File | null = null\n private _files: File[] | null = null\n private _settings: Map<string, unknown> | null = null\n\n // Cache URL parts at construction time for hot-path access\n private readonly _url: string\n private readonly _parsedUrl: URL\n readonly method: string\n readonly params: Record<string, string>\n\n constructor(private readonly nativeRequest: NativeRequest) {\n this._url = nativeRequest.url\n this._parsedUrl = new URL(this._url)\n this._nativeHeaders = nativeRequest.headers\n this.method = nativeRequest.method\n this.params = nativeRequest.params\n }\n\n /**\n * Gets the full URL of the request.\n *\n * @returns The complete URL string\n * @example\n * ```typescript\n * const url = request.url; // \"http://localhost:3000/api/users?page=1\"\n * ```\n */\n get url(): string { return this._url }\n\n /**\n * Gets the pathname portion of the URL.\n * Uses lazy parsing for optimal performance - the pathname is only extracted when first accessed.\n *\n * @returns The pathname component of the URL\n * @example\n * ```typescript\n * // For URL \"http://localhost:3000/api/users?page=1\"\n * const pathname = request.pathname; // \"/api/users\"\n * ```\n */\n get pathname(): string {\n return this._pathname ??= this._parsedUrl.pathname\n }\n\n /**\n * Gets the hostname portion of the URL.\n * Uses lazy parsing - the hostname is only extracted when first accessed.\n *\n * @returns The hostname component of the URL (without port)\n * @example\n * ```typescript\n * // For URL \"http://localhost:3000/api/users\"\n * const hostname = request.hostname; // \"localhost\"\n * ```\n */\n get hostname(): string {\n return this._hostname ??= this.headers.get('x-forwarded-host') ?? this._parsedUrl.hostname\n }\n\n /**\n * Gets all request headers as a key-value object.\n * Uses lazy parsing - headers are materialized only when first accessed.\n * All header keys are normalized to lowercase.\n *\n * @returns An object containing all headers with a .get() method for efficient lookups\n * @example\n * ```typescript\n * const headers = request.headers;\n * const contentType = headers['content-type']; // Direct access\n * const auth = headers.get('Authorization'); // Using .get() method\n * ```\n */\n get headers(): HeadersProxy {\n if (this._headers !== null) return this._headers\n const native = this._nativeHeaders\n // Create proxy that uses native .get() and materializes properties lazily\n const proxy = Object.create(NULL_PROTO) as HeadersProxy\n // Materialize all headers for NestJS decorators that iterate over keys\n native.forEach((value: string, key: string) => {\n proxy[key.toLowerCase()] = value\n })\n proxy.get = (key: string) => native.get(key)\n return this._headers = proxy\n }\n\n /**\n * Gets the parsed query parameters from the URL.\n * Uses lazy parsing - query string is only parsed when first accessed.\n *\n * @returns Parsed query parameters as an object\n * @example\n * ```typescript\n * // For URL \"http://localhost:3000/api/users?page=1&limit=10\"\n * const query = request.query;\n * console.log(query.page); // \"1\"\n * console.log(query.limit); // \"10\"\n * ```\n */\n get query(): ParsedQs {\n return this._query ??= parse(this._parsedUrl.searchParams.toString())\n }\n\n /**\n * Gets the parsed request body.\n *\n * @returns The parsed body content (could be JSON, form data, etc.)\n * @example\n * ```typescript\n * const body = request.body;\n * console.log(body); // { name: \"John\", email: \"john@example.com\" }\n * ```\n */\n get body(): unknown { return this._body }\n\n /**\n * Sets the parsed request body.\n * Typically used by body parser middleware.\n *\n * @param body - The parsed body content to set\n * @example\n * ```typescript\n * request.setBody({ name: \"John\", email: \"john@example.com\" });\n * ```\n */\n setBody(body: unknown): void { this._body = body }\n\n /**\n * Gets the raw request body as an ArrayBuffer.\n *\n * @returns The raw body data or null if not set\n * @example\n * ```typescript\n * const rawBody = request.rawBody;\n * if (rawBody) {\n * const text = new TextDecoder().decode(rawBody);\n * }\n * ```\n */\n get rawBody(): ArrayBuffer | null { return this._rawBody }\n\n /**\n * Sets the raw request body as an ArrayBuffer.\n *\n * @param rawBody - The raw body data to set\n * @example\n * ```typescript\n * const buffer = await request.arrayBuffer();\n * request.setRawBody(buffer);\n * ```\n */\n setRawBody(rawBody: ArrayBuffer): void { this._rawBody = rawBody }\n\n /**\n * Gets the uploaded file from the request.\n * Used for single file uploads.\n *\n * @returns The uploaded file or null if no file was uploaded\n * @example\n * ```typescript\n * const file = request.file;\n * if (file) {\n * console.log(file.name); // \"avatar.png\"\n * console.log(file.size); // 2048\n * }\n * ```\n */\n get file(): File | null { return this._file }\n\n /**\n * Sets the uploaded file in the request.\n * Typically used by file upload middleware.\n *\n * @param file - The file to set\n * @example\n * ```typescript\n * const formData = await request.formData();\n * const file = formData.get('avatar') as File;\n * request.setFile(file);\n * ```\n */\n setFile(file: File): void { this._file = file }\n\n /**\n * Gets all uploaded files from the request.\n * Used for multiple file uploads.\n *\n * @returns Array of uploaded files or null if no files were uploaded\n * @example\n * ```typescript\n * const files = request.files;\n * if (files) {\n * files.forEach(file => {\n * console.log(file.name, file.size);\n * });\n * }\n * ```\n */\n get files(): File[] | null { return this._files }\n\n /**\n * Sets multiple uploaded files in the request.\n * Typically used by file upload middleware.\n *\n * @param files - Array of files to set\n * @example\n * ```typescript\n * const formData = await request.formData();\n * const files = formData.getAll('attachments') as File[];\n * request.setFiles(files);\n * ```\n */\n setFiles(files: File[]): void { this._files = files }\n\n /**\n * Gets a custom setting/property stored in the request.\n * Useful for passing data between middleware and handlers.\n *\n * @param key - The setting key to retrieve\n * @returns The stored value or undefined if not found\n * @example\n * ```typescript\n * // In middleware\n * request.set('user', { id: 1, name: 'John' });\n *\n * // In handler\n * const user = request.get('user');\n * console.log(user); // { id: 1, name: 'John' }\n * ```\n */\n get(key: string): unknown { return this._settings?.get(key) }\n\n /**\n * Sets a custom setting/property in the request.\n * Useful for passing data between middleware and handlers.\n *\n * @param key - The setting key to store\n * @param value - The value to store\n * @example\n * ```typescript\n * request.set('user', { id: 1, name: 'John' });\n * request.set('startTime', Date.now());\n * ```\n */\n set(key: string, value: unknown): void {\n (this._settings ??= new Map()).set(key, value)\n }\n\n /**\n * Gets the AbortSignal for the request.\n * Can be used to detect if the request has been cancelled.\n *\n * @returns The request's AbortSignal\n * @example\n * ```typescript\n * const signal = request.signal;\n * signal.addEventListener('abort', () => {\n * console.log('Request was cancelled');\n * });\n * ```\n */\n get signal(): AbortSignal { return this.nativeRequest.signal }\n\n /**\n * Gets the cookies from the request.\n *\n * @returns A Map-like object containing all cookies\n * @example\n * ```typescript\n * const cookies = request.cookies;\n * const sessionId = cookies.get('sessionId');\n * console.log(sessionId?.value);\n * ```\n */\n get cookies(): CookieMap { return this.nativeRequest.cookies }\n\n /**\n * Parses the request body as JSON.\n *\n * @returns Promise that resolves to the parsed JSON data\n * @example\n * ```typescript\n * const data = await request.json();\n * console.log(data); // { name: \"John\", email: \"john@example.com\" }\n * ```\n */\n json(): Promise<unknown> { return this.nativeRequest.json() }\n\n /**\n * Reads the request body as text.\n *\n * @returns Promise that resolves to the body text\n * @example\n * ```typescript\n * const text = await request.text();\n * console.log(text); // \"Hello, World!\"\n * ```\n */\n text(): Promise<string> { return this.nativeRequest.text() }\n\n /**\n * Parses the request body as FormData.\n *\n * @returns Promise that resolves to the parsed FormData\n * @example\n * ```typescript\n * const formData = await request.formData();\n * const name = formData.get('name');\n * console.log(name); // \"John\"\n * ```\n */\n // eslint-disable-next-line @typescript-eslint/no-deprecated, sonarjs/deprecation\n formData(): Promise<FormData> { return this.nativeRequest.formData() as unknown as Promise<FormData> }\n\n /**\n * Reads the request body as an ArrayBuffer.\n *\n * @returns Promise that resolves to the body as ArrayBuffer\n * @example\n * ```typescript\n * const buffer = await request.arrayBuffer();\n * console.log(buffer.byteLength); // 1024\n * ```\n */\n arrayBuffer(): Promise<ArrayBuffer> { return this.nativeRequest.arrayBuffer() }\n\n /**\n * Reads the request body as a Blob.\n *\n * @returns Promise that resolves to the body as Blob\n * @example\n * ```typescript\n * const blob = await request.blob();\n * console.log(blob.type); // \"image/png\"\n * ```\n */\n blob(): Promise<Blob> { return this.nativeRequest.blob() }\n\n /**\n * Reads the request body as a Uint8Array.\n *\n * @returns Promise that resolves to the body as Uint8Array\n * @example\n * ```typescript\n * const bytes = await request.bytes();\n * console.log(bytes.length); // 1024\n * ```\n */\n bytes(): Promise<Uint8Array> { return this.nativeRequest.bytes() }\n\n /**\n * Creates a deep clone of the request.\n * Clones both the native request and all cached properties.\n *\n * @returns A new BunRequest instance with cloned data\n * @example\n * ```typescript\n * const originalRequest = new BunRequest(nativeRequest);\n * const clonedRequest = originalRequest.clone();\n *\n * // Modifications to clone don't affect original\n * clonedRequest.set('user', { id: 1 });\n * console.log(originalRequest.get('user')); // undefined\n * ```\n */\n clone(): BunRequest {\n const cloned = new BunRequest(this.nativeRequest.clone())\n cloned._pathname = this._pathname\n cloned._body = this._body\n cloned._rawBody = this._rawBody\n cloned._file = this._file\n cloned._files = this._files\n cloned._headers = this._headers\n cloned._query = this._query\n cloned._settings = this._settings\n return cloned\n }\n}\n",
|
|
10
|
-
"/* eslint-disable sonarjs/no-nested-assignment */\nimport { BodyInit, Cookie, CookieInit, CookieMap, CookieStoreDeleteOptions } from 'bun'\nimport { StreamableFile } from '@nestjs/common'\n\n// Pre-allocated JSON content type header\nconst JSON_CONTENT_TYPE = 'application/json'\n\n/**\n * A high-performance response builder for Bun's native Response object.\n * Provides methods to build responses with headers, cookies, and various body types.\n * Uses lazy initialization and optimized response building for maximum performance.\n *\n * @example\n * ```typescript\n * const response = new BunResponse();\n * response.setStatus(200);\n * response.setHeader('Content-Type', 'application/json');\n * response.cookie('sessionId', 'abc123');\n * response.end({ message: 'Success' });\n * ```\n */\nexport class BunResponse {\n private resolve!: (value: Response) => void\n private readonly response: Promise<Response>\n private readonly cookieMap = new CookieMap()\n\n // Use Map for O(1) header operations - faster than Headers for small sets\n private _headers: Map<string, string> | null = null\n private statusCode = 200\n private ended = false\n // Cache for cookie headers to avoid repeated string operations\n private _cookieHeaderCache: string | null = null\n\n constructor() {\n // Keep constructor minimal to reduce allocation overhead\n this.response = new Promise<Response>((r) => {\n this.resolve = r\n })\n }\n\n // Lazy headers initialization\n private get headersMap(): Map<string, string> {\n return this._headers ??= new Map()\n }\n\n /**\n * Sets a cookie in the response.\n * Can be called with either a cookie options object or name-value pair.\n *\n * @param options - Cookie configuration object\n * @example\n * ```typescript\n * // Using name-value pair\n * response.cookie('sessionId', 'abc123');\n *\n * // Using options object\n * response.cookie({\n * name: 'sessionId',\n * value: 'abc123',\n * httpOnly: true,\n * secure: true,\n * maxAge: 3600\n * });\n * ```\n */\n cookie(options: CookieInit | Cookie): void\n /**\n * Sets a cookie in the response using name and value.\n *\n * @param name - The cookie name\n * @param value - The cookie value\n */\n cookie(name: string, value: string): void\n cookie(...args: unknown[]): void {\n // Invalidate cookie header cache when cookies change\n this._cookieHeaderCache = null\n if (args.length === 1) {\n this.cookieMap.set(args[0] as CookieInit | Cookie)\n }\n else {\n this.cookieMap.set(\n args[0] as string,\n args[1] as string,\n )\n }\n }\n\n /**\n * Deletes a cookie from the response.\n *\n * @param optionsOrName - Cookie name or delete options\n * @example\n * ```typescript\n * // Delete by name\n * response.deleteCookie('sessionId');\n *\n * // Delete with options\n * response.deleteCookie({\n * name: 'sessionId',\n * path: '/',\n * domain: 'example.com'\n * });\n * ```\n */\n deleteCookie(optionsOrName: CookieStoreDeleteOptions | string): void\n /**\n * Deletes a cookie from the response with additional options.\n *\n * @param optionsOrName - Cookie name\n * @param options - Additional delete options (path, domain, etc.)\n */\n deleteCookie(optionsOrName: string, options: Omit<CookieStoreDeleteOptions, 'name'>): void\n deleteCookie(optionsOrName: CookieStoreDeleteOptions | string, options?: Omit<CookieStoreDeleteOptions, 'name'>): void {\n if (typeof optionsOrName === 'string') {\n this.cookieMap.delete(optionsOrName, options as unknown as Omit<CookieStoreDeleteOptions, 'name'>)\n }\n else {\n this.cookieMap.delete(optionsOrName)\n }\n }\n\n /**\n * Sends a redirect response to the specified URL.\n * Ends the response after calling this method.\n *\n * @param url - The URL to redirect to\n * @param statusCode - HTTP status code for the redirect (default: 302)\n * @example\n * ```typescript\n * // Temporary redirect (302)\n * response.redirect('/login');\n *\n * // Permanent redirect (301)\n * response.redirect('/new-page', 301);\n *\n * // See Other (303)\n * response.redirect('/success', 303);\n * ```\n */\n redirect(url: string, statusCode = 302): void {\n if (this.ended) return\n this.ended = true\n this.resolve(Response.redirect(url, statusCode))\n }\n\n /**\n * Ends the response and sends the body to the client.\n * Automatically handles JSON serialization, streams, and binary data.\n * Can only be called once per response.\n *\n * @param body - The response body (JSON, string, Uint8Array, StreamableFile, or undefined)\n * @example\n * ```typescript\n * // Send JSON response\n * response.end({ message: 'Success', data: { id: 1 } });\n *\n * // Send empty response\n * response.setStatus(204);\n * response.end();\n *\n * // Send binary data\n * const buffer = new Uint8Array([1, 2, 3]);\n * response.end(buffer);\n *\n * // Send file stream\n * const file = new StreamableFile(stream);\n * response.end(file);\n * ```\n */\n end(body?: unknown): void {\n if (this.ended) return\n this.ended = true\n /**\n * According to RFC 6265, multiple Set-Cookie attributes should be separated by semicolons.\n * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie#syntax\n * @see https://bun.com/docs/runtime/cookies#tosetcookieheaders-:-string[]\n */\n this._cookieHeaderCache ??= this.cookieMap.toSetCookieHeaders().join('; ')\n if (this._cookieHeaderCache.length > 0) {\n this.setHeader('set-cookie', this._cookieHeaderCache)\n }\n\n // Fast path: check for most common case first (plain objects/arrays for JSON)\n // Avoid expensive instanceof checks when possible\n if (body !== null && typeof body === 'object') {\n // Check special types first with early returns\n if (body instanceof Uint8Array || body instanceof Blob) {\n this.resolve(this.createResponse(body))\n return\n }\n if (body instanceof StreamableFile) {\n this.resolve(this.buildStreamableResponse(body))\n return\n }\n // Default: treat as JSON-serializable object\n this.resolve(this.buildJsonResponse(body))\n return\n }\n\n if (!body) {\n this.resolve(this.createResponse(null))\n return\n }\n\n // String or primitive\n this.resolve(this.buildJsonResponse(body))\n }\n\n /**\n * Sets a response header.\n * Header names are automatically normalized to lowercase.\n *\n * @param name - The header name\n * @param value - The header value\n * @example\n * ```typescript\n * response.setHeader('Content-Type', 'application/json');\n * response.setHeader('Cache-Control', 'no-cache');\n * response.setHeader('X-Custom-Header', 'custom-value');\n * ```\n */\n setHeader(name: string, value: string): void {\n this.headersMap.set(name.toLowerCase(), value)\n }\n\n /**\n * Gets the value of a response header.\n * Header lookup is case-insensitive.\n *\n * @param name - The header name to retrieve\n * @returns The header value or null if not set\n * @example\n * ```typescript\n * response.setHeader('Content-Type', 'application/json');\n * const contentType = response.getHeader('content-type');\n * console.log(contentType); // \"application/json\"\n *\n * const missing = response.getHeader('X-Missing');\n * console.log(missing); // null\n * ```\n */\n getHeader(name: string): string | null {\n return this._headers?.get(name.toLowerCase()) ?? null\n }\n\n /**\n * Appends a value to an existing response header.\n * If the header doesn't exist, it will be created.\n * Multiple values are joined with a comma as per RFC 9110.\n *\n * @param name - The header name\n * @param value - The value to append\n * @example\n * ```typescript\n * response.setHeader('Cache-Control', 'no-cache');\n * response.appendHeader('Cache-Control', 'no-store');\n * // Results in: \"Cache-Control: no-cache, no-store\"\n *\n * response.appendHeader('X-Custom', 'value1');\n * response.appendHeader('X-Custom', 'value2');\n * // Results in: \"X-Custom: value1, value2\"\n * ```\n */\n appendHeader(name: string, value: string): void {\n const key = name.toLowerCase()\n const headers = this.headersMap\n const existing = headers.get(key)\n /**\n * According to RFC 9110, multiple header values should be concatenated with a comma.\n * @see https://datatracker.ietf.org/doc/html/rfc9110#section-5.3.3\n */\n headers.set(key, existing ? `${existing}, ${value}` : value)\n }\n\n /**\n * Removes a response header.\n * Header lookup is case-insensitive.\n *\n * @param name - The header name to remove\n * @example\n * ```typescript\n * response.setHeader('X-Custom-Header', 'value');\n * response.removeHeader('X-Custom-Header');\n *\n * const header = response.getHeader('X-Custom-Header');\n * console.log(header); // null\n * ```\n */\n removeHeader(name: string): void {\n this._headers?.delete(name.toLowerCase())\n }\n\n /**\n * Sets the HTTP status code for the response.\n *\n * @param code - The HTTP status code (e.g., 200, 404, 500)\n * @example\n * ```typescript\n * response.setStatus(200); // OK\n * response.setStatus(201); // Created\n * response.setStatus(400); // Bad Request\n * response.setStatus(404); // Not Found\n * response.setStatus(500); // Internal Server Error\n * ```\n */\n setStatus(code: number): void {\n this.statusCode = code\n }\n\n /**\n * Gets the current HTTP status code of the response.\n *\n * @returns The HTTP status code\n * @example\n * ```typescript\n * response.setStatus(404);\n * const status = response.getStatus();\n * console.log(status); // 404\n * ```\n */\n getStatus(): number {\n return this.statusCode\n }\n\n /**\n * Returns a Promise that resolves to the native Response object.\n * The Promise resolves when end() or redirect() is called.\n *\n * @returns Promise that resolves to the Bun Response object\n * @example\n * ```typescript\n * const response = new BunResponse();\n * response.setStatus(200);\n * response.end({ message: 'Success' });\n *\n * const nativeResponse = await response.res();\n * console.log(nativeResponse.status); // 200\n * ```\n */\n res(): Promise<Response> {\n return this.response\n }\n\n /**\n * Checks if the response has been ended.\n * Once ended, no further modifications can be made to the response.\n *\n * @returns true if the response has been ended, false otherwise\n * @example\n * ```typescript\n * const response = new BunResponse();\n * console.log(response.isEnded()); // false\n *\n * response.end({ message: 'Done' });\n * console.log(response.isEnded()); // true\n *\n * // This will be ignored since response is already ended\n * response.setHeader('X-Custom', 'value');\n * ```\n */\n isEnded(): boolean {\n return this.ended\n }\n\n private buildStreamableResponse(body: StreamableFile): Response {\n const streamHeaders = body.getHeaders()\n const headers = this.headersMap\n if (streamHeaders.type && !headers.has('content-type')) {\n headers.set('content-type', streamHeaders.type)\n }\n if (streamHeaders.disposition && !headers.has('content-disposition')) {\n headers.set('content-disposition', streamHeaders.disposition as string)\n }\n if (streamHeaders.length !== undefined && !headers.has('content-length')) {\n headers.set('content-length', String(streamHeaders.length))\n }\n return this.createResponse(body.getStream())\n }\n\n private buildJsonResponse(body: unknown): Response {\n const headers = this._headers\n // Hot path: no headers\n if (headers === null || headers.size === 0) {\n return Response.json(body, { status: this.statusCode })\n }\n // Set content-type only if not already set\n if (!headers.has('content-type')) {\n headers.set('content-type', JSON_CONTENT_TYPE)\n }\n return Response.json(body, {\n status: this.statusCode,\n headers: Object.fromEntries(headers),\n })\n }\n\n private createResponse(body: BodyInit | null): Response {\n const headers = this._headers\n if (headers === null || headers.size === 0) {\n return new Response(body, { status: this.statusCode })\n }\n return new Response(body, {\n status: this.statusCode,\n headers: Object.fromEntries(headers),\n })\n }\n}\n",
|
|
8
|
+
"import { ErrorHandler, RequestHandler } from '@nestjs/common/interfaces/index.js'\nimport { ErrorLike } from 'bun'\n\nimport { BunRequest } from './bun.request.js'\nimport { BunResponse } from './bun.response.js'\n\ntype MiddlewareHandler = RequestHandler<BunRequest, BunResponse>\ninterface MiddlewareRunOptions {\n req: BunRequest\n res: BunResponse\n method: string\n path: string\n requestHandler: MiddlewareHandler\n}\n\n// Shared empty array to avoid allocations\nconst EMPTY_HANDLERS: readonly MiddlewareHandler[] = new Array<MiddlewareHandler>(0)\n\n// Reusable noop function for error handler\nconst noop = (): void => { /* noop */ }\n\nexport class BunMiddlewareEngine {\n private readonly globalMiddlewares: MiddlewareHandler[] = []\n private readonly routeMiddleware = new Map<string, MiddlewareHandler[]>()\n // Group route middleware by method for faster prefix matching\n private readonly routeMiddlewareByMethod = new Map<string, Map<string, MiddlewareHandler[]>>()\n private readonly wildcardMiddleware = new Map<string, MiddlewareHandler[]>()\n private readonly middlewareCache = new Map<string, MiddlewareHandler[]>()\n private errorHandler: ErrorHandler<BunRequest, BunResponse> | null = null\n private notFoundHandler: MiddlewareHandler | null = null\n\n useGlobal(middleware: MiddlewareHandler): void {\n this.globalMiddlewares.push(middleware)\n }\n\n useRoute(method: string, path: string, middleware: MiddlewareHandler): void {\n const key = `${method}:${path}`;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n (this.routeMiddleware.get(key) ?? (this.routeMiddleware.set(key, []).get(key)!)).push(middleware);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n (this.routeMiddlewareByMethod.get(method) ?? this.routeMiddlewareByMethod.set(method, new Map()).get(method)!)\n .set(path, ((this.routeMiddlewareByMethod.get(method)?.get(path)) ?? []))\n .get(path)!\n .push(middleware)\n }\n\n useWildcard(method: string, middleware: MiddlewareHandler): void {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n (this.wildcardMiddleware.get(method) ?? this.wildcardMiddleware.set(method, []).get(method)!).push(middleware)\n }\n\n useErrorHandler(handler: ErrorHandler<BunRequest, BunResponse>): void {\n this.errorHandler = handler\n }\n\n useNotFoundHandler(handler: MiddlewareHandler): void {\n this.notFoundHandler = handler\n }\n\n findRouteHandler(method: string, path: string): MiddlewareHandler | null {\n // Try exact match first (method-specific, then ALL)\n const exactHandler = this.findExactRouteHandler(method, path)\n if (exactHandler) return exactHandler\n\n // Try prefix match\n return this.findPrefixRouteHandler(method, path)\n }\n\n private findExactRouteHandler(method: string, path: string): MiddlewareHandler | null {\n const exactKey = `${method}:${path}`\n const exactMiddleware = this.routeMiddleware.get(exactKey)\n if (exactMiddleware && exactMiddleware.length > 0) {\n return exactMiddleware[exactMiddleware.length - 1]\n }\n\n const allExactKey = `ALL:${path}`\n const allExactMiddleware = this.routeMiddleware.get(allExactKey)\n if (allExactMiddleware && allExactMiddleware.length > 0) {\n return allExactMiddleware[allExactMiddleware.length - 1]\n }\n\n return null\n }\n\n private findPrefixRouteHandler(method: string, path: string): MiddlewareHandler | null {\n const methodMap = this.routeMiddlewareByMethod.get(method)\n const allMethodMap = this.routeMiddlewareByMethod.get('ALL')\n\n if (!methodMap && !allMethodMap) return null\n\n const mapsToCheck: Map<string, MiddlewareHandler[]>[] = []\n if (methodMap) mapsToCheck.push(methodMap)\n if (allMethodMap) mapsToCheck.push(allMethodMap)\n\n return this.findBestMatchInMaps(mapsToCheck, path)\n }\n\n private findBestMatchInMaps(\n maps: Map<string, MiddlewareHandler[]>[],\n path: string,\n ): MiddlewareHandler | null {\n let bestMatch: MiddlewareHandler | null = null\n let bestMatchLength = 0\n const pathLen = path.length\n\n for (const map of maps) {\n for (const [keyPath, middleware] of map) {\n if (middleware.length === 0 || keyPath.length <= bestMatchLength) continue\n\n if (this.isPrefixMatch(path, pathLen, keyPath)) {\n bestMatch = middleware[middleware.length - 1]\n bestMatchLength = keyPath.length\n }\n }\n }\n\n return bestMatch\n }\n\n private isPrefixMatch(path: string, pathLen: number, keyPath: string): boolean {\n const keyPathLen = keyPath.length\n return path === keyPath || (pathLen > keyPathLen && path.charCodeAt(keyPathLen) === 47 && path.startsWith(keyPath))\n }\n\n async run(options: MiddlewareRunOptions): Promise<BunResponse> {\n try {\n const middlewares = this.getMiddlewareChain(options.method, options.path)\n await this.executeChain(middlewares, options.requestHandler, options.req, options.res)\n return options.res\n }\n catch (error) {\n return this.handleError(error, options.req, options.res)\n }\n }\n\n private getMiddlewareChain(method: string, path: string): MiddlewareHandler[] {\n const cacheKey = `${method}:${path}`\n let cached = this.middlewareCache.get(cacheKey)\n if (cached !== undefined) return cached\n\n cached = this.buildMiddlewareChain(method, path, cacheKey)\n this.middlewareCache.set(cacheKey, cached)\n return cached\n }\n\n private buildMiddlewareChain(\n method: string,\n path: string,\n cacheKey: string,\n ): MiddlewareHandler[] {\n // Minimize array operations and allocations\n const global = this.globalMiddlewares\n const globalLen = global.length\n const wildcardAll = this.wildcardMiddleware.get('ALL')\n const wildcardMethod = this.wildcardMiddleware.get(method)\n const routeMiddleware = this.findRouteMiddleware(method, path, cacheKey)\n\n const wildcardAllLen = wildcardAll?.length ?? 0\n const wildcardMethodLen = wildcardMethod?.length ?? 0\n const routeLen = routeMiddleware.length\n\n const totalLen = globalLen + wildcardAllLen + wildcardMethodLen + routeLen\n if (totalLen === 0) return EMPTY_HANDLERS as MiddlewareHandler[]\n\n // Avoid iterator overhead from for...of loops\n const chain = new Array<MiddlewareHandler>(totalLen)\n let idx = 0\n\n // Global middlewares\n for (let i = 0; i < globalLen; i++) chain[idx++] = global[i]\n // Wildcard middlewares\n if (wildcardAll) for (let i = 0; i < wildcardAllLen; i++) chain[idx++] = wildcardAll[i]\n // Method-specific wildcard middlewares\n if (wildcardMethod) for (let i = 0; i < wildcardMethodLen; i++) chain[idx++] = wildcardMethod[i]\n // Route-specific middlewares\n for (let i = 0; i < routeLen; i++) chain[idx++] = routeMiddleware[i]\n\n return chain\n }\n\n private findRouteMiddleware(\n method: string,\n path: string,\n cacheKey: string,\n ): readonly MiddlewareHandler[] {\n const exactMiddleware = this.routeMiddleware.get(cacheKey)\n if (exactMiddleware !== undefined) return exactMiddleware\n return this.findBestPrefixMatch(method, path)\n }\n\n private findBestPrefixMatch(\n method: string,\n path: string,\n ): readonly MiddlewareHandler[] {\n const methodMap = this.routeMiddlewareByMethod.get(method)\n if (!methodMap) return EMPTY_HANDLERS\n\n let bestMatch: MiddlewareHandler[] | null = null\n let bestMatchLength = 0\n const pathLen = path.length\n\n for (const [keyPath, middleware] of methodMap) {\n const keyPathLen = keyPath.length\n if (keyPathLen <= bestMatchLength || middleware.length === 0) continue\n\n // Fast path check: exact match or prefix match with /\n if (path === keyPath || (pathLen > keyPathLen && path.charCodeAt(keyPathLen) === 47 /* '/' */ && path.startsWith(keyPath))) {\n bestMatch = middleware\n bestMatchLength = keyPathLen\n }\n }\n\n return bestMatch ?? EMPTY_HANDLERS\n }\n\n private async executeChain(\n chain: MiddlewareHandler[],\n requestHandler: MiddlewareHandler,\n req: BunRequest,\n res: BunResponse,\n ): Promise<void> {\n const chainLength = chain.length\n let index = 0\n\n const next = async (err?: ErrorLike): Promise<void> => {\n if (err) throw err\n\n // Process middleware chain\n if (index < chainLength) {\n const handler = chain[index++]\n const result = handler(req, res, next) as unknown\n if (result instanceof Promise) await result\n return\n }\n\n // Process request handler at the end only if response hasn't been ended\n if (index === chainLength) {\n index++\n // Skip handler if response already ended by middleware\n if (!res.isEnded()) {\n const result = requestHandler(req, res, next) as unknown\n if (result instanceof Promise) await result\n }\n return\n }\n\n // If next is called after the handler, call not found handler\n if (index > chainLength && !res.isEnded()) {\n const result = this.notFoundHandler?.(req, res, noop) as unknown\n if (result instanceof Promise) await result\n }\n }\n\n await next()\n }\n\n private async handleError(\n error: unknown,\n req: BunRequest,\n res: BunResponse,\n ): Promise<BunResponse> {\n if (this.errorHandler !== null) {\n const result = this.errorHandler(error, req, res, noop) as unknown\n if (result instanceof Promise) await result\n return res\n }\n throw error\n }\n}\n",
|
|
9
|
+
"/* eslint-disable sonarjs/no-nested-assignment */\nimport { CookieMap, BunRequest as NativeRequest } from 'bun'\nimport { ParsedQs, parse } from 'qs'\n\n// Optimized headers type - use native Headers for hot-path .get()\ntype HeadersProxy = Record<string, string> & {\n get: (key: string) => string | null\n}\n\n// Pre-allocated empty object for Object.create(null) pattern\nconst NULL_PROTO = Object.getPrototypeOf(Object.create(null)) as object\n\n/**\n * A high-performance request wrapper for Bun's native request object.\n * Provides lazy parsing and caching for optimal performance in NestJS applications.\n *\n * @example\n * ```typescript\n * const bunRequest = new BunRequest(nativeRequest);\n * const pathname = bunRequest.pathname; // Lazily parsed\n * const query = bunRequest.query; // Parsed only when accessed\n * ```\n */\nexport class BunRequest {\n private _nativeHeaders: Headers\n private _headers: HeadersProxy | null = null\n private _hostname: string | null = null\n private _pathname: string | null = null\n private _query: ParsedQs | null = null\n private _body: unknown = null\n private _rawBody: ArrayBuffer | null = null\n private _file: File | null = null\n private _files: File[] | null = null\n private _settings: Map<string, unknown> | null = null\n\n // Cache URL parts at construction time for hot-path access\n private readonly _url: string\n private readonly _parsedUrl: URL\n readonly method: string\n readonly params: Record<string, string>\n\n constructor(private readonly nativeRequest: NativeRequest) {\n this._url = nativeRequest.url\n this._parsedUrl = new URL(this._url)\n this._nativeHeaders = nativeRequest.headers\n this.method = nativeRequest.method\n this.params = nativeRequest.params\n }\n\n /**\n * Gets a mock socket object for compatibility with Node.js middleware.\n * Some middleware (like Better Auth) check req.socket.encrypted to determine if the connection is HTTPS.\n *\n * @returns A mock socket object with encrypted property\n */\n get socket(): { encrypted: boolean } {\n return {\n encrypted: this._parsedUrl.protocol === 'https:',\n }\n }\n\n /**\n * Gets the URL path and query string of the request.\n * Returns the pathname + search params for Node.js/Express compatibility.\n * For the full URL including protocol and host, use the original() method to access the native request.\n *\n * @returns The URL path and query string (e.g., \"/api/users?page=1\")\n * @example\n * ```typescript\n * const url = request.url; // \"/api/users?page=1\"\n * // For full URL: request.original().url // \"http://localhost:3000/api/users?page=1\"\n * ```\n */\n get url(): string {\n return this._parsedUrl.pathname + this._parsedUrl.search\n }\n\n /**\n * Gets the original native Bun request object.\n *\n * @returns The underlying Bun request\n * @example\n * ```typescript\n * const nativeReq = request.original();\n * console.log(nativeReq.url); // Full URL with protocol and host\n * ```\n */\n original(): NativeRequest {\n return this.nativeRequest\n }\n\n /**\n * Gets the pathname portion of the URL.\n * Uses lazy parsing for optimal performance - the pathname is only extracted when first accessed.\n *\n * @returns The pathname component of the URL\n * @example\n * ```typescript\n * // For URL \"http://localhost:3000/api/users?page=1\"\n * const pathname = request.pathname; // \"/api/users\"\n * ```\n */\n get pathname(): string {\n return this._pathname ??= this._parsedUrl.pathname\n }\n\n /**\n * Gets the hostname portion of the URL.\n * Uses lazy parsing - the hostname is only extracted when first accessed.\n *\n * @returns The hostname component of the URL (without port)\n * @example\n * ```typescript\n * // For URL \"http://localhost:3000/api/users\"\n * const hostname = request.hostname; // \"localhost\"\n * ```\n */\n get hostname(): string {\n return this._hostname ??= this.headers.get('x-forwarded-host') ?? this._parsedUrl.hostname\n }\n\n /**\n * Gets all request headers as a key-value object.\n * Uses lazy parsing - headers are materialized only when first accessed.\n * All header keys are normalized to lowercase.\n *\n * @returns An object containing all headers with a .get() method for efficient lookups\n * @example\n * ```typescript\n * const headers = request.headers;\n * const contentType = headers['content-type']; // Direct access\n * const auth = headers.get('Authorization'); // Using .get() method\n * ```\n */\n get headers(): HeadersProxy {\n if (this._headers !== null) return this._headers\n const native = this._nativeHeaders\n // Create proxy that uses native .get() and materializes properties lazily\n const proxy = Object.create(NULL_PROTO) as HeadersProxy\n // Materialize all headers for NestJS decorators that iterate over keys\n native.forEach((value: string, key: string) => {\n proxy[key.toLowerCase()] = value\n })\n proxy.get = (key: string) => native.get(key)\n return this._headers = proxy\n }\n\n /**\n * Gets the parsed query parameters from the URL.\n * Uses lazy parsing - query string is only parsed when first accessed.\n *\n * @returns Parsed query parameters as an object\n * @example\n * ```typescript\n * // For URL \"http://localhost:3000/api/users?page=1&limit=10\"\n * const query = request.query;\n * console.log(query.page); // \"1\"\n * console.log(query.limit); // \"10\"\n * ```\n */\n get query(): ParsedQs {\n return this._query ??= parse(this._parsedUrl.searchParams.toString())\n }\n\n /**\n * Gets the parsed request body.\n *\n * @returns The parsed body content (could be JSON, form data, etc.)\n * @example\n * ```typescript\n * const body = request.body;\n * console.log(body); // { name: \"John\", email: \"john@example.com\" }\n * ```\n */\n get body(): unknown { return this._body }\n\n /**\n * Sets the parsed request body.\n * Typically used by body parser middleware.\n *\n * @param body - The parsed body content to set\n * @example\n * ```typescript\n * request.setBody({ name: \"John\", email: \"john@example.com\" });\n * ```\n */\n setBody(body: unknown): void { this._body = body }\n\n /**\n * Gets the raw request body as an ArrayBuffer.\n *\n * @returns The raw body data or null if not set\n * @example\n * ```typescript\n * const rawBody = request.rawBody;\n * if (rawBody) {\n * const text = new TextDecoder().decode(rawBody);\n * }\n * ```\n */\n get rawBody(): ArrayBuffer | null { return this._rawBody }\n\n /**\n * Sets the raw request body as an ArrayBuffer.\n *\n * @param rawBody - The raw body data to set\n * @example\n * ```typescript\n * const buffer = await request.arrayBuffer();\n * request.setRawBody(buffer);\n * ```\n */\n setRawBody(rawBody: ArrayBuffer): void { this._rawBody = rawBody }\n\n /**\n * Gets the uploaded file from the request.\n * Used for single file uploads.\n *\n * @returns The uploaded file or null if no file was uploaded\n * @example\n * ```typescript\n * const file = request.file;\n * if (file) {\n * console.log(file.name); // \"avatar.png\"\n * console.log(file.size); // 2048\n * }\n * ```\n */\n get file(): File | null { return this._file }\n\n /**\n * Sets the uploaded file in the request.\n * Typically used by file upload middleware.\n *\n * @param file - The file to set\n * @example\n * ```typescript\n * const formData = await request.formData();\n * const file = formData.get('avatar') as File;\n * request.setFile(file);\n * ```\n */\n setFile(file: File): void { this._file = file }\n\n /**\n * Gets all uploaded files from the request.\n * Used for multiple file uploads.\n *\n * @returns Array of uploaded files or null if no files were uploaded\n * @example\n * ```typescript\n * const files = request.files;\n * if (files) {\n * files.forEach(file => {\n * console.log(file.name, file.size);\n * });\n * }\n * ```\n */\n get files(): File[] | null { return this._files }\n\n /**\n * Sets multiple uploaded files in the request.\n * Typically used by file upload middleware.\n *\n * @param files - Array of files to set\n * @example\n * ```typescript\n * const formData = await request.formData();\n * const files = formData.getAll('attachments') as File[];\n * request.setFiles(files);\n * ```\n */\n setFiles(files: File[]): void { this._files = files }\n\n /**\n * Gets a custom setting/property stored in the request.\n * Useful for passing data between middleware and handlers.\n *\n * @param key - The setting key to retrieve\n * @returns The stored value or undefined if not found\n * @example\n * ```typescript\n * // In middleware\n * request.set('user', { id: 1, name: 'John' });\n *\n * // In handler\n * const user = request.get('user');\n * console.log(user); // { id: 1, name: 'John' }\n * ```\n */\n get(key: string): unknown { return this._settings?.get(key) }\n\n /**\n * Sets a custom setting/property in the request.\n * Useful for passing data between middleware and handlers.\n *\n * @param key - The setting key to store\n * @param value - The value to store\n * @example\n * ```typescript\n * request.set('user', { id: 1, name: 'John' });\n * request.set('startTime', Date.now());\n * ```\n */\n set(key: string, value: unknown): void {\n (this._settings ??= new Map()).set(key, value)\n }\n\n /**\n * Gets the AbortSignal for the request.\n * Can be used to detect if the request has been cancelled.\n *\n * @returns The request's AbortSignal\n * @example\n * ```typescript\n * const signal = request.signal;\n * signal.addEventListener('abort', () => {\n * console.log('Request was cancelled');\n * });\n * ```\n */\n get signal(): AbortSignal { return this.nativeRequest.signal }\n\n /**\n * Gets the cookies from the request.\n *\n * @returns A Map-like object containing all cookies\n * @example\n * ```typescript\n * const cookies = request.cookies;\n * const sessionId = cookies.get('sessionId');\n * console.log(sessionId?.value);\n * ```\n */\n get cookies(): CookieMap { return this.nativeRequest.cookies }\n\n /**\n * Parses the request body as JSON.\n *\n * @returns Promise that resolves to the parsed JSON data\n * @example\n * ```typescript\n * const data = await request.json();\n * console.log(data); // { name: \"John\", email: \"john@example.com\" }\n * ```\n */\n json(): Promise<unknown> { return this.nativeRequest.json() }\n\n /**\n * Reads the request body as text.\n *\n * @returns Promise that resolves to the body text\n * @example\n * ```typescript\n * const text = await request.text();\n * console.log(text); // \"Hello, World!\"\n * ```\n */\n text(): Promise<string> { return this.nativeRequest.text() }\n\n /**\n * Parses the request body as FormData.\n *\n * @returns Promise that resolves to the parsed FormData\n * @example\n * ```typescript\n * const formData = await request.formData();\n * const name = formData.get('name');\n * console.log(name); // \"John\"\n * ```\n */\n // eslint-disable-next-line @typescript-eslint/no-deprecated, sonarjs/deprecation\n formData(): Promise<FormData> { return this.nativeRequest.formData() as unknown as Promise<FormData> }\n\n /**\n * Reads the request body as an ArrayBuffer.\n *\n * @returns Promise that resolves to the body as ArrayBuffer\n * @example\n * ```typescript\n * const buffer = await request.arrayBuffer();\n * console.log(buffer.byteLength); // 1024\n * ```\n */\n arrayBuffer(): Promise<ArrayBuffer> { return this.nativeRequest.arrayBuffer() }\n\n /**\n * Reads the request body as a Blob.\n *\n * @returns Promise that resolves to the body as Blob\n * @example\n * ```typescript\n * const blob = await request.blob();\n * console.log(blob.type); // \"image/png\"\n * ```\n */\n blob(): Promise<Blob> { return this.nativeRequest.blob() }\n\n /**\n * Reads the request body as a Uint8Array.\n *\n * @returns Promise that resolves to the body as Uint8Array\n * @example\n * ```typescript\n * const bytes = await request.bytes();\n * console.log(bytes.length); // 1024\n * ```\n */\n bytes(): Promise<Uint8Array> { return this.nativeRequest.bytes() }\n\n /**\n * Creates a deep clone of the request.\n * Clones both the native request and all cached properties.\n *\n * @returns A new BunRequest instance with cloned data\n * @example\n * ```typescript\n * const originalRequest = new BunRequest(nativeRequest);\n * const clonedRequest = originalRequest.clone();\n *\n * // Modifications to clone don't affect original\n * clonedRequest.set('user', { id: 1 });\n * console.log(originalRequest.get('user')); // undefined\n * ```\n */\n clone(): BunRequest {\n const cloned = new BunRequest(this.nativeRequest.clone())\n cloned._pathname = this._pathname\n cloned._body = this._body\n cloned._rawBody = this._rawBody\n cloned._file = this._file\n cloned._files = this._files\n cloned._headers = this._headers\n cloned._query = this._query\n cloned._settings = this._settings\n return cloned\n }\n}\n",
|
|
10
|
+
"/* eslint-disable sonarjs/no-nested-assignment */\nimport { BodyInit, Cookie, CookieInit, CookieMap, CookieStoreDeleteOptions } from 'bun'\nimport { StreamableFile } from '@nestjs/common'\n\n// Pre-allocated JSON content type header\nconst JSON_CONTENT_TYPE = 'application/json'\n\n/**\n * A high-performance response builder for Bun's native Response object.\n * Provides methods to build responses with headers, cookies, and various body types.\n * Uses lazy initialization and optimized response building for maximum performance.\n *\n * @example\n * ```typescript\n * const response = new BunResponse();\n * response.setStatus(200);\n * response.setHeader('Content-Type', 'application/json');\n * response.cookie('sessionId', 'abc123');\n * response.end({ message: 'Success' });\n * ```\n */\nexport class BunResponse {\n private resolve!: (value: Response) => void\n private readonly response: Promise<Response>\n private readonly cookieMap = new CookieMap()\n private static readonly textDecoder = new TextDecoder()\n\n // Use Map for O(1) header operations - faster than Headers for small sets\n private headers: Map<string, string> | null = null\n private statusCode = 200\n private ended = false\n // Cache for cookie headers to avoid repeated operations\n private cookieHeaders: string[] | null = null\n // Buffer for accumulated write() calls before end()\n private chunks: (string | Uint8Array)[] = []\n\n constructor() {\n // Keep constructor minimal to reduce allocation overhead\n this.response = new Promise<Response>((r) => {\n this.resolve = r\n })\n }\n\n // Lazy headers initialization\n private get headersMap(): Map<string, string> {\n return this.headers ??= new Map()\n }\n\n /**\n * Sets a cookie in the response.\n * Can be called with either a cookie options object or name-value pair.\n *\n * @param options - Cookie configuration object\n * @example\n * ```typescript\n * // Using name-value pair\n * response.cookie('sessionId', 'abc123');\n *\n * // Using options object\n * response.cookie({\n * name: 'sessionId',\n * value: 'abc123',\n * httpOnly: true,\n * secure: true,\n * maxAge: 3600\n * });\n * ```\n */\n cookie(options: CookieInit | Cookie): void\n /**\n * Sets a cookie in the response using name and value.\n *\n * @param name - The cookie name\n * @param value - The cookie value\n */\n cookie(name: string, value: string): void\n cookie(...args: unknown[]): void {\n // Invalidate cookie headers cache when cookies change\n this.cookieHeaders = null\n if (args.length === 1) {\n this.cookieMap.set(args[0] as CookieInit | Cookie)\n }\n else {\n this.cookieMap.set(\n args[0] as string,\n args[1] as string,\n )\n }\n }\n\n /**\n * Deletes a cookie from the response.\n *\n * @param optionsOrName - Cookie name or delete options\n * @example\n * ```typescript\n * // Delete by name\n * response.deleteCookie('sessionId');\n *\n * // Delete with options\n * response.deleteCookie({\n * name: 'sessionId',\n * path: '/',\n * domain: 'example.com'\n * });\n * ```\n */\n deleteCookie(optionsOrName: CookieStoreDeleteOptions | string): void\n /**\n * Deletes a cookie from the response with additional options.\n *\n * @param optionsOrName - Cookie name\n * @param options - Additional delete options (path, domain, etc.)\n */\n deleteCookie(optionsOrName: string, options: Omit<CookieStoreDeleteOptions, 'name'>): void\n deleteCookie(optionsOrName: CookieStoreDeleteOptions | string, options?: Omit<CookieStoreDeleteOptions, 'name'>): void {\n if (typeof optionsOrName === 'string') {\n this.cookieMap.delete(optionsOrName, options as unknown as Omit<CookieStoreDeleteOptions, 'name'>)\n }\n else {\n this.cookieMap.delete(optionsOrName)\n }\n }\n\n /**\n * Sends a redirect response to the specified URL.\n * Ends the response after calling this method.\n *\n * @param url - The URL to redirect to\n * @param statusCode - HTTP status code for the redirect (default: 302)\n * @example\n * ```typescript\n * // Temporary redirect (302)\n * response.redirect('/login');\n *\n * // Permanent redirect (301)\n * response.redirect('/new-page', 301);\n *\n * // See Other (303)\n * response.redirect('/success', 303);\n * ```\n */\n redirect(url: string, statusCode = 302): void {\n if (this.ended) return\n this.ended = true\n this.resolve(Response.redirect(url, statusCode))\n }\n\n /**\n * Ends the response and sends the body to the client.\n * Automatically handles JSON serialization, streams, and binary data.\n * Can only be called once per response.\n * If write() was called before end(), accumulated chunks will be sent.\n *\n * @param body - The response body (JSON, string, Uint8Array, StreamableFile, or undefined)\n * @example\n * ```typescript\n * // Send JSON response\n * response.end({ message: 'Success', data: { id: 1 } });\n *\n * // Send empty response\n * response.setStatus(204);\n * response.end();\n *\n * // Send binary data\n * const buffer = new Uint8Array([1, 2, 3]);\n * response.end(buffer);\n *\n * // Send file stream\n * const file = new StreamableFile(stream);\n * response.end(file);\n *\n * // Send accumulated chunks from write() calls\n * response.write('Hello ');\n * response.write('World');\n * response.end('!'); // Sends \"Hello World!\"\n * ```\n */\n end(body?: unknown): void {\n if (this.ended) return\n this.ended = true\n\n // Apply cookies to headers before sending response\n this.applyCookieHeaders()\n\n // If there are accumulated chunks from write() calls, combine them with the final body\n if (this.chunks.length > 0) {\n const finalBody = this.combineChunks(body)\n // When chunks are combined, send as plain text/binary, not JSON\n this.resolve(this.createResponse(finalBody))\n return\n }\n\n this.sendResponse(body)\n }\n\n /**\n * Applies cookie headers to the response.\n * According to RFC 6265, each cookie must be sent as a separate Set-Cookie header.\n * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie\n */\n private applyCookieHeaders(): void {\n this.cookieHeaders ??= this.cookieMap.toSetCookieHeaders()\n if (this.cookieHeaders.length > 0) {\n // Multiple Set-Cookie headers are sent by joining with newline for HTTP/1.1 compatibility\n this.setHeader('set-cookie', this.cookieHeaders.join('\\n'))\n }\n }\n\n private sendResponse(body?: unknown): void {\n // Fast path: check for most common case first (plain objects/arrays for JSON)\n // Avoid expensive instanceof checks when possible\n if (body !== null && typeof body === 'object') {\n // Check special types first with early returns\n if (body instanceof Uint8Array || body instanceof Blob) {\n this.resolve(this.createResponse(body))\n return\n }\n if (body instanceof StreamableFile) {\n this.resolve(this.buildStreamableResponse(body))\n return\n }\n // Default: treat as JSON-serializable object\n this.resolve(this.buildJsonResponse(body))\n return\n }\n\n if (!body) {\n this.resolve(this.createResponse(null))\n return\n }\n\n // String or primitive\n this.resolve(this.buildJsonResponse(body))\n }\n\n // eslint-disable-next-line sonarjs/function-return-type\n private combineChunks(finalChunk?: unknown): string | Uint8Array {\n const hasStrings = this.chunks.some(chunk => typeof chunk === 'string')\n const finalIsString = typeof finalChunk === 'string'\n\n // If all chunks are strings, concatenate as strings\n if (hasStrings || finalIsString) {\n return this.combineAsString(finalChunk)\n }\n\n // All chunks are Uint8Arrays, concatenate as binary data\n return this.combineAsBinary(finalChunk)\n }\n\n private combineAsString(finalChunk?: unknown): string {\n const decoder = BunResponse.textDecoder\n const parts: string[] = this.chunks.map(chunk =>\n typeof chunk === 'string' ? chunk : decoder.decode(chunk),\n )\n if (finalChunk !== undefined && finalChunk !== null) {\n if (typeof finalChunk === 'string') {\n parts.push(finalChunk)\n }\n else if (finalChunk instanceof Uint8Array) {\n parts.push(decoder.decode(finalChunk))\n }\n else if (typeof finalChunk === 'object') {\n parts.push(JSON.stringify(finalChunk))\n }\n else {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n parts.push(String(finalChunk))\n }\n }\n return parts.join('')\n }\n\n private combineAsBinary(finalChunk?: unknown): Uint8Array {\n const binaryChunks = this.chunks as Uint8Array[]\n\n // Calculate total length\n let totalLength = 0\n for (const chunk of binaryChunks) {\n totalLength += chunk.length\n }\n if (finalChunk instanceof Uint8Array) {\n totalLength += finalChunk.length\n }\n\n // Combine all chunks\n const result = new Uint8Array(totalLength)\n let offset = 0\n for (const chunk of binaryChunks) {\n result.set(chunk, offset)\n offset += chunk.length\n }\n if (finalChunk instanceof Uint8Array) {\n result.set(finalChunk, offset)\n }\n return result\n }\n\n /**\n * Sets a response header.\n * Header names are automatically normalized to lowercase.\n *\n * @param name - The header name\n * @param value - The header value\n * @example\n * ```typescript\n * response.setHeader('Content-Type', 'application/json');\n * response.setHeader('Cache-Control', 'no-cache');\n * response.setHeader('X-Custom-Header', 'custom-value');\n * ```\n */\n setHeader(name: string, value: string): void {\n this.headersMap.set(name.toLowerCase(), value)\n }\n\n /**\n * Writes the response status and headers (Node.js compatibility method).\n * This method is provided for compatibility with Node.js HTTP response objects.\n *\n * @param statusCode - The HTTP status code\n * @param headers - Optional headers to set\n * @example\n * ```typescript\n * response.writeHead(200, { 'Content-Type': 'application/json' });\n * response.writeHead(404);\n * ```\n */\n writeHead(statusCode: number, headers?: Record<string, string>): void {\n this.statusCode = statusCode\n if (headers) {\n for (const [name, value] of Object.entries(headers)) {\n this.setHeader(name, value)\n }\n }\n }\n\n /**\n * Stub method for Node.js EventEmitter compatibility.\n * This is a no-op method provided for compatibility with Node.js HTTP response objects.\n * Some middleware may try to listen for events like 'close' on the response object.\n *\n * @param event - The event name\n * @param listener - The event listener function\n * @returns This response object for chaining\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n on(event: string, listener: (...args: unknown[]) => void): this {\n // No-op for compatibility\n return this\n }\n\n /**\n * Stub method for Node.js EventEmitter compatibility.\n * This is a no-op method provided for compatibility with Node.js HTTP response objects.\n *\n * @param event - The event name\n * @param listener - The event listener function\n * @returns This response object for chaining\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n off(event: string, listener: (...args: unknown[]) => void): this {\n // No-op for compatibility\n return this\n }\n\n /**\n * Property for Node.js HTTP response compatibility.\n * Always returns false since Bun responses don't have a destroyed state.\n */\n readonly destroyed = false\n\n /**\n * Stub method for Node.js HTTP response compatibility.\n * This is a no-op method provided for compatibility with Node.js HTTP response objects.\n *\n * @param error - Optional error\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n destroy(error?: Error): void {\n // No-op for compatibility\n }\n\n /**\n * Stub method for Node.js EventEmitter compatibility.\n * This is a no-op method provided for compatibility with Node.js HTTP response objects.\n *\n * @param event - The event name\n * @param listener - The event listener function\n * @returns This response object for chaining\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n once(event: string, listener: (...args: unknown[]) => void): this {\n // No-op for compatibility\n return this\n }\n\n /**\n * Stub method for Node.js HTTP response compatibility.\n * This method writes data to the response stream.\n * Data is accumulated in a buffer until end() is called.\n * Mimics Node.js behavior where write() can be called multiple times.\n *\n * @param chunk - The data to write (string, Uint8Array, or other types that can be stringified)\n * @returns true if the chunk was successfully buffered, false if the response has already ended\n * @example\n * ```typescript\n * // Write string chunks\n * response.write('Hello ');\n * response.write('World');\n * response.end('!'); // Sends \"Hello World!\"\n *\n * // Write binary chunks\n * const chunk1 = new Uint8Array([1, 2, 3]);\n * const chunk2 = new Uint8Array([4, 5, 6]);\n * response.write(chunk1);\n * response.write(chunk2);\n * response.end(); // Sends combined binary data\n *\n * // Mixed usage (converts to string)\n * response.write('Status: ');\n * response.write(200);\n * response.end(); // Sends \"Status: 200\"\n * ```\n */\n write(chunk: unknown): boolean {\n // Node.js behavior: writing after end() should be ignored and return false\n if (this.ended) {\n return false\n }\n\n // Handle string chunks\n if (typeof chunk === 'string') {\n this.chunks.push(chunk)\n return true\n }\n\n // Handle binary chunks\n if (chunk instanceof Uint8Array) {\n this.chunks.push(chunk)\n return true\n }\n\n // Handle Buffer (which is a Uint8Array subclass in Node.js)\n if (chunk instanceof Buffer) {\n this.chunks.push(new Uint8Array(chunk))\n return true\n }\n\n // For other types, convert to string (Node.js behavior)\n if (chunk != null) {\n if (typeof chunk === 'object') {\n this.chunks.push(JSON.stringify(chunk))\n }\n else {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n this.chunks.push(String(chunk))\n }\n return true\n }\n\n // Empty chunk is valid, just return true\n return true\n }\n\n /**\n * Gets the value of a response header.\n * Header lookup is case-insensitive.\n *\n * @param name - The header name to retrieve\n * @returns The header value or null if not set\n * @example\n * ```typescript\n * response.setHeader('Content-Type', 'application/json');\n * const contentType = response.getHeader('content-type');\n * console.log(contentType); // \"application/json\"\n *\n * const missing = response.getHeader('X-Missing');\n * console.log(missing); // null\n * ```\n */\n getHeader(name: string): string | null {\n return this.headers?.get(name.toLowerCase()) ?? null\n }\n\n /**\n * Appends a value to an existing response header.\n * If the header doesn't exist, it will be created.\n * Multiple values are joined with a comma as per RFC 9110.\n *\n * @param name - The header name\n * @param value - The value to append\n * @example\n * ```typescript\n * response.setHeader('Cache-Control', 'no-cache');\n * response.appendHeader('Cache-Control', 'no-store');\n * // Results in: \"Cache-Control: no-cache, no-store\"\n *\n * response.appendHeader('X-Custom', 'value1');\n * response.appendHeader('X-Custom', 'value2');\n * // Results in: \"X-Custom: value1, value2\"\n * ```\n */\n appendHeader(name: string, value: string): void {\n const key = name.toLowerCase()\n const headers = this.headersMap\n const existing = headers.get(key)\n /**\n * According to RFC 9110, multiple header values should be concatenated with a comma.\n * @see https://datatracker.ietf.org/doc/html/rfc9110#section-5.3.3\n */\n headers.set(key, existing ? `${existing}, ${value}` : value)\n }\n\n /**\n * Removes a response header.\n * Header lookup is case-insensitive.\n *\n * @param name - The header name to remove\n * @example\n * ```typescript\n * response.setHeader('X-Custom-Header', 'value');\n * response.removeHeader('X-Custom-Header');\n *\n * const header = response.getHeader('X-Custom-Header');\n * console.log(header); // null\n * ```\n */\n removeHeader(name: string): void {\n this.headers?.delete(name.toLowerCase())\n }\n\n /**\n * Sets the HTTP status code for the response.\n *\n * @param code - The HTTP status code (e.g., 200, 404, 500)\n * @example\n * ```typescript\n * response.setStatus(200); // OK\n * response.setStatus(201); // Created\n * response.setStatus(400); // Bad Request\n * response.setStatus(404); // Not Found\n * response.setStatus(500); // Internal Server Error\n * ```\n */\n setStatus(code: number): void {\n this.statusCode = code\n }\n\n /**\n * Gets the current HTTP status code of the response.\n *\n * @returns The HTTP status code\n * @example\n * ```typescript\n * response.setStatus(404);\n * const status = response.getStatus();\n * console.log(status); // 404\n * ```\n */\n getStatus(): number {\n return this.statusCode\n }\n\n /**\n * Returns a Promise that resolves to the native Response object.\n * The Promise resolves when end() or redirect() is called.\n *\n * @returns Promise that resolves to the Bun Response object\n * @example\n * ```typescript\n * const response = new BunResponse();\n * response.setStatus(200);\n * response.end({ message: 'Success' });\n *\n * const nativeResponse = await response.res();\n * console.log(nativeResponse.status); // 200\n * ```\n */\n res(): Promise<Response> {\n return this.response\n }\n\n /**\n * Checks if the response has been ended.\n * Once ended, no further modifications can be made to the response.\n *\n * @returns true if the response has been ended, false otherwise\n * @example\n * ```typescript\n * const response = new BunResponse();\n * console.log(response.isEnded()); // false\n *\n * response.end({ message: 'Done' });\n * console.log(response.isEnded()); // true\n *\n * // This will be ignored since response is already ended\n * response.setHeader('X-Custom', 'value');\n * ```\n */\n isEnded(): boolean {\n return this.ended\n }\n\n private buildStreamableResponse(body: StreamableFile): Response {\n const streamHeaders = body.getHeaders()\n const headers = this.headersMap\n if (streamHeaders.type && !headers.has('content-type')) {\n headers.set('content-type', streamHeaders.type)\n }\n if (streamHeaders.disposition && !headers.has('content-disposition')) {\n headers.set('content-disposition', streamHeaders.disposition as string)\n }\n if (streamHeaders.length !== undefined && !headers.has('content-length')) {\n headers.set('content-length', String(streamHeaders.length))\n }\n return this.createResponse(body.getStream())\n }\n\n private buildJsonResponse(body: unknown): Response {\n const headers = this.headers\n // Hot path: no headers\n if (headers === null || headers.size === 0) {\n return Response.json(body, { status: this.statusCode })\n }\n // Set content-type only if not already set\n if (!headers.has('content-type')) {\n headers.set('content-type', JSON_CONTENT_TYPE)\n }\n return Response.json(body, {\n status: this.statusCode,\n headers: Object.fromEntries(headers),\n })\n }\n\n private createResponse(body: BodyInit | null): Response {\n const headers = this.headers\n if (headers === null || headers.size === 0) {\n return new Response(body, { status: this.statusCode })\n }\n return new Response(body, {\n status: this.statusCode,\n headers: Object.fromEntries(headers),\n })\n }\n}\n",
|
|
11
11
|
"import {\n CustomVersioningOptions,\n HeaderVersioningOptions,\n MediaTypeVersioningOptions,\n VersionValue,\n} from '@nestjs/common/interfaces/version-options.interface.js'\nimport { VERSION_NEUTRAL, VersioningOptions, VersioningType } from '@nestjs/common'\n\nimport { BunRequest } from './bun.request.js'\nimport { BunResponse } from './bun.response.js'\n\ntype VersionHandler = (req: BunRequest, res: BunResponse, next: () => void) => unknown\n\n/**\n * Metadata attached to request for custom versioning two-pass execution\n */\nexport interface CustomVersioningMeta {\n _customVersioningPhase?: 'discovery' | 'execution'\n _customVersioningCandidates?: Map<string, { priority: number, execute: () => unknown }>\n _customVersioningBestCandidate?: string\n}\n\n/** Helper to execute handler and await if needed */\nasync function executeHandler(handler: VersionHandler, req: BunRequest, res: BunResponse, next: () => void): Promise<unknown> {\n const result = handler(req, res, next)\n return result instanceof Promise ? await result : result\n}\n\n/** Helper to call next and await if needed */\nfunction callNext(next: () => void | Promise<void>): void | Promise<void> {\n return next()\n}\n\n/**\n * Middleware for handling NestJS versioning in BunAdapter.\n * Supports URI, Header, Media Type, and Custom versioning strategies.\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport class BunVersionFilterMiddleware {\n /**\n * Creates a version-filtered handler wrapper.\n */\n static createFilter(\n handler: VersionHandler,\n version: VersionValue,\n versioningOptions: VersioningOptions,\n ): VersionHandler {\n if (version === VERSION_NEUTRAL || versioningOptions.type === VersioningType.URI) {\n return handler\n }\n\n // Use switch instead of object creation for better performance\n switch (versioningOptions.type) {\n case VersioningType.CUSTOM:\n return this.createCustomVersionFilter(handler, version, versioningOptions as CustomVersioningOptions)\n case VersioningType.MEDIA_TYPE:\n return this.createMediaTypeVersionFilter(handler, version, versioningOptions as MediaTypeVersioningOptions)\n case VersioningType.HEADER:\n return this.createHeaderVersionFilter(handler, version, versioningOptions as HeaderVersioningOptions)\n default:\n throw new Error('Unsupported versioning options')\n }\n }\n\n /** Checks if the handler version matches the requested version (optimized with Set for arrays) */\n private static createVersionMatcher(handlerVersion: VersionValue): (requestedVersion: string | undefined) => boolean {\n if (Array.isArray(handlerVersion)) {\n const versionSet = new Set(handlerVersion)\n return requestedVersion => requestedVersion !== undefined && versionSet.has(requestedVersion)\n }\n return requestedVersion => requestedVersion == handlerVersion\n }\n\n /** Pre-computes whether handler accepts VERSION_NEUTRAL */\n private static computeAcceptsNeutral(version: VersionValue): boolean {\n return version === VERSION_NEUTRAL\n || (Array.isArray(version) && version.includes(VERSION_NEUTRAL))\n }\n\n /** Extracts header value from request - optimized to use .get() directly */\n private static getHeader(req: BunRequest, name: string): string | undefined {\n // Headers.get() is case-insensitive per spec, so we only need one call\n return req.headers.get(name) ?? undefined\n }\n\n /** Creates a filter for Custom versioning (uses extractor function) */\n private static createCustomVersionFilter(\n handler: VersionHandler,\n version: VersionValue,\n options: CustomVersioningOptions,\n ): VersionHandler {\n // Pre-compute version set for O(1) lookups\n const isVersionArray = Array.isArray(version)\n const versionSet = isVersionArray ? new Set(version as string[]) : null\n const singleVersion = isVersionArray ? null : version as string\n\n return async (req, res, next) => {\n const extracted = options.extractor(req)\n const reqMeta = req as CustomVersioningMeta\n\n // Initialize metadata on first handler\n reqMeta._customVersioningPhase ??= 'discovery'\n reqMeta._customVersioningCandidates ??= new Map()\n\n const isDiscovery = reqMeta._customVersioningPhase === 'discovery'\n\n // Inline findVersionMatch for performance\n const extractedIsArray = Array.isArray(extracted)\n const extractedVersions = extractedIsArray ? extracted : [extracted]\n let match: string | undefined\n let matchIndex = -1\n\n for (let i = 0; i < extractedVersions.length; i++) {\n const extractedVersion = extractedVersions[i]\n if (versionSet ? versionSet.has(extractedVersion) : extractedVersion === singleVersion) {\n match = extractedVersion\n matchIndex = i\n break\n }\n }\n\n if (match) {\n if (isDiscovery) {\n reqMeta._customVersioningCandidates.set(match, {\n priority: matchIndex,\n execute: () => handler(req, res, next),\n })\n return callNext(next)\n }\n\n if (reqMeta._customVersioningBestCandidate === match) {\n return executeHandler(handler, req, res, next)\n }\n }\n\n return callNext(next)\n }\n }\n\n /** Creates a filter for Media Type (Accept header) versioning */\n private static createMediaTypeVersionFilter(\n handler: VersionHandler,\n version: VersionValue,\n options: MediaTypeVersioningOptions,\n ): VersionHandler {\n // Pre-compute at filter creation time\n const acceptsNeutral = this.computeAcceptsNeutral(version)\n const versionMatches = this.createVersionMatcher(version)\n const keyLength = options.key.length\n\n return async (req, res, next) => {\n const acceptHeader = this.getHeader(req, 'accept')\n\n if (acceptHeader) {\n // Find semicolon position without creating intermediate array\n const semiIndex = acceptHeader.indexOf(';')\n if (semiIndex !== -1) {\n const versionPart = acceptHeader.substring(semiIndex + 1).trim()\n // Find the key and extract version after it\n const keyIndex = versionPart.indexOf(options.key)\n if (keyIndex !== -1) {\n const headerVersion = versionPart.substring(keyIndex + keyLength)\n if (versionMatches(headerVersion)) {\n return executeHandler(handler, req, res, next)\n }\n return callNext(next)\n }\n }\n }\n\n // No version param found\n if (acceptsNeutral) {\n return executeHandler(handler, req, res, next)\n }\n return callNext(next)\n }\n }\n\n /** Creates a filter for Header versioning (custom header) */\n private static createHeaderVersionFilter(\n handler: VersionHandler,\n version: VersionValue,\n options: HeaderVersioningOptions & { defaultVersion?: VersionValue },\n ): VersionHandler {\n // Pre-compute at filter creation time\n const acceptsNeutral = this.computeAcceptsNeutral(version)\n const versionMatches = this.createVersionMatcher(version)\n const defaultVersion = options.defaultVersion\n const hasNeutralDefault = defaultVersion === VERSION_NEUTRAL\n const resolvedDefault = this.resolveDefaultVersion(version, defaultVersion)\n const headerName = options.header\n\n return async (req, res, next) => {\n let headerVersion: string | undefined = this.getHeader(req, headerName)?.trim()\n\n // Treat empty or whitespace-only as undefined\n if (headerVersion === '') headerVersion = undefined\n\n // Apply default version if no header provided\n headerVersion ??= resolvedDefault\n\n // No version provided\n if (!headerVersion) {\n // Handle VERSION_NEUTRAL default or neutral-accepting handler\n if ((hasNeutralDefault || !defaultVersion) && acceptsNeutral) {\n return executeHandler(handler, req, res, next)\n }\n return callNext(next)\n }\n\n if (versionMatches(headerVersion)) {\n return executeHandler(handler, req, res, next)\n }\n return callNext(next)\n }\n }\n\n /** Resolves default version that matches handler version */\n private static resolveDefaultVersion(\n handlerVersion: VersionValue,\n defaultVersion: VersionValue | undefined,\n ): string | undefined {\n if (defaultVersion === undefined || defaultVersion === VERSION_NEUTRAL) {\n return undefined\n }\n\n const handlerVersions = Array.isArray(handlerVersion) ? handlerVersion : [handlerVersion]\n\n if (typeof defaultVersion === 'string') {\n return handlerVersions.includes(defaultVersion) ? defaultVersion : undefined\n }\n\n if (Array.isArray(defaultVersion)) {\n return defaultVersion.find(dv => typeof dv === 'string' && handlerVersions.includes(dv)) as string | undefined\n }\n\n return undefined\n }\n\n /** Selects the best custom versioning candidate after discovery phase */\n static selectBestCustomVersionCandidate(req: BunRequest): string | null {\n const { _customVersioningPhase: phase, _customVersioningCandidates: candidates } = req as CustomVersioningMeta\n\n if (phase !== 'discovery' || !candidates?.size) return null\n\n let bestVersion: string | null = null\n let bestPriority = Infinity\n\n for (const [version, { priority }] of candidates) {\n if (priority < bestPriority) {\n bestPriority = priority\n bestVersion = version\n }\n }\n\n return bestVersion\n }\n\n /** Switches the request to execution phase for custom versioning */\n static setCustomVersioningExecutionPhase(req: BunRequest, bestVersion: string): void {\n const reqMeta = req as CustomVersioningMeta\n reqMeta._customVersioningPhase = 'execution'\n reqMeta._customVersioningBestCandidate = bestVersion\n }\n\n /** Checks if request has custom versioning candidates pending */\n static hasCustomVersioningCandidates(req: BunRequest): boolean {\n const { _customVersioningPhase: phase, _customVersioningCandidates: candidates } = req as CustomVersioningMeta\n return phase === 'discovery' && !!candidates?.size\n }\n}\n",
|
|
12
12
|
"import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'\nimport { basename, join } from 'node:path'\nimport { HttpAdapterHost } from '@nestjs/core'\nimport { Observable } from 'rxjs'\nimport { randomUUIDv7 } from 'bun'\nimport { tmpdir } from 'node:os'\n\nimport { BunAdapter } from './bun.adapter.js'\nimport { BunRequest } from './bun.request.js'\n\n@Injectable()\nexport class BunFileInterceptor implements NestInterceptor {\n private readonly uploadDir = Bun.env.BUN_UPLOAD_DIR\n constructor(private readonly adapter: HttpAdapterHost) {\n const httpAdapter = this.adapter.httpAdapter as unknown as BunAdapter\n this.uploadDir ??= join(tmpdir(), 'uploads', httpAdapter.getHttpServer().id, randomUUIDv7())\n }\n\n async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<unknown>> {\n const request = context.switchToHttp().getRequest<BunRequest>()\n if (!request.files?.length) {\n return next.handle()\n }\n\n const files = await Promise.all(\n request.files.map(async (file) => {\n const destPath = join(this.uploadDir as unknown as string, basename(file.name))\n await Bun.write(destPath, file)\n return Bun.file(destPath) as File\n }),\n )\n request.setFile(files[0])\n request.setFiles(files)\n\n return next.handle()\n }\n}\n"
|
|
13
13
|
],
|
|
14
|
-
"mappings": "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",
|
|
15
|
-
"debugId": "
|
|
14
|
+
"mappings": "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",
|
|
15
|
+
"debugId": "43ACC6E0AFE16AD764756E2164756E21",
|
|
16
16
|
"names": []
|
|
17
17
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@krisanalfa/bunest-adapter",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "High-performance Bun adapter for NestJS framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"repository": {
|
|
38
38
|
"type": "git",
|
|
39
|
-
"url": "
|
|
39
|
+
"url": "https://github.com/krisanalfa/bunest.git",
|
|
40
40
|
"directory": "packages/bunest-adapter"
|
|
41
41
|
},
|
|
42
42
|
"bugs": {
|
|
@@ -44,21 +44,23 @@
|
|
|
44
44
|
},
|
|
45
45
|
"homepage": "https://github.com/krisanalfa/bunest#readme",
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@nestjs/common": "^11.
|
|
48
|
-
"@nestjs/core": "^11.
|
|
47
|
+
"@nestjs/common": "^11.1.11",
|
|
48
|
+
"@nestjs/core": "^11.1.11"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"cors": "^2.8.5",
|
|
52
|
-
"qs": "^6.14.
|
|
52
|
+
"qs": "^6.14.1"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@nestjs/testing": "^11.1.
|
|
55
|
+
"@nestjs/testing": "^11.1.11",
|
|
56
|
+
"@thallesp/nestjs-better-auth": "^2.2.0",
|
|
56
57
|
"@types/cors": "^2.8.19",
|
|
57
58
|
"@types/helmet": "^4.0.0",
|
|
58
59
|
"@types/qs": "^6.14.0",
|
|
59
60
|
"class-transformer": "^0.5.1",
|
|
60
61
|
"class-validator": "^0.14.3",
|
|
61
|
-
"helmet": "^8.1.0"
|
|
62
|
+
"helmet": "^8.1.0",
|
|
63
|
+
"rxjs": "^7.8.2"
|
|
62
64
|
},
|
|
63
65
|
"engines": {
|
|
64
66
|
"bun": ">=1.3.0"
|