Volver a la documentación
Guía 10

Desarrollo

Guía para contribuir al codebase: setup, estructura monorepo, scripts, convenciones, i18n.

4 min de lectura

Guía para contribuir al codebase: setup, estructura monorepo, scripts, convenciones, i18n.

Setup

bash
git clone <repo> && cd simmetric-chat
pnpm install            # instala las dependencias de todos los packages
cp .env.example .env    # .env raíz = única config runtime; luego edita JWT_SECRET, COLLECTOR_SECRET
pnpm db:generate        # client Prisma (+ fix symlink Prisma 7/pnpm)
pnpm db:migrate         # aplica las migraciones (prisma migrate dev)
pnpm db:seed            # roles, permisos, config, admin bootstrap
pnpm dev                # arranca server/collector/widget/frontend via turborepo

PostgreSQL 16 en local (p. ej. docker compose -f docker/docker-compose.infra.yml up -d postgres). pnpm db:migrate aplica las migraciones Prisma (packages/server/prisma/migrations); pnpm db:seed siembra roles/permisos y el admin bootstrap (admin / admin123, mustChangePassword=true). Las migraciones son additive-only: las destructivas exigen consentimiento explícito (PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION) y pnpm audit:migrations regenera docs/MIGRATION_AUDIT.md para commitear en la misma PR.

Estructura monorepo

pnpm workspaces + Turborepo. 5 package + Tauri:

PackagePuertoStackRol
shared-TS + ZodTipos, schema, constantes (leaf, dep solo zod)
server3000Express + PrismaAPI, RBAC, agent, RAG FTS/RRF, backup
collector3210ExpressIngesta, parsing, embedding, vector store
widget3211Express + Preact IIFEWidget embebible
frontend5173Vite + React 19 + TailwindSPA admin/chat
src-tauri-Rust + TauriDesktop app

Grafo de dependencias: shared ← {server, collector, frontend, widget}. Modularidad strict: server↔collector = HTTP only (COLLECTOR_SECRET); widget↔server = API key (X-Api-Key). Ningún import directo entre server/collector/widget.

Scripts comunes

ScriptScopeDescripción
pnpm devrootTurborepo: arranca todos los servicios en paralelo
pnpm buildrootBuild producción todos los package (depende de ^build)
pnpm lintrootESLint 10 flat config, todos los package
pnpm typecheckrootTypeScript strict mode
pnpm testrootJest (5 proyectos, Postgres-free) via Turborepo
pnpm test:allrootLas mismas 5 suites via jest.config.cjs (Jest puro)
pnpm test:e2erootPlaywright
pnpm db:generaterootRegenera el client Prisma
pnpm db:migrateserverprisma migrate dev
pnpm db:seedserverSeed roles/permisos/config
pnpm audit:migrationsserverAudit de migraciones destructivas → docs/MIGRATION_AUDIT.md
pnpm i18n:checkrootVerifica la paridad de traducciones en 8 locale
pnpm kniprootGate dead-code (archivos/dependencias/exports sin usar)
pnpm license:checkserverVerifica la licencia configurada sin boot del servidor

Scripts por-package en packages/<pkg>/package.json. Turborepo cachea outputs y dependencias entre tasks. pnpm db:generate debe correr antes de build/lint/typecheck/test (la task turbo build depende de ello).

Convenciones de código

  • TypeScript strict en todo; sin any no justificado (target ES2022).
  • Zod para validación de input (shared define schemas reutilizables; valida con safeParse en los route handler → 400 en vez de 500).
  • Prisma como ORM (Prisma 7, driver adapter); schema en packages/server/prisma/schema.prisma. Nunca new PrismaClient(): singleton desde src/utils/prisma (pool driver-adapter + withSoftDelete()).
  • RBAC via middleware: requirePermission, requireAdmin, requireWorkspaceAccess (31 permisos en shared/src/constants/permissions.ts).
  • Error handling: respuestas { error } (400/401/403/404/409/402/429/500); validación Zod → 400 con details; license gating → 402 { error, feature, tier }.
  • SSE para streaming chat (@microsoft/fetch-event-source en el frontend).
  • Logging: env LOG_LEVEL; usa el logger configurado, no console.log directo en prod.
  • Commit: formato Conventional Commits (feat:, fix:, docs:, refactor:...); un cambio lógico por commit; un bullet [Unreleased] en CHANGELOG.md por cada cambio a packages/*/src/** (pnpm changelog:check).

Frontend (React 19)

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

Server (Express)

  • Routes en src/routes/, servicios en src/services/, middleware en src/middleware/.
  • Agent en src/agent/ (orchestrator.ts, builtinSkills.ts, mcpClient.ts).
  • Config env en src/config/env.ts (Zod, process.exit(1) si inválida).
  • OpenAPI via anotaciones @openapi JSDoc → Swagger en /api-docs.
  • Job queue pg-boss (Postgres-backed): 8 cron scheduler (backup, MCP health-check, reaper, synthesis); los pipelines OCR + synthesis permanecen en un poller setInterval 10s. Multi-instance-ready sin infraestructura extra (ver 02 - Architecture).

i18n

8 locale con archivos concretos: en, it, ru, de, fr, es, zh, pt (EN es la baseline; paridad strict - ningún idioma puede quedarse atrás). Añade las claves en los ocho archivos. pnpm i18n:check (frontend + widget) sale 1 con claves faltantes o extra en cualquier locale respecto a en; el check del widget también falla con valores string vacíos. El conjunto locale del widget está pinnado contra ALL_LANGUAGES del frontend por widgetLocalesParity.test.ts - añade/elimina idiomas en ambos sitios a la vez.

Añadir una feature (workflow)

  1. Schema shared - tipos/Zod en packages/shared/src/.
  2. Prisma - modelo + migración (pnpm db:migrate; audit si es destructiva).
  3. Server - servicio + route + middleware RBAC/license.
  4. Frontend - UI + hook + i18n (los 8 idiomas).
  5. Test - unit (mock Prisma) + integration (worker DB) + E2E si es user-facing.
  6. Docs - actualiza docs/ y OpenAPI @openapi; changelog [Unreleased] si toca src/.

Extensiones comunes

  • Nueva skill de agente: registerSkill en server/src/agent/builtinSkills.ts.
  • Nuevo endpoint: route en server/src/routes/ + mount en src/index.ts.
  • Nuevo permiso: PERMISSION_NAMES en shared/src/constants/permissions.ts + roles.
  • Nuevo provider LLM: preset en shared/src/constants/providerPresets.ts (seed en provider_presets) + handler en server/src/agent/llmStreaming.ts + providerService.
  • Nuevo destino backup: implementa IBackupDestinationProvider en los providers backup del plugin Enterprise (services/backup/providers/).