Skip to content

Latest commit

 

History

History
168 lines (137 loc) · 3.3 KB

README.md

File metadata and controls

168 lines (137 loc) · 3.3 KB

trpc-uwebsockets

uWebSockets.js adapter for tRPC

Installation

Latest stable version

yarn add trpc-uwebsockets@latest

Or install beta version with subscription support

yarn add trpc-uwebsockets@beta

Usage

Import needed packages

import { App } from 'uWebSockets.js';
import { inferAsyncReturnType, initTRPC } from '@trpc/server';
import { CreateContextOptions } from 'trpc-uwebsockets';
import z from 'zod';

Define tRPC, context, and router

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

const createContext = ({ req, res }: CreateContextOptions) => {
  const getUser = () => {
    if (req.headers.authorization === 'meow') {
      return {
        name: 'KATT',
      };
    }
    return null;
  };
  return {
    req,
    res,
    user: getUser(),
  };
};
export type Context = inferAsyncReturnType<typeof createContext>;

const router = t.router({
  hello: t.procedure
    .input(
      z
        .object({
          who: z.string().nullish(),
        })
        .nullish()
    )
    .query(({ input, ctx }) => {
      return {
        text: `hello ${input?.who ?? ctx.user?.name ?? 'world'}`,
      };
    }),
});

Initialize uWebsockets server and attach tRPC

const app = App();

createUWebSocketsHandler(app, '/trpc', {
  router,
  createContext,
});

/* dont crash on unknown request */
app.any('/*', (res) => {
  res.writeStatus('404 NOT FOUND');
  res.end();
});

app.listen('0.0.0.0', 8000, () => {
  console.log('Server listening on http://localhost:8000');
});

API

Create context options

type CreateContextOptions = {
  /* read-only request information */
  req: {
    headers: Record<string, string>;
    method: 'POST' | 'GET';
    query: URLSearchParams;
    path: string;
  };
  /* see https://unetworking.github.io/uWebSockets.js/generated/interfaces/HttpResponse.html */
  res: {
    writeStatus(status: RecognizedString): HttpResponse;
    writeHeader(key: RecognizedString, value: RecognizedString): HttpResponse;
  };
};

Enabling subscrptions

Simple method: enable subscriptions when creating the main handler.

createUWebSocketsHandler(app, '/trpc', {
  router,
  createContext,
  enableSubscriptions: true,
});

Recommended method: enable subscriptions after registering main request handler.

const app = App();

createUWebSocketsHandler(app, '/trpc', {
  router,
  createContext: ({ req, res }) => {},
});

applyWSHandler(app, '/trpc', {
  router,
  createContext: ({ req, res }) => {},
});

example of subscrption client

import {
  createTRPCProxyClient,
  createWSClient,
  httpBatchLink,
  splitLink,
  wsLink,
} from '@trpc/client';

const host = `localhost:8080/trpc`;
const wsClient = createWSClient({ url: `ws://${host}` });
const client = createTRPCProxyClient<AppRouter>({
  links: [
    splitLink({
      condition(op) {
        return op.type === 'subscription';
      },
      true: wsLink({ client: wsClient }),
      false: httpBatchLink({
        url: `http://${host}`,
        headers: headers,
      }),
    }),
  ],
});