/trpc-bun-adapter

Use tRPC with bun and fun

Primary LanguageTypeScriptMIT LicenseMIT

tRPC Bun Adapter

npm version License

Description

trpc-bun-adapter is a tRPC adapter for Bun.

Start both HTTP and WebSockets transports with ease.

Quick Start

Install packages:

bun install @trpc/server trpc-bun-adapter

Create a server.ts file with the following content:

import {initTRPC} from '@trpc/server';
import {createBunServeHandler} from 'trpc-bun-adapter';

const t = initTRPC.create();

export const router = t.router({
    ping: t.procedure.query(() => "pong"),
});

Bun.serve(createBunServeHandler({ router }));

To start the server, run:

bun run server.ts
bun run --watch server.ts # to restart on file changes

Check that it works:

curl http://localhost:3000/ping

Example

for a full example, see the example directory.

API Reference

Ensure you have created a router.ts file as outlined in the tRPC documentation: Define Routers.

createBunServeHandler

Creates a Bun serve handler:

import {createBunServeHandler, CreateBunContextOptions} from 'trpc-bun-adapter';
import {router} from './router';

const createContext = (opts: CreateBunContextOptions) => ({
    user: 1,
});

Bun.serve(
    createBunServeHandler(
        {
            router,
            // optional arguments:
            endpoint: '/trpc', // Default to ""
            createContext,
            onError: console.error,
            responseMeta(opts) {
                return {
                    status: 202,
                    headers: {},
                }
            },
            batching: {
                enabled: true,
            },
        },
        {
            // Bun serve options
            port: 3001,
            fetch(request, server) {
                // will be executed if it's not a TRPC request
                return new Response("Hello world");
            },
        },
    ),
);

To add response headers like Cross-origin resource sharing (CORS) use responseMeta option:

Bun.serve(
   createBunServeHandler({
         router: appRouter,
         responseMeta(opts) {
            return {
               status: 200,
               headers: {
                  "Access-Control-Allow-Origin": "*",
                  "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
                  "Access-Control-Allow-Headers": "Content-Type, Authorization"
               }
            };
         }
      }
   )
);

createBunHttpHandler

Creates a Bun HTTP handler for tRPC HTTP requests:

import {createBunHttpHandler, CreateBunContextOptions} from 'trpc-bun-adapter';
import {router} from './router';

const createContext = (opts: CreateBunContextOptions) => ({
    user: 1,
});

const bunHandler = createBunHttpHandler({
    router,
    // optional arguments:
    endpoint: '/trpc', // Default to ""
    createContext,
    onError: console.error,
    responseMeta(opts) {
        return {
            status: 202,
            headers: {},
        }
    },
    batching: {
        enabled: true,
    },
    emitWsUpgrades: false, // pass true to upgrade to WebSocket
});

Bun.serve({
    fetch(request, response) {
        return bunHandler(request, response) ?? new Response("Not found", {status: 404});
    }
});

createBunWsHandler

Creates a Bun WebSocket handler for tRPC websocket requests:

import { createBunWSHandler, CreateBunContextOptions } from './src';
import { router } from './router';

const createContext = (opts: CreateBunContextOptions) => ({
    user: 1,
});

const websocket = createBunWSHandler({
    router,
    // optional arguments:
    createContext,
    onError: console.error,
    batching: {
        enabled: true,
    },
});

Bun.serve({
    fetch(request, server) {
        if (server.upgrade(request, {data: {req: request}})) {
            return;
        }

        return new Response("Please use websocket protocol", {status: 404});
    },
    websocket,
});

CreateBunContextOptions

To ensure your router recognizes the context type, define a createContext function utilizing the CreateBunContextOptions type:

import { initTRPC } from '@trpc/server';
import type { CreateBunContextOptions } from "src/createBunHttpHandler";

export const createContext = async (opts: CreateBunContextOptions) => {
    return {
        authorization: req.headers.get('Authorization')
    };
};

With createContext defined, you can use it in your router to access the context, such as the authorization information:

const t = initTRPC.context<typeof createContext>().create();

export const router = t.router({
    session: t.procedure.query(({ ctx }) => ctx.authorization),
});

Finally, pass your createContext function besides router to createBunHttpHandler. This integrates your custom context into the HTTP handler setup:

createBunHttpHandler({
    router,
    createContext,
})

Read more documentation about tRPC contexts here: Contexts

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Feel free to open issues and pull requests.