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/next-app-dir

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

experimental_caller setup for Next.js App Router server actions

To create procedures that work as server actions, use experimental_caller with experimental_nextAppDirCaller. The pathExtractor option extracts metadata (such as a span property) to identify procedures for logging and observability, since server actions don't have a router path like user.byId.

Server actions setup example with experimental_caller and pathExtractor

```ts import { initTRPC, TRPCError } from '@trpc/server'; import { experimental_nextAppDirCaller } from '@trpc/server/adapters/next-app-dir'; interface Meta { span: string; } export const t = initTRPC.meta<Meta>().create(); export const serverActionProcedure = t.procedure.experimental_caller( experimental_nextAppDirCaller({ pathExtractor: ({ meta }) => (meta as Meta)?.span ?? '', }), ); ``` This creates a base procedure that can be invoked as plain functions (server actions).

Add context to server actions via middleware

Since server actions don't go through an HTTP adapter with a createContext function, use a middleware to provide context such as session data. The middleware receives opts with next() to pass context to the handler.

Server action procedure with context middleware

```ts export const serverActionProcedure = t.procedure .experimental_caller( experimental_nextAppDirCaller({ pathExtractor: ({ meta }) => (meta as Meta)?.span ?? '', }), ) .use(async (opts) => { const user = await currentUser(); return opts.next({ ctx: { user } }); }); ``` This adds user context from the currentUser() function to all server action procedures.

Protected server action procedure

```ts export const protectedAction = serverActionProcedure.use((opts) => { if (!opts.ctx.user) { throw new TRPCError({ code: 'UNAUTHORIZED', }); } return opts.next({ ctx: { ...opts.ctx, user: opts.ctx.user, // ensures type is non-nullable }, }); }); ``` This creates a reusable base procedure that requires authentication and makes the user type non-nullable.

Define server action with mutation and input validation

```ts 'use server'; import { z } from 'zod'; import { protectedAction } from '../server/trpc'; export const createPost = protectedAction .input( z.object({ title: z.string(), }), ) .mutation(async (opts) => { // opts.ctx.user is typed as non-nullable // opts.input is typed as { title: string } // Create the post... }); ``` Define server actions in a file with the "use server" directive. The procedure becomes a plain async function that can be used as a server action, with input validation and type inference.

Call server action from client component

```tsx 'use client'; import { createPost } from '../_actions'; export function PostForm() { return ( <form onSubmit={async (e) => { e.preventDefault(); const title = new FormData(e.currentTarget).get('title') as string; await createPost({ title }); }} > <input type="text" name="title" /> <button type="submit">Create Post</button> </form> ); } ``` Import the server action and call it from a client component. Server actions work with both the action attribute for progressive enhancement and programmatic calls via onSubmit.

Add metadata to server actions for observability

```ts export const createPost = protectedAction .meta({ span: 'create-post' }) .input( z.object({ title: z.string(), }), ) .mutation(async (opts) => { // ... }); ``` Use the .meta() method to tag actions for logging or tracing. The span property from metadata is passed to pathExtractor for observability tools.

Server Actions provides tRPC features

By defining server actions using tRPC procedures, you get input validation, authentication and authorization through middlewares, output validation, data transformers, and more.

Server Actions integration uses experimental_ prefix

The Server Actions integration uses the experimental_ prefix and is still under active development. The API may change in future releases.

Server Actions vs mutations tradeoffs

Use Server Actions when you want progressive enhancement (forms that work without JavaScript) or when the action doesn't need to update client-side React Query cache. Use useMutation when you need to update the client-side cache, show optimistic updates, or manage complex loading/error states in the UI. Server Actions are not a replacement for all tRPC mutations, and can be incrementally adopted alongside existing tRPC API.

API handler responseMeta for caching

The `createNextApiHandler` from `@trpc/server/adapters/next` accepts a `responseMeta` callback that receives `opts` with properties: `ctx`, `paths`, `errors`, and `type`. This allows caching API responses based on path patterns, error states, and request type.

API handler responseMeta caching example

Example: check if all paths include 'public', no errors occurred, and the request type is 'query', then set cache headers. This pattern allows selective caching of public query endpoints.

tRPC server runtime adapters

Community adapters connect tRPC to various server runtimes and frameworks: tRPC-uWebSockets (uWebSockets.js), trpc-koa-adapter (Koa), trpc-bun-adapter (Bun runtime), cloudflare-pages-plugin-trpc (Cloudflare Pages), electron-trpc (Electron), and serverless adapters for AWS Lambda, SQS, and API Gateway.

tRPC transport layer adapters

Community projects provide tRPC adapters using alternative transport layers: trpc-rabbitmq (RabbitMQ transport), trpc-mqtt (MQTT transport), trpc-redis (Redis transport), and @h4ad/serverless-adapter (AWS SQS, AWS API Gateway).

NestJS integration for tRPC

NestJS-tRPC (nestjs-trpc.io) provides an opinionated approach to building end-to-end typesafe APIs with tRPC within the NestJS framework.

resolveHTTPRequest replaced by resolveRequest

The function resolveHTTPRequest has been replaced by resolveRequest which uses Fetch APIs (Request/Response). This is a breaking change for HTTP-adapters but should not affect end users.

Explicit Content-Type checks

tRPC v11 now performs explicit checks for the Content-Type header when making POST requests. Requests with unexpected Content-Type headers will receive a 415 Unsupported Media Type error.

Method overriding support

tRPC v11 adds support for method overriding, allowing you to override the HTTP method for procedures to always use POST in order to work around limitations like max URL lengths.

Route handler with fetchRequestHandler for Next.js App Router

In app/api/trpc/[trpc]/route.ts, import fetchRequestHandler from @trpc/server/adapters/fetch. Create a handler function that calls fetchRequestHandler with endpoint: '/api/trpc', req, router: appRouter, and createContext. Export the handler as both GET and POST named exports: export { handler as GET, handler as POST }. Both HTTP methods must be exported or Next.js will return 405 Method Not Allowed.

tRPC response handler location in Next.js

In the next-prisma-websockets-starter example, the tRPC response handler is located at ./src/api/trpc/[trpc].tsx

Give your agent this brain