Skip to main content

server-setup

Initialize tRPC with initTRPC.create(), define routers with t.router(), create procedures with .query()/.mutation()/.subscription(), configure context with createContext(), export AppRouter type, merge routers with t.mergeRouters(), lazy-load routers with lazy().

معلومات المصدر

المستودع
trpc/trpc
آخر نشاط في المصدر
٢٨ مارس ٢٠٢٦ في ١٠:٥٨
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٤٠٬٦٨٩
التفرعات
١٬٧٠١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
server-setup
description
Initialize tRPC with initTRPC.create(), define routers with t.router(), create procedures with .query()/.mutation()/.subscription(), configure context with createContext(), export AppRouter type, merge routers with t.mergeRouters(), lazy-load routers with lazy().
type
core
library
trpc
library_version
11.16.0
requires
[]
sources
["trpc/trpc:www/docs/server/overview.md","trpc/trpc:www/docs/server/routers.md","trpc/trpc:www/docs/server/procedures.md","trpc/trpc:www/docs/server/context.md","trpc/trpc:www/docs/server/merging-routers.md","trpc/trpc:www/docs/main/quickstart.mdx","trpc/trpc:packages/server/src/unstable-core-do-not-import/initTRPC.ts","trpc/trpc:packages/server/src/unstable-core-do-not-import/router.ts"]
# tRPC -- Server Setup ## Setup ```ts // server/trpc.ts import { initTRPC } from '@trpc/server'; const t = initTRPC.create(); export const router = t.router; export const publicProcedure = t.procedure; ``` ```ts // server/appRouter.ts import { z } from 'zod'; import { publicProcedure, router } from './trpc'; type User = { id: string; name: string }; export const appRouter = router({ userList: publicProcedure.query(async (): Promise<User[]> => { return [{ id: '1', name: 'Katt' }]; }), userById: publicProcedure .input(z.string()) .query(async ({ input }): Promise<User> => { return { id: input, name: 'Katt' }; }), userCreate: publicProcedure .input(z.object({ name: z.string() })) .mutation(async ({ input }): Promise<User> => { return { id: '1', ...input }; }), }); export type AppRouter = typeof appRouter; ``` ```ts // server/index.ts import { createHTTPServer } from '@trpc/server/adapters/standalone'; import { appRouter } from './appRouter'; const server = createHTTPServer({ router: appRouter }); server.listen(3000); ``` ## Core Patterns ### Context with typed session ```ts // server/context.ts import type { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone'; export async function createContext(opts: CreateHTTPContextOptions) { const token = opts.req.headers['authorization']; return { token }; } export type Context = Awaited<ReturnType<typeof createContext>>; ``` ```ts // server/trpc.ts import { initTRPC } from '@trpc/server'; import type { Context } from './context'; const t = initTRPC.context<Context>().create(); export const router = t.router; export const publicProcedure = t.procedure; ``` ```ts // server/index.ts import { createHTTPServer } from '@trpc/server/adapters/standalone'; import { appRouter } from './appRouter'; import { createContext } from './context'; const server = createHTTPServer({ router: appRouter, createContext, }); server.listen(3000); ``` ### Inner/outer context split for testability ```ts // server/context.ts import type { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone'; import { db } from './db'; interface CreateInnerContextOptions { session: { user: { email: string } } | null; } export async function createContextInner(opts?: CreateInnerContextOptions) { return { db, session: opts?.session ?? null, }; } export async function createContext(opts: CreateHTTPContextOptions) { const session = getSessionFromCookie(opts.req); const contextInner = await createContextInner({ session }); return { ...contextInner, req: opts.req, res: opts.res, }; } export type Context = Awaited<ReturnType<typeof createContextInner>>; ``` Infer `Context` from `createContextInner` so server-side callers and tests never need HTTP request objects. ### Merging child routers ```ts // server/routers/user.ts import { publicProcedure, router } from '../trpc'; export const userRouter = router({ list: publicProcedure.query(() => []), }); ``` ```ts // server/routers/post.ts import { z } from 'zod'; import { publicProcedure, router } from '../trpc'; export const postRouter = router({ create: publicProcedure .input(z.object({ title: z.string() })) .mutation(({ input }) => ({ id: '1', ...input })), list: publicProcedure.query(() => []), }); ``` ```ts // server/routers/_app.ts import { router } from '../trpc'; import { postRouter } from './post'; import { userRouter } from './user'; export const appRouter = router({ user: userRouter, post: postRouter, }); export type AppRouter = typeof appRouter; ``` ### Lazy-loaded routers for serverless cold starts ```ts // server/routers/_app.ts import { lazy } from '@trpc/server'; import { router } from '../trpc'; export const appRouter = router({ // Short-hand when the module has exactly one router exported greeting: lazy(() => import('./greeting.js')), // Use .then() to pick a named export when the module exports multiple routers user: lazy(() => import('./user.js').then((m) => m.userRouter)), }); export type AppRouter = typeof appRouter; ``` ## Common Mistakes ### [CRITICAL] Calling initTRPC.create() more than once Wrong: ```ts // file: userRouter.ts import { initTRPC } from '@trpc/server'; const t = initTRPC.create(); export const userRouter = t.router({}); // file: postRouter.ts import { initTRPC } from '@trpc/server'; const t2 = initTRPC.create(); export const postRouter = t2.router({}); ``` Correct: ```ts // file: trpc.ts (single file, created once) import { initTRPC } from '@trpc/server'; import type { Context } from './context'; const t = initTRPC.context<Context>().create(); export const router = t.router; export const publicProcedure = t.procedure; ``` Multiple tRPC instances cause type mismatches and runtime errors when routers from different instances are merged. Source: www/docs/server/routers.md ### [HIGH] Using reserved words as procedure names Wrong: ```ts import { publicProcedure, router } from './trpc'; const appRouter = router({ then: publicProcedure.query(() => 'hello'), }); ``` Correct: ```ts import { publicProcedure, router } from './trpc'; const appRouter = router({ next: publicProcedure.query(() => 'hello'), }); ``` Router creation throws if procedure names are "then", "call", or "apply" because these conflict with JavaScript Proxy internals. Source: packages/server/src/unstable-core-do-not-import/router.ts ### [CRITICAL] Importing AppRouter as a value import Wrong: ```ts // client.ts import { AppRouter } from '../server/router'; ``` Correct: ```ts // client.ts import type { AppRouter } from '../server/router'; ``` A non-type import pulls the entire server bundle into the client; use `import type` so it is stripped at build time. Source: www/docs/server/routers.md ### [MEDIUM] Creating context without inner/outer split Wrong: ```ts import type { CreateExpressContextOptions } from '@trpc/server/adapters/express'; export function createContext({ req }: CreateExpressContextOptions) { return { db: prisma, user: getUserFromReq(req) }; } ``` Correct: ```ts import type { CreateExpressContextOptions } from '@trpc/server/adapters/express'; export function createContextInner(opts: { user?: User }) { return { db: prisma, user: opts.user ?? null }; } export function createContext({ req }: CreateExpressContextOptions) { return createContextInner({ user: getUserFromReq(req) }); } ``` Without an inner context factory, server-side callers and tests must construct HTTP request objects to get context. Source: www/docs/server/context.md ### [HIGH] Merging routers with different transformers Wrong: ```ts import { initTRPC } from '@trpc/server'; import superjson from 'superjson'; const t1 = initTRPC.create({ transformer: superjson }); const t2 = initTRPC.create(); const router1 = t1.router({ a: t1.procedure.query(() => 'a') }); const router2 = t2.router({ b: t2.procedure.query(() => 'b') }); t1.mergeRouters(router1, router2); ``` Correct: ```ts import { initTRPC } from '@trpc/server'; import superjson from 'superjson'; const t = initTRPC.create({ transformer: superjson }); const router1 = t.router({ a: t.procedure.query(() => 'a') }); const router2 = t.router({ b: t.procedure.query(() => 'b') }); t.mergeRouters(router1, router2); ``` `t.mergeRouters()` throws at runtime if the routers were created with different transformer or errorFormatter configurations. Source: packages/server/src/unstable-core-do-not-import/router.ts ### [CRITICAL] Importing appRouter value into client code Wrong: ```ts // client.ts import { appRouter } from '../server/router'; type AppRouter = typeof appRouter; ``` Correct: ```ts // client.ts import type { AppRouter } from '../server/router'; // server/router.ts export type AppRouter = typeof appRouter; ``` Importing the appRouter value bundles the entire server into the client, even if you only use `typeof`. Source: www/docs/server/routers.md ## See Also - `middlewares` -- add auth, logging, context extension to procedures - `validators` -- add input/output validation with Zod - `error-handling` -- throw and format typed errors - `server-side-calls` -- call procedures from server code - `adapter-standalone` -- mount on Node.js HTTP server - `adapter-fetch` -- mount on edge runtimes
عرض على GitHub