Segmenta использует tRPC v11 для типобезопасного взаимодействия между клиентом и сервером. Это означает, что типы автоматически выводятся из серверных роутеров и доступны на клиенте без кодогенерации.

Архитектура

Клиент (Next.js)

    │  @trpc/react-query
    │  Хуки: trpc.auth.login.useMutation()

Express middleware (@trpc/server/adapters/express)

    │  Контекст: user, services, withDatabase

tRPC-роутеры (packages/trpc/src/routers/)

    │  Zod-валидация входных данных

База данных (Drizzle ORM)

Типы процедур

ТипОписаниеПример
publicProcedureДоступна без авторизацииПолучение списка серверов
protectedProcedureТребует авторизованного пользователяПолучение профиля
adminProcedureТребует права admin.*Управление настройками
moderatorProcedureТребует права tickets.* или moderator.*Управление тикетами

Корневой роутер

Все подроутеры объединяются в packages/trpc/src/routers/index.ts:
router({
  auth,            // Авторизация, регистрация, OAuth
  users,           // Профиль, 2FA, аватары
  servers,         // Minecraft серверы
  news,            // Новости
  settings,        // Настройки сайта
  connections,     // Подключённые аккаунты
  admin,           // Админ-панель
  verification,    // Верификация пользователей
  seo,             // SEO-метаданные
  payments,        // Платежи
  analytics,       // Аналитика
  privileges,      // Привилегии и группы
  rules,           // Правила
  notifications,   // Уведомления
  modules,         // Модули (динамические роутеры)
  team,            // Команда
  shop,            // Магазин
  tickets,         // Тикеты
  site,            // Публичные данные сайта
  votes,           // Голосования
  navigation,      // Навигация
  punishments,     // Наказания (баны, муты, варны)
  launcherAuth,    // Авторизация в лаунчере
})

Использование на клиенте

Запросы (query)

import { trpc } from '@/lib/trpc';

// В React-компоненте
const { data: servers } = trpc.servers.getVisible.useQuery();

// Вне React
const servers = await trpc.servers.getVisible.query();

Мутации

const loginMutation = trpc.auth.login.useMutation();

await loginMutation.mutateAsync({
  login: 'username',
  password: 'password123',
});

Типы

Типы ответов доступны через RouterOutputs:
import type { RouterOutputs } from '@segmenta/trpc';

type User = RouterOutputs['users']['getMy'];
type Server = RouterOutputs['servers']['getAll'][number];

Валидация

Все входные данные валидируются через Zod. При невалидных данных tRPC автоматически возвращает ошибку BAD_REQUEST с описанием проблемы.

Ошибки

tRPC использует стандартные коды ошибок:
КодОписание
UNAUTHORIZEDТребуется авторизация
FORBIDDENНедостаточно прав
NOT_FOUNDРесурс не найден
CONFLICTКонфликт (дубликат)
BAD_REQUESTНевалидные данные
INTERNAL_SERVER_ERRORВнутренняя ошибка сервера