Skip to Content

Node and Bun

Platform adapters, and running the same app on either runtime.

The kernel is a function from a Fetch Request to a Response. An adapter connects it to a runtime's HTTP server.

import { bunAdapter } from '@sukujs/platform-bun';

const app = await Suku.create({ features: [AppFeature], adapter: bunAdapter() });
await app.listen(3000);

Bun runs TypeScript directly and emits decorator metadata, so no build step is needed.

One entry point for both

const adapter = typeof Bun !== 'undefined' ? bunAdapter() : nodeAdapter();

Listening and closing

const server = await app.listen(3000);                       // 0.0.0.0:3000
await app.listen({ port: 0, hostname: '127.0.0.1' });        // a free port, loopback only

server.url;         // "http://127.0.0.1:53124"
await app.close();  // stop accepting, finish in-flight requests, dispose singletons

app.close({ force: true }) also drops connections that are still open.

Node adapter options

import { createServer } from 'node:https';

nodeAdapter({
  createServer: () => createServer({ key, cert }),
  onError: (error) => new Response('Something broke', { status: 500 }),
});

getNodeRaw(request) returns the underlying IncomingMessage and ServerResponse when you need them.

Other runtimes

Anything that can call a fetch handler can host Suku through app.handle.

export default { fetch: (request: Request) => app.handle(request) };   // Cloudflare Workers, Deno, ...

Official adapters for those runtimes are not published yet. For VPS (PM2, systemd), Docker Compose, Cloudflare Workers and Vercel, see Deployment.

Writing an adapter

import type { PlatformAdapter } from '@sukujs/core';

export const myAdapter = (): PlatformAdapter => ({
  name: 'mine',
  async serve(handler, { port = 3000, hostname = '0.0.0.0' } = {}) {
    const server = startServer({ port, hostname, onRequest: handler });
    return { hostname, port, url: `http://${hostname}:${port}`, close: () => server.stop() };
  },
});

On this page