npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nextrush/adapter-bun

v1.0.0

Published

Bun HTTP adapter for NextRush

Readme

@nextrush/adapter-bun

Bun HTTP adapter for NextRush -- connects an Application to Bun.serve() with graceful shutdown and NextRush's shared Web-standard Context.

npm version downloads bundle size types ESM only license

| | | | --- | --- | | Purpose | Run a NextRush Application on Bun via Bun.serve() | | Package type | Adapter | | Status | Stable | | Included in nextrush? | No -- standalone install, chosen per deployment target | | Support tier | Public -- stable (sealed public API) -- see ADR-0005 | | Maintenance | Active | | Runtime | Bun only (this adapter) -- part of the universal Node / Bun / Deno / Edge family | | Requires | Bun >=1.0.0 -- ESM-only -- TypeScript >=5.x | | Introduced | v1.0.0 |

Highlights

  • Zero extra runtime dependencies beyond NextRush's own core/errors/runtime/stream/types packages
  • ESM-only, tree-shakable, side-effect-free
  • Fully typed -- strict TypeScript, zero any
  • Server-level request body cap set to 1 MB by default -- overrides Bun's native 128 MB default, matching @nextrush/body-parser's own JSON default

Installation

bun add @nextrush/adapter-bun @nextrush/core
# npm i @nextrush/adapter-bun @nextrush/core (if managing the project with npm/pnpm, still run with bun)

[!NOTE] This adapter is not included in the nextrush meta package. Install it directly when your deployment target is Bun; pick a different @nextrush/adapter-* package for another runtime.

Quick start

import { createApp } from '@nextrush/core';
import { serve } from '@nextrush/adapter-bun';

const app = createApp();

app.use(async (ctx) => {
  ctx.json({ message: 'Hello from Bun!' });
});

await serve(app, {
  port: 8080,
  onListen: ({ port }) => console.log(`Server running on port ${port}`),
});

serve() boots the app's extensions (app.ready()), starts Bun.serve(), and returns a ServerInstance with close()/reload()/address().

Capabilities

Capabilities

  • serve(app, options) -- starts a Bun HTTP server bound to the app
  • createHandler(app, options) -- a bare (request, server) => Promise<Response> fetch handler for a hand-rolled Bun.serve() call
  • listen(app, port) -- serve() shorthand with a console-logged startup message
  • Graceful shutdown -- opt-in SIGTERM/SIGINT wiring to the same connection-drain close()
  • TLS -- cert/key/ca passed straight through to Bun.serve()

Performance

  • Bun's own request/response path avoids Node's http module overhead; the adapter adds a thin context-creation and timeout-race layer on top, not a second HTTP implementation

Developer experience

  • Same serve(app, options) / listen(app, port) shape as @nextrush/adapter-node, @nextrush/adapter-deno, and @nextrush/adapter-edge -- only the import changes

Mental model

Bun.serve() ---> trackedHandler ---> BunContext ---> your middleware/routes
                      |
                      +-- in-flight request count (for graceful drain)

Rule: the adapter never re-implements HTTP -- it wraps one fetch(request, server) handler around Bun.serve() and hands your app a BunContext built on the shared Web-standard base used by every non-Node adapter.

[!TIP] The full request lifecycle and shutdown sequence (Mermaid) are in ARCHITECTURE.md.

Common tasks

Start a server

import { serve } from '@nextrush/adapter-bun';

const server = await serve(app, { port: 8080 });
console.log(`Listening on ${server.host}:${server.port}`);

Wire graceful shutdown to OS signals

const server = await serve(app, {
  port: 8080,
  gracefulShutdown: true, // installs SIGTERM + SIGINT handlers
});

// Or override the signal set / drain timeout:
const server2 = await serve(app, {
  port: 8080,
  gracefulShutdown: { signals: ['SIGTERM'], timeout: 5_000 },
});

Omitting gracefulShutdown installs no signal handler -- process behavior is unchanged. close() (called manually or via a signal) always stops accepting new connections, drains in-flight requests up to shutdownTimeout, then tears down the app's extensions.

Use a custom Bun.serve() setup

import { createHandler } from '@nextrush/adapter-bun';

const handler = createHandler(app, { timeout: 10_000 });

Bun.serve({
  port: 8080,
  fetch: handler,
});

Enable TLS

await serve(app, {
  port: 443,
  tls: {
    cert: Bun.file('./cert.pem'),
    key: Bun.file('./key.pem'),
  },
});

Note: Bun's Bun.serve() TLS provides HTTPS (HTTP/1.1 over TLS). HTTP/2 (h2) over TLS on Bun requires the node:http2 API per Bun's documentation — it is not negotiated via ALPN through the native tls option. The framework's RuntimeCapabilities.http2 reports false for Bun until empirical verification confirms otherwise (see RFC-028 §Risks).

API overview

