Voltar para a documentação
Guia 10

Desenvolvimento

Guia para contribuir para o codebase: setup, estrutura monorepo, scripts, convenções, i18n.

4 min de leitura

Guia para contribuir para o codebase: setup, estrutura monorepo, scripts, convenções, i18n.

Setup

bash
git clone <repo> && cd simmetric-chat
pnpm install            # instala as dependências de todos os packages
cp .env.example .env    # .env raiz = única config runtime; depois edita JWT_SECRET, COLLECTOR_SECRET
pnpm db:generate        # client Prisma (+ fix symlink Prisma 7/pnpm)
pnpm db:migrate         # aplica as migrações (prisma migrate dev)
pnpm db:seed            # roles, permissões, config, admin bootstrap
pnpm dev                # arranca server/collector/widget/frontend via turborepo

PostgreSQL 16 em local (p. ex. docker compose -f docker/docker-compose.infra.yml up -d postgres). pnpm db:migrate aplica as migrações Prisma (packages/server/prisma/migrations); pnpm db:seed semeia roles/permissões e o admin bootstrap (admin / admin123, mustChangePassword=true). As migrações são additive-only: as destrutivas exigem consentimento explícito (PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION) e pnpm audit:migrations regenera docs/MIGRATION_AUDIT.md para commitar na mesma PR.

Estrutura monorepo

pnpm workspaces + Turborepo. 5 package + Tauri:

PackagePortaStackPapel
shared-TS + ZodTipos, schema, constantes (leaf, dep só zod)
server3000Express + PrismaAPI, RBAC, agent, RAG FTS/RRF, backup
collector3210ExpressIngestão, parsing, embedding, vector store
widget3211Express + Preact IIFEWidget embutível
frontend5173Vite + React 19 + TailwindSPA admin/chat
src-tauri-Rust + TauriDesktop app

Grafo de dependências: shared ← {server, collector, frontend, widget}. Modularidade strict: server↔collector = HTTP only (COLLECTOR_SECRET); widget↔server = API key (X-Api-Key). Nenhum import direto entre server/collector/widget.

Scripts comuns

ScriptScopeDescrição
pnpm devrootTurborepo: arranca todos os serviços em paralelo
pnpm buildrootBuild de produção de todos os package (depende de ^build)
pnpm lintrootESLint 10 flat config, todos os package
pnpm typecheckrootTypeScript strict mode
pnpm testrootJest (5 projetos, Postgres-free) via Turborepo
pnpm test:allrootAs mesmas 5 suites via jest.config.cjs (Jest puro)
pnpm test:e2erootPlaywright
pnpm db:generaterootRegenera o client Prisma
pnpm db:migrateserverprisma migrate dev
pnpm db:seedserverSeed roles/permissões/config
pnpm audit:migrationsserverAudit de migrações destrutivas → docs/MIGRATION_AUDIT.md
pnpm i18n:checkrootVerifica a paridade de traduções em 8 locale
pnpm kniprootGate dead-code (ficheiros/dependências/exports sem uso)
pnpm license:checkserverVerifica a licença configurada sem boot do servidor

Scripts por-package em packages/<pkg>/package.json. Turborepo cacheia outputs e dependências entre tasks. pnpm db:generate tem de correr antes de build/lint/typecheck/test (a task turbo build depende disso).

Convenções de código

  • TypeScript strict em todo o lado; sem any não justificado (target ES2022).
  • Zod para validação de input (shared define schemas reutilizáveis; valida com safeParse nos route handler → 400 em vez de 500).
  • Prisma como ORM (Prisma 7, driver adapter); schema em packages/server/prisma/schema.prisma. Nunca new PrismaClient(): singleton de src/utils/prisma (pool driver-adapter + withSoftDelete()).
  • RBAC via middleware: requirePermission, requireAdmin, requireWorkspaceAccess (31 permissões em shared/src/constants/permissions.ts).
  • Error handling: respostas { error } (400/401/403/404/409/402/429/500); validação Zod → 400 com details; license gating → 402 { error, feature, tier }.
  • SSE para streaming chat (@microsoft/fetch-event-source no frontend).
  • Logging: env LOG_LEVEL; usa o logger configurado, não console.log direto em prod.
  • Commit: formato Conventional Commits (feat:, fix:, docs:, refactor:...); uma alteração lógica por commit; um bullet [Unreleased] em CHANGELOG.md por cada alteração a packages/*/src/** (pnpm changelog:check).

Frontend (React 19)

  • State 3-tier (server-persisted / session / local) - TanStack Query para REST/CRUD, React Context para o estado de UI, fetchEventSource para SSE.
  • shadcn/ui + Tailwind para o admin; o widget usa Preact + Tailwind, NÃO shadcn (bundle IIFE).
  • i18n via hook; ficheiros em packages/frontend/src/i18n/<locale>/translation.json.
  • Shortcuts chat: /model (paleta Cmd+K), comparação Cmd+Shift+M.
  • ESLint: React Compiler + rules-of-hooks error no código; formato de módulo ESM (root + frontend) vs CommonJS (server/collector/shared/widget) - respeita o tsconfig por package.

Server (Express)

  • Routes em src/routes/, serviços em src/services/, middleware em src/middleware/.
  • Agent em src/agent/ (orchestrator.ts, builtinSkills.ts, mcpClient.ts).
  • Config env em src/config/env.ts (Zod, process.exit(1) se inválida).
  • OpenAPI via anotações @openapi JSDoc → Swagger em /api-docs.
  • Job queue pg-boss (Postgres-backed): 8 cron scheduler (backup, MCP health-check, reaper, synthesis); os pipelines OCR + synthesis ficam num poller setInterval 10s. Multi-instance-ready sem infraestrutura extra (ver 02 - Architecture).

i18n

8 locale com ficheiros concretos: en, it, ru, de, fr, es, zh, pt (EN é a baseline; paridade strict - nenhum idioma pode ficar para trás). Adiciona as chaves nos oito ficheiros. pnpm i18n:check (frontend + widget) sai 1 com chaves em falta ou a mais em qualquer locale face a en; o check do widget também falha com valores string vazios. O conjunto locale do widget está pinado contra ALL_LANGUAGES do frontend por widgetLocalesParity.test.ts - adiciona/remove idiomas nos dois sítios ao mesmo tempo.

Adicionar uma feature (workflow)

  1. Schema shared - tipos/Zod em packages/shared/src/.
  2. Prisma - modelo + migração (pnpm db:migrate; audit se destrutiva).
  3. Server - serviço + route + middleware RBAC/license.
  4. Frontend - UI + hook + i18n (os 8 idiomas).
  5. Test - unit (mock Prisma) + integration (worker DB) + E2E se user-facing.
  6. Docs - atualiza docs/ e OpenAPI @openapi; changelog [Unreleased] se tocar src/.

Extensões comuns

  • Nova skill de agente: registerSkill em server/src/agent/builtinSkills.ts.
  • Novo endpoint: route em server/src/routes/ + mount em src/index.ts.
  • Nova permissão: PERMISSION_NAMES em shared/src/constants/permissions.ts + roles.
  • Novo provider LLM: preset em shared/src/constants/providerPresets.ts (seed em provider_presets) + handler em server/src/agent/llmStreaming.ts + providerService.
  • Novo destino backup: implementa IBackupDestinationProvider nos providers backup do plugin Enterprise (services/backup/providers/).