Skip to main content

tRPC

info

The following examples only work with tRPC over HTTP, you cannot use this framework to support websocket or subscriptions.

First, you need to ensure you have the libs installed, so run this code:

npm i --save @trpc/server body-parser

body-parser is needed to parse the body of the request to JSON.

Then, you just need to use the TrpcFramework when you create your adapter, like:

index.ts
import * as trpc from '@trpc/server';
import { ServerlessAdapter } from '@h4ad/serverless-adapter';
import { TrpcFramework, TrpcAdapterContext, TrpcFrameworkOptions } from '@h4ad/serverless-adapter/frameworks/trpc';
import { JsonBodyParserFramework } from '@h4ad/serverless-adapter/frameworks/body-parser';
import { CorsFramework } from '@h4ad/serverless-adapter/frameworks/cors';
import { z } from 'zod';

type CustomContext = { currentDate: Date };
type TrpcContext = TrpcAdapterContext<CustomContext>;

const t = trpc.initTRPC.context<TrpcContext>().create();
const appRouter = t.router({
getUser: t.procedure.input(z.string()).query((req) => {
req.input; // string
return { id: req.input, name: 'Bilbo' };
}),
createUser: t.procedure
// validate input with Zod
.input(z.object({ name: z.string().min(5) }))
.mutation(({ input }) => {
return {
created: true,
newName: input.name,
};
})
});

const frameworkOptions: TrpcFrameworkOptions<CustomContext> = {
createContext: () => ({ currentDate: new Date() }),
};

const framework = new TrpcFramework<TrpcContext>(frameworkOptions);
const jsonFramework = new JsonBodyParserFramework(framework);
const corsFramework = new CorsFramework(jsonFramework); // see more about: https://serverless-adapter.viniciusl.com.br/docs/main/frameworks/cors

export const handler = ServerlessAdapter.new(appRouter)
.setFramework(corsFramework)
// continue to set the other options here.
//.setHandler(new DefaultHandler())
//.setResolver(new PromiseResolver())
//.addAdapter(new AlbAdapter())
//.addAdapter(new SQSAdapter())
//.addAdapter(new SNSAdapter())
// after put all methods necessary, just call the build method.
.build();
tip

Need more examples? See more examples here.

Integrating with Adapters

This framework is a little special when dealing with request URLs because of the structure of tRPC.

So when you integrate with an adapter like SQSAdapter, when you receive an event, the adapter will forward the request to /sqs by default but because of the structure of tRPC, the framework will change the request URL to just sqs.

With this behavior, to integrate with SQSAdapter, you will create the following mutation:

index.ts
import type { SQSEvent } from 'aws-lambda';
import * as trpc from '@trpc/server';
import { TrpcAdapterContext } from '@h4ad/serverless-adapter/frameworks/trpc';
import { z } from 'zod';

type TrpcContext = TrpcAdapterContext<unknown>;

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

const appRouter = t.router({
sqs: t.procedure
.input(z.object({Records: z.array(z.any())}))
.mutation(({ctx, input}) => {
if (ctx.getHeader('host') !== 'sqs.amazonaws.com')
throw new TRPCError({
code: 'UNAUTHORIZED',
message: 'Wrong host.',
});

const event = input as SQSEvent;

// Do whatever you want
// and you dont need to return nothing
}),
});
About another adapters

Never forget to check the host header as you could introduce a security hole when adding support for AWS Api Gateway and other adapters.

tip

You can see a working example here.

Default Context and Custom context

By default, we provide you with a few methods to get information from the request and modify the response, to learn more, take a look at TrpcAdapterBaseContext.

Also, you can pass new properties to the context by setting the createContext function inside the options, like the code below:

index.ts
import * as trpc from '@trpc/server';
import { ServerlessAdapter } from '@h4ad/serverless-adapter';
import { TrpcFramework, TrpcAdapterContext, TrpcFrameworkOptions } from '@h4ad/serverless-adapter/frameworks/trpc';
import { JsonBodyParserFramework } from '@h4ad/serverless-adapter/frameworks/body-parser';
import { CorsFramework } from '@h4ad/serverless-adapter/frameworks/cors';

type CustomContext = { potato: boolean };
type TrpcContext = TrpcAdapterContext<CustomContext>;

const t = trpc.initTRPC.context<TrpcContext>().create();
const appRouter = t.router({
add: t.procedure
.mutation(({ ctx }) => {
// get the request url
const requestUrl = ctx.getUrl();

// this will change the status code of the request to 204.
ctx.setStatus(204);
}),
});

const frameworkOptions: TrpcFrameworkOptions<TrpcContext> = {
// you can return a promise
createContext: () => Promise.resolve({ potato: true }),
// createContext: () => ({ potato: false }),
};

const framework = new TrpcFramework<TrpcContext>(frameworkOptions);
const jsonFramework = new JsonBodyParserFramework(framework);
const corsFramework = new CorsFramework(jsonFramework); // see more about: https://serverless-adapter.viniciusl.com.br/docs/main/frameworks/cors

export const handler = ServerlessAdapter.new(appRouter)
.setFramework(corsFramework)
// continue to set the other options here.
//.setHandler(new DefaultHandler())
//.setResolver(new PromiseResolver())
//.addAdapter(new AlbAdapter())
//.addAdapter(new SQSAdapter())
//.addAdapter(new SNSAdapter())
// after put all methods necessary, just call the build method.
.build();
tip

Is your application instance creation asynchronous? Look the LazyFramework which helps you in asynchronous startup.

tip

Need to deal with CORS? See CorsFramework which helps you to add correct headers.