6.7 KiB
6. Desarrollo
6.1 Requisitos
-
Node 22 y npm 10.
-
Docker (PostgreSQL, MongoDB y Redis).
-
Acceso al Nexus de Pireon para
@pi/ui. El scope está en.npmrc(sin token); el token va en tu~/.npmrc:npm config set //nexus.pireon.dev/repository/npm-releases/:_authToken "<token>"
6.2 Puesta en marcha
npm install
docker compose up -d postgres mongo redis
cp .env.example .env # ajusta PIREON_*
npx nx serve api # http://localhost:3000 (GraphiQL en /graphql)
npx nx serve web # http://localhost:4200
nx serve web usa apps/web/proxy.conf.json para enviar /api y /graphql (también el WebSocket) a la API, así que
la web y la API comparten origen igual que en Docker.
6.3 Comandos
| Comando | Qué hace |
|---|---|
npx nx run-many -t lint |
Lint de todo, incluidas las reglas de capas y contextos |
npx nx run-many -t test |
Tests unitarios (dominio y aplicación, API y web) |
npx nx e2e api |
Flujo completo de la API contra Docker, con Pireon simulado |
npx nx run-many -t build |
Builds de la API y la web |
npx nx run web:codegen |
Regenera los tipos GraphQL del cliente desde apps/api/schema.gql |
npx nx run api:prune |
Build de la API con package.json y lockfile podados (lo usa Docker) |
npx nx graph |
Grafo de dependencias entre proyectos |
npx nx test api-tracker-domain |
Tests de una librería concreta (api-<contexto>-<capa>, web-<contexto>-<capa>) |
Tests
| Dónde | Qué se prueba | Herramienta |
|---|---|---|
api/*/domain |
Reglas de los agregados y reconstrucción desde el historial de eventos | Jest |
api/*/application |
Commands contra un event store en memoria (incluida la concurrencia) | Jest + @nestjs/testing |
apps/api/e2e |
Todo el flujo: GraphQL → Postgres → Redis → Mongo → subscriptions | Jest contra Docker |
web/*/domain, web/*/application |
Sesión y reducers del tablero | Jest / Vitest |
apps/web |
Rutas y guards | Vitest |
El e2e sustituye a Pireon por usuarios fijos (token-ana, token-bob…) con overrideProvider(IdentityProvider); el
resto de la pila es real.
6.4 Cómo añadir una funcionalidad
Ejemplo: marcar un ticket como bloqueado con un motivo. El recorrido es siempre el mismo, de dentro hacia fuera.
API
- Dominio (
libs/api/tracker/domain)- Evento
issue-blocked.event.tscon@AutowiredEvent, que extiendeTrackerEvent. - En
Issue, el métodoblock(actorId, reason)valida y hacethis.apply(new IssueBlockedEvent(…)); el handleronIssueBlockedEvent(event)cambia el estado. - Test en
issue.spec.ts, incluida la reconstrucción desde el historial (replay).
- Evento
- Aplicación (
libs/api/tracker/application)commands/block-issue.command.tsyblock-issue.command-handler.ts: rehidratar (WriteAccess), llamar al dominio ycommitAndWait(). Registrar el handler encommand-handlers.ts.- Método en
IssuesService. - Proyección
event-handlers/issue-blocked.event-handler.ts(@EventsHandler) que actualiza el read model y avisa porReadModelNotifier. Añadir el evento alActivityEventHandlery una frase enactivity-summary.ts. - Si el read model cambia, añadir el campo a
IssueReadModel(dominio) y al esquema Mongo (infraestructura).
- Presenters (
libs/api/tracker/presenters): input y mutationblockIssueenIssueResolver, que llama al service. - Arrancar la API para regenerar
apps/api/schema.gql.
Web
npx nx run web:codegentras añadir la mutation aissues.graphql.- Dominio: método en el puerto
IssuesGateway. Infraestructura: implementarlo enGraphqlIssuesGateway. - Aplicación: evento
blockRequestedenissuePageEvents, su efecto enIssueStore(runCommand) y el métodoblock(reason)enIssueFacade. - Presenters: botón y formulario en la página del ticket que llaman a
facade.block(reason).
El lint impide atajos: si un resolver intenta usar un repositorio o una página intenta usar Apollo, falla. Y como application solo
exporta facades, una página tampoco puede tocar un store ni despachar eventos por su cuenta.
6.5 Problemas conocidos
| Síntoma | Causa y solución |
|---|---|
npm install falla con Cannot read properties of null (reading 'edgesOut') |
Bug de npm con un peer opcional de Vite que arrastra vitest 5. El overrides de package.json fija vitest; no lo quites |
401 al instalar @pi/ui |
Falta el token del Nexus en ~/.npmrc |
nx serve web arranca en el puerto 3000 |
Nx carga el .env raíz (PORT=3000) en todas las tareas; apps/web/.env lo fija en 4200 |
| La API no ve un evento nuevo al deserializar | La clase del evento no tiene @AutowiredEvent o no se importa |
Un componente de @pi/ui lanza Unable to find icon |
Falta registrar ese icono en libs/web/shared/ui/src/lib/icons.ts |
Tablas antiguas (projects, issues, outbox) en tu Postgres local |
Restos de una versión anterior sin event sourcing; docker compose down -v empieza de cero |