first commit
This commit is contained in:
93
docs/06-desarrollo.md
Normal file
93
docs/06-desarrollo.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# 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`:
|
||||
|
||||
```sh
|
||||
npm config set //nexus.pireon.dev/repository/npm-releases/:_authToken "<token>"
|
||||
```
|
||||
|
||||
## 6.2 Puesta en marcha
|
||||
|
||||
```sh
|
||||
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
|
||||
|
||||
1. **Dominio** (`libs/api/tracker/domain`)
|
||||
- Evento `issue-blocked.event.ts` con `@AutowiredEvent`, que extiende `TrackerEvent`.
|
||||
- En `Issue`, el método `block(actorId, reason)` valida y hace `this.apply(new IssueBlockedEvent(…))`; el handler
|
||||
`onIssueBlockedEvent(event)` cambia el estado.
|
||||
- Test en `issue.spec.ts`, incluida la reconstrucción desde el historial (`replay`).
|
||||
2. **Aplicación** (`libs/api/tracker/application`)
|
||||
- `commands/block-issue.command.ts` y `block-issue.command-handler.ts`: rehidratar (`WriteAccess`), llamar al
|
||||
dominio y `commitAndWait()`. Registrar el handler en `command-handlers.ts`.
|
||||
- Método en `IssuesService`.
|
||||
- Proyección `event-handlers/issue-blocked.event-handler.ts` (`@EventsHandler`) que actualiza el read model y avisa
|
||||
por `ReadModelNotifier`. Añadir el evento al `ActivityEventHandler` y una frase en `activity-summary.ts`.
|
||||
- Si el read model cambia, añadir el campo a `IssueReadModel` (dominio) y al esquema Mongo (infraestructura).
|
||||
3. **Presenters** (`libs/api/tracker/presenters`): input y mutation `blockIssue` en `IssueResolver`, que llama al service.
|
||||
4. Arrancar la API para regenerar `apps/api/schema.gql`.
|
||||
|
||||
### Web
|
||||
|
||||
5. `npx nx run web:codegen` tras añadir la mutation a `issues.graphql`.
|
||||
6. **Dominio**: método en el puerto `IssuesGateway`. **Infraestructura**: implementarlo en `GraphqlIssuesGateway`.
|
||||
7. **Aplicación**: evento `blockRequested` en `issuePageEvents`, su efecto en `IssueStore` (`runCommand`) y el método
|
||||
`block(reason)` en `IssueFacade`.
|
||||
8. **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 |
|
||||
Reference in New Issue
Block a user