@fluojs/platform-bun 1.0.0-beta.3 → 1.0.0-beta.5
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 +5 -3
- package/README.md +5 -3
- package/dist/adapter.d.ts +2 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +61 -8
- package/package.json +3 -3
package/README.ko.md
CHANGED
|
@@ -74,7 +74,9 @@ export class MyGateway {}
|
|
|
74
74
|
### 네이티브 `routes` Object 가속
|
|
75
75
|
Bun `>=1.2.3`에서는 어댑터가 의미 보존이 가능한 static/param fluo route를 `Bun.serve({ routes })`에 선택적으로 등록한 뒤, 매칭된 요청도 다시 shared fluo dispatcher로 흘려보냅니다.
|
|
76
76
|
|
|
77
|
-
이
|
|
77
|
+
의미 보존이 가능한 unversioned route에서는 Bun이 미리 고른 descriptor와 params를 공유 dispatcher에 전달하므로 duplicate route matching을 건너뛰면서도 raw body, multipart, SSE, error response, shutdown drain, websocket upgrade delegation을 모두 기존 shared 실행 경로에 유지합니다. same-shape param route처럼 의미가 어긋날 수 있는 경우, `ALL` 메서드 handler, normalization-sensitive path, non-URI versioning처럼 안전하게 선등록할 수 없는 경우에는 의미를 바꾸지 않도록 해당 route를 fetch-only dispatch로 폴백합니다.
|
|
78
|
+
|
|
79
|
+
Native handoff가 붙은 뒤 app middleware가 framework request의 method 또는 path를 rewrite하면 dispatcher는 stale handoff를 버리고 rewrite된 요청을 다시 매칭합니다. `OPTIONS` 같은 미지원 메서드와 CORS preflight 동작은 fluo route가 명시적으로 소유하지 않는 한 공유 dispatcher/middleware 경로가 계속 소유합니다.
|
|
78
80
|
|
|
79
81
|
## 공개 API 개요
|
|
80
82
|
|
|
@@ -94,7 +96,7 @@ Bun `>=1.2.3`에서는 어댑터가 의미 보존이 가능한 static/param fluo
|
|
|
94
96
|
|
|
95
97
|
- **런타임 host**: 이 패키지는 listen 시점에 `globalThis.Bun.serve()`가 필요합니다. 테스트에서는 Bun 호환 test double을 제공할 수 있지만, production 사용은 Bun 전용입니다.
|
|
96
98
|
- **요청 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` 경로로
|
|
99
|
+
- **네이티브 route 가속**: Bun의 `routes` object를 사용할 수 있고 fluo route shape를 의미 보존 상태로 선등록할 수 있을 때만 Bun이 path matching을 먼저 처리하고, 이후 요청은 다시 shared dispatcher로 넘깁니다. 지원하지 않거나 모호한 route shape는 일반 `fetch` 경로로 폴백하며, middleware가 handler matching 전에 method/path를 rewrite하면 stale handoff는 무시됩니다.
|
|
98
100
|
- **Multipart 동작**: Multipart 요청은 `rawBody`를 노출하지 않으며 multipart limit은 shared runtime parser를 통해 계속 적용됩니다.
|
|
99
101
|
- **시작 target**: `hostname`, `port`, `tls`는 `Bun.serve()`로 전달됩니다. 시작 로그는 설정된 HTTP 또는 HTTPS listen URL을 보고합니다.
|
|
100
102
|
- **종료 소유권**: `close()`는 새 유입을 중단하고, in-flight HTTP handler를 기다린 뒤, drain이 끝나면 adapter state를 정리하며 `runBunApplication()`이 등록한 signal listener를 제거합니다.
|
|
@@ -102,7 +104,7 @@ Bun `>=1.2.3`에서는 어댑터가 의미 보존이 가능한 static/param fluo
|
|
|
102
104
|
|
|
103
105
|
## Conformance 커버리지
|
|
104
106
|
|
|
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을 검증하는 집중 테스트를 포함합니다.
|
|
107
|
+
`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-path multi-method handoff, versioning fallback, normalization-sensitive fallback, OPTIONS/CORS ownership, same-shape route fallback을 검증하는 Bun fetch-style portability assertion과 startup logging, shutdown listener cleanup, in-flight drain, timeout reporting, websocket binding delegation을 검증하는 집중 테스트를 포함합니다.
|
|
106
108
|
|
|
107
109
|
저장소의 더 넓은 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
110
|
|
package/README.md
CHANGED
|
@@ -74,7 +74,9 @@ export class MyGateway {}
|
|
|
74
74
|
### Native `routes` Object Acceleration
|
|
75
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
76
|
|
|
77
|
-
|
|
77
|
+
For semantically safe unversioned routes, Bun hands the pre-matched descriptor and params to the shared dispatcher so duplicate route matching is skipped while raw body, multipart, SSE, error responses, shutdown drain behavior, and websocket upgrade delegation stay on the same shared execution path. If route shape parity is unsafe, such as same-shape parameter routes with different param names, `ALL`-method handlers, normalization-sensitive paths, or non-URI versioning, the adapter falls back to fetch-only dispatch for those routes instead of changing fluo semantics.
|
|
78
|
+
|
|
79
|
+
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.
|
|
78
80
|
|
|
79
81
|
## Public API Overview
|
|
80
82
|
|
|
@@ -94,7 +96,7 @@ The adapter also exports the typed Bun integration seams used by realtime packag
|
|
|
94
96
|
|
|
95
97
|
- **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
98
|
- **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.
|
|
99
|
+
- **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.
|
|
98
100
|
- **Multipart behavior**: Multipart requests never expose `rawBody`, and multipart limits continue to flow through the shared runtime parser.
|
|
99
101
|
- **Startup target**: `hostname`, `port`, and `tls` are forwarded to `Bun.serve()`. Startup logs report the configured HTTP or HTTPS listen URL.
|
|
100
102
|
- **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()`.
|
|
@@ -102,7 +104,7 @@ The adapter also exports the typed Bun integration seams used by realtime packag
|
|
|
102
104
|
|
|
103
105
|
## Conformance Coverage
|
|
104
106
|
|
|
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.
|
|
107
|
+
`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, same-path multi-method handoff, versioning fallback, normalization-sensitive fallback, OPTIONS/CORS ownership, 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
108
|
|
|
107
109
|
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
110
|
|
package/dist/adapter.d.ts
CHANGED
|
@@ -172,13 +172,14 @@ export interface RunBunApplicationOptions extends BootstrapBunApplicationOptions
|
|
|
172
172
|
}
|
|
173
173
|
/** HTTP application adapter backed by native `Bun.serve()`. */
|
|
174
174
|
export declare class BunHttpApplicationAdapter implements HttpApplicationAdapter, BunWebSocketBindingHost {
|
|
175
|
-
private readonly options;
|
|
176
175
|
private closeInFlight?;
|
|
177
176
|
private dispatcher?;
|
|
178
177
|
private inFlightDrain?;
|
|
179
178
|
private inFlightRequestCount;
|
|
180
179
|
private server?;
|
|
181
180
|
private realtimeBinding?;
|
|
181
|
+
private readonly options;
|
|
182
|
+
private readonly webRequestResponseFactory;
|
|
182
183
|
constructor(options?: BunAdapterOptions);
|
|
183
184
|
/** Returns the active Bun server handle after `listen()` starts. */
|
|
184
185
|
getServer(): BunServerLike | undefined;
|
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,EAEV,sBAAsB,EACtB,UAAU,EACV,cAAc,EACd,sBAAsB,EACvB,MAAM,cAAc,CAAC;
|
|
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,7 @@
|
|
|
1
1
|
import { createFetchStyleHttpAdapterRealtimeCapability } from '@fluojs/http';
|
|
2
|
+
import { bindRawRequestNativeRouteHandoff, isRoutePathNormalizationSensitive } from '@fluojs/http/internal';
|
|
2
3
|
import { createNodeShutdownSignalRegistration, defaultNodeShutdownSignals } from '@fluojs/runtime/node';
|
|
3
|
-
import { dispatchWebRequest } from '@fluojs/runtime/web';
|
|
4
|
+
import { createWebRequestResponseFactory, dispatchWebRequest } from '@fluojs/runtime/web';
|
|
4
5
|
import { bootstrapHttpAdapterApplication, runHttpAdapterApplication } from '@fluojs/runtime/internal/http-adapter';
|
|
5
6
|
|
|
6
7
|
/** Shutdown signal names that `runBunApplication()` can register. */
|
|
@@ -47,8 +48,15 @@ export class BunHttpApplicationAdapter {
|
|
|
47
48
|
inFlightRequestCount = 0;
|
|
48
49
|
server;
|
|
49
50
|
realtimeBinding;
|
|
51
|
+
options;
|
|
52
|
+
webRequestResponseFactory;
|
|
50
53
|
constructor(options = {}) {
|
|
51
54
|
this.options = options;
|
|
55
|
+
this.webRequestResponseFactory = createWebRequestResponseFactory({
|
|
56
|
+
maxBodySize: options.maxBodySize,
|
|
57
|
+
multipart: options.multipart,
|
|
58
|
+
rawBody: options.rawBody
|
|
59
|
+
});
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
/** Returns the active Bun server handle after `listen()` starts. */
|
|
@@ -154,9 +162,7 @@ export class BunHttpApplicationAdapter {
|
|
|
154
162
|
return await dispatchWebRequest({
|
|
155
163
|
dispatcher: this.dispatcher,
|
|
156
164
|
dispatcherNotReadyMessage: DEFAULT_DISPATCHER_NOT_READY_MESSAGE,
|
|
157
|
-
|
|
158
|
-
multipart: this.options.multipart,
|
|
159
|
-
rawBody: this.options.rawBody,
|
|
165
|
+
factory: this.webRequestResponseFactory,
|
|
160
166
|
request
|
|
161
167
|
});
|
|
162
168
|
} finally {
|
|
@@ -200,13 +206,16 @@ export function createBunFetchHandler({
|
|
|
200
206
|
multipart,
|
|
201
207
|
rawBody
|
|
202
208
|
}) {
|
|
209
|
+
const factory = createWebRequestResponseFactory({
|
|
210
|
+
maxBodySize,
|
|
211
|
+
multipart,
|
|
212
|
+
rawBody
|
|
213
|
+
});
|
|
203
214
|
return async function bunFetchHandler(request) {
|
|
204
215
|
return await dispatchWebRequest({
|
|
205
216
|
dispatcher,
|
|
206
217
|
dispatcherNotReadyMessage,
|
|
207
|
-
|
|
208
|
-
multipart,
|
|
209
|
-
rawBody,
|
|
218
|
+
factory,
|
|
210
219
|
request
|
|
211
220
|
});
|
|
212
221
|
};
|
|
@@ -286,16 +295,18 @@ function createBunNativeRoutes(dispatcher, handleRequest, bun) {
|
|
|
286
295
|
return undefined;
|
|
287
296
|
}
|
|
288
297
|
const unsafeShapes = collectUnsafeNativeRouteShapes(descriptors);
|
|
298
|
+
const versionSensitiveRouteKeys = collectVersionSensitiveRouteKeys(descriptors);
|
|
289
299
|
const routes = new Map();
|
|
290
300
|
for (const descriptor of descriptors) {
|
|
291
301
|
const method = toBunRouteMethod(descriptor.route.method);
|
|
292
|
-
if (!method) {
|
|
302
|
+
if (!method || !isSafeBunNativeRouteDescriptor(descriptor, method) || versionSensitiveRouteKeys.has(`${method}:${descriptor.route.path}`)) {
|
|
293
303
|
continue;
|
|
294
304
|
}
|
|
295
305
|
if (unsafeShapes.has(`${method}:${createBunRouteShapeKey(descriptor.route.path)}`)) {
|
|
296
306
|
continue;
|
|
297
307
|
}
|
|
298
308
|
const routeHandlers = routes.get(descriptor.route.path) ?? {};
|
|
309
|
+
routeHandlers[method] = createBunNativeRouteHandoffHandler(descriptor, handleRequest);
|
|
299
310
|
for (const bunRouteMethod of bunRouteMethods) {
|
|
300
311
|
routeHandlers[bunRouteMethod] ??= handleRequest;
|
|
301
312
|
}
|
|
@@ -303,6 +314,22 @@ function createBunNativeRoutes(dispatcher, handleRequest, bun) {
|
|
|
303
314
|
}
|
|
304
315
|
return routes.size > 0 ? Object.fromEntries(routes) : undefined;
|
|
305
316
|
}
|
|
317
|
+
function isSafeBunNativeRouteDescriptor(descriptor, method) {
|
|
318
|
+
return method !== 'OPTIONS' && descriptor.route.version === undefined;
|
|
319
|
+
}
|
|
320
|
+
function createBunNativeRouteHandoffHandler(descriptor, handleRequest) {
|
|
321
|
+
return async (request, server) => {
|
|
322
|
+
const requestPath = new URL(request.url).pathname;
|
|
323
|
+
const params = normalizeNativeRouteParams(request.params);
|
|
324
|
+
if (!isRoutePathNormalizationSensitive(requestPath) && !hasNativeRouteParamSeparators(params)) {
|
|
325
|
+
bindRawRequestNativeRouteHandoff(request, {
|
|
326
|
+
descriptor,
|
|
327
|
+
params
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
return await handleRequest(request, server);
|
|
331
|
+
};
|
|
332
|
+
}
|
|
306
333
|
function supportsBunNativeRoutes(bun) {
|
|
307
334
|
return compareBunVersions(bun.version, MINIMUM_BUN_NATIVE_ROUTES_VERSION) >= 0;
|
|
308
335
|
}
|
|
@@ -355,6 +382,32 @@ function createBunRouteShapeKey(path) {
|
|
|
355
382
|
}
|
|
356
383
|
return `/${segments.map(segment => segment.startsWith(':') ? ':' : segment).join('/')}`;
|
|
357
384
|
}
|
|
385
|
+
function normalizeNativeRouteParams(params) {
|
|
386
|
+
return params ? {
|
|
387
|
+
...params
|
|
388
|
+
} : {};
|
|
389
|
+
}
|
|
390
|
+
function hasNativeRouteParamSeparators(params) {
|
|
391
|
+
return Object.values(params).some(value => value.includes('/'));
|
|
392
|
+
}
|
|
393
|
+
function collectVersionSensitiveRouteKeys(descriptors) {
|
|
394
|
+
const grouped = new Map();
|
|
395
|
+
for (const descriptor of descriptors) {
|
|
396
|
+
const method = toBunRouteMethod(descriptor.route.method);
|
|
397
|
+
if (!method) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
const routeKey = `${method}:${descriptor.route.path}`;
|
|
401
|
+
const current = grouped.get(routeKey) ?? {
|
|
402
|
+
count: 0,
|
|
403
|
+
hasVersioned: false
|
|
404
|
+
};
|
|
405
|
+
current.count += 1;
|
|
406
|
+
current.hasVersioned ||= descriptor.route.version !== undefined;
|
|
407
|
+
grouped.set(routeKey, current);
|
|
408
|
+
}
|
|
409
|
+
return new Set([...grouped.entries()].filter(([, current]) => current.count > 1 || current.hasVersioned).map(([routeKey]) => routeKey));
|
|
410
|
+
}
|
|
358
411
|
function toBunRouteMethod(method) {
|
|
359
412
|
return method === 'ALL' ? undefined : method;
|
|
360
413
|
}
|
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.5",
|
|
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.4",
|
|
36
|
+
"@fluojs/runtime": "^1.0.0-beta.6"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"vitest": "^3.2.4"
|