@fluojs/platform-bun 1.0.7 → 3.0.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.ko.md CHANGED
@@ -28,7 +28,7 @@ npm install @fluojs/platform-bun
28
28
 
29
29
  fluo 애플리케이션을 [Bun](https://bun.sh/) 런타임에서 실행할 때 이 패키지를 사용합니다. 이 어댑터는 Bun의 고성능 `Request`/`Response` 브리지와 네이티브 `fetch` 방식의 아키텍처를 활용하여 Bun 사용자에게 원활하고 빠른 경험을 제공합니다.
30
30
 
31
- 애플리케이션 종료 중에는 websocket upgrade 시도를 포함한 모든 새 유입을 `503` shutdown 응답으로 중단하고, Bun이 서버를 강제로 내리기 전에 활성 HTTP 핸들러가 bounded drain window 안에서 마무리될 있도록 동작합니다. 시그널 기반 종료가 `forceExitTimeoutMs`를 넘기거나 실패하면 fluo는 그 상태를 로그와 `process.exitCode`로 보고하고, 최종 프로세스 종료는 Bun 또는 주변 호스트에 맡깁니다.
31
+ 애플리케이션 종료 중에는 websocket upgrade 시도를 포함한 모든 새 유입을 `503` shutdown 응답으로 중단하고, realtime binding 평가부터 HTTP 응답 또는 upgrade 결과까지 수락된 작업을 drain하기 전에 `server.stop(stopActiveConnections)`를 시작합니다. bounded timeout은 caller-facing `close()` promise만 reject합니다. 수락된 작업과 adapter state는 underlying drain 끝날 때까지 유지됩니다. 따라서 timeout이 추가 teardown을 강제하지 않습니다. 시그널 기반 종료가 `forceExitTimeoutMs`를 넘기거나 실패하면 fluo는 그 상태를 로그와 `process.exitCode`로 보고하고, 최종 프로세스 종료는 Bun 또는 주변 호스트에 맡깁니다.
32
32
 
33
33
  ## 빠른 시작
34
34
 
@@ -46,9 +46,29 @@ await app.listen();
46
46
 
47
47
  ## 주요 패턴
48
48
 
49
+ ### Early Hints 미지원
50
+
51
+ Bun은 Fluo의 Web 표준 response facade를 사용하므로 `context.response.earlyHints`가 없습니다. 사용 전에 capability 존재 여부를 확인하세요. Adapter는 Early Hints를 조용히 무시하거나 early field를 final `Response`에 복사하지 않습니다. 애플리케이션 코드가 관찰 가능한 HTTP `103`을 emit해야 한다면 Node.js, Express, Fastify adapter를 사용하세요.
52
+
53
+ ### 스트리밍 멀티파트 소비
54
+
55
+ 애플리케이션 bootstrap에서 `multipart: { strategy: 'stream' }`을 설정하면 멀티파트 데이터를 점진적으로
56
+ 받습니다. 멀티파트 route에서 `RequestContext.request.body`는 `AsyncIterableIterator<MultipartPart>`입니다.
57
+ field part는 `kind: 'field'`, `name`, `value`, `headers`를, file part는 `kind: 'file'`, `name`, `filename`,
58
+ `contentType`, `headers`, 그리고 `stream`의 single-consumer `ReadableStream<Uint8Array>`를 제공합니다. 다음
59
+ part를 요청하기 전에 각 file stream을 끝까지 소비하거나 cancel하세요.
60
+
61
+ Runtime route dispatch는 route를 위해 만든 iterator를 소유하며 handler가 끝난 뒤 자동으로 `return()`을 호출해
62
+ active source를 cancel하고 release합니다. Standalone `parseMultipartStream(...)` consumer는 이 책임을 직접
63
+ 집니다. iterator를 끝까지 소비하거나 일찍 끝낼 때 `return()`을 호출하세요.
64
+
65
+ ### 바이트 범위와 캐시 검증
66
+
67
+ Bun은 fetch dispatch를 통해 공유 `@fluojs/http` 단일 byte-range 및 `If-Range` contract를 보존합니다. Conditional-request 평가가 cache validator를 선택한 뒤 유효한 `Range: bytes=` 요청은 portable `206` identity-byte response를 만들고, `If-Range`는 선택된 validator를 재사용합니다. Malformed 또는 multi-range field는 전체 response를 유지하고 충족 불가능한 range는 body 없는 `416`을 만들며, `HEAD`는 stream을 소비하지 않고 GET metadata를 반영합니다.
68
+
49
69
  ### 수동 Fetch 처리
50
70
  Bun 서버를 직접 관리하려는 경우 fetch 핸들러를 직접 사용할 수 있습니다.
51
- `dispatcher`는 이미 bootstrap된 application의 `app.getHttpDispatcher()`에서 가져와야 합니다. handler는 raw-body와 multipart request parsing을 보존하지만, shutdown ownership, websocket upgrade, native `routes` acceleration은 주변 `Bun.serve(...)` host 또는 managed adapter 경로가 소유합니다.
71
+ `dispatcher`는 이미 bootstrap된 application의 `app.getHttpDispatcher()`에서 가져와야 합니다. `createBunFetchHandler(...)`는 동기적으로 fetch bridge를 만들고 raw-body와 multipart request parsing을 보존하지만, shutdown ownership, websocket upgrade, native `routes` acceleration은 주변 `Bun.serve(...)` host 또는 managed adapter 경로가 소유합니다.
52
72
 
53
73
  ```typescript
54
74
  import { createBunFetchHandler } from '@fluojs/platform-bun';
@@ -64,12 +84,20 @@ Bun.serve({
64
84
  ```
65
85
 
66
86
  ### 네이티브 WebSocket 업그레이드
67
- 어댑터는 `@fluojs/websockets/bun` 바인딩을 통해 Bun의 네이티브 `server.upgrade()`를 지원합니다.
87
+ 어댑터는 `@fluojs/websockets/bun` 바인딩을 통해 Bun의 네이티브 `server.upgrade()`를 지원합니다. `getRealtimeCapability()`는 fetch-style capability version 1을 보존하면서 optional versioned `bindingInstallation` extension을 추가합니다. First-party WebSocket 및 Socket.IO module은 `app.listen()` 전에 이 protocol-neutral installer를 사용하고 adapter는 설치된 값을 Bun binding contract로 parse합니다. 런타임이 해당 바인딩을 설치하고 등록된 게이트웨이를 찾을 수 있도록 `app.listen()` 전에 application module에서 `BunWebSocketModule.forRoot(...)`를 import하세요.
68
88
 
69
89
  ```typescript
70
- // Bun 어댑터가 활성화된 경우 게이트웨이는 자동으로 Bun의 네이티브 업그레이드를 사용합니다.
90
+ import { Module } from '@fluojs/core';
91
+ import { BunWebSocketModule, WebSocketGateway } from '@fluojs/websockets/bun';
92
+
71
93
  @WebSocketGateway({ path: '/ws' })
72
- export class MyGateway {}
94
+ class MyGateway {}
95
+
96
+ @Module({
97
+ imports: [BunWebSocketModule.forRoot()],
98
+ providers: [MyGateway],
99
+ })
100
+ export class AppModule {}
73
101
  ```
74
102
 
75
103
  ### 네이티브 `routes` Object 가속
@@ -79,6 +107,8 @@ Bun `>=1.2.3`에서는 어댑터가 의미 보존이 가능한 static/param fluo
79
107
 
80
108
  Native handoff가 붙은 뒤 app middleware가 framework request의 method 또는 path를 rewrite하면 dispatcher는 stale handoff를 버리고 rewrite된 요청을 다시 매칭합니다. `OPTIONS` 같은 미지원 메서드와 CORS preflight 동작은 fluo route가 명시적으로 소유하지 않는 한 공유 dispatcher/middleware 경로가 계속 소유합니다.
81
109
 
110
+ `QUERY`, `PURGE` 같은 검증된 custom route는 Bun native `routes` 가속을 사용할 수 있어도 의도적으로 fetch fallback에 남습니다. Bun은 `Request`를 통해 원래 method와 body를 전달하고 shared dispatcher가 `ALL`보다 exact method를 먼저 매칭합니다. `CONNECT`는 일반 controller routing conformance 범위 밖에 유지됩니다.
111
+
82
112
  ## 공개 API 개요
83
113
 
84
114
  - `createBunAdapter(options)`: Bun 어댑터를 위한 권장 팩토리입니다.
@@ -88,10 +118,10 @@ Native handoff가 붙은 뒤 app middleware가 framework request의 method 또
88
118
 
89
119
  어댑터는 realtime 패키지가 사용하는 타입 지정 Bun 통합 seam도 함께 내보냅니다.
90
120
 
91
- - `BunHttpApplicationAdapter`: `Bun.serve()`를 기반으로 동작하는 `HttpApplicationAdapter` 구현체입니다.
121
+ - `BunHttpApplicationAdapter`: `Bun.serve()`를 기반으로 동작하는 `HttpApplicationAdapter` 구현체이며 `getRealtimeCapability()`는 fetch-style capability version 1을 보존하면서 optional `bindingInstallation`을 포함합니다.
92
122
  - `BunAdapterOptions`: `createBunAdapter()`가 받는 host, port, TLS, raw-body, multipart, shutdown 옵션입니다.
93
123
  - `BootstrapBunApplicationOptions` 및 `RunBunApplicationOptions`: Bun 호스팅 애플리케이션의 bootstrap/run 옵션입니다.
94
- - `BunWebSocketBinding` 및 `BunRealtimeBindingHost`: 일반 HTTP dispatch 전에 `@fluojs/websockets/bun`이 사용하는 binding 계약입니다.
124
+ - `BunWebSocketBinding`, `BunWebSocketUpgradeHost` 및 `BunRealtimeBindingHost`: 일반 HTTP dispatch 전에 `@fluojs/websockets/bun`이 사용하는 binding 계약입니다. Binding은 upgrade 가능한 host만 받으며 adapter가 소유하는 Bun server lifecycle이나 raw fetch handler는 받지 않습니다.
95
125
  - `BunWebSocketBindingHost`: Bun realtime binding 설정을 위한 backward-compatible alias입니다.
96
126
  - `BunServeOptions`, `BunServerLike`, `BunWebSocketHandler`, `BunServerWebSocket`, `BunWebSocketMessage`, `BunApplicationSignal`, `BunCorsInput`, `BunTlsOptions`, `CreateBunFetchHandlerOptions`: 저수준 Bun host, websocket, signal, CORS, TLS, fetch-handler integration type입니다.
97
127
 
@@ -100,17 +130,31 @@ Native handoff가 붙은 뒤 app middleware가 framework request의 method 또
100
130
  - **런타임 host**: 이 패키지는 listen 시점에 `globalThis.Bun.serve()`가 필요합니다. 테스트에서는 Bun 호환 test double을 제공할 수 있지만, production 사용은 Bun 전용입니다.
101
131
  - **요청 portability**: Fetch 요청은 shared web dispatcher를 통해 변환되며 malformed cookie 값, query 배열, `rawBody: true`일 때 JSON/text raw body, custom `createBunFetchHandler(...)` 설정의 byte-exact request handoff, SSE framing을 보존합니다.
102
132
  - **네이티브 route 가속**: Bun의 `routes` object를 사용할 수 있고 fluo route shape를 의미 보존 상태로 선등록할 수 있을 때만 Bun이 path matching을 먼저 처리하고, 이후 요청은 다시 shared dispatcher로 넘깁니다. 지원하지 않거나 모호한 route shape는 일반 `fetch` 경로로 폴백하며, middleware가 handler matching 전에 method/path를 rewrite하면 stale handoff는 무시됩니다.
103
- - **네이티브 route gate**: Native route는 Bun `>=1.2.3`에서만 활성화됩니다. Adapter는 안전한 native-route entry가 실제로 활성화될 때만 `routes` 옵션을 전달하고, 그 외에는 `routes` 옵션 자체를 생략합니다. Versioned route, `ALL` handler, same-shape conflict, normalization-sensitive path, `OPTIONS`/CORS preflight는 fetch/shared-dispatch path에 남습니다.
133
+ - **네이티브 route gate**: Native route는 Bun `>=1.2.3`에서만 활성화됩니다. Adapter는 안전한 native-route entry가 실제로 활성화될 때만 `routes` 옵션을 전달하고, 그 외에는 `routes` 옵션 자체를 생략합니다. Versioned route, `ALL` handler, custom method, same-shape conflict, normalization-sensitive path, `OPTIONS`/CORS preflight는 fetch/shared-dispatch path에 남습니다.
104
134
  - **Multipart 동작**: Multipart 요청은 `rawBody`를 노출하지 않으며 multipart limit은 shared runtime parser를 통해 계속 적용됩니다.
105
135
  - **시작 target**: `hostname`, `port`, `tls`는 `Bun.serve()`로 전달됩니다. 시작 로그는 설정된 HTTP 또는 HTTPS listen URL을 보고합니다.
106
136
  - **Lifecycle guard**: 이미 시작된 adapter에서 `listen()`을 다시 호출해도 원래 live dispatcher binding을 유지합니다. Realtime/websocket binding은 `listen()`이 시작되기 전에만 구성할 수 있으며, 이후 binding을 설정하거나 지우려는 시도는 live wiring에 영향을 주지 않은 채 수락되지 않고 빠르게 실패합니다.
107
- - **종료 소유권**: `close()`는 새 HTTP 및 websocket-upgrade 유입을 `503` shutdown 응답으로 중단하고, in-flight HTTP handler를 기다린 뒤, drain이 끝나면 adapter state를 정리하며 `runBunApplication()`이 등록한 signal listener를 제거합니다.
108
- - **Realtime seam**: Bun websocket binding은 서버를 시작하는 `listen()` 전에 구성해야 합니다. Adapter가 새 유입을 받는 동안 Upgrade 요청은 HTTP dispatch로 넘어가기 전에 구성된 binding에 먼저 전달되며, binding이 response를 반환하거나 요청 업그레이드에 성공한 경우에만 HTTP fallback을 억제합니다.
137
+ - **종료 소유권**: `close()`는 새 HTTP 및 websocket-upgrade 유입을 `503` shutdown 응답으로 중단하고 `server.stop(stopActiveConnections)`를 시작한 뒤, Bun server 종료와 수락된 모든 요청을 realtime binding 평가부터 HTTP 응답 또는 upgrade 완료까지 기다립니다. bounded timeout은 caller-facing `close()` promise만 reject합니다. 수락된 작업과 adapter state는 underlying drain이 끝날 때까지 유지되며, 그 뒤에야 `close()`가 adapter state를 정리합니다. `runBunApplication()`은 등록한 signal listener를 `app.close()`가 시작될 때 adapter drain 이전에 제거합니다.
138
+ - **Realtime seam**: `getRealtimeCapability()`는 fetch-style version 1을 보존하면서 optional version 1 `bindingInstallation` contract를 노출합니다. Bun websocket binding은 서버를 시작하는 `listen()` 전에 구성해야 합니다. Capability installer는 protocol package를 위한 canonical configuration path이며 `fetch` 및 `websocket` host contract가 없는 값을 거부합니다. Startup 이후 live server의 binding은 고정되고 adapter `close()` boundary가 Bun 종료와 요청 drain이 끝난 후 retained binding state를 정리합니다. Adapter가 새 유입을 받는 동안 Upgrade 요청은 HTTP dispatch로 넘어가기 전에 구성된 binding에 먼저 전달되며, 비동기 binding 평가 도중 shutdown시작되어도 이미 수락된 요청에는 dispatcher가 유지되고, binding이 response를 반환하거나 요청 업그레이드에 성공한 경우에만 HTTP fallback을 억제합니다. Binding host는 `upgrade(...)`만 노출하므로 adapter가 소유하는 `stop()`과 raw `fetch()` 제어는 realtime seam 밖에 남습니다.
109
139
  - **Adapter instance helper**: `BunHttpApplicationAdapter`는 `getServer()`, `getListenTarget()`, `getRealtimeCapability()`, `configureRealtimeBinding()`, `configureWebSocketBinding()`, `listen()`, `close()`를 노출합니다.
110
140
 
141
+ ### 안정적인 진단 코드
142
+
143
+ 패키지가 생성하는 caller-visible failure는 기존 `Error` 또는 `TypeError` class와 message를 유지하면서 `error.code`에 안정적인 문자열을 노출합니다.
144
+
145
+ | 코드 | Error class | 실패 조건 |
146
+ | --- | --- | --- |
147
+ | `BUN_ADAPTER_INVALID_OPTION` | `Error` | 숫자형 adapter 또는 shutdown option이 문서화된 범위를 벗어납니다. |
148
+ | `BUN_ADAPTER_REALTIME_BINDING_INVALID` | `TypeError` | Realtime capability installer가 필수 `fetch` 및 `websocket` contract가 없는 값을 받습니다. |
149
+ | `BUN_ADAPTER_REALTIME_BINDING_LOCKED` | `Error` | `listen()`이 Bun server를 시작한 뒤 caller가 realtime/websocket binding을 변경하려고 합니다. |
150
+ | `BUN_ADAPTER_RUNTIME_UNAVAILABLE` | `Error` | `listen()`이 호출 가능한 `globalThis.Bun.serve()`를 찾지 못합니다. |
151
+ | `BUN_ADAPTER_SHUTDOWN_TIMEOUT` | `Error` | Caller-facing `close()` 대기가 bounded shutdown timeout을 초과합니다. |
152
+
153
+ Bun 또는 application code에서 전파된 error에는 package-owned code를 덧붙이지 않고 원래 class, message, metadata를 유지합니다.
154
+
111
155
  ## Conformance 커버리지
112
156
 
113
- `packages/platform-bun/src/adapter.test.ts`는 문서화된 계약을 검증하는 package-local regression 대상입니다. 이 파일은 malformed cookie, byte-exact JSON/text raw-body 보존, multipart raw-body 제외, SSE framing, native-route param parity, same-path multi-method handoff, middleware rewrite 이후 stale native handoff rematch, versioning fallback, normalization-sensitive fallback, OPTIONS/CORS ownership, same-shape route fallback, TLS listen-target reporting을 검증하는 Bun fetch-style portability assertion과 startup logging, duplicate listen idempotency, shutdown listener cleanup, in-flight drain, timeout validation/reporting, shutdown 503 ingress rejection, websocket binding delegation 검증하는 집중 테스트를 포함합니다.
157
+ `packages/platform-bun/src/adapter.test.ts`는 문서화된 계약을 검증하는 package-local regression 대상입니다. 이 파일은 conditional request, single-byte range 및 `If-Range`, custom `QUERY`/extension-method fallback, malformed cookie, byte-exact JSON/text raw-body 보존, managed/custom fetch handler의 multipart raw-body 제외, SSE framing, native-route param parity, same-path multi-method handoff, middleware request path 또는 method를 rewrite 뒤의 stale native handoff rematch, versioning fallback, normalization-sensitive fallback, OPTIONS/CORS ownership, same-shape route fallback, TLS listen-target reporting을 검증하는 Bun fetch-style portability assertion과 startup logging, duplicate listen idempotency, shutdown listener cleanup, in-flight drain, 비동기 realtime binding 평가 중 close, binding 완료 후 HTTP fallback, timeout validation/reporting, shutdown 503 ingress rejection, signal-driven close rejection reporting, upgrade-only host를 통한 websocket binding delegation/short-circuit 동작을 검증하는 집중 테스트를 포함합니다.
114
158
 
115
159
  저장소의 더 넓은 suite도 `packages/testing/src/portability/web-runtime-adapter-portability.test.ts`에서 `createWebRuntimeHttpAdapterPortabilityHarness(...)`로 Bun을 Deno 및 Cloudflare Workers와 함께 실행해 fetch-style platform 간 shared web-runtime portability baseline을 맞춥니다.
116
160
 
package/README.md CHANGED
@@ -28,7 +28,7 @@ This package is intended to run on Bun. The published manifest intentionally doe
28
28
 
29
29
  Use this package when running fluo applications on the [Bun](https://bun.sh/) runtime. This adapter leverages Bun's high-performance `Request`/`Response` bridge and native `fetch`-style architecture, providing a seamless and fast experience for Bun users.
30
30
 
31
- During application shutdown, the adapter stops all new ingress, including websocket upgrade attempts, with a `503` shutdown response and gives active HTTP handlers a bounded drain window before Bun forcefully tears the server down. If signal-driven shutdown exceeds `forceExitTimeoutMs` or fails, fluo reports that condition through logging and `process.exitCode` while leaving final process termination to Bun or the surrounding host.
31
+ During application shutdown, the adapter stops all new ingress, including websocket upgrade attempts, with a `503` shutdown response and starts `server.stop(stopActiveConnections)` before draining accepted work from realtime binding evaluation through its HTTP response or upgrade outcome. The bounded timeout only rejects the caller-facing `close()` promise: accepted work and adapter state remain retained until the underlying drain settles, so the timeout does not force another teardown. If signal-driven shutdown exceeds `forceExitTimeoutMs` or fails, fluo reports that condition through logging and `process.exitCode` while leaving final process termination to Bun or the surrounding host.
32
32
 
33
33
  ## Quick Start
34
34
 
@@ -46,9 +46,29 @@ await app.listen();
46
46
 
47
47
  ## Common Patterns
48
48
 
49
+ ### Early Hints are unsupported
50
+
51
+ Bun uses Fluo's Web-standard response facade, so `context.response.earlyHints` is absent. Check for capability presence before use. The adapter does not silently ignore Early Hints and does not copy early fields into the final `Response`; use a Node.js, Express, or Fastify adapter when application code must emit observable HTTP `103` responses.
52
+
53
+ ### Streaming multipart consumption
54
+
55
+ Set `multipart: { strategy: 'stream' }` at application bootstrap to receive multipart data incrementally. For
56
+ multipart routes, `RequestContext.request.body` is an `AsyncIterableIterator<MultipartPart>`: field parts expose
57
+ `kind: 'field'`, `name`, `value`, and `headers`; file parts expose `kind: 'file'`, `name`, `filename`,
58
+ `contentType`, `headers`, and a single-consumer `ReadableStream<Uint8Array>` at `stream`. Finish or cancel each file
59
+ stream before requesting the next part.
60
+
61
+ Runtime route dispatch owns an iterator created for a route and automatically calls `return()` after the handler
62
+ finishes, cancelling and releasing an active source. Standalone `parseMultipartStream(...)` consumers own that
63
+ responsibility: consume the iterator to completion or call `return()` when ending early.
64
+
65
+ ### Byte Ranges and Cache Validation
66
+
67
+ Bun preserves the shared `@fluojs/http` single-byte-range and `If-Range` contract through its fetch dispatch. After conditional-request evaluation selects cache validators, a valid `Range: bytes=` request yields the portable `206` identity-byte response; `If-Range` reuses those selected validators, while malformed or multi-range fields retain the full response and an unsatisfiable range yields bodyless `416`. `HEAD` mirrors GET metadata without consuming a stream.
68
+
49
69
  ### Manual Fetch Handling
50
70
  If you prefer to manage the Bun server yourself, you can use the fetch handler directly.
51
- The `dispatcher` should come from the already bootstrapped application via `app.getHttpDispatcher()`. The handler preserves raw-body and multipart request parsing, while shutdown ownership, websocket upgrades, and native `routes` acceleration remain responsibilities of the surrounding `Bun.serve(...)` host or the managed adapter path.
71
+ The `dispatcher` should come from the already bootstrapped application via `app.getHttpDispatcher()`. `createBunFetchHandler(...)` synchronously creates the fetch bridge and preserves raw-body and multipart request parsing, while shutdown ownership, websocket upgrades, and native `routes` acceleration remain responsibilities of the surrounding `Bun.serve(...)` host or the managed adapter path.
52
72
 
53
73
  ```typescript
54
74
  import { createBunFetchHandler } from '@fluojs/platform-bun';
@@ -64,12 +84,20 @@ Bun.serve({
64
84
  ```
65
85
 
66
86
  ### Native WebSocket Upgrade
67
- The adapter supports Bun's native `server.upgrade()` through the `@fluojs/websockets/bun` binding.
87
+ The adapter supports Bun's native `server.upgrade()` through the `@fluojs/websockets/bun` binding. `getRealtimeCapability()` preserves fetch-style capability version 1 and adds the optional versioned `bindingInstallation` extension; first-party WebSocket and Socket.IO modules use that protocol-neutral installer before `app.listen()`, and the adapter parses the installed value into its Bun binding contract. Import `BunWebSocketModule.forRoot(...)` into the application module before `app.listen()` so the runtime can install that binding and discover the registered gateways.
68
88
 
69
89
  ```typescript
70
- // gateways automatically use Bun's native upgrade when the Bun adapter is active
90
+ import { Module } from '@fluojs/core';
91
+ import { BunWebSocketModule, WebSocketGateway } from '@fluojs/websockets/bun';
92
+
71
93
  @WebSocketGateway({ path: '/ws' })
72
- export class MyGateway {}
94
+ class MyGateway {}
95
+
96
+ @Module({
97
+ imports: [BunWebSocketModule.forRoot()],
98
+ providers: [MyGateway],
99
+ })
100
+ export class AppModule {}
73
101
  ```
74
102
 
75
103
  ### Native `routes` Object Acceleration
@@ -79,6 +107,8 @@ For semantically safe unversioned routes, Bun hands the pre-matched descriptor a
79
107
 
80
108
  If app middleware rewrites the framework request method or path after a Bun native handoff is attached, the dispatcher discards that stale handoff and rematches the rewritten request. Unsupported methods such as `OPTIONS` and CORS preflight behavior remain owned by the shared dispatcher/middleware path unless a fluo route explicitly owns them.
81
109
 
110
+ Validated custom routes such as `QUERY` and `PURGE` intentionally remain on the fetch fallback even when Bun native `routes` acceleration is available. Bun receives the original method and body through `Request`, and the shared dispatcher performs exact-method matching before `ALL`. `CONNECT` remains outside ordinary controller routing conformance.
111
+
82
112
  ## Public API Overview
83
113
 
84
114
  - `createBunAdapter(options)`: Recommended factory for the Bun adapter.
@@ -88,10 +118,10 @@ If app middleware rewrites the framework request method or path after a Bun nati
88
118
 
89
119
  The adapter also exports the typed Bun integration seams used by realtime packages:
90
120
 
91
- - `BunHttpApplicationAdapter`: `HttpApplicationAdapter` implementation backed by `Bun.serve()`.
121
+ - `BunHttpApplicationAdapter`: `HttpApplicationAdapter` implementation backed by `Bun.serve()`; its `getRealtimeCapability()` preserves fetch-style capability version 1 and includes optional `bindingInstallation`.
92
122
  - `BunAdapterOptions`: host, port, TLS, raw-body, multipart, and shutdown options accepted by `createBunAdapter()`.
93
123
  - `BootstrapBunApplicationOptions` and `RunBunApplicationOptions`: application bootstrap/run options for Bun-hosted apps.
94
- - `BunWebSocketBinding` and `BunRealtimeBindingHost`: binding contracts used by `@fluojs/websockets/bun` before normal HTTP dispatch.
124
+ - `BunWebSocketBinding`, `BunWebSocketUpgradeHost`, and `BunRealtimeBindingHost`: binding contracts used by `@fluojs/websockets/bun` before normal HTTP dispatch. Bindings receive only an upgrade-capable host, not the adapter-owned Bun server lifecycle or raw fetch handler.
95
125
  - `BunWebSocketBindingHost`: Backward-compatible alias for configuring Bun realtime bindings.
96
126
  - `BunServeOptions`, `BunServerLike`, `BunWebSocketHandler`, `BunServerWebSocket`, `BunWebSocketMessage`, `BunApplicationSignal`, `BunCorsInput`, `BunTlsOptions`, and `CreateBunFetchHandlerOptions`: Lower-level Bun host, websocket, signal, CORS, TLS, and fetch-handler integration types.
97
127
 
@@ -100,17 +130,31 @@ The adapter also exports the typed Bun integration seams used by realtime packag
100
130
  - **Runtime host**: This package requires `globalThis.Bun.serve()` at listen time. Tests may provide a Bun-compatible test double, but production use is Bun-only.
101
131
  - **Request portability**: Fetch requests are translated through the shared web dispatcher, preserving malformed cookie values, query arrays, JSON/text raw bodies when `rawBody: true`, byte-exact request handoff for custom `createBunFetchHandler(...)` setups, and SSE framing.
102
132
  - **Native route acceleration**: When Bun's `routes` object is available and a fluo route shape is semantically safe to pre-register, the adapter lets Bun short-circuit path matching before handing the request back to the shared dispatcher. Unsupported or ambiguous route shapes fall back to the regular `fetch` path, and stale handoffs are ignored if middleware rewrites method/path before handler matching.
103
- - **Native route gate**: Native routes are enabled only on Bun `>=1.2.3`; the adapter omits the `routes` option entirely unless safe native-route entries are concretely enabled. Versioned routes, `ALL` handlers, same-shape conflicts, normalization-sensitive paths, and `OPTIONS`/CORS preflight stay on the fetch/shared-dispatch path.
133
+ - **Native route gate**: Native routes are enabled only on Bun `>=1.2.3`; the adapter omits the `routes` option entirely unless safe native-route entries are concretely enabled. Versioned routes, `ALL` handlers, custom methods, same-shape conflicts, normalization-sensitive paths, and `OPTIONS`/CORS preflight stay on the fetch/shared-dispatch path.
104
134
  - **Multipart behavior**: Multipart requests never expose `rawBody`, and multipart limits continue to flow through the shared runtime parser.
105
135
  - **Startup target**: `hostname`, `port`, and `tls` are forwarded to `Bun.serve()`. Startup logs report the configured HTTP or HTTPS listen URL.
106
136
  - **Lifecycle guards**: `listen()` is idempotent for an already-started adapter and keeps the original live dispatcher binding. Realtime/websocket bindings must be configured before `listen()` starts; later attempts to set or clear the binding fail fast instead of being accepted without affecting live wiring.
107
- - **Shutdown ownership**: `close()` stops new HTTP and websocket-upgrade ingress with a `503` shutdown response, waits for in-flight HTTP handlers, clears adapter state after drain settles, and removes signal listeners registered by `runBunApplication()`.
108
- - **Realtime seam**: Bun websocket bindings must be configured before `listen()` starts the server. Upgrade requests are offered to the configured binding before falling back to HTTP dispatch while the adapter is accepting new ingress; HTTP fallback is suppressed only after the binding returns a response or successfully upgrades the request.
137
+ - **Shutdown ownership**: `close()` stops new HTTP and websocket-upgrade ingress with a `503` shutdown response, starts `server.stop(stopActiveConnections)`, and waits for Bun server termination and every accepted request from realtime binding evaluation through HTTP response or upgrade completion. The bounded timeout only rejects the caller-facing `close()` promise: accepted work and adapter state remain retained until the underlying drain settles, after which `close()` clears adapter state. `runBunApplication()` removes its registered signal listeners when `app.close()` begins, before the adapter starts draining.
138
+ - **Realtime seam**: `getRealtimeCapability()` preserves fetch-style version 1 and exposes its optional version 1 `bindingInstallation` contract. Bun websocket bindings must be configured before `listen()` starts the server. The capability installer is the canonical configuration path for protocol packages and rejects values without `fetch` and `websocket` host contracts. After startup the binding remains frozen for the live server; the adapter `close()` boundary clears its retained binding state after Bun termination and request drain settle. Upgrade requests are offered to the configured binding before falling back to HTTP dispatch while the adapter is accepting new ingress; an accepted request keeps its dispatcher available if shutdown begins during asynchronous binding evaluation, and HTTP fallback is suppressed only after the binding returns a response or successfully upgrades the request. The binding host exposes only `upgrade(...)`, so adapter-owned `stop()` and raw `fetch()` control remain outside the realtime seam.
109
139
  - **Adapter instance helpers**: `BunHttpApplicationAdapter` exposes `getServer()`, `getListenTarget()`, `getRealtimeCapability()`, `configureRealtimeBinding()`, `configureWebSocketBinding()`, `listen()`, and `close()`.
110
140
 
141
+ ### Stable diagnostic codes
142
+
143
+ Package-generated caller-visible failures retain their existing `Error` or `TypeError` class and message while exposing a stable string through `error.code`:
144
+
145
+ | Code | Error class | Failure |
146
+ | --- | --- | --- |
147
+ | `BUN_ADAPTER_INVALID_OPTION` | `Error` | A numeric adapter or shutdown option is outside its documented range. |
148
+ | `BUN_ADAPTER_REALTIME_BINDING_INVALID` | `TypeError` | The realtime capability installer receives a value without the required `fetch` and `websocket` contracts. |
149
+ | `BUN_ADAPTER_REALTIME_BINDING_LOCKED` | `Error` | A caller attempts to change the realtime/websocket binding after `listen()` starts the Bun server. |
150
+ | `BUN_ADAPTER_RUNTIME_UNAVAILABLE` | `Error` | `listen()` cannot find a callable `globalThis.Bun.serve()`. |
151
+ | `BUN_ADAPTER_SHUTDOWN_TIMEOUT` | `Error` | The caller-facing `close()` wait exceeds its bounded shutdown timeout. |
152
+
153
+ Errors propagated from Bun or application code keep their original class, message, and metadata instead of receiving a package-owned code.
154
+
111
155
  ## Conformance Coverage
112
156
 
113
- `packages/platform-bun/src/adapter.test.ts` is the package-local regression target for the documented contract. It includes Bun fetch-style portability assertions for malformed cookies, byte-exact JSON/text raw-body preservation, multipart raw-body exclusion, SSE framing, native-route param parity, same-path multi-method handoff, stale native handoff rematching after middleware rewrites, versioning fallback, normalization-sensitive fallback, OPTIONS/CORS ownership, same-shape route fallback, and TLS listen-target reporting, plus focused tests for startup logging, duplicate listen idempotency, shutdown listener cleanup, in-flight drain behavior, timeout validation/reporting, shutdown 503 ingress rejection, and websocket binding delegation.
157
+ `packages/platform-bun/src/adapter.test.ts` is the package-local regression target for the documented contract. It includes Bun fetch-style portability assertions for conditional requests, single-byte ranges and `If-Range`, custom `QUERY`/extension-method fallback, malformed cookies, byte-exact JSON/text raw-body preservation, multipart raw-body exclusion for managed and custom fetch handlers, SSE framing, native-route param parity, same-path multi-method handoff, stale native handoff rematching after middleware rewrites the request path or method, versioning fallback, normalization-sensitive fallback, OPTIONS/CORS ownership, same-shape route fallback, and TLS listen-target reporting, plus focused tests for startup logging, duplicate listen idempotency, shutdown listener cleanup, in-flight drain behavior, close during asynchronous realtime binding evaluation, HTTP fallback after binding completion, timeout validation/reporting, shutdown 503 ingress rejection, signal-driven close rejection reporting, and websocket binding delegation/short-circuit behavior through an upgrade-only host.
114
158
 
115
159
  The broader repository suite also exercises Bun through `createWebRuntimeHttpAdapterPortabilityHarness(...)` alongside Deno and Cloudflare Workers in `packages/testing/src/portability/web-runtime-adapter-portability.test.ts`, keeping the shared web-runtime portability baseline aligned across fetch-style platforms.
116
160
 
package/dist/adapter.d.ts CHANGED
@@ -1,18 +1,12 @@
1
- import type { CorsOptions, Dispatcher, HttpApplicationAdapter, HttpMethod, MiddlewareLike, SecurityHeadersOptions } from '@fluojs/http';
2
- import type { Application, CreateApplicationOptions, ModuleType, MultipartOptions, UploadedFile } from '@fluojs/runtime';
1
+ import type { CorsOptions, Dispatcher, HttpApplicationAdapter, MiddlewareLike, SecurityHeadersOptions } from '@fluojs/http';
2
+ import type { Application, CreateApplicationOptions, ModuleType, MultipartOptions } from '@fluojs/runtime';
3
3
  import { type HttpAdapterListenTarget } from '@fluojs/runtime/internal/http-adapter';
4
- declare module '@fluojs/http' {
5
- interface FrameworkRequest {
6
- files?: UploadedFile[];
7
- rawBody?: Uint8Array;
8
- }
9
- }
10
4
  type BunHostname = string;
11
5
  type BunRequestLike = Request & {
12
6
  params?: Readonly<Record<string, string>>;
13
7
  };
14
8
  type BunRouteHandler = (request: BunRequestLike, server: BunServerLike) => Response | Promise<Response> | undefined | Promise<Response | undefined>;
15
- type BunRouteMethod = Exclude<HttpMethod, 'ALL'>;
9
+ type BunRouteMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
16
10
  type BunRouteMethodMap = Partial<Record<BunRouteMethod, BunRouteHandler | Response>>;
17
11
  type BunRouteValue = BunRouteHandler | Response | BunRouteMethodMap;
18
12
  /** Shutdown signal names that `runBunApplication()` can register. */
@@ -58,11 +52,18 @@ export interface BunWebSocketHandler<TData = unknown> {
58
52
  }
59
53
  /** Fetch-style websocket binding consumed before normal HTTP dispatch. */
60
54
  export interface BunWebSocketBinding<TData = unknown> {
61
- fetch(request: Request, server: BunServerLike): Response | Promise<Response> | undefined | Promise<Response | undefined>;
55
+ fetch(request: Request, server: BunWebSocketUpgradeHost): Response | Promise<Response> | undefined | Promise<Response | undefined>;
62
56
  idleTimeout?: number;
63
57
  maxRequestBodySize?: number;
64
58
  websocket: BunWebSocketHandler<TData>;
65
59
  }
60
+ /** Upgrade-only Bun host exposed to websocket bindings before normal HTTP dispatch. */
61
+ export interface BunWebSocketUpgradeHost {
62
+ upgrade<TData = unknown>(request: Request, options?: {
63
+ data?: TData;
64
+ headers?: HeadersInit;
65
+ }): boolean;
66
+ }
66
67
  /** Host contract exposed by Bun adapters that can install a realtime binding. */
67
68
  export interface BunRealtimeBindingHost {
68
69
  configureRealtimeBinding<TData>(binding: BunWebSocketBinding<TData> | undefined): void;
@@ -89,7 +90,7 @@ export interface BunServerLike {
89
90
  fetch?(request: Request): Response | Promise<Response> | undefined | Promise<Response | undefined>;
90
91
  hostname?: BunHostname;
91
92
  port?: number;
92
- stop(closeActiveConnections?: boolean): void;
93
+ stop(closeActiveConnections?: boolean): Promise<void>;
93
94
  upgrade<TData = unknown>(request: Request, options?: {
94
95
  data?: TData;
95
96
  headers?: HeadersInit;
@@ -177,6 +178,7 @@ export declare class BunHttpApplicationAdapter implements HttpApplicationAdapter
177
178
  private server?;
178
179
  private realtimeBinding?;
179
180
  private readonly options;
181
+ private readonly shutdownTimeoutMs;
180
182
  private readonly webRequestResponseFactory;
181
183
  constructor(options?: BunAdapterOptions);
182
184
  /** Returns the active Bun server handle after `listen()` starts. */
@@ -185,6 +187,7 @@ export declare class BunHttpApplicationAdapter implements HttpApplicationAdapter
185
187
  getListenTarget(): HttpAdapterListenTarget;
186
188
  /** Reports Bun's fetch-style websocket capability for realtime package integration. */
187
189
  getRealtimeCapability(): import("@fluojs/http").FetchStyleHttpAdapterRealtimeCapability;
190
+ private installRealtimeBinding;
188
191
  /** Configures the official realtime binding before the Bun server starts. */
189
192
  configureRealtimeBinding<TData>(binding: BunWebSocketBinding<TData> | undefined): void;
190
193
  /** Configures a Bun websocket binding through the legacy websocket host name. */
@@ -193,7 +196,6 @@ export declare class BunHttpApplicationAdapter implements HttpApplicationAdapter
193
196
  listen(dispatcher: Dispatcher): Promise<void>;
194
197
  /** Stops ingress, waits for in-flight HTTP handlers, and releases adapter state. */
195
198
  close(): Promise<void>;
196
- private dispatchHttpRequest;
197
199
  private trackInFlightRequest;
198
200
  private waitForInFlightRequests;
199
201
  }
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
package/dist/adapter.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { bindRawRequestNativeRouteHandoff, createFetchStyleHttpAdapterRealtimeCapability, isRoutePathNormalizationSensitive } from '@fluojs/http/internal';
2
2
  import { bootstrapHttpAdapterApplication, createDefaultApplicationLogger, runHttpAdapterApplication } from '@fluojs/runtime/internal/http-adapter';
3
- import { createWebRequestResponseFactory, dispatchWebRequest } from '@fluojs/runtime/web';
3
+ import { createWebRequestResponseFactory, dispatchWebRequest, startWebRequestDispatch } from '@fluojs/runtime/web';
4
4
 
5
5
  /** Shutdown signal names that `runBunApplication()` can register. */
6
6
 
@@ -16,6 +16,8 @@ import { createWebRequestResponseFactory, dispatchWebRequest } from '@fluojs/run
16
16
 
17
17
  /** Fetch-style websocket binding consumed before normal HTTP dispatch. */
18
18
 
19
+ /** Upgrade-only Bun host exposed to websocket bindings before normal HTTP dispatch. */
20
+
19
21
  /** Host contract exposed by Bun adapters that can install a realtime binding. */
20
22
 
21
23
  /** Backward-compatible host contract for Bun websocket-specific bindings. */
@@ -38,7 +40,25 @@ const DEFAULT_SHUTDOWN_TIMEOUT_MS = 10_000;
38
40
  const DEFAULT_FORCE_EXIT_TIMEOUT_MS = 30_000;
39
41
  const MINIMUM_BUN_NATIVE_ROUTES_VERSION = '1.2.3';
40
42
  const EMPTY_NATIVE_ROUTE_PARAMS = Object.freeze({});
43
+ const BUN_ADAPTER_CLOSE_TIMEOUT_MS = Symbol('fluo.bunAdapterCloseTimeoutMs');
44
+ const BUN_ADAPTER_DIAGNOSTIC_CODES = {
45
+ invalidOption: 'BUN_ADAPTER_INVALID_OPTION',
46
+ realtimeBindingInvalid: 'BUN_ADAPTER_REALTIME_BINDING_INVALID',
47
+ realtimeBindingLocked: 'BUN_ADAPTER_REALTIME_BINDING_LOCKED',
48
+ runtimeUnavailable: 'BUN_ADAPTER_RUNTIME_UNAVAILABLE',
49
+ shutdownTimeout: 'BUN_ADAPTER_SHUTDOWN_TIMEOUT'
50
+ };
41
51
  const BUN_WEBSOCKET_SUPPORT_REASON = 'Bun exposes Bun.serve() + server.upgrade() request-upgrade hosting. Use @fluojs/websockets/bun for the official raw websocket binding.';
52
+ function attachBunAdapterDiagnosticCode(error, code) {
53
+ Object.defineProperty(error, 'code', {
54
+ enumerable: true,
55
+ value: code
56
+ });
57
+ return error;
58
+ }
59
+ function isBunWebSocketBinding(value) {
60
+ return typeof value === 'object' && value !== null && typeof Reflect.get(value, 'fetch') === 'function' && typeof Reflect.get(value, 'websocket') === 'object' && Reflect.get(value, 'websocket') !== null;
61
+ }
42
62
 
43
63
  /** HTTP application adapter backed by native `Bun.serve()`. */
44
64
  export class BunHttpApplicationAdapter {
@@ -49,17 +69,20 @@ export class BunHttpApplicationAdapter {
49
69
  server;
50
70
  realtimeBinding;
51
71
  options;
72
+ shutdownTimeoutMs;
52
73
  webRequestResponseFactory;
53
74
  constructor(options = {}) {
75
+ const internalOptions = options;
54
76
  validateNonNegativeIntegerOption('idleTimeout', options.idleTimeout);
55
77
  validateNonNegativeIntegerOption('maxBodySize', options.maxBodySize);
78
+ validateNonNegativeIntegerOption('shutdownTimeoutMs', internalOptions[BUN_ADAPTER_CLOSE_TIMEOUT_MS]);
56
79
  validatePortOption(options.port);
57
80
  this.options = options;
81
+ this.shutdownTimeoutMs = internalOptions[BUN_ADAPTER_CLOSE_TIMEOUT_MS] ?? DEFAULT_SHUTDOWN_TIMEOUT_MS;
58
82
  this.webRequestResponseFactory = createWebRequestResponseFactory({
59
83
  consumeOriginalBody: true,
60
84
  maxBodySize: options.maxBodySize,
61
85
  multipart: options.multipart,
62
- preferNativeJsonBodyReader: true,
63
86
  rawBody: options.rawBody
64
87
  });
65
88
  }
@@ -85,14 +108,27 @@ export class BunHttpApplicationAdapter {
85
108
  /** Reports Bun's fetch-style websocket capability for realtime package integration. */
86
109
  getRealtimeCapability() {
87
110
  return createFetchStyleHttpAdapterRealtimeCapability(BUN_WEBSOCKET_SUPPORT_REASON, {
111
+ bindingInstallation: {
112
+ install: binding => this.installRealtimeBinding(binding)
113
+ },
88
114
  support: 'supported'
89
115
  });
90
116
  }
117
+ installRealtimeBinding(binding) {
118
+ if (binding === undefined) {
119
+ this.configureRealtimeBinding(undefined);
120
+ return;
121
+ }
122
+ if (!isBunWebSocketBinding(binding)) {
123
+ throw attachBunAdapterDiagnosticCode(new TypeError('Bun realtime binding installation requires fetch and websocket host contracts.'), BUN_ADAPTER_DIAGNOSTIC_CODES.realtimeBindingInvalid);
124
+ }
125
+ this.configureRealtimeBinding(binding);
126
+ }
91
127
 
92
128
  /** Configures the official realtime binding before the Bun server starts. */
93
129
  configureRealtimeBinding(binding) {
94
130
  if (this.server) {
95
- throw new Error('Bun websocket binding must be configured before Bun adapter listen() starts the server.');
131
+ throw attachBunAdapterDiagnosticCode(new Error('Bun websocket binding must be configured before Bun adapter listen() starts the server.'), BUN_ADAPTER_DIAGNOSTIC_CODES.realtimeBindingLocked);
96
132
  }
97
133
  this.realtimeBinding = binding;
98
134
  }
@@ -117,13 +153,29 @@ export class BunHttpApplicationAdapter {
117
153
  if (this.closeInFlight) {
118
154
  return createShutdownResponse();
119
155
  }
120
- if (realtimeBinding) {
121
- const realtimeResult = await dispatchRealtimeBindingRequest(realtimeBinding, request, server);
122
- if (realtimeResult.handled !== undefined || realtimeResult.upgraded) {
123
- return realtimeResult.handled;
156
+ const release = this.trackInFlightRequest();
157
+ let releaseAfterResponse = true;
158
+ try {
159
+ if (realtimeBinding) {
160
+ const realtimeResult = await dispatchRealtimeBindingRequest(realtimeBinding, request, server);
161
+ if (realtimeResult.handled !== undefined || realtimeResult.upgraded) {
162
+ return realtimeResult.handled;
163
+ }
164
+ }
165
+ const dispatch = startWebRequestDispatch({
166
+ dispatcher: this.dispatcher,
167
+ dispatcherNotReadyMessage: DEFAULT_DISPATCHER_NOT_READY_MESSAGE,
168
+ factory: this.webRequestResponseFactory,
169
+ request
170
+ });
171
+ releaseAfterResponse = false;
172
+ void dispatch.completion.finally(release).catch(() => {});
173
+ return await dispatch.response;
174
+ } finally {
175
+ if (releaseAfterResponse) {
176
+ release();
124
177
  }
125
178
  }
126
- return await this.dispatchHttpRequest(request);
127
179
  };
128
180
  const nativeRoutes = createBunNativeRoutes(dispatcher, handleRequest, bun);
129
181
  const serveOptions = {
@@ -145,11 +197,12 @@ export class BunHttpApplicationAdapter {
145
197
  /** Stops ingress, waits for in-flight HTTP handlers, and releases adapter state. */
146
198
  async close() {
147
199
  if (this.closeInFlight) {
148
- await waitForCloseWithTimeout(this.closeInFlight, DEFAULT_SHUTDOWN_TIMEOUT_MS);
200
+ await waitForCloseWithTimeout(this.closeInFlight, this.shutdownTimeoutMs);
149
201
  return;
150
202
  }
151
203
  if (!this.server) {
152
204
  this.dispatcher = undefined;
205
+ this.realtimeBinding = undefined;
153
206
  return;
154
207
  }
155
208
  const server = this.server;
@@ -160,26 +213,11 @@ export class BunHttpApplicationAdapter {
160
213
  }
161
214
  this.closeInFlight = undefined;
162
215
  this.dispatcher = undefined;
216
+ this.realtimeBinding = undefined;
163
217
  });
164
218
  this.closeInFlight = closeInFlight;
165
219
  void closeInFlight.catch(() => {});
166
- await waitForCloseWithTimeout(closeInFlight, DEFAULT_SHUTDOWN_TIMEOUT_MS);
167
- }
168
- async dispatchHttpRequest(request) {
169
- if (this.closeInFlight) {
170
- return createShutdownResponse();
171
- }
172
- const release = this.trackInFlightRequest();
173
- try {
174
- return await dispatchWebRequest({
175
- dispatcher: this.dispatcher,
176
- dispatcherNotReadyMessage: DEFAULT_DISPATCHER_NOT_READY_MESSAGE,
177
- factory: this.webRequestResponseFactory,
178
- request
179
- });
180
- } finally {
181
- release();
182
- }
220
+ await waitForCloseWithTimeout(closeInFlight, this.shutdownTimeoutMs);
183
221
  }
184
222
  trackInFlightRequest() {
185
223
  this.inFlightRequestCount += 1;
@@ -223,7 +261,6 @@ export function createBunFetchHandler({
223
261
  consumeOriginalBody: true,
224
262
  maxBodySize,
225
263
  multipart,
226
- preferNativeJsonBodyReader: true,
227
264
  rawBody
228
265
  });
229
266
  return async function bunFetchHandler(request) {
@@ -278,7 +315,7 @@ export async function bootstrapBunApplication(rootModule, options) {
278
315
  export async function runBunApplication(rootModule, options) {
279
316
  validateNonNegativeIntegerOption('forceExitTimeoutMs', options.forceExitTimeoutMs);
280
317
  const logger = createDefaultApplicationLogger();
281
- const adapter = createBunAdapter({
318
+ const adapterOptions = {
282
319
  development: options.development,
283
320
  hostname: options.hostname,
284
321
  idleTimeout: options.idleTimeout,
@@ -287,8 +324,10 @@ export async function runBunApplication(rootModule, options) {
287
324
  port: options.port,
288
325
  rawBody: options.rawBody,
289
326
  stopActiveConnections: options.stopActiveConnections,
290
- tls: options.tls
291
- });
327
+ tls: options.tls,
328
+ [BUN_ADAPTER_CLOSE_TIMEOUT_MS]: options.forceExitTimeoutMs ?? DEFAULT_FORCE_EXIT_TIMEOUT_MS
329
+ };
330
+ const adapter = new BunHttpApplicationAdapter(adapterOptions);
292
331
  return runHttpAdapterApplication(rootModule, {
293
332
  ...options,
294
333
  shutdownRegistration: createBunShutdownSignalRegistration(options.shutdownSignals ?? defaultBunShutdownSignals())
@@ -350,7 +389,7 @@ async function closeBunApplicationFromSignal(app, logger, signal, forceExitTimeo
350
389
  function requireBunGlobal() {
351
390
  const bun = globalThis.Bun;
352
391
  if (!bun || typeof bun.serve !== 'function') {
353
- throw new Error('Bun adapter requires globalThis.Bun.serve(). Run this package inside Bun or provide a Bun-compatible test double.');
392
+ throw attachBunAdapterDiagnosticCode(new Error('Bun adapter requires globalThis.Bun.serve(). Run this package inside Bun or provide a Bun-compatible test double.'), BUN_ADAPTER_DIAGNOSTIC_CODES.runtimeUnavailable);
354
393
  }
355
394
  return bun;
356
395
  }
@@ -360,7 +399,7 @@ function resolvePort(port) {
360
399
  function validatePortOption(port) {
361
400
  const resolved = port ?? DEFAULT_PORT;
362
401
  if (!Number.isInteger(resolved) || resolved < 0 || resolved > 65535) {
363
- throw new Error(`Invalid port value: ${String(resolved)}. Expected an integer between 0 and 65535.`);
402
+ throw attachBunAdapterDiagnosticCode(new Error(`Invalid port value: ${String(resolved)}. Expected an integer between 0 and 65535.`), BUN_ADAPTER_DIAGNOSTIC_CODES.invalidOption);
364
403
  }
365
404
  return resolved;
366
405
  }
@@ -369,24 +408,19 @@ function validateNonNegativeIntegerOption(name, value) {
369
408
  return;
370
409
  }
371
410
  if (!Number.isInteger(value) || value < 0) {
372
- throw new Error(`Invalid ${name} value: ${String(value)}. Expected a non-negative integer.`);
411
+ throw attachBunAdapterDiagnosticCode(new Error(`Invalid ${name} value: ${String(value)}. Expected a non-negative integer.`), BUN_ADAPTER_DIAGNOSTIC_CODES.invalidOption);
373
412
  }
374
413
  }
375
414
  async function dispatchRealtimeBindingRequest(binding, request, server) {
376
415
  let upgraded = false;
377
- const trackedServer = {
378
- fetch: server.fetch ? trackedRequest => server.fetch?.(trackedRequest) : undefined,
379
- hostname: server.hostname,
380
- port: server.port,
381
- stop: closeActiveConnections => server.stop(closeActiveConnections),
416
+ const upgradeHost = {
382
417
  upgrade(upgradeRequest, options) {
383
418
  const didUpgrade = server.upgrade(upgradeRequest, options);
384
419
  upgraded ||= didUpgrade;
385
420
  return didUpgrade;
386
- },
387
- url: server.url
421
+ }
388
422
  };
389
- const handled = await binding.fetch(request, trackedServer);
423
+ const handled = await binding.fetch(request, upgradeHost);
390
424
  return {
391
425
  handled,
392
426
  upgraded
@@ -518,12 +552,29 @@ function collectVersionSensitiveRouteKeys(descriptors) {
518
552
  return new Set([...grouped.entries()].filter(([, current]) => current.count > 1 || current.hasVersioned).map(([routeKey]) => routeKey));
519
553
  }
520
554
  function toBunRouteMethod(method) {
521
- return method === 'ALL' ? undefined : method;
555
+ switch (method) {
556
+ case 'GET':
557
+ case 'POST':
558
+ case 'PUT':
559
+ case 'PATCH':
560
+ case 'DELETE':
561
+ case 'OPTIONS':
562
+ case 'HEAD':
563
+ return method;
564
+ default:
565
+ return undefined;
566
+ }
522
567
  }
523
568
  function closeBunServerWithDrain(server, stopActiveConnections, waitForDrain) {
524
569
  return (async () => {
525
- server.stop(stopActiveConnections);
526
- await waitForDrain();
570
+ const results = await Promise.allSettled([server.stop(stopActiveConnections), waitForDrain()]);
571
+ const rejections = results.flatMap(result => result.status === 'rejected' ? [result.reason] : []);
572
+ if (rejections.length === 1) {
573
+ throw rejections[0];
574
+ }
575
+ if (rejections.length > 1) {
576
+ throw new AggregateError(rejections, 'Bun server shutdown failed.');
577
+ }
527
578
  })();
528
579
  }
529
580
  function createDeferred() {
@@ -556,7 +607,7 @@ function createShutdownResponse() {
556
607
  function waitForCloseWithTimeout(closePromise, timeoutMs) {
557
608
  return new Promise((resolve, reject) => {
558
609
  const timeoutHandle = setTimeout(() => {
559
- reject(new Error(`Bun adapter shutdown timeout exceeded ${String(timeoutMs)}ms.`));
610
+ reject(attachBunAdapterDiagnosticCode(new Error(`Bun adapter shutdown timeout exceeded ${String(timeoutMs)}ms.`), BUN_ADAPTER_DIAGNOSTIC_CODES.shutdownTimeout));
560
611
  }, timeoutMs);
561
612
  void closePromise.then(() => {
562
613
  clearTimeout(timeoutHandle);
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "platform",
9
9
  "server"
10
10
  ],
11
- "version": "1.0.7",
11
+ "version": "3.0.0",
12
12
  "private": false,
13
13
  "license": "MIT",
14
14
  "repository": {
@@ -32,11 +32,12 @@
32
32
  "dist"
33
33
  ],
34
34
  "dependencies": {
35
- "@fluojs/http": "^1.1.2",
36
- "@fluojs/runtime": "^1.1.8"
35
+ "@fluojs/http": "^3.0.0",
36
+ "@fluojs/runtime": "^3.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "vitest": "^3.2.4"
39
+ "vitest": "^4.1.11",
40
+ "@fluojs/testing": "^3.0.0"
40
41
  },
41
42
  "scripts": {
42
43
  "prebuild": "node ../../tooling/scripts/clean-dist.mjs",