| Export | Signature | Since | Stability | Description | | ------ | --------- | ----- | --------- | ----------- | | serve | (app: Application, options?: ServeOptions) => Promise<ServerInstance> | 1.0.0 | Stable | Starts Bun.serve() bound to the app | | createHandler | (app: Application, options?: HandlerOptions) => BunFetchHandler | 1.0.0 | Stable | Bare fetch handler for a custom Bun.serve() call | | listen | (app: Application, port?: number) => Promise<ServerInstance> | 1.0.0 | Stable | serve() shorthand with a startup log line | | BunContext | class | 1.0.0 | Stable | Bun-specific Context implementation | | createBunContext | (request: Request, clientIp?: string, trustProxy?: boolean) => BunContext | 1.0.0 | Stable | Constructs a BunContext | | EmptyBodySource / createEmptyBodySource | -- | 1.0.0 | Stable | Body source for bodyless requests, re-exported from @nextrush/runtime | | BodyConsumedError / BodyTooLargeError | -- | 1.0.0 | Stable | Shared body-reading errors, re-exported from @nextrush/runtime | | getContentType / getContentLength | (headers: Headers) => string \| undefined / (headers: Headers) => number \| undefined | 1.0.0 | Deprecated | Unused internally since body-parser owns content-type/length handling; kept for backward compatibility | | type ServeOptions | -- | 1.0.0 | Stable | serve() options | | type ServerInstance | -- | 1.0.0 | Stable | Return value of serve()/listen() | | type GracefulShutdownOptions | -- | 1.0.0 | Stable | Shape of ServeOptions.gracefulShutdown when not a plain boolean |

Options

ServeOptions (passed to serve()):

| Option | Type | Required | Default | Security-sensitive | Description | | ------ | ---- | -------- | ------- | ------------------ | ----------- | | port | number | No | 8080 | -- | Port to listen on | | host | string | No | '0.0.0.0' | Warning | Host to bind to -- canonical option; use with care in shared/multi-tenant environments | | onListen | (info: { port; host; hostname }) => void | No | -- | -- | Called once the server is listening | | onError | (error: Error) => void | No | logs via app.logger | -- | Called on an uncaught request error | | tls | { cert; key; ca? } | No | -- | Warning | Enables HTTPS | | maxRequestBodySize | number | No | 1048576 (1 MB) | Warning | Server-level request body cap in bytes -- overrides Bun's native 128 MB default; matches @nextrush/adapter-node's effective 1 MB default | | timeout | number | No | 30000 (30 s) | -- | Per-request timeout; returns 504 on expiry | | development | boolean | No | false | -- | Enables Bun's development-mode features | | shutdownTimeout | number | No | 30000 (30 s) | -- | Drain grace period before force-closing connections | | logger | Logger | No | app.logger | -- | Logger for adapter diagnostics | | gracefulShutdown | boolean \| GracefulShutdownOptions | No | undefined (no signal handler) | -- | Wires SIGTERM/SIGINT to close() |

Performance

Bun's own HTTP implementation avoids the syscall overhead of Node's http module; this adapter adds one context-creation call and a Promise.race-based timeout per request on top. See apps/benchmark for cross-runtime comparisons run on your own hardware.

Compatibility

Requirements

| Requirement | Version | | ----------- | ------- | | NextRush | 3.x | | Bun | >=1.0.0 | | TypeScript | >=5.x |

Runtimes

| Runtime | Supported | Notes | | ------- | --------- | ----- | | Bun >=1.0.0 | Yes | This package | | Node.js / Deno / Edge | Yes | Via @nextrush/adapter-node / @nextrush/adapter-deno / @nextrush/adapter-edge -- pinned by the internal conformance suite |

Integration

  • Peer dependencies: none (depends directly on @nextrush/core, @nextrush/errors, @nextrush/runtime, @nextrush/stream, @nextrush/types)
  • Works with: @nextrush/body-parser for body parsing beyond the raw bodySource/WebBodySource access BunContext exposes
  • Incompatible with: other @nextrush/adapter-* packages in the same process (only one adapter binds a server per app)

[!IMPORTANT] NextRush is ESM-only, permanently -- no CommonJS build. See the Module Format Policy.

Troubleshooting

Cause: maxRequestBodySize defaults to 1 MB, well below Bun's own 128 MB default -- this is deliberate, matching @nextrush/body-parser's JSON default so both layers agree on the limit. Fix: raise maxRequestBodySize for the routes that need larger payloads.

await serve(app, { maxRequestBodySize: 50 * 1024 * 1024 }); // 50 MB

Cause: another process already holds port/host, or the host/port combination is invalid. Fix: serve() normalizes the underlying Bun.serve() error into the same typed startup error every NextRush adapter throws -- catch it and inspect error.code.

FAQ

Can I use this without nextrush? Yes -- install @nextrush/adapter-bun alongside @nextrush/core directly; the meta package is not required.

Why ESM-only? See the Module Format Policy.

Does it work on Bun's hot reload? Yes -- bun --hot run server.ts reloads the module graph as usual; server.reload(options) also updates non-structural Bun.serve() options (like development) on an existing server.

Is ctx.bodySource the same shape as the Node adapter's? BunContext is built on the shared WebContextBase/WebBodySource from @nextrush/runtime, the same base every non-Node adapter (Bun, Deno, Edge) uses -- body-reading behavior is identical across those three by construction, not by convention.

Package relationships

                 depends on            @nextrush/core, @nextrush/errors,
@nextrush/adapter-bun ----------->     @nextrush/runtime, @nextrush/stream,
                                        @nextrush/types
                 often used with       @nextrush/body-parser
                 usually used next     @nextrush/router

Architecture

Maintaining or contributing to this package? The internal design -- module layout, request lifecycle, shutdown sequence, invariants, and trade-offs (with diagrams) -- is in ARCHITECTURE.md.

Resources


MIT (c) Tanzim Hossain