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

@mgvdev/nestjs-bun-adapter

v0.1.0

Published

Bun HTTP adapter for NestJS

Readme

@mgvdev/nestjs-bun-adapter

A lightweight NestJS HTTP adapter powered by Bun.

It replaces the default Express/Fastify adapter by Bun.serve() and provides native WebSocket support, file uploads, streaming, sessions, rate limiting and compression — all without leaving the Bun runtime.

Requirements

Installation

bun add @mgvdev/nestjs-bun-adapter

Peer dependencies (NestJS core packages) must be installed in your project.

Basic usage

import 'reflect-metadata';
import { NestFactory } from '@nestjs/core';
import { BunHttpAdapter } from '@mgvdev/nestjs-bun-adapter';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, new BunHttpAdapter());
  await app.listen(3000);
}
bootstrap();

Start the application with Bun:

bun run src/main.ts

Adapter options

const adapter = new BunHttpAdapter({
  maxBodySize: 1024 * 1024, // 1 MB body limit
  gracefulShutdown: true,     // wait for active connections on close()
});
  • maxBodySize: maximum body size in bytes (returns 413 Payload Too Large when exceeded)
  • gracefulShutdown: when true, app.close() stops accepting new connections and waits for active ones to close. Defaults to false for tests and short-lived processes.

WebSockets

Use BunWsAdapter together with @nestjs/websockets:

import { NestFactory } from '@nestjs/core';
import { BunHttpAdapter, BunWsAdapter } from '@mgvdev/nestjs-bun-adapter';

async function bootstrap() {
  const adapter = new BunHttpAdapter();
  const app = await NestFactory.create(AppModule, adapter);

  const wsAdapter = new BunWsAdapter(app);
  wsAdapter.setHttpAdapter(adapter);
  app.useWebSocketAdapter(wsAdapter);

  await app.listen(3000);
}
bootstrap();

CORS

Enable CORS the standard NestJS way:

app.enableCors({
  origin: 'http://localhost:3001',
  credentials: true,
});

Static assets

app.useStaticAssets(join(__dirname, '..', 'public'), { prefix: '/public' });

File upload

Use the built-in interceptors with multipart forms:

import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@mgvdev/nestjs-bun-adapter';

@Controller('upload')
export class UploadController {
  @Post()
  @UseInterceptors(FileInterceptor('file'))
  upload(@UploadedFile() file: Express.Multer.File) {
    return { filename: file.originalname, size: file.size };
  }
}

Sessions

import { sessionMiddleware, MemorySessionStore } from '@mgvdev/nestjs-bun-adapter';

app.use(sessionMiddleware({
  secret: 'change-me-in-production',
  name: 'myapp.sid',
  cookie: { httpOnly: true, maxAge: 24 * 60 * 60 * 1000 },
  store: new MemorySessionStore(),
}));

Access the session in controllers via req.session:

@Get('profile')
profile(@Req() req: Request & { session: any }) {
  req.session.data.visits = (req.session.data.visits || 0) + 1;
  return { visits: req.session.data.visits };
}

Rate limiting

import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { RateLimiterInterceptor } from '@mgvdev/nestjs-bun-adapter';

@Controller('api')
export class ApiController {
  @Get()
  @UseInterceptors(RateLimiterInterceptor({ windowMs: 60000, max: 10 }))
  findAll() {
    return { ok: true };
  }
}

A RateLimiterGuard is also available.

Response compression

import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { CompressionInterceptor } from '@mgvdev/nestjs-bun-adapter';

@Controller('data')
export class DataController {
  @Get()
  @UseInterceptors(CompressionInterceptor({ threshold: 1024, level: 6 }))
  getLargePayload() {
    return 'a'.repeat(5000);
  }
}

Supported encodings: br (brotli), gzip and deflate. The interceptor picks the best encoding based on the Accept-Encoding header and quality values.

Swagger / OpenAPI

@nestjs/swagger works out of the box to generate an OpenAPI document:

bun add @nestjs/swagger
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';

const config = new DocumentBuilder().setTitle('My API').setVersion('1.0').build();
const document = SwaggerModule.createDocument(app, config);

// Serve the JSON spec from a controller or expose it directly:
app.use('/api-json', (req, res) => res.json(document));

Note: SwaggerModule.setup() is not supported because it relies on Express/Fastify middleware. You can serve the generated document through a standard NestJS controller instead.

Streaming

Stream a file with NestJS StreamableFile:

import { Controller, Get, StreamableFile } from '@nestjs/common';
import { createReadStream } from 'fs';

@Controller('stream')
export class StreamController {
  @Get('file')
  getFile(): StreamableFile {
    const stream = createReadStream('./big-file.bin');
    return new StreamableFile(stream);
  }
}

Server-Sent Events are supported by returning an Observable:

import { Controller, Get, Sse } from '@nestjs/common';
import { interval, map } from 'rxjs';

@Controller('sse')
export class SseController {
  @Sse('events')
  events() {
    return interval(1000).pipe(map((count) => ({ data: { count } })));
  }
}

View engine

app.setViewEngine('ejs');
app.setBaseViewsDir(join(__dirname, '..', 'views'));
@Get('hello')
@Render('hello')
getHello() {
  return { name: 'World' };
}

Middlewares intégrés

Request logger

import { RequestLoggerInterceptor } from '@mgvdev/nestjs-bun-adapter';

@Controller('api')
@UseInterceptors(RequestLoggerInterceptor())
export class ApiController {}

Format personnalisable :

RequestLoggerInterceptor({
  format: (info) => `${info.method} ${info.url} ${info.statusCode} - ${info.duration}ms`,
})

Security headers

import { SecurityHeadersInterceptor } from '@mgvdev/nestjs-bun-adapter';

@Controller('api')
@UseInterceptors(SecurityHeadersInterceptor())
export class ApiController {}

Headers configurables : X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Strict-Transport-Security, Referrer-Policy, Content-Security-Policy.

Timeout

import { TimeoutInterceptor } from '@mgvdev/nestjs-bun-adapter';

@Controller('api')
@UseInterceptors(TimeoutInterceptor({ ms: 5000 }))
export class ApiController {}

Request ID

import { requestIdMiddleware, RequestIdInterceptor } from '@mgvdev/nestjs-bun-adapter';

app.use(requestIdMiddleware());

Le middleware génère un x-request-id s'il n'est pas fourni et l'expose dans req.requestId. L'intercepteur RequestIdInterceptor peut être utilisé pour répercuter l'ID dans la réponse.

Cache mémoire

import { CacheInterceptor } from '@mgvdev/nestjs-bun-adapter';

@Controller('api')
@UseInterceptors(CacheInterceptor({ ttl: 60000 }))
export class ApiController {}

Graceful shutdown

const app = await NestFactory.create(AppModule, new BunHttpAdapter());
app.enableShutdownHooks();
await app.listen(3000);

Compatibility

| Feature | Status | | ---------------------- | ------ | | Controllers & routing | ✅ | | Middleware | ✅ | | Guards | ✅ | | Interceptors | ✅ | | Pipes | ✅ | | Exception filters | ✅ | | URI versioning | ✅ | | CORS | ✅ | | Static assets | ✅ | | View engine | ✅ | | Multipart upload | ✅ | | Streaming | ✅ | | WebSockets | ✅ | | Swagger / OpenAPI | ✅ | | HTTP/2 | ✅ | | Request logger | ✅ | | Security headers | ✅ | | Timeout interceptor | ✅ | | Request ID | ✅ | | Cache interceptor | ✅ |

License

MIT