К документации
Руководство 10

Разработка

Руководство для контрибьюторов в codebase: setup, структура monorepo, скрипты, конвенции, i18n.

3 мин чтения

Руководство для контрибьюторов в codebase: setup, структура monorepo, скрипты, конвенции, i18n.

Setup

bash
git clone <repo> && cd simmetric-chat
pnpm install            # устанавливает зависимости всех package
cp .env.example .env    # корневой .env = единственный runtime config; затем отредактируй JWT_SECRET, COLLECTOR_SECRET
pnpm db:generate        # Prisma client (+ fix symlink Prisma 7/pnpm)
pnpm db:migrate         # применяет миграции (prisma migrate dev)
pnpm db:seed            # роли, разрешения, config, bootstrap admin
pnpm dev                # запускает server/collector/widget/frontend через turborepo

PostgreSQL 16 локально (например, docker compose -f docker/docker-compose.infra.yml up -d postgres). pnpm db:migrate применяет миграции Prisma (packages/server/prisma/migrations); pnpm db:seed сеет роли/разрешения и bootstrap admin (admin / admin123, mustChangePassword=true). Миграции additive-only: деструктивные требуют явного согласия (PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION), и pnpm audit:migrations регенерирует docs/MIGRATION_AUDIT.md для коммита в той же PR.

Структура monorepo

pnpm workspaces + Turborepo. 5 package + Tauri:

PackageПортStackРоль
shared-TS + ZodТипы, schema, константы (leaf, зависимость только zod)
server3000Express + PrismaAPI, RBAC, agent, RAG FTS/RRF, backup
collector3210ExpressИнгестия, parsing, embedding, vector store
widget3211Express + Preact IIFEВстраиваемый виджет
frontend5173Vite + React 19 + TailwindSPA admin/chat
src-tauri-Rust + TauriDesktop-приложение

Граф зависимостей: shared ← {server, collector, frontend, widget}. Строгая модульность: server↔collector = только HTTP (COLLECTOR_SECRET); widget↔server = API key (X-Api-Key). Никаких прямых импортов между server/collector/widget.

Общие скрипты

СкриптScopeОписание
pnpm devrootTurborepo: запускает все сервисы параллельно
pnpm buildrootПродакшен-сборка всех package (зависит от ^build)
pnpm lintrootESLint 10 flat config, все package
pnpm typecheckrootTypeScript strict mode
pnpm testrootJest (5 проектов, Postgres-free) через Turborepo
pnpm test:allrootТе же 5 suite через jest.config.cjs (чистый Jest)
pnpm test:e2erootPlaywright
pnpm db:generaterootРегенерирует Prisma client
pnpm db:migrateserverprisma migrate dev
pnpm db:seedserverSeed ролей/разрешений/config
pnpm audit:migrationsserverАудит деструктивных миграций → docs/MIGRATION_AUDIT.md
pnpm i18n:checkrootПроверяет паритет переводов по 8 locale
pnpm kniprootDead-code gate (неиспользуемые файлы/зависимости/export)
pnpm license:checkserverПроверяет настроенную лицензию без boot сервера

Скрипты по package в packages/<pkg>/package.json. Turborepo кэширует output и зависимости между task'ами. pnpm db:generate должен выполняться до build/lint/typecheck/test (task turbo build зависит от него).

Конвенции кода

  • TypeScript strict везде; никаких необоснованных any (target ES2022).
  • Zod для валидации входа (shared определяет переиспользуемые schema; валидируй safeParse в route handler → 400 вместо 500).
  • Prisma как ORM (Prisma 7, driver adapter); schema в packages/server/prisma/schema.prisma. Никогда new PrismaClient(): singleton из src/utils/prisma (driver-adapter pool + withSoftDelete()).
  • RBAC через middleware: requirePermission, requireAdmin, requireWorkspaceAccess (31 разрешение в shared/src/constants/permissions.ts).
  • Error handling: ответы { error } (400/401/403/404/409/402/429/500); Zod-валидация → 400 с details; license gating → 402 { error, feature, tier }.
  • SSE для стриминга чата (@microsoft/fetch-event-source на фронтенде).
  • Logging: env LOG_LEVEL; используй настроенный logger, не прямой console.log в prod.
  • Commit: формат Conventional Commits (feat:, fix:, docs:, refactor:...); одно логическое изменение на commit; bullet [Unreleased] в CHANGELOG.md на каждое изменение packages/*/src/** (pnpm changelog:check).

Frontend (React 19)

  • 3-tier state (server-persisted / session / local) - TanStack Query для REST/CRUD, React Context для UI-состояния, fetchEventSource для SSE.
  • shadcn/ui + Tailwind для admin; виджет использует Preact + Tailwind, НЕ shadcn (IIFE bundle).
  • i18n через hook; файлы в packages/frontend/src/i18n/<locale>/translation.json.
  • Chat shortcuts: /model (палитра Cmd+K), сравнение Cmd+Shift+M.
  • ESLint: React Compiler + rules-of-hooks error в исходниках; формат модулей ESM (root + frontend) vs CommonJS (server/collector/shared/widget) - соблюдай tsconfig каждого package.

Server (Express)

  • Routes в src/routes/, сервисы в src/services/, middleware в src/middleware/.
  • Agent в src/agent/ (orchestrator.ts, builtinSkills.ts, mcpClient.ts).
  • Config env в src/config/env.ts (Zod, process.exit(1) при невалидных значениях).
  • OpenAPI через @openapi JSDoc-аннотации → Swagger на /api-docs.
  • Job queue pg-boss (Postgres-backed): 8 cron scheduler (backup, MCP health-check, reaper, synthesis); пайплайны OCR + synthesis остаются на setInterval 10s poller. Multi-instance-ready без дополнительной инфраструктуры (см. 02 - Architecture).

i18n

8 locale с конкретными файлами: en, it, ru, de, fr, es, zh, pt (EN - baseline; строгий паритет - ни один язык не может отставать). Добавляй ключи во все восемь файлов. pnpm i18n:check (frontend + widget) выходит 1 при отсутствующих или лишних ключах в любом locale относительно en; widget check также падает на пустых строковых значениях. Набор locale виджета запинован против ALL_LANGUAGES фронтенда через widgetLocalesParity.test.ts - добавляй/удаляй языки в обоих местах вместе.

Добавление функции (workflow)

  1. Shared schema - типы/Zod в packages/shared/src/.
  2. Prisma - модель + миграция (pnpm db:migrate; audit если деструктивная).
  3. Server - сервис + route + middleware RBAC/license.
  4. Frontend - UI + hook + i18n (все 8 языков).
  5. Test - unit (Prisma mock) + integration (worker DB) + E2E если user-facing.
  6. Docs - обнови docs/ и OpenAPI @openapi; changelog [Unreleased] если затрагивает src/.

Частые расширения

  • Новый agent skill: registerSkill в server/src/agent/builtinSkills.ts.
  • Новый endpoint: route в server/src/routes/ + mount в src/index.ts.
  • Новое разрешение: PERMISSION_NAMES в shared/src/constants/permissions.ts + роли.
  • Новый LLM provider: preset в shared/src/constants/providerPresets.ts (seed в provider_presets) + handler в server/src/agent/llmStreaming.ts + providerService.
  • Новое назначение backup: реализуй IBackupDestinationProvider в backup-провайдерах Enterprise-плагина (services/backup/providers/).