UNPKG

@trpc/server

Version:

The tRPC server library

124 lines (91 loc) • 4.33 kB
# Define Routers From https://trpc.io/docs/server/routers To begin building your tRPC-based API, you'll first need to define your router. Once you've mastered the fundamentals, you can [customize your routers](https://trpc.io/docs/server/routers#advanced-usage) for more advanced use cases. ## Initialize tRPC You should initialize tRPC **exactly once** per application. Multiple instances of tRPC will cause issues: for example, `t.mergeRouters()` throws if the routers come from different instances that each set a [transformer](https://trpc.io/docs/server/data-transformers) or [error formatter](https://trpc.io/docs/server/error-formatting). Create `t` in one file and import your procedures and `router` from it everywhere. ```ts no-check title="server/trpc.ts" import { initTRPC } from '@trpc/server'; // You can use any variable name you like. // We use t to keep things simple. const t = initTRPC.create(); export const router = t.router; export const publicProcedure = t.procedure; ``` You'll notice we are exporting certain methods of the `t` variable here rather than `t` itself. This is to establish a certain set of procedures that we will use idiomatically in our codebase. ## Defining a router Next, let's define a router with a procedure to use in our application. We have now created an API "endpoint". In order for these endpoints to be exposed to the frontend, your [Adapter](https://trpc.io/docs/server/adapters) should be configured with your `appRouter` instance. ```ts no-check title="server/_app.ts" import { publicProcedure, router } from './trpc'; const appRouter = router({ greeting: publicProcedure.query(() => 'hello tRPC v11!'), }); // Export only the type of a router! // This prevents us from importing server code on the client. export type AppRouter = typeof appRouter; ``` On the client, import it with `import type { AppRouter } from '...'` and never import the `appRouter` value: a type-only import is always erased, so your server code can't end up in the client bundle. Procedures can't be named `then`, `call` or `apply`: `router()` throws if you use these names. ## Defining an inline sub-router When you define an inline sub-router, you can represent your router as a plain object. In the below example, `nested1` and `nested2` are equal: ```ts no-check title="server/_app.ts" import * as trpc from '@trpc/server'; import { publicProcedure, router } from './trpc'; const appRouter = router({ // Using the router() method nested1: router({ proc: publicProcedure.query(() => '...'), }), // Using an inline sub-router nested2: { proc: publicProcedure.query(() => '...'), }, }); ``` ## Advanced usage When initializing your router, tRPC allows you to: - Setup [request contexts](https://trpc.io/docs/server/context) - Assign [metadata](https://trpc.io/docs/server/metadata) to procedures - [Format](https://trpc.io/docs/server/error-formatting) and [handle](https://trpc.io/docs/server/error-handling) errors - [Transform data](https://trpc.io/docs/server/data-transformers) as needed - Customize the [runtime configuration](https://trpc.io/docs/server/routers#runtime-configuration) You can use method chaining to customize your `t`-object on initialization. For example: ```ts no-check const t = initTRPC.context<Context>().meta<Meta>().create({ /* [...] */ }); ``` ### Runtime Configuration ```ts no-check interface RootConfig { /** * Use a data transformer * @see https://trpc.io/docs/v11/data-transformers */ transformer: DataTransformerOptions; /** * Use custom error formatting * @see https://trpc.io/docs/v11/error-formatting */ errorFormatter: ErrorFormatter; /** * Allow `@trpc/server` to run in non-server environments * @warning **Use with caution**, this should likely mainly be used within testing. * @default false */ allowOutsideOfServer: boolean; /** * Is this a server environment? * @warning **Use with caution**, this should likely mainly be used within testing. * @default typeof window === 'undefined' || 'Deno' in window || process.env.NODE_ENV === 'test' */ isServer: boolean; /** * Is this development? * Will be used to decide if the API should return stack traces * @default process.env.NODE_ENV !== 'production' */ isDev: boolean; } ```