tRPC serveri konstruktor kimi yığılır: initTRPC hazırlıq yaradır, router procedure-ləri toplayır, procedure isə addımlar zəncirdir (giriş yoxlaması, middleware, sizin kodunuz), adapter isə hamısını HTTP-yə qoşur. Bu dərsdə hər hissəni qeydlər serveri nümunəsində araşdıracağıq — modulun sonunda məhz bu server layihəyə çevriləcək.

Kontekst: hər procedure-ə nə lazımdır

Hər sorğunun öz «əşyaları» var: verilənlər bazasına qoşulma, kimin daxil olduğu haqqında məlumat, başlıqlar. Bütün bunlar kontekstdə (ctx) toplanır — hər sorğu üçün yenidən yaradılan və hər procedure-ə düşən obyektdə. Bənzətmə: ofisdə ziyarətçi nişanı. Hər ziyarətçinin (sorğunun) nişanı fərdidir, hər əməkdaş (procedure) kiminlə işlədiyini anlamaq üçün ona baxır.

ts
// server/context.ts
import { db } from './db';
import { getUserId } from './auth'; // your own function: session, JWT, cookie

export async function createContext(opts: { headers: Headers }) {
  return {
    db,
    userId: await getUserId(opts.headers), // string | null
  };
}

export type Context = Awaited<ReturnType<typeof createContext>>;

getUserId-in içində nə olması sizdən asılıdır: Auth.js sessiyası, başlıqdakı JWT, cookie. Kontekstin tipini TypeScript funksiyanın qaytardığı dəyərdən götürür — onu əllə yazmaq lazım deyil.

💡 Next.js üçün tRPC sənədlərində belə funksiya createTRPCContext adlanır. Amma eyni adlı funksiya @trpc/tanstack-react-query-də də var, ona görə kursda öz funksiyamızı createContext adlandırırıq — qarışmamaq üçün.

initTRPC: serverin hazırlığı

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;
export const createCallerFactory = t.createCallerFactory;

initTRPC.context<Context>().create() t obyektini yaradır — tikinti hissələri dəsti. Biz yalnız lazım olanları ixrac edirik: router (procedure-ləri toplayır), publicProcedure (istənilən şəxsin çağıra biləcəyi procedure) və createCallerFactory (serverdə çağırışlar və testlər üçün lazım olacaq). t-nin özünü kənara vermirik ki, bütün fayllar eyni dəstdən istifadə etsin.

Procedure-lər: query və mutation

Procedure — konveyerdir: çağırış addımlardan ardıcıl keçir və istənilən addım onu xəta ilə dayandıra bilər.

Çağırışın yolu: kontekst, middleware, giriş yoxlaması, resolver, cavab; xətalar konveyeri kəsir
Çağırışın yolu: kontekst, middleware, giriş yoxlaması, resolver, cavab; xətalar konveyeri kəsir

Procedure zəncirlə yığılır: publicProcedure-dən başlayırıq, addımlar əlavə edirik (.input(...), .use(...)) və .query(...) ya da .mutation(...) ilə bitiririk — bu, resolver-dir, yəni sizin funksiyanızdır.