new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

tRPC · all subjects

server adapters/overview

41 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Adapter common conventions

Adapters typically support context creation via createContext and globally handle errors via onError, allowing you to choose an appropriate host for your application.

Serverless API adapter options

For serverless solutions, tRPC supports AWS Lambda and Fetch adapters for edge runtimes.

Full-stack framework adapter options

For full-stack frameworks, tRPC offers full integrations like Next.js, or you can use the Fetch adapter with Next.js, Astro, Remix, or SolidStart.

Serverful API adapter options

For serverful APIs, tRPC provides the Standalone adapter for running a standard Node.js HTTP Server, or you can use Express or Fastify adapters to hook into existing APIs.

tRPC is not a server on its own

tRPC must be served using other hosts such as a Node.js HTTP Server, Express, Next.js, or other frameworks. Adapters act as the glue between the host system and the tRPC API.

API Gateway payload format versions

API Gateway has two payload format versions: Version 1.0 uses APIGatewayProxyEvent and is required for REST APIs. Version 2.0 uses APIGatewayProxyEventV2 and can be chosen for HTTP APIs. The version affects the structure of the event object passed to the Lambda handler.

AWS Lambda Response Streaming support

AWS Lambda supports streaming responses to clients with both Lambda Function URLs and API Gateway REST APIs. For API Gateway REST APIs, response streaming requires configuring the integration with responseTransferMode: STREAM.

awsLambdaStreamingRequestHandler signature

The awsLambdaStreamingRequestHandler function receives event, context, and a responseStream parameter (a writable stream). The handler must be wrapped with the awslambda.streamifyResponse() decorator to enable streaming. The awslambda namespace is automatically provided by the Lambda execution environment; types can be imported from @types/aws-lambda.

CreateContext for AWS Lambda

The createContext function for AWS Lambda receives an object with event (APIGatewayProxyEvent or APIGatewayProxyEventV2) and context (Lambda context) properties, wrapped in CreateAWSLambdaContextOptions generic type.

AWS Lambda streaming response example

Example of setting up tRPC with AWS Lambda Response Streaming: ```ts /// <reference types="aws-lambda" /> import type { APIGatewayProxyEventV2 } from 'aws-lambda'; import type { CreateAWSLambdaContextOptions } from '@trpc/server/adapters/aws-lambda'; import { awsLambdaStreamingRequestHandler } from '@trpc/server/adapters/aws-lambda'; import { appRouter } from './router'; const createContext = ({ event, context, }: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>) => ({}); type Context = Awaited<ReturnType<typeof createContext>>; export const handler = awslambda.streamifyResponse( awsLambdaStreamingRequestHandler({ router: appRouter, createContext, }), ); ```

tRPC endpoint format for API Gateway

tRPC endpoints on API Gateway follow the format GET https://<execution-api-link>/<procedure-name>?input=INPUT, where INPUT is a URI-encoded JSON string.

AWS Lambda adapter supported API Gateway versions

The AWS Lambda adapter supports API Gateway REST API (v1), HTTP API (v2), and Lambda Function URL use cases.

httpBatchLink requires single API Gateway Resource

httpBatchLink requires the router to work on a single API Gateway Resource. If you need a Resource per procedure, use httpLink instead.

Install AWS Lambda adapter

To use tRPC with AWS Lambda, install the @trpc/server package with yarn add @trpc/server.

awsLambdaRequestHandler function signature

The awsLambdaRequestHandler function takes an object with two properties: router (the tRPC router) and createContext (a function that receives CreateAWSLambdaContextOptions<APIGatewayProxyEventV2> and returns the context type).

Express adapter installation

To add tRPC to an Express project, install dependencies with: yarn add @trpc/server zod. Zod is not required but is used in sample routers.

Express middleware setup with context

import { initTRPC } from '@trpc/server'; import * as trpcExpress from '@trpc/server/adapters/express'; import express from 'express'; const createContext = ({ req, res, }: trpcExpress.CreateExpressContextOptions) => ({}); // no context type Context = Awaited<ReturnType<typeof createContext>>; const t = initTRPC.context<Context>().create(); const appRouter = t.router({ // [...] }); const app = express(); app.use( '/trpc', trpcExpress.createExpressMiddleware({ router: appRouter, createContext, }), ); app.listen(4000);

Express adapter endpoint URL format for queries

Query procedures in Express are accessed via GET requests at http://localhost:4000/trpc/{procedureName}?input=INPUT where INPUT is a URI-encoded JSON string.

Express adapter endpoint URL format for mutations

Mutation procedures in Express are accessed via POST requests to http://localhost:4000/trpc/{procedureName} with the request body containing the input data.

CreateExpressContextOptions type

The CreateExpressContextOptions type from @trpc/server/adapters/express contains req and res properties representing the Express request and response objects.

Astro fetchRequestHandler example

In Astro, implement the fetch adapter in src/pages/trpc/[trpc].ts like this: ```ts import { fetchRequestHandler } from '@trpc/server/adapters/fetch'; import type { APIRoute } from 'astro'; import { createContext } from '../../server/context'; import { appRouter } from '../../server/router'; export const ALL: APIRoute = (opts) => { return fetchRequestHandler({ endpoint: '/trpc', req: opts.request, router: appRouter, createContext, }); }; ```

Fetch adapter supported edge runtimes

tRPC provides a fetch adapter that works with any edge runtime following the WinterCG Minimum Common Web Platform API specification. Supported runtimes include Cloudflare Workers, Deno Deploy, and Vercel Edge Runtime. The adapter also integrates with frameworks using web platform APIs like Astro (SSR mode), Remix, and SolidStart.

Required Web APIs for fetch adapter

The tRPC fetch adapter requires the following Fetch APIs: Request, Response, fetch, Headers, and URL. If a runtime supports these APIs, it can use the tRPC server.

fetchRequestHandler function parameters

The fetchRequestHandler function accepts the following parameters: endpoint (string specifying the tRPC endpoint path), req (a Request object), router (the tRPC router), and createContext (a function to create context for each request).

FetchCreateContextFnOptions type

FetchCreateContextFnOptions is a type exported from '@trpc/server/adapters/fetch' that provides the context creation function with req (the Request object) and resHeaders (response headers) parameters.

Cloudflare Worker fetchRequestHandler example

In a Cloudflare Worker, use the fetch adapter like this: ```ts import { fetchRequestHandler } from '@trpc/server/adapters/fetch'; import { createContext } from './context'; import { appRouter } from './router'; export default { async fetch(request: Request): Promise<Response> { return fetchRequestHandler({ endpoint: '/trpc', req: request, router: appRouter, createContext, }); }, }; ``` Run `wrangler dev server.ts` to start the server.

Remix fetchRequestHandler example

In Remix, implement the fetch adapter in app/routes/trpc.$trpc.ts like this: ```ts import type { ActionFunctionArgs, LoaderFunctionArgs } from '@remix-run/node'; import { fetchRequestHandler } from '@trpc/server/adapters/fetch'; import { createContext } from '~/server/context'; import { appRouter } from '~/server/router'; export const loader = async (args: LoaderFunctionArgs) => { return handleRequest(args); }; export const action = async (args: ActionFunctionArgs) => { return handleRequest(args); }; function handleRequest(args: LoaderFunctionArgs | ActionFunctionArgs) { return fetchRequestHandler({ endpoint: '/trpc', req: args.request, router: appRouter, createContext, }); } ```

SolidStart fetchRequestHandler example

In SolidStart, implement the fetch adapter in src/routes/api/trpc/[trpc].ts like this: ```ts import { fetchRequestHandler } from '@trpc/server/adapters/fetch'; import type { APIEvent } from '@solidjs/start/server'; import { createContext } from '../../server/context'; import { appRouter } from '../../server/router'; const handler = (event: APIEvent) => fetchRequestHandler({ endpoint: '/api/trpc', req: event.request, router: appRouter, createContext, }); export { handler as GET, handler as POST }; ```

Deno Oak fetchRequestHandler example

In Deno Oak, implement the fetch adapter in app.ts like this: ```ts import { Application, Router } from 'https://deno.land/x/oak/mod.ts'; import { fetchRequestHandler } from 'npm:@trpc/server/adapters/fetch'; import { createContext } from './context.ts'; import { appRouter } from './router.ts'; const app = new Application(); const router = new Router(); router.all('/trpc/(.*)', async (ctx) => { const res = await fetchRequestHandler({ endpoint: '/trpc', req: new Request(ctx.request.url, { headers: ctx.request.headers, body: ctx.request.method !== 'GET' && ctx.request.method !== 'HEAD' ? ctx.request.body({ type: 'stream' }).value : void 0, method: ctx.request.method, }), router: appRouter, createContext, }); ctx.response.status = res.status; ctx.response.headers = res.headers; ctx.response.body = res.body; }); app.use(router.routes()); app.use(router.allowedMethods()); await app.listen({ port: 3000 }); ```

Deno Deploy fetchRequestHandler example

In Deno Deploy, implement the fetch adapter in server.ts like this: ```ts import { fetchRequestHandler } from 'npm:@trpc/server/adapters/fetch'; import { createContext } from './context.ts'; import { appRouter } from './router.ts'; function handler(request) { return fetchRequestHandler({ endpoint: '/trpc', req: request, router: appRouter, createContext, }); } Deno.serve(handler); ``` Run `deno run --allow-net=:8000 --allow-env ./server.ts` to start the server.

Vercel Edge Runtime fetchRequestHandler example

In Vercel Edge Runtime, implement the fetch adapter in server.ts using Service Worker-style addEventListener like this: ```ts import { fetchRequestHandler } from '@trpc/server/adapters/fetch'; import { createContext } from './context'; import { appRouter } from './router'; addEventListener('fetch', (event: any) => { return event.respondWith( fetchRequestHandler({ endpoint: '/trpc', req: event.request, router: appRouter, createContext, }), ); }); ``` Run `edge-runtime --listen server.ts --port 3000` to start the server.

Sample context implementation for fetch adapter

A sample context implementation for the fetch adapter: ```ts import type { FetchCreateContextFnOptions } from '@trpc/server/adapters/fetch'; export function createContext({ req, resHeaders, }: FetchCreateContextFnOptions) { const user = { name: req.headers.get('username') ?? 'anonymous' }; return { req, resHeaders, user }; } export type Context = Awaited<ReturnType<typeof createContext>>; ```

tRPC queries are standard HTTP GET requests enabling HTTP cache headers

All tRPC queries are normal HTTP GET requests, which means you can use standard HTTP cache headers to cache responses. This approach works with any hosting provider that supports standard HTTP cache headers, such as Vercel, Cloudflare, and AWS CloudFront.

Use responseMeta callback to set cache headers

Most tRPC adapters support a responseMeta callback that lets you set HTTP headers, including cache headers, based on the procedures being called. This callback receives options with paths, errors, and type fields.

responseMeta function parameters and return value

The responseMeta callback receives options with properties: paths (array of procedure paths), errors (array of errors), and type (the request type, such as 'query'). It returns an object with a headers property containing a Headers object.

Cache headers caution with personal data and batching

Always be careful with caching, especially if you handle personal information. Since batching is enabled by default, it is recommended to set cache headers in the responseMeta function and make sure there are not any concurrent calls that may include personal data, or to omit cache headers completely if there is an auth header or cookie.

Example responseMeta implementation with cache control headers

The following code demonstrates setting cache headers using responseMeta: it checks if all paths include 'public', no errors occurred, and the request is a query. If all conditions are met, it sets the cache-control header to 's-maxage=1, stale-while-revalidate=86400' to cache for 1 day with 1-second revalidation. ```ts const server = createHTTPServer({ router: appRouter, createContext, responseMeta(opts) { const { paths, errors, type } = opts; const allPublic = paths && paths.every((path) => path.includes('public')); const allOk = errors.length === 0; const isQuery = type === 'query'; if (allPublic && allOk && isQuery) { const ONE_DAY_IN_SECONDS = 60 * 60 * 24; return { headers: new Headers([ [ 'cache-control', `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`, ], ]), }; } return {}; }, }); ```

Server setup overview topics

Backend setup covers defining routers and procedures, setting up context, adding input validation, and using middlewares to extend your API. Once the API is defined, it can be hosted using adapters for platforms like Express, Fastify, Next.js, AWS Lambda, and more.

tRPC parses request body based on Content-Type header

When a request is handled by tRPC, it takes care of parsing the request body based on the Content-Type header of the request. If you encounter errors like 'Failed to parse body as XXX', make sure that your server (e.g., Express, Next.js) is not parsing the request body before tRPC handles it.

Express body parsing configuration for tRPC

Example showing incorrect and correct Express body parsing configuration for tRPC: ```ts import express from 'express'; import * as trpcExpress from '@trpc/server/adapters/express'; import { appRouter } from './router'; // incorrect - express.json() tries to parse body before tRPC const app1 = express(); app1.use(express.json()); app1.post('/express/hello', (req, res) => { res.end(); }); app1.use('/trpc', trpcExpress.createExpressMiddleware({ router: appRouter })); // correct - express.json() only used in "/express/*" path const app2 = express(); app2.use('/express', express.json()); app2.post('/express/hello', (req, res) => { res.end(); }); app2.use('/trpc', trpcExpress.createExpressMiddleware({ router: appRouter })); ```

tRPC server adapters available

tRPC supports Node.js standalone HTTP server (simplest for local dev), Express middleware, Fastify plugin, AWS Lambda with API Gateway v1/v2 or Function URLs, and Fetch API / Edge adapters for Cloudflare Workers, Deno, Vercel Edge, Astro, and Remix.

Give your agent this brain