Skip to content

Commit

Permalink
fix(server): improve Bun support
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Sep 20, 2022
1 parent 8f8975e commit 60a73cc
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/calm-carrots-smoke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@whatwg-node/server': patch
---

Improve Bun support
16 changes: 16 additions & 0 deletions packages/server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,22 @@ import myServerAdapter from './myServerAdapter'
export { myServerAdapter as get, myServerAdapter as post }
```

### Bun

[Bun](https://bun.sh/) is a modern JavaScript runtime like Node or Deno, and it supports Fetch API as a first class citizen.
So the configuration is really simple like any other JS runtime;

```ts
import myServerAdapter from './myServerAdapter'

Bun.serve(myServerAdapter)

const server = Bun.serve(yoga)
console.info(
`Server is running on ${server.hostname}`,
)
```

## File Uploads / Multipart Requests

Multipart requests are a type of HTTP request that allows you to send blobs together with regular text data which has a mime-type `multipart/form-data`.
Expand Down
55 changes: 30 additions & 25 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@ function createServerAdapter<
): ServerAdapter<TServerContext, TBaseObject> {
const handleRequest =
typeof serverAdapterBaseObject === 'function' ? serverAdapterBaseObject : serverAdapterBaseObject.handle;
function fetchFn(input: RequestInfo | URL, init?: RequestInit, ...ctx: any[]) {
if (typeof input === 'string' || input instanceof URL) {
return handleRequest(new RequestCtor(input, init), Object.assign({}, ...ctx));
}
return handleRequest(input, Object.assign({}, init, ...ctx));
}

function handleNodeRequest(nodeRequest: NodeRequest, serverContext: TServerContext) {
const request = normalizeNodeRequest(nodeRequest, RequestCtor);
Expand Down Expand Up @@ -140,26 +134,11 @@ function createServerAdapter<
event.respondWith(response$);
}

function genericRequestHandler(input: any, ctx: any = {}, ...rest: any[]) {
function handleRequestWithWaitUntil(request: Request, ctx: any, ...rest: any[]) {
if ('process' in globalThis && process.versions?.['bun'] != null) {
// This is required for bun
input.text();
request.text();
}
// If it is a Node request
if (isReadable(input) && ctx != null && isServerResponse(ctx)) {
return requestListener(input as unknown as NodeRequest, ctx);
}
// Is input a container object over Request?
if (input.request) {
// Is it FetchEvent?
if (input.respondWith) {
return handleEvent(input);
}
// In this input is also the context
return handleRequest(input.request, input);
}
// Or is it Request itself?
// Then ctx is present and it is the context
if (rest?.length > 0) {
ctx = Object.assign({}, ctx, ...rest);
}
Expand All @@ -168,7 +147,7 @@ function createServerAdapter<
ctx.waitUntil = (p: Promise<unknown>) => {
waitUntilPromises.push(p);
};
const response$ = handleRequest(input, {
const response$ = handleRequest(request, {
...ctx,
waitUntil(p: Promise<unknown>) {
waitUntilPromises.push(p);
Expand All @@ -178,7 +157,33 @@ function createServerAdapter<
return handleWaitUntils(waitUntilPromises).then(() => response$);
}
}
return handleRequest(input, ctx);
return handleRequest(request, ctx);
}

function genericRequestHandler(input: any, ctx: any = {}, ...rest: any[]) {
// If it is a Node request
if (isReadable(input) && ctx != null && isServerResponse(ctx)) {
return requestListener(input as unknown as NodeRequest, ctx);
}
// Is input a container object over Request?
if (input.request) {
// Is it FetchEvent?
if (input.respondWith) {
return handleEvent(input);
}
// In this input is also the context
return handleRequestWithWaitUntil(input.request, input, ...rest);
}
// Or is it Request itself?
// Then ctx is present and it is the context
return handleRequestWithWaitUntil(input, ctx, ...rest);
}

function fetchFn(input: RequestInfo | URL, init?: RequestInit, ...ctx: any[]) {
if (typeof input === 'string' || input instanceof URL) {
return handleRequestWithWaitUntil(new RequestCtor(input, init), Object.assign({}, ...ctx));
}
return handleRequestWithWaitUntil(input, Object.assign({}, init, ...ctx));
}

const adapterObj: ServerAdapterObject<TServerContext, TBaseObject> = {
Expand Down

0 comments on commit 60a73cc

Please sign in to comment.