@fluojs/platform-bun 1.0.0-beta.1 → 1.0.0-beta.3
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 +30 -0
- package/README.md +30 -0
- package/dist/adapter.d.ts +89 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +175 -13
- package/package.json +3 -3
package/README.ko.md
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
- [빠른 시작](#빠른-시작)
|
|
12
12
|
- [주요 패턴](#주요-패턴)
|
|
13
13
|
- [공개 API 개요](#공개-api-개요)
|
|
14
|
+
- [어댑터 계약](#어댑터-계약)
|
|
15
|
+
- [Conformance 커버리지](#conformance-커버리지)
|
|
14
16
|
- [관련 패키지](#관련-패키지)
|
|
15
17
|
- [예제 소스](#예제-소스)
|
|
16
18
|
|
|
@@ -69,6 +71,11 @@ Bun.serve({
|
|
|
69
71
|
export class MyGateway {}
|
|
70
72
|
```
|
|
71
73
|
|
|
74
|
+
### 네이티브 `routes` Object 가속
|
|
75
|
+
Bun `>=1.2.3`에서는 어댑터가 의미 보존이 가능한 static/param fluo route를 `Bun.serve({ routes })`에 선택적으로 등록한 뒤, 매칭된 요청도 다시 shared fluo dispatcher로 흘려보냅니다.
|
|
76
|
+
|
|
77
|
+
이 방식은 raw body, multipart, SSE, error response, shutdown drain, websocket upgrade delegation을 모두 기존 shared 실행 경로에 유지합니다. same-shape param route처럼 의미가 어긋날 수 있는 경우나 `ALL` 메서드 handler처럼 안전하게 선등록할 수 없는 경우에는 의미를 바꾸지 않도록 해당 route를 fetch-only dispatch로 폴백합니다.
|
|
78
|
+
|
|
72
79
|
## 공개 API 개요
|
|
73
80
|
|
|
74
81
|
- `createBunAdapter(options)`: Bun 어댑터를 위한 권장 팩토리입니다.
|
|
@@ -76,6 +83,29 @@ export class MyGateway {}
|
|
|
76
83
|
- `bootstrapBunApplication(module, options)`: 암시적 시작 로그 없이 애플리케이션을 부트스트랩하는 고급 헬퍼입니다.
|
|
77
84
|
- `runBunApplication(module, options)`: 시그널 연결을 포함한 빠른 시작을 위한 호환 헬퍼입니다.
|
|
78
85
|
|
|
86
|
+
어댑터는 realtime 패키지가 사용하는 타입 지정 Bun 통합 seam도 함께 내보냅니다.
|
|
87
|
+
|
|
88
|
+
- `BunHttpApplicationAdapter`: `Bun.serve()`를 기반으로 동작하는 `HttpApplicationAdapter` 구현체입니다.
|
|
89
|
+
- `BunAdapterOptions`: `createBunAdapter()`가 받는 host, port, TLS, raw-body, multipart, shutdown 옵션입니다.
|
|
90
|
+
- `BootstrapBunApplicationOptions` 및 `RunBunApplicationOptions`: Bun 호스팅 애플리케이션의 bootstrap/run 옵션입니다.
|
|
91
|
+
- `BunWebSocketBinding` 및 `BunRealtimeBindingHost`: 일반 HTTP dispatch 전에 `@fluojs/websockets/bun`이 사용하는 binding 계약입니다.
|
|
92
|
+
|
|
93
|
+
## 어댑터 계약
|
|
94
|
+
|
|
95
|
+
- **런타임 host**: 이 패키지는 listen 시점에 `globalThis.Bun.serve()`가 필요합니다. 테스트에서는 Bun 호환 test double을 제공할 수 있지만, production 사용은 Bun 전용입니다.
|
|
96
|
+
- **요청 portability**: Fetch 요청은 shared web dispatcher를 통해 변환되며 malformed cookie 값, query 배열, `rawBody: true`일 때 JSON/text raw body, SSE framing을 보존합니다.
|
|
97
|
+
- **네이티브 route 가속**: Bun의 `routes` object를 사용할 수 있고 fluo route shape를 의미 보존 상태로 선등록할 수 있을 때만 Bun이 path matching을 먼저 처리하고, 이후 요청은 다시 shared dispatcher로 넘깁니다. 지원하지 않거나 모호한 route shape는 일반 `fetch` 경로로 폴백합니다.
|
|
98
|
+
- **Multipart 동작**: Multipart 요청은 `rawBody`를 노출하지 않으며 multipart limit은 shared runtime parser를 통해 계속 적용됩니다.
|
|
99
|
+
- **시작 target**: `hostname`, `port`, `tls`는 `Bun.serve()`로 전달됩니다. 시작 로그는 설정된 HTTP 또는 HTTPS listen URL을 보고합니다.
|
|
100
|
+
- **종료 소유권**: `close()`는 새 유입을 중단하고, in-flight HTTP handler를 기다린 뒤, drain이 끝나면 adapter state를 정리하며 `runBunApplication()`이 등록한 signal listener를 제거합니다.
|
|
101
|
+
- **Realtime seam**: Bun websocket binding은 서버를 시작하는 `listen()` 전에 구성해야 합니다. Upgrade 요청은 HTTP dispatch로 넘어가기 전에 구성된 binding에 먼저 전달됩니다.
|
|
102
|
+
|
|
103
|
+
## Conformance 커버리지
|
|
104
|
+
|
|
105
|
+
`packages/platform-bun/src/adapter.test.ts`는 문서화된 계약을 검증하는 package-local regression 대상입니다. 이 파일은 malformed cookie, JSON/text raw-body 보존, multipart raw-body 제외, SSE framing, native-route param parity, same-shape route fallback을 검증하는 Bun fetch-style portability assertion과 startup logging, shutdown listener cleanup, in-flight drain, timeout reporting, websocket binding delegation을 검증하는 집중 테스트를 포함합니다.
|
|
106
|
+
|
|
107
|
+
저장소의 더 넓은 suite도 `packages/testing/src/portability/web-runtime-adapter-portability.test.ts`에서 `createWebRuntimeHttpAdapterPortabilityHarness(...)`로 Bun을 Deno 및 Cloudflare Workers와 함께 실행해 fetch-style platform 간 shared web-runtime portability baseline을 맞춥니다.
|
|
108
|
+
|
|
79
109
|
## 관련 패키지
|
|
80
110
|
|
|
81
111
|
- `@fluojs/runtime`: 핵심 런타임입니다.
|
package/README.md
CHANGED
|
@@ -11,6 +11,8 @@ Bun-backed HTTP adapter for the fluo runtime, built on native `Bun.serve()`.
|
|
|
11
11
|
- [Quick Start](#quick-start)
|
|
12
12
|
- [Common Patterns](#common-patterns)
|
|
13
13
|
- [Public API Overview](#public-api-overview)
|
|
14
|
+
- [Adapter Contract](#adapter-contract)
|
|
15
|
+
- [Conformance Coverage](#conformance-coverage)
|
|
14
16
|
- [Related Packages](#related-packages)
|
|
15
17
|
- [Example Sources](#example-sources)
|
|
16
18
|
|
|
@@ -69,6 +71,11 @@ The adapter supports Bun's native `server.upgrade()` through the `@fluojs/websoc
|
|
|
69
71
|
export class MyGateway {}
|
|
70
72
|
```
|
|
71
73
|
|
|
74
|
+
### Native `routes` Object Acceleration
|
|
75
|
+
On Bun `>=1.2.3`, the adapter opportunistically registers safe static and parameterized fluo routes through `Bun.serve({ routes })` while still routing matched requests back through the shared fluo dispatcher.
|
|
76
|
+
|
|
77
|
+
This keeps raw body, multipart, SSE, error responses, shutdown drain behavior, and websocket upgrade delegation on the same shared execution path. If route shape parity is unsafe, such as same-shape parameter routes with different param names or `ALL`-method handlers, the adapter falls back to fetch-only dispatch for those routes instead of changing fluo semantics.
|
|
78
|
+
|
|
72
79
|
## Public API Overview
|
|
73
80
|
|
|
74
81
|
- `createBunAdapter(options)`: Recommended factory for the Bun adapter.
|
|
@@ -76,6 +83,29 @@ export class MyGateway {}
|
|
|
76
83
|
- `bootstrapBunApplication(module, options)`: Advanced bootstrap without implicit startup logging.
|
|
77
84
|
- `runBunApplication(module, options)`: Compatibility helper for quick startup with signal wiring.
|
|
78
85
|
|
|
86
|
+
The adapter also exports the typed Bun integration seams used by realtime packages:
|
|
87
|
+
|
|
88
|
+
- `BunHttpApplicationAdapter`: `HttpApplicationAdapter` implementation backed by `Bun.serve()`.
|
|
89
|
+
- `BunAdapterOptions`: host, port, TLS, raw-body, multipart, and shutdown options accepted by `createBunAdapter()`.
|
|
90
|
+
- `BootstrapBunApplicationOptions` and `RunBunApplicationOptions`: application bootstrap/run options for Bun-hosted apps.
|
|
91
|
+
- `BunWebSocketBinding` and `BunRealtimeBindingHost`: binding contracts used by `@fluojs/websockets/bun` before normal HTTP dispatch.
|
|
92
|
+
|
|
93
|
+
## Adapter Contract
|
|
94
|
+
|
|
95
|
+
- **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.
|
|
96
|
+
- **Request portability**: Fetch requests are translated through the shared web dispatcher, preserving malformed cookie values, query arrays, JSON/text raw bodies when `rawBody: true`, and SSE framing.
|
|
97
|
+
- **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.
|
|
98
|
+
- **Multipart behavior**: Multipart requests never expose `rawBody`, and multipart limits continue to flow through the shared runtime parser.
|
|
99
|
+
- **Startup target**: `hostname`, `port`, and `tls` are forwarded to `Bun.serve()`. Startup logs report the configured HTTP or HTTPS listen URL.
|
|
100
|
+
- **Shutdown ownership**: `close()` stops new ingress, waits for in-flight HTTP handlers, clears adapter state after drain settles, and removes signal listeners registered by `runBunApplication()`.
|
|
101
|
+
- **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.
|
|
102
|
+
|
|
103
|
+
## Conformance Coverage
|
|
104
|
+
|
|
105
|
+
`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, JSON/text raw-body preservation, multipart raw-body exclusion, SSE framing, native-route param parity, and same-shape route fallback, plus focused tests for startup logging, shutdown listener cleanup, in-flight drain behavior, timeout reporting, and websocket binding delegation.
|
|
106
|
+
|
|
107
|
+
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.
|
|
108
|
+
|
|
79
109
|
## Related Packages
|
|
80
110
|
|
|
81
111
|
- `@fluojs/runtime`: Core framework runtime.
|
package/dist/adapter.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CorsOptions, Dispatcher, HttpApplicationAdapter, MiddlewareLike, SecurityHeadersOptions } from '@fluojs/http';
|
|
1
|
+
import type { CorsOptions, Dispatcher, HttpApplicationAdapter, HttpMethod, MiddlewareLike, SecurityHeadersOptions } from '@fluojs/http';
|
|
2
2
|
import type { Application, ApplicationLogger, CreateApplicationOptions, ModuleType, MultipartOptions, UploadedFile } from '@fluojs/runtime';
|
|
3
3
|
import { type HttpAdapterListenTarget } from '@fluojs/runtime/internal/http-adapter';
|
|
4
4
|
declare module '@fluojs/http' {
|
|
@@ -8,10 +8,22 @@ declare module '@fluojs/http' {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
type BunHostname = string;
|
|
11
|
+
type BunRequestLike = Request & {
|
|
12
|
+
params?: Readonly<Record<string, string>>;
|
|
13
|
+
};
|
|
14
|
+
type BunRouteHandler = (request: BunRequestLike, server: BunServerLike) => Response | Promise<Response> | undefined | Promise<Response | undefined>;
|
|
15
|
+
type BunRouteMethod = Exclude<HttpMethod, 'ALL'>;
|
|
16
|
+
type BunRouteMethodMap = Partial<Record<BunRouteMethod, BunRouteHandler | Response>>;
|
|
17
|
+
type BunRouteValue = BunRouteHandler | Response | BunRouteMethodMap;
|
|
18
|
+
/** Shutdown signal names that `runBunApplication()` can register. */
|
|
11
19
|
export type BunApplicationSignal = 'SIGINT' | 'SIGTERM';
|
|
20
|
+
/** CORS input accepted by Bun application bootstrap helpers. */
|
|
12
21
|
export type BunCorsInput = false | string | string[] | CorsOptions;
|
|
22
|
+
/** TLS options forwarded to `Bun.serve()` without adapter-level normalization. */
|
|
13
23
|
export type BunTlsOptions = Record<string, unknown>;
|
|
24
|
+
/** Message payloads accepted by Bun server websocket bindings. */
|
|
14
25
|
export type BunWebSocketMessage = string | ArrayBuffer | Uint8Array;
|
|
26
|
+
/** Minimal Bun server websocket shape used by the official websocket binding seam. */
|
|
15
27
|
export interface BunServerWebSocket<TData = unknown> {
|
|
16
28
|
readonly data: TData;
|
|
17
29
|
readonly readyState: number;
|
|
@@ -25,6 +37,7 @@ export interface BunServerWebSocket<TData = unknown> {
|
|
|
25
37
|
subscribe(topic: string): void;
|
|
26
38
|
unsubscribe(topic: string): void;
|
|
27
39
|
}
|
|
40
|
+
/** Callback contract forwarded to the `websocket` option of `Bun.serve()`. */
|
|
28
41
|
export interface BunWebSocketHandler<TData = unknown> {
|
|
29
42
|
backpressureLimit?: number;
|
|
30
43
|
close?(socket: BunServerWebSocket<TData>, code: number, reason: string): void | Promise<void>;
|
|
@@ -43,18 +56,22 @@ export interface BunWebSocketHandler<TData = unknown> {
|
|
|
43
56
|
publishToSelf?: boolean;
|
|
44
57
|
sendPings?: boolean;
|
|
45
58
|
}
|
|
59
|
+
/** Fetch-style websocket binding consumed before normal HTTP dispatch. */
|
|
46
60
|
export interface BunWebSocketBinding<TData = unknown> {
|
|
47
61
|
fetch(request: Request, server: BunServerLike): Response | Promise<Response> | undefined | Promise<Response | undefined>;
|
|
48
62
|
idleTimeout?: number;
|
|
49
63
|
maxRequestBodySize?: number;
|
|
50
64
|
websocket: BunWebSocketHandler<TData>;
|
|
51
65
|
}
|
|
66
|
+
/** Host contract exposed by Bun adapters that can install a realtime binding. */
|
|
52
67
|
export interface BunRealtimeBindingHost {
|
|
53
68
|
configureRealtimeBinding<TData>(binding: BunWebSocketBinding<TData> | undefined): void;
|
|
54
69
|
}
|
|
70
|
+
/** Backward-compatible host contract for Bun websocket-specific bindings. */
|
|
55
71
|
export interface BunWebSocketBindingHost extends BunRealtimeBindingHost {
|
|
56
72
|
configureWebSocketBinding<TData>(binding: BunWebSocketBinding<TData> | undefined): void;
|
|
57
73
|
}
|
|
74
|
+
/** Subset of `Bun.serve()` options used by the adapter and its tests. */
|
|
58
75
|
export interface BunServeOptions {
|
|
59
76
|
development?: boolean;
|
|
60
77
|
error?: (error: Error) => Response | Promise<Response>;
|
|
@@ -63,9 +80,11 @@ export interface BunServeOptions {
|
|
|
63
80
|
idleTimeout?: number;
|
|
64
81
|
maxRequestBodySize?: number;
|
|
65
82
|
port?: number;
|
|
83
|
+
routes?: Record<string, BunRouteValue>;
|
|
66
84
|
tls?: BunTlsOptions;
|
|
67
85
|
websocket?: BunWebSocketHandler;
|
|
68
86
|
}
|
|
87
|
+
/** Minimal Bun server handle used by fluo for fetch dispatch, upgrades, and shutdown. */
|
|
69
88
|
export interface BunServerLike {
|
|
70
89
|
fetch?(request: Request): Response | Promise<Response> | undefined | Promise<Response | undefined>;
|
|
71
90
|
hostname?: BunHostname;
|
|
@@ -77,45 +96,81 @@ export interface BunServerLike {
|
|
|
77
96
|
}): boolean;
|
|
78
97
|
url?: URL;
|
|
79
98
|
}
|
|
99
|
+
/** Options for `createBunAdapter()`. */
|
|
80
100
|
export interface BunAdapterOptions {
|
|
101
|
+
/** Enables Bun development-mode behavior when supported by the host runtime. */
|
|
81
102
|
development?: boolean;
|
|
103
|
+
/** Hostname passed through to `Bun.serve()`. */
|
|
82
104
|
hostname?: BunHostname;
|
|
105
|
+
/** Idle timeout passed through to `Bun.serve()`. */
|
|
83
106
|
idleTimeout?: number;
|
|
107
|
+
/** Maximum request body size forwarded as Bun's `maxRequestBodySize`. */
|
|
84
108
|
maxBodySize?: number;
|
|
109
|
+
/** Multipart parsing limits used by the shared web request dispatcher. */
|
|
85
110
|
multipart?: MultipartOptions;
|
|
111
|
+
/** Port passed through to `Bun.serve()`, defaulting to 3000. */
|
|
86
112
|
port?: number;
|
|
113
|
+
/** Preserves raw bodies for non-multipart requests when enabled. */
|
|
87
114
|
rawBody?: boolean;
|
|
115
|
+
/** Whether shutdown asks Bun to stop active connections immediately. */
|
|
88
116
|
stopActiveConnections?: boolean;
|
|
117
|
+
/** TLS options forwarded to `Bun.serve()` for HTTPS startup. */
|
|
89
118
|
tls?: BunTlsOptions;
|
|
90
119
|
}
|
|
120
|
+
/** Options for creating a standalone Bun `fetch(request)` handler. */
|
|
91
121
|
export interface CreateBunFetchHandlerOptions {
|
|
122
|
+
/** Dispatcher that receives translated fluo framework requests. */
|
|
92
123
|
dispatcher: Dispatcher;
|
|
124
|
+
/** Error message used when a request arrives before dispatcher binding is ready. */
|
|
93
125
|
dispatcherNotReadyMessage?: string;
|
|
126
|
+
/** Maximum request body size enforced by the shared web dispatcher. */
|
|
94
127
|
maxBodySize?: number;
|
|
128
|
+
/** Multipart parsing limits used by the shared web dispatcher. */
|
|
95
129
|
multipart?: MultipartOptions;
|
|
130
|
+
/** Preserves raw bodies for JSON and text requests when enabled. */
|
|
96
131
|
rawBody?: boolean;
|
|
97
132
|
}
|
|
133
|
+
/** Bootstrap options for Bun applications that do not install shutdown signal wiring. */
|
|
98
134
|
export interface BootstrapBunApplicationOptions extends Omit<CreateApplicationOptions, 'adapter' | 'logger' | 'middleware'> {
|
|
135
|
+
/** CORS policy applied by the shared HTTP bootstrap path. */
|
|
99
136
|
cors?: BunCorsInput;
|
|
137
|
+
/** Enables Bun development-mode behavior when supported by the host runtime. */
|
|
100
138
|
development?: boolean;
|
|
139
|
+
/** Global route prefix applied by the shared HTTP bootstrap path. */
|
|
101
140
|
globalPrefix?: string;
|
|
141
|
+
/** Routes excluded from the global prefix. */
|
|
102
142
|
globalPrefixExclude?: readonly string[];
|
|
143
|
+
/** Hostname passed through to `Bun.serve()`. */
|
|
103
144
|
hostname?: BunHostname;
|
|
145
|
+
/** Idle timeout passed through to `Bun.serve()`. */
|
|
104
146
|
idleTimeout?: number;
|
|
147
|
+
/** Application logger used for startup, shutdown, and failure reporting. */
|
|
105
148
|
logger?: ApplicationLogger;
|
|
149
|
+
/** Maximum request body size forwarded as Bun's `maxRequestBodySize`. */
|
|
106
150
|
maxBodySize?: number;
|
|
151
|
+
/** Middleware applied by the shared HTTP bootstrap path. */
|
|
107
152
|
middleware?: MiddlewareLike[];
|
|
153
|
+
/** Multipart parsing limits used by the shared web request dispatcher. */
|
|
108
154
|
multipart?: MultipartOptions;
|
|
155
|
+
/** Port passed through to `Bun.serve()`, defaulting to 3000. */
|
|
109
156
|
port?: number;
|
|
157
|
+
/** Preserves raw bodies for non-multipart requests when enabled. */
|
|
110
158
|
rawBody?: boolean;
|
|
159
|
+
/** Security header policy applied by the shared HTTP bootstrap path. */
|
|
111
160
|
securityHeaders?: false | SecurityHeadersOptions;
|
|
161
|
+
/** Whether shutdown asks Bun to stop active connections immediately. */
|
|
112
162
|
stopActiveConnections?: boolean;
|
|
163
|
+
/** TLS options forwarded to `Bun.serve()` for HTTPS startup. */
|
|
113
164
|
tls?: BunTlsOptions;
|
|
114
165
|
}
|
|
166
|
+
/** Run options for Bun applications with optional shutdown signal wiring. */
|
|
115
167
|
export interface RunBunApplicationOptions extends BootstrapBunApplicationOptions {
|
|
168
|
+
/** Maximum signal-driven shutdown duration before fluo reports timeout via `process.exitCode`. */
|
|
116
169
|
forceExitTimeoutMs?: number;
|
|
170
|
+
/** Shutdown signals to register, or `false` to disable signal wiring. */
|
|
117
171
|
shutdownSignals?: false | readonly BunApplicationSignal[];
|
|
118
172
|
}
|
|
173
|
+
/** HTTP application adapter backed by native `Bun.serve()`. */
|
|
119
174
|
export declare class BunHttpApplicationAdapter implements HttpApplicationAdapter, BunWebSocketBindingHost {
|
|
120
175
|
private readonly options;
|
|
121
176
|
private closeInFlight?;
|
|
@@ -125,20 +180,53 @@ export declare class BunHttpApplicationAdapter implements HttpApplicationAdapter
|
|
|
125
180
|
private server?;
|
|
126
181
|
private realtimeBinding?;
|
|
127
182
|
constructor(options?: BunAdapterOptions);
|
|
183
|
+
/** Returns the active Bun server handle after `listen()` starts. */
|
|
128
184
|
getServer(): BunServerLike | undefined;
|
|
185
|
+
/** Returns the bind target and externally logged URL for the current Bun server. */
|
|
129
186
|
getListenTarget(): HttpAdapterListenTarget;
|
|
187
|
+
/** Reports Bun's fetch-style websocket capability for realtime package integration. */
|
|
130
188
|
getRealtimeCapability(): import("@fluojs/http").FetchStyleHttpAdapterRealtimeCapability;
|
|
189
|
+
/** Configures the official realtime binding before the Bun server starts. */
|
|
131
190
|
configureRealtimeBinding<TData>(binding: BunWebSocketBinding<TData> | undefined): void;
|
|
191
|
+
/** Configures a Bun websocket binding through the legacy websocket host name. */
|
|
132
192
|
configureWebSocketBinding<TData>(binding: BunWebSocketBinding<TData> | undefined): void;
|
|
193
|
+
/** Starts the Bun server and binds framework dispatch to native fetch requests. */
|
|
133
194
|
listen(dispatcher: Dispatcher): Promise<void>;
|
|
195
|
+
/** Stops ingress, waits for in-flight HTTP handlers, and releases adapter state. */
|
|
134
196
|
close(): Promise<void>;
|
|
135
197
|
private dispatchHttpRequest;
|
|
136
198
|
private trackInFlightRequest;
|
|
137
199
|
private waitForInFlightRequests;
|
|
138
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Creates a standalone Bun-compatible fetch handler.
|
|
203
|
+
*
|
|
204
|
+
* @param options - Dispatcher and request parsing options for translating native requests.
|
|
205
|
+
* @returns A `fetch(request)` handler suitable for custom `Bun.serve()` calls.
|
|
206
|
+
*/
|
|
139
207
|
export declare function createBunFetchHandler({ dispatcher, dispatcherNotReadyMessage, maxBodySize, multipart, rawBody, }: CreateBunFetchHandlerOptions): (request: Request) => Promise<Response>;
|
|
208
|
+
/**
|
|
209
|
+
* Creates the recommended Bun HTTP adapter instance.
|
|
210
|
+
*
|
|
211
|
+
* @param options - Bun server and request parsing options.
|
|
212
|
+
* @returns A fluo HTTP application adapter backed by `Bun.serve()`.
|
|
213
|
+
*/
|
|
140
214
|
export declare function createBunAdapter(options?: BunAdapterOptions): HttpApplicationAdapter;
|
|
215
|
+
/**
|
|
216
|
+
* Bootstraps a fluo application with the Bun adapter without starting signal wiring.
|
|
217
|
+
*
|
|
218
|
+
* @param rootModule - Root fluo module to compile.
|
|
219
|
+
* @param options - Bun adapter and application bootstrap options.
|
|
220
|
+
* @returns The bootstrapped application; call `listen()` to start serving.
|
|
221
|
+
*/
|
|
141
222
|
export declare function bootstrapBunApplication(rootModule: ModuleType, options: BootstrapBunApplicationOptions): Promise<Application>;
|
|
223
|
+
/**
|
|
224
|
+
* Bootstraps, starts, and wires shutdown handling for a Bun-hosted fluo application.
|
|
225
|
+
*
|
|
226
|
+
* @param rootModule - Root fluo module to compile.
|
|
227
|
+
* @param options - Bun adapter, application, and shutdown options.
|
|
228
|
+
* @returns The running application instance.
|
|
229
|
+
*/
|
|
142
230
|
export declare function runBunApplication(rootModule: ModuleType, options: RunBunApplicationOptions): Promise<Application>;
|
|
143
231
|
export {};
|
|
144
232
|
//# sourceMappingURL=adapter.d.ts.map
|
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EAEV,sBAAsB,EACtB,UAAU,EACV,cAAc,EACd,sBAAsB,EACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,wBAAwB,EACxB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,uCAAuC,CAAC;AAE/C,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,gBAAgB;QACxB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;QACvB,OAAO,CAAC,EAAE,UAAU,CAAC;KACtB;CACF;AAOD,KAAK,WAAW,GAAG,MAAM,CAAC;AAC1B,KAAK,cAAc,GAAG,OAAO,GAAG;IAC9B,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC3C,CAAC;AACF,KAAK,eAAe,GAAG,CACrB,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,aAAa,KAClB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;AAC9E,KAAK,cAAc,GAAG,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AACjD,KAAK,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,eAAe,GAAG,QAAQ,CAAC,CAAC,CAAC;AACrF,KAAK,aAAa,GAAG,eAAe,GAAG,QAAQ,GAAG,iBAAiB,CAAC;AAEpE,qEAAqE;AACrE,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExD,gEAAgE;AAChE,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,WAAW,CAAC;AAEnE,kFAAkF;AAClF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,kEAAkE;AAClE,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;AAEpE,sFAAsF;AACtF,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,OAAO;IACjD,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IACjC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAClE,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACrC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC3D,IAAI,CAAC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/D,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,8EAA8E;AAC9E,MAAM,WAAW,mBAAmB,CAAC,KAAK,GAAG,OAAO;IAClD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,KAAK,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,KAAK,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChG,IAAI,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,iBAAiB,CAAC,EACd,OAAO,GACP;QACE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;QAC/H,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;KAClI,CAAC;IACN,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB,CAAC,KAAK,GAAG,OAAO;IAClD,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IACzH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;CACvC;AAED,iFAAiF;AACjF,MAAM,WAAW,sBAAsB;IACrC,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;CACxF;AAED,6EAA6E;AAC7E,MAAM,WAAW,uBAAwB,SAAQ,sBAAsB;IACrE,yBAAyB,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;CACzF;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvD,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IACzH,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC;AAED,yFAAyF;AACzF,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IACnG,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,sBAAsB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7C,OAAO,CAAC,KAAK,GAAG,OAAO,EACrB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,KAAK,CAAC;QACb,OAAO,CAAC,EAAE,WAAW,CAAC;KACvB,GACA,OAAO,CAAC;IACX,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,wCAAwC;AACxC,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gEAAgE;IAChE,GAAG,CAAC,EAAE,aAAa,CAAC;CACrB;AAED,sEAAsE;AACtE,MAAM,WAAW,4BAA4B;IAC3C,mEAAmE;IACnE,UAAU,EAAE,UAAU,CAAC;IACvB,oFAAoF;IACpF,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,yFAAyF;AACzF,MAAM,WAAW,8BAA+B,SAAQ,IAAI,CAAC,wBAAwB,EAAE,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;IACzH,6DAA6D;IAC7D,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,gDAAgD;IAChD,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,eAAe,CAAC,EAAE,KAAK,GAAG,sBAAsB,CAAC;IACjD,wEAAwE;IACxE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gEAAgE;IAChE,GAAG,CAAC,EAAE,aAAa,CAAC;CACrB;AAED,6EAA6E;AAC7E,MAAM,WAAW,wBAAyB,SAAQ,8BAA8B;IAC9E,kGAAkG;IAClG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yEAAyE;IACzE,eAAe,CAAC,EAAE,KAAK,GAAG,SAAS,oBAAoB,EAAE,CAAC;CAC3D;AASD,+DAA+D;AAC/D,qBAAa,yBAA0B,YAAW,sBAAsB,EAAE,uBAAuB;IAQnF,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,aAAa,CAAC,CAAiB;IACvC,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,MAAM,CAAC,CAAgB;IAC/B,OAAO,CAAC,eAAe,CAAC,CAA+B;gBAE1B,OAAO,GAAE,iBAAsB;IAE5D,oEAAoE;IACpE,SAAS,IAAI,aAAa,GAAG,SAAS;IAItC,oFAAoF;IACpF,eAAe,IAAI,uBAAuB;IAa1C,uFAAuF;IACvF,qBAAqB;IAOrB,6EAA6E;IAC7E,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAAG,SAAS,GAAG,IAAI;IAQtF,iFAAiF;IACjF,yBAAyB,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAAG,SAAS,GAAG,IAAI;IAIvF,mFAAmF;IAC7E,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCnD,oFAAoF;IAC9E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAgCd,mBAAmB;IAqBjC,OAAO,CAAC,oBAAoB;YAqBd,uBAAuB;CAOtC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,yBAAgE,EAChE,WAAW,EACX,SAAS,EACT,OAAO,GACR,EAAE,4BAA4B,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAWxE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,sBAAsB,CAExF;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,WAAW,CAAC,CAgBtB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,WAAW,CAAC,CAmBtB"}
|
package/dist/adapter.js
CHANGED
|
@@ -2,10 +2,44 @@ import { createFetchStyleHttpAdapterRealtimeCapability } from '@fluojs/http';
|
|
|
2
2
|
import { createNodeShutdownSignalRegistration, defaultNodeShutdownSignals } from '@fluojs/runtime/node';
|
|
3
3
|
import { dispatchWebRequest } from '@fluojs/runtime/web';
|
|
4
4
|
import { bootstrapHttpAdapterApplication, runHttpAdapterApplication } from '@fluojs/runtime/internal/http-adapter';
|
|
5
|
+
|
|
6
|
+
/** Shutdown signal names that `runBunApplication()` can register. */
|
|
7
|
+
|
|
8
|
+
/** CORS input accepted by Bun application bootstrap helpers. */
|
|
9
|
+
|
|
10
|
+
/** TLS options forwarded to `Bun.serve()` without adapter-level normalization. */
|
|
11
|
+
|
|
12
|
+
/** Message payloads accepted by Bun server websocket bindings. */
|
|
13
|
+
|
|
14
|
+
/** Minimal Bun server websocket shape used by the official websocket binding seam. */
|
|
15
|
+
|
|
16
|
+
/** Callback contract forwarded to the `websocket` option of `Bun.serve()`. */
|
|
17
|
+
|
|
18
|
+
/** Fetch-style websocket binding consumed before normal HTTP dispatch. */
|
|
19
|
+
|
|
20
|
+
/** Host contract exposed by Bun adapters that can install a realtime binding. */
|
|
21
|
+
|
|
22
|
+
/** Backward-compatible host contract for Bun websocket-specific bindings. */
|
|
23
|
+
|
|
24
|
+
/** Subset of `Bun.serve()` options used by the adapter and its tests. */
|
|
25
|
+
|
|
26
|
+
/** Minimal Bun server handle used by fluo for fetch dispatch, upgrades, and shutdown. */
|
|
27
|
+
|
|
28
|
+
/** Options for `createBunAdapter()`. */
|
|
29
|
+
|
|
30
|
+
/** Options for creating a standalone Bun `fetch(request)` handler. */
|
|
31
|
+
|
|
32
|
+
/** Bootstrap options for Bun applications that do not install shutdown signal wiring. */
|
|
33
|
+
|
|
34
|
+
/** Run options for Bun applications with optional shutdown signal wiring. */
|
|
35
|
+
|
|
5
36
|
const DEFAULT_PORT = 3000;
|
|
6
37
|
const DEFAULT_DISPATCHER_NOT_READY_MESSAGE = 'Bun adapter received a request before dispatcher binding completed.';
|
|
7
38
|
const DEFAULT_SHUTDOWN_TIMEOUT_MS = 10_000;
|
|
39
|
+
const MINIMUM_BUN_NATIVE_ROUTES_VERSION = '1.2.3';
|
|
8
40
|
const BUN_WEBSOCKET_SUPPORT_REASON = 'Bun exposes Bun.serve() + server.upgrade() request-upgrade hosting. Use @fluojs/websockets/bun for the official raw websocket binding.';
|
|
41
|
+
|
|
42
|
+
/** HTTP application adapter backed by native `Bun.serve()`. */
|
|
9
43
|
export class BunHttpApplicationAdapter {
|
|
10
44
|
closeInFlight;
|
|
11
45
|
dispatcher;
|
|
@@ -16,9 +50,13 @@ export class BunHttpApplicationAdapter {
|
|
|
16
50
|
constructor(options = {}) {
|
|
17
51
|
this.options = options;
|
|
18
52
|
}
|
|
53
|
+
|
|
54
|
+
/** Returns the active Bun server handle after `listen()` starts. */
|
|
19
55
|
getServer() {
|
|
20
56
|
return this.server;
|
|
21
57
|
}
|
|
58
|
+
|
|
59
|
+
/** Returns the bind target and externally logged URL for the current Bun server. */
|
|
22
60
|
getListenTarget() {
|
|
23
61
|
const protocol = this.options.tls ? 'https' : 'http';
|
|
24
62
|
const configuredHostname = this.options.hostname ?? 'localhost';
|
|
@@ -30,20 +68,28 @@ export class BunHttpApplicationAdapter {
|
|
|
30
68
|
url
|
|
31
69
|
};
|
|
32
70
|
}
|
|
71
|
+
|
|
72
|
+
/** Reports Bun's fetch-style websocket capability for realtime package integration. */
|
|
33
73
|
getRealtimeCapability() {
|
|
34
74
|
return createFetchStyleHttpAdapterRealtimeCapability(BUN_WEBSOCKET_SUPPORT_REASON, {
|
|
35
75
|
support: 'supported'
|
|
36
76
|
});
|
|
37
77
|
}
|
|
78
|
+
|
|
79
|
+
/** Configures the official realtime binding before the Bun server starts. */
|
|
38
80
|
configureRealtimeBinding(binding) {
|
|
39
81
|
if (this.server && binding !== undefined) {
|
|
40
82
|
throw new Error('Bun websocket binding must be configured before Bun adapter listen() starts the server.');
|
|
41
83
|
}
|
|
42
84
|
this.realtimeBinding = binding;
|
|
43
85
|
}
|
|
86
|
+
|
|
87
|
+
/** Configures a Bun websocket binding through the legacy websocket host name. */
|
|
44
88
|
configureWebSocketBinding(binding) {
|
|
45
89
|
this.configureRealtimeBinding(binding);
|
|
46
90
|
}
|
|
91
|
+
|
|
92
|
+
/** Starts the Bun server and binds framework dispatch to native fetch requests. */
|
|
47
93
|
async listen(dispatcher) {
|
|
48
94
|
this.dispatcher = dispatcher;
|
|
49
95
|
if (this.server) {
|
|
@@ -51,28 +97,32 @@ export class BunHttpApplicationAdapter {
|
|
|
51
97
|
}
|
|
52
98
|
const bun = requireBunGlobal();
|
|
53
99
|
const realtimeBinding = this.realtimeBinding;
|
|
100
|
+
const handleRequest = async (request, server) => {
|
|
101
|
+
if (this.server === undefined) {
|
|
102
|
+
this.server = server;
|
|
103
|
+
}
|
|
104
|
+
if (realtimeBinding) {
|
|
105
|
+
const handled = await realtimeBinding.fetch(request, server);
|
|
106
|
+
if (handled !== undefined || isWebSocketUpgradeRequest(request)) {
|
|
107
|
+
return handled;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return await this.dispatchHttpRequest(request);
|
|
111
|
+
};
|
|
54
112
|
this.server = bun.serve({
|
|
55
113
|
development: this.options.development,
|
|
56
|
-
fetch:
|
|
57
|
-
if (this.server === undefined) {
|
|
58
|
-
this.server = server;
|
|
59
|
-
}
|
|
60
|
-
if (realtimeBinding) {
|
|
61
|
-
const handled = await realtimeBinding.fetch(request, server);
|
|
62
|
-
if (handled !== undefined || isWebSocketUpgradeRequest(request)) {
|
|
63
|
-
return handled;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return await this.dispatchHttpRequest(request);
|
|
67
|
-
},
|
|
114
|
+
fetch: handleRequest,
|
|
68
115
|
hostname: this.options.hostname,
|
|
69
116
|
idleTimeout: realtimeBinding?.idleTimeout ?? this.options.idleTimeout,
|
|
70
117
|
maxRequestBodySize: realtimeBinding?.maxRequestBodySize ?? this.options.maxBodySize,
|
|
71
118
|
port: resolvePort(this.options.port),
|
|
119
|
+
routes: createBunNativeRoutes(dispatcher, handleRequest, bun),
|
|
72
120
|
tls: this.options.tls,
|
|
73
121
|
websocket: realtimeBinding?.websocket
|
|
74
122
|
});
|
|
75
123
|
}
|
|
124
|
+
|
|
125
|
+
/** Stops ingress, waits for in-flight HTTP handlers, and releases adapter state. */
|
|
76
126
|
async close() {
|
|
77
127
|
if (this.closeInFlight) {
|
|
78
128
|
await waitForCloseWithTimeout(this.closeInFlight, DEFAULT_SHUTDOWN_TIMEOUT_MS);
|
|
@@ -136,6 +186,13 @@ export class BunHttpApplicationAdapter {
|
|
|
136
186
|
await this.inFlightDrain?.promise;
|
|
137
187
|
}
|
|
138
188
|
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Creates a standalone Bun-compatible fetch handler.
|
|
192
|
+
*
|
|
193
|
+
* @param options - Dispatcher and request parsing options for translating native requests.
|
|
194
|
+
* @returns A `fetch(request)` handler suitable for custom `Bun.serve()` calls.
|
|
195
|
+
*/
|
|
139
196
|
export function createBunFetchHandler({
|
|
140
197
|
dispatcher,
|
|
141
198
|
dispatcherNotReadyMessage = DEFAULT_DISPATCHER_NOT_READY_MESSAGE,
|
|
@@ -154,9 +211,24 @@ export function createBunFetchHandler({
|
|
|
154
211
|
});
|
|
155
212
|
};
|
|
156
213
|
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Creates the recommended Bun HTTP adapter instance.
|
|
217
|
+
*
|
|
218
|
+
* @param options - Bun server and request parsing options.
|
|
219
|
+
* @returns A fluo HTTP application adapter backed by `Bun.serve()`.
|
|
220
|
+
*/
|
|
157
221
|
export function createBunAdapter(options = {}) {
|
|
158
222
|
return new BunHttpApplicationAdapter(options);
|
|
159
223
|
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Bootstraps a fluo application with the Bun adapter without starting signal wiring.
|
|
227
|
+
*
|
|
228
|
+
* @param rootModule - Root fluo module to compile.
|
|
229
|
+
* @param options - Bun adapter and application bootstrap options.
|
|
230
|
+
* @returns The bootstrapped application; call `listen()` to start serving.
|
|
231
|
+
*/
|
|
160
232
|
export async function bootstrapBunApplication(rootModule, options) {
|
|
161
233
|
return bootstrapHttpAdapterApplication(rootModule, options, createBunAdapter({
|
|
162
234
|
development: options.development,
|
|
@@ -170,6 +242,14 @@ export async function bootstrapBunApplication(rootModule, options) {
|
|
|
170
242
|
tls: options.tls
|
|
171
243
|
}));
|
|
172
244
|
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Bootstraps, starts, and wires shutdown handling for a Bun-hosted fluo application.
|
|
248
|
+
*
|
|
249
|
+
* @param rootModule - Root fluo module to compile.
|
|
250
|
+
* @param options - Bun adapter, application, and shutdown options.
|
|
251
|
+
* @returns The running application instance.
|
|
252
|
+
*/
|
|
173
253
|
export async function runBunApplication(rootModule, options) {
|
|
174
254
|
const adapter = createBunAdapter({
|
|
175
255
|
development: options.development,
|
|
@@ -197,6 +277,87 @@ function requireBunGlobal() {
|
|
|
197
277
|
function resolvePort(port) {
|
|
198
278
|
return typeof port === 'number' && Number.isFinite(port) ? port : DEFAULT_PORT;
|
|
199
279
|
}
|
|
280
|
+
function createBunNativeRoutes(dispatcher, handleRequest, bun) {
|
|
281
|
+
if (!supportsBunNativeRoutes(bun)) {
|
|
282
|
+
return undefined;
|
|
283
|
+
}
|
|
284
|
+
const descriptors = dispatcher.describeRoutes?.();
|
|
285
|
+
if (!descriptors || descriptors.length === 0) {
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
const unsafeShapes = collectUnsafeNativeRouteShapes(descriptors);
|
|
289
|
+
const routes = new Map();
|
|
290
|
+
for (const descriptor of descriptors) {
|
|
291
|
+
const method = toBunRouteMethod(descriptor.route.method);
|
|
292
|
+
if (!method) {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (unsafeShapes.has(`${method}:${createBunRouteShapeKey(descriptor.route.path)}`)) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const routeHandlers = routes.get(descriptor.route.path) ?? {};
|
|
299
|
+
for (const bunRouteMethod of bunRouteMethods) {
|
|
300
|
+
routeHandlers[bunRouteMethod] ??= handleRequest;
|
|
301
|
+
}
|
|
302
|
+
routes.set(descriptor.route.path, routeHandlers);
|
|
303
|
+
}
|
|
304
|
+
return routes.size > 0 ? Object.fromEntries(routes) : undefined;
|
|
305
|
+
}
|
|
306
|
+
function supportsBunNativeRoutes(bun) {
|
|
307
|
+
return compareBunVersions(bun.version, MINIMUM_BUN_NATIVE_ROUTES_VERSION) >= 0;
|
|
308
|
+
}
|
|
309
|
+
function compareBunVersions(left, right) {
|
|
310
|
+
if (typeof left !== 'string') {
|
|
311
|
+
return -1;
|
|
312
|
+
}
|
|
313
|
+
const leftSegments = parseBunVersionSegments(left);
|
|
314
|
+
const rightSegments = parseBunVersionSegments(right);
|
|
315
|
+
const length = Math.max(leftSegments.length, rightSegments.length);
|
|
316
|
+
for (let index = 0; index < length; index += 1) {
|
|
317
|
+
const leftValue = leftSegments[index] ?? 0;
|
|
318
|
+
const rightValue = rightSegments[index] ?? 0;
|
|
319
|
+
if (leftValue === rightValue) {
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
return leftValue > rightValue ? 1 : -1;
|
|
323
|
+
}
|
|
324
|
+
return 0;
|
|
325
|
+
}
|
|
326
|
+
function parseBunVersionSegments(version) {
|
|
327
|
+
return version.match(/\d+/g)?.map(segment => Number.parseInt(segment, 10)) ?? [];
|
|
328
|
+
}
|
|
329
|
+
function collectUnsafeNativeRouteShapes(descriptors) {
|
|
330
|
+
const signatures = new Map();
|
|
331
|
+
const unsafe = new Set();
|
|
332
|
+
for (const descriptor of descriptors) {
|
|
333
|
+
const shapeKey = createBunRouteShapeKey(descriptor.route.path);
|
|
334
|
+
const paramSignature = descriptor.metadata.pathParams.join(',');
|
|
335
|
+
if (descriptor.route.method === 'ALL') {
|
|
336
|
+
for (const method of bunRouteMethods) {
|
|
337
|
+
unsafe.add(`${method}:${shapeKey}`);
|
|
338
|
+
}
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
const key = `${descriptor.route.method}:${shapeKey}`;
|
|
342
|
+
const current = signatures.get(key) ?? new Set();
|
|
343
|
+
current.add(paramSignature);
|
|
344
|
+
signatures.set(key, current);
|
|
345
|
+
if (current.size > 1) {
|
|
346
|
+
unsafe.add(key);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return unsafe;
|
|
350
|
+
}
|
|
351
|
+
function createBunRouteShapeKey(path) {
|
|
352
|
+
const segments = path.split('/').filter(Boolean);
|
|
353
|
+
if (segments.length === 0) {
|
|
354
|
+
return '/';
|
|
355
|
+
}
|
|
356
|
+
return `/${segments.map(segment => segment.startsWith(':') ? ':' : segment).join('/')}`;
|
|
357
|
+
}
|
|
358
|
+
function toBunRouteMethod(method) {
|
|
359
|
+
return method === 'ALL' ? undefined : method;
|
|
360
|
+
}
|
|
200
361
|
function closeBunServerWithDrain(server, stopActiveConnections, waitForDrain) {
|
|
201
362
|
return (async () => {
|
|
202
363
|
server.stop(stopActiveConnections);
|
|
@@ -246,4 +407,5 @@ function waitForCloseWithTimeout(closePromise, timeoutMs) {
|
|
|
246
407
|
}
|
|
247
408
|
function isWebSocketUpgradeRequest(request) {
|
|
248
409
|
return request.headers.get('upgrade')?.toLowerCase() === 'websocket';
|
|
249
|
-
}
|
|
410
|
+
}
|
|
411
|
+
const bunRouteMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"platform",
|
|
9
9
|
"server"
|
|
10
10
|
],
|
|
11
|
-
"version": "1.0.0-beta.
|
|
11
|
+
"version": "1.0.0-beta.3",
|
|
12
12
|
"private": false,
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"repository": {
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"dist"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@fluojs/http": "^1.0.0-beta.
|
|
36
|
-
"@fluojs/runtime": "^1.0.0-beta.
|
|
35
|
+
"@fluojs/http": "^1.0.0-beta.3",
|
|
36
|
+
"@fluojs/runtime": "^1.0.0-beta.4"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"vitest": "^3.2.4"
|