@ronaldjdevfs/forge 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +130 -8
  2. package/package.json +2 -2
  3. package/skills/forge/SKILL.md +86 -15
  4. package/skills/forge/profiles/express-drizzle.md +107 -0
  5. package/skills/forge/profiles/fastify-mongodb.md +103 -0
  6. package/skills/forge/profiles/fastify-prisma.md +81 -0
  7. package/skills/forge/profiles/nestjs-mongodb.md +92 -0
  8. package/skills/forge/profiles/nestjs-postgres.md +98 -0
  9. package/skills/forge/reference/api-design.md +62 -0
  10. package/skills/forge/reference/assay.md +82 -0
  11. package/skills/forge/reference/cast.md +81 -7
  12. package/skills/forge/reference/data-patterns.md +86 -0
  13. package/skills/forge/reference/di-strategies.md +50 -0
  14. package/skills/forge/reference/errors.md +65 -0
  15. package/skills/forge/reference/events.md +95 -0
  16. package/skills/forge/reference/help.md +40 -0
  17. package/skills/forge/reference/hooks.md +62 -0
  18. package/skills/forge/reference/observability.md +66 -0
  19. package/skills/forge/reference/patterns.md +52 -0
  20. package/skills/forge/reference/principles.md +6 -0
  21. package/skills/forge/reference/reforge.md +69 -5
  22. package/skills/forge/reference/relocate.md +15 -2
  23. package/skills/forge/reference/security-patterns.md +87 -0
  24. package/skills/forge/reference/testing-patterns.md +69 -0
  25. package/skills/forge/scripts/assay.mjs +481 -0
  26. package/skills/forge/scripts/context.mjs +147 -43
  27. package/skills/forge/scripts/detect.mjs +371 -22
  28. package/skills/forge/scripts/forge-api.mjs +373 -0
  29. package/skills/forge/scripts/forge-config.mjs +268 -0
  30. package/skills/forge/scripts/forge-signals.mjs +131 -0
  31. package/skills/forge/scripts/forge-state.mjs +97 -0
  32. package/skills/forge/scripts/formatter.mjs +133 -0
  33. package/skills/forge/scripts/graph.mjs +5 -21
  34. package/skills/forge/scripts/hook.mjs +250 -0
  35. package/skills/forge/scripts/inspect.mjs +171 -22
  36. package/skills/forge/scripts/parse-imports.mjs +249 -0
  37. package/skills/forge/scripts/pin.mjs +151 -0
  38. package/skills/forge/scripts/posttool.mjs +224 -0
  39. package/skills/forge/scripts/profile.mjs +124 -20
  40. package/skills/forge/scripts/registry/rules.mjs +344 -0
  41. package/skills/forge/scripts/rename.mjs +669 -0
  42. package/skills/forge/scripts/rollback.mjs +213 -0
  43. package/skills/forge/scripts/update.mjs +114 -0
  44. package/skills/forge/templates/feature/domain-error.ts.md +9 -0
  45. package/skills/forge/templates/feature/domain-event.ts.md +9 -0
  46. package/skills/forge/templates/feature/event-handler.ts.md +10 -0
  47. package/skills/forge/templates/feature/use-case.ts.md +10 -2
  48. package/skills/forge/tests/core.test.mjs +403 -0
package/README.md CHANGED
@@ -46,7 +46,7 @@ Los proyectos backend degeneran en código acoplado porque la infraestructura t
46
46
  Detecta el stack tecnológico, ejecuta bootstrap de platform/shared/infra si no existen, determina el perfil activo, analiza ownership y prepara el proyecto. Crea `ARCHITECTURE.md` si no existe.
47
47
 
48
48
  ```
49
- Boot sequence: context → bootstrap → profile → armorergraphchaininscribe
49
+ Boot sequence: context → armorer → profile → graphchaininspectarchitecture → execute → architecture
50
50
  ```
51
51
 
52
52
  ### `cast` — Crear feature
@@ -143,6 +143,99 @@ src/shared/
143
143
  └── utils/ # <util>.ts (formatDate, pagination)
144
144
  ```
145
145
 
146
+ ### `assay` — Ensayo multi-persona
147
+
148
+ Evalúa la arquitectura desde 5 perspectivas distintas:
149
+
150
+ | Persona | Enfoque |
151
+ |---------|---------|
152
+ | **Jeff Bezos** | Acoplamiento, escalabilidad, equipos autónomos (API mandate) |
153
+ | **Martin Fowler** | Refactoring, deuda técnica, microservicios vs monolitos |
154
+ | **Hacker** | Seguridad, performance, edge cases, vulnerabilidades |
155
+ | **Alex (PM)** | Tiempo de entrega, complejidad, ROI técnico |
156
+ | **Dra. Carter** | Dependencias cíclicas, violaciones de capas, salud estructural |
157
+
158
+ ```
159
+ forge assay # Ensayo completo (5 personas)
160
+ forge assay --persona=bezos # Solo Bezos
161
+ forge assay --persona=fowler # Solo Fowler
162
+ forge assay --save # Persiste en .forge/assay/
163
+ forge assay --json # Salida JSON
164
+ ```
165
+
166
+ ### `nail / unnail` — Shortcuts de navegación
167
+
168
+ Fija rutas del proyecto como atajos para acceso rápido:
169
+
170
+ ```
171
+ nail src/features/auth # Crea atajo "auth"
172
+ nail src/platform/config # Crea atajo "config"
173
+ nail --list # Lista atajos
174
+ unnail auth # Elimina atajo
175
+ ```
176
+
177
+ ### `forge state` — Estado persistente
178
+
179
+ Muestra y guarda el estado post-auditoría:
180
+
181
+ ```
182
+ forge state # Último score, grade, violaciones
183
+ forge state --show # Estado detallado
184
+ forge state --json # Salida JSON
185
+ forge state --history # Histórico de auditorías
186
+ ```
187
+
188
+ ### `forge hook` — Git pre-commit hook
189
+
190
+ Instala un hook pre-commit que valida la arquitectura en cada commit:
191
+
192
+ ```
193
+ forge hook install # Instalar hook
194
+ forge hook status # Ver estado
195
+ forge hook check # Validar archivos staged
196
+ forge hook uninstall # Eliminar hook
197
+ ```
198
+
199
+ ### `forge rollback` — Restauración
200
+
201
+ Restaura el proyecto a un punto anterior:
202
+
203
+ ```
204
+ forge rollback # Último checkpoint
205
+ forge rollback --list # Lista checkpoints
206
+ forge rollback --id <checkpoint> # Restaurar específico
207
+ ```
208
+
209
+ ### `forge update` — Actualización
210
+
211
+ Verifica si hay una nueva versión de Forge disponible.
212
+
213
+ ### Inline Ignores
214
+
215
+ Forge soporta excepciones línea por línea para reglas arquitectónicas:
216
+
217
+ ```ts
218
+ // forge-ignore-next-line
219
+ import { something } from "../infra/prisma"; // ← no se reporta
220
+
221
+ // forge-ignore: R1
222
+ import { PrismaClient } from "../../infra/prisma/client"; // ← solo R1 ignorada
223
+
224
+ // forge-ignore: R1, R8
225
+ import { crossFeature } from "../other-feature/domain/Entity"; // ← R1 y R8 ignoradas
226
+ ```
227
+
228
+ Usar `quench --show-ignores` para listar todos los ignores en el código.
229
+
230
+ ### Flags adicionales
231
+
232
+ | Flag | Comando | Descripción |
233
+ |------|---------|-------------|
234
+ | `--fix` | `quench` | Auto-corrige violaciones WARNING/INFO (missing @injectable(), tsconfig, naming, container.resolve) |
235
+ | `--show-ignores` | `quench` | Muestra los inline ignores encontrados en el código |
236
+ | `--persona=<id>` | `assay` | Filtra ensayo por una persona (bezos, fowler, hacker, pm, senior) |
237
+ | `--save` | `assay` | Persiste ensayo en `.forge/assay/` |
238
+
146
239
  ---
147
240
 
148
241
  ## Modelo arquitectónico
@@ -224,7 +317,12 @@ Ver `reference/patterns.md` para el detalle completo.
224
317
  | `express-mongodb` | Express | MongoDB | Mongoose | tsyringe |
225
318
  | `express-postgres` | Express | PostgreSQL | raw pg | Manual |
226
319
  | `express-prisma` | Express | PostgreSQL | Prisma | tsyringe |
320
+ | `express-drizzle` | Express | PostgreSQL | Drizzle | tsyringe |
321
+ | `fastify-mongodb` | Fastify | MongoDB | Mongoose | Manual |
227
322
  | `fastify-postgres` | Fastify | PostgreSQL | Prisma | Manual |
323
+ | `fastify-prisma` | Fastify | PostgreSQL | Prisma | Manual |
324
+ | `nestjs-mongodb` | NestJS | MongoDB | Mongoose | NestJS DI |
325
+ | `nestjs-postgres` | NestJS | PostgreSQL | Prisma | NestJS DI |
228
326
  | `nestjs-prisma` | NestJS | PostgreSQL | Prisma | NestJS DI |
229
327
 
230
328
  Cada perfil define estructura de directorios, setup de DI, routing, persistencia, testing y naming conventions.
@@ -251,17 +349,33 @@ Donde vive toda la inteligencia arquitectónica:
251
349
  | `scripts/profile.mjs` | Matchea stack contra perfiles conocidos o sintetiza uno genérico |
252
350
  | `scripts/graph.mjs` | Grafo completo: 6 tipos de nodo, 4 capas, 9 reglas (R1-R9), risk score, dependency health |
253
351
  | `scripts/chain.mjs` | Grafo multi-capa (platform, features, shared, infra) con orden topológico |
254
- | `scripts/detect.mjs` | 6 categorías de chequeo arquitectónico (110 pts) |
352
+ | `scripts/detect.mjs` | Validación de reglas R1-R9 con inline ignores y `--fix` |
255
353
  | `scripts/inspect.mjs` | Orquesta auditoría completa con reporte coloreado |
256
354
  | `scripts/architecture.mjs` | Genera/actualiza `ARCHITECTURE.md` vivo |
257
355
  | `scripts/bootstrap.mjs` | Inicializa platform/shared/infra según perfil (interno) |
356
+ | `scripts/formatter.mjs` | Output unificado: colores, JSON, scoreBar, formatCheck |
357
+ | `scripts/registry/rules.mjs` | Registry de reglas R1-R9 + custom rules desacoplado |
358
+ | `scripts/assay.mjs` | Ensayo multi-persona (Bezos, Fowler, Hacker, PM, Arquitecta) |
359
+ | `scripts/posttool.mjs` | PostToolUse hook con `--reminder` y `--strict` |
360
+ | `scripts/forge-config.mjs` | Persistencia de config, estado e histórico |
361
+ | `scripts/forge-state.mjs` | CLI wrapper de estado post-auditoría |
362
+ | `scripts/forge-signals.mjs` | Manejo de señales (SIGINT, SIGTERM) |
363
+ | `scripts/forge-api.mjs` | Validación de contratos API |
364
+ | `scripts/hook.mjs` | Gestión de git pre-commit hook |
365
+ | `scripts/pin.mjs` | Shortcuts de navegación (`nail`/`unnail`) |
366
+ | `scripts/rollback.mjs` | Restauración de puntos de guardado |
367
+ | `scripts/rename.mjs` | Renombrado bulk de componentes |
368
+ | `scripts/parse-imports.mjs` | Parsing de imports ESM |
369
+ | `scripts/update.mjs` | Verificador de actualizaciones |
258
370
  | `reference/` | Documentación detallada de cada comando y principios |
259
371
  | `reference/patterns.md` | Convenciones de nomenclatura globales |
260
- | `profiles/` | Convenciones por stack tecnológico |
261
- | `templates/feature/` | Templates TypeScript para features |
262
- | `templates/platform/` | Templates para componentes de platform |
263
- | `templates/shared/` | Templates para shared (errors, contracts, types, utils) |
264
- | `templates/infra/` | Templates para infra (prisma, mongodb, redis, mail) |
372
+ | `reference/assay.md` | Documentación del comando assay |
373
+ | `reference/hooks.md` | Documentación del sistema de hooks |
374
+ | `profiles/` | 10 perfiles tecnológicos detallados |
375
+ | `templates/feature/` | 11 templates TypeScript para features |
376
+ | `templates/platform/` | 6 templates para componentes de platform |
377
+ | `templates/shared/` | 4 templates para shared (errors, contracts, types, utils) |
378
+ | `templates/infra/` | 4 templates para infra (prisma, mongodb, redis, mail) |
265
379
 
266
380
  ---
267
381
 
@@ -297,7 +411,7 @@ forge install -g # global
297
411
 
298
412
  ## Uso
299
413
 
300
- Una vez instalada, OpenCode carga automáticamente la skill `forge` al trabajar en el proyecto. Los comandos se invocan por lenguaje natural:
414
+ Una vez instalada, OpenCode carga automáticamente la skill `forge` al trabajar en el proyecto. Usa `forge --help` para ver la lista completa de comandos. Los comandos también se invocan por lenguaje natural:
301
415
 
302
416
  | Lenguaje natural | Comando |
303
417
  |---|---|
@@ -311,6 +425,14 @@ Una vez instalada, OpenCode carga automáticamente la skill `forge` al trabajar
311
425
  | "cadena", "grafo", "acoplamiento" | `chain` |
312
426
  | "inscribir", "grabar", "ARCHITECTURE.md" | `inscribe` |
313
427
  | "fundir", "compartir", "mover a shared" | `smelt` |
428
+ | "examinar", "calidad", "opinión", "critique" | `assay` |
429
+ | "fijar", "pinar", "shortcut" | `nail` |
430
+ | "desfijar", "despinar" | `unnail` |
431
+ | "estado", "state", "último audit" | `forge state --show` |
432
+ | "hook", "pre-commit", "githook" | `forge hook` |
433
+ | "api", "contrato", "openapi", "swagger" | `forge api` |
434
+ | "rollback", "restaurar", "deshacer" | `forge rollback` |
435
+ | "actualizar", "update", "nueva versión" | `forge update` |
314
436
 
315
437
  ---
316
438
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@ronaldjdevfs/forge",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Forge — Architecture Operating System for backend systems. Arquitectura Hexagonal, DDD pragmático y vertical slices.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "forge": "./src/cli.js"
7
+ "forge": "src/cli.js"
8
8
  },
9
9
  "files": [
10
10
  "src/",
@@ -100,6 +100,7 @@ inspect=$(node .opencode/skills/forge/scripts/inspect.mjs --json 2>/dev/null)
100
100
 
101
101
  | Lenguaje natural | Comando | Archivo |
102
102
  |---|---|---|
103
+ | "ayuda", "help", "comandos", "lista", "--help" | `forge --help` | `reference/help.md` |
103
104
  | "inicializar", "setup", "empezar" | `forge` | `reference/forge.md` |
104
105
  | "crear feature", "nuevo dominio" | `cast` | `reference/cast.md` |
105
106
  | "inspeccionar", "diagnóstico", "evaluar" | `inspect` | `reference/inspect.md` |
@@ -112,6 +113,13 @@ inspect=$(node .opencode/skills/forge/scripts/inspect.mjs --json 2>/dev/null)
112
113
  | "grafo", "graph", "nodo", "violaciones", "risk score" | `graph` | `scripts/graph.mjs` |
113
114
  | "fundir", "compartir", "mover a shared" | `smelt` | `reference/smelt.md` |
114
115
  | "ownership", "huérfanos", "armorer" | `inspect` | (incluido en auditoría) |
116
+ | "fijar", "pinar", "atajo", "shortcut" | `nail` | `scripts/pin.mjs` |
117
+ | "desfijar", "despinar", "remover atajo" | `unnail` | `scripts/pin.mjs` |
118
+ | "hook", "pre-commit", "githook", "validar commit" | `forge hook` | `reference/hooks.md` |
119
+ | "api", "contrato", "openapi", "swagger", "graphql" | `forge api` | `scripts/forge-api.mjs` |
120
+ | "rollback", "restaurar", "deshacer", "backup" | `forge rollback` | `scripts/rollback.mjs` |
121
+ | "estado", "state", "último audit" | `forge state --show` | `scripts/forge-state.mjs` |
122
+ | "examinar","calidad", "assay", "opinión", "personas", "critique", "evaluación cualitativa" | `assay` | `reference/assay.md` |
115
123
 
116
124
  ---
117
125
 
@@ -140,6 +148,23 @@ Para cada comando, Forge sigue este flujo:
140
148
  - Si `ARCHITECTURE.md` está desactualizado (fecha de auditoría > 7 días), sugerir `forge inscribe`.
141
149
  - Todos los resultados se muestran con severidades: `[CRITICAL]`, `[ERROR]`, `[WARNING]`, `[INFO]`, `[SUGGESTION]`.
142
150
 
151
+ ### Inline Ignores
152
+
153
+ Forge soporta comentarios inline para excepcionar violaciones línea por línea:
154
+
155
+ ```ts
156
+ // forge-ignore-next-line
157
+ import { something } from "../infra/prisma"; // ← esta línea no se reporta
158
+
159
+ // forge-ignore: R1
160
+ import { PrismaClient } from "../../infra/prisma/client"; // ← solo R1 ignorada
161
+
162
+ // forge-ignore: R1, R8
163
+ import { crossFeature } from "../other-feature/domain/Entity"; // ← R1 y R8 ignoradas
164
+ ```
165
+
166
+ ---
167
+
143
168
  ## ARCHITECTURE.md
144
169
 
145
170
  Forge mantiene un archivo `ARCHITECTURE.md` en la raíz del proyecto con el contexto persistente. Contiene:
@@ -147,15 +172,15 @@ Forge mantiene un archivo `ARCHITECTURE.md` en la raíz del proyecto con el cont
147
172
  ```md
148
173
  # Architecture State
149
174
 
150
- Project Name: <name>
151
- Framework: <detectado>
152
- Runtime: <detectado>
153
- Database: <detectado>
154
- ORM: <detectado>
155
- DI Strategy: <detectado>
156
- Profile: <detectado>
157
- Architecture: hexagonal-feature (Platform + Features + Shared + Infra)
158
- Last Audit: <fecha> (score: <puntaje>)
175
+ - Project Name: <name>
176
+ - Framework: <detectado>
177
+ - Runtime: <detectado>
178
+ - Database: <detectado>
179
+ - ORM: <detectado>
180
+ - DI Strategy: <detectado>
181
+ - Profile: <detectado>
182
+ - Architecture: hexagonal-feature (Platform + Features + Shared + Infra)
183
+ - Last Audit: <fecha> (score: <puntaje>)
159
184
 
160
185
  ## Platform
161
186
  - platform/config/
@@ -175,11 +200,11 @@ Last Audit: <fecha> (score: <puntaje>)
175
200
  ...
176
201
 
177
202
  ## Ownership
178
- Health: healthy | degraded | critical
179
- Score: 0-100
180
- Orphans: 0
181
- Duplicates: 0
182
- Misplaced: 0
203
+ - Health: healthy | degraded | critical
204
+ - Score: 0-100
205
+ - Orphans: 0
206
+ - Duplicates: 0
207
+ - Misplaced: 0
183
208
 
184
209
  ## Architecture Graph
185
210
  ...
@@ -198,10 +223,56 @@ El agente DEBE leer este archivo al inicio de cada interacción y actualizarlo a
198
223
  |---|---|
199
224
  | `reference/principles.md` | Manifiesto y 12 principios inquebrantables |
200
225
  | `reference/patterns.md` | Convenciones de nomenclatura globales (PascalCase.artifact, kebab dirs, etc.) |
226
+ | `reference/errors.md` | Manejo de errores tipados en dominio y aplicación |
227
+ | `reference/di-strategies.md` | Estrategias de inyección de dependencias según tamaño |
228
+ | `reference/testing-patterns.md` | Pirámide de tests, unit mocks, integration tests |
229
+ | `reference/api-design.md` | REST / GraphQL, paginación, validación, contratos |
230
+ | `reference/observability.md` | Logging, tracing, métricas, health checks |
231
+ | `reference/data-patterns.md` | Repository, Unit of Work, CQRS, Event Sourcing |
232
+ | `reference/security-patterns.md` | AuthN, AuthZ, RBAC, rate limiting, validación |
233
+ | `reference/events.md` | Eventos de dominio, outbox pattern, sagas |
234
+ | `reference/hooks.md` | Git pre-commit hook para validación arquitectónica |
235
+ | `reference/help.md` | Lista completa de comandos y flags de Forge |
236
+ | `reference/assay.md` | Ensayo arquitectónico multi-persona — interpretación cualitativa del audit |
201
237
  | `profiles/` | Perfiles tecnológicos detallados (Express, Fastify, NestJS, etc.) |
202
- | `scripts/` | Scripts de análisis: context, detect, inspect, chain, profile, graph, architecture, armorer, bootstrap |
238
+ | `scripts/` | Scripts: context, detect, inspect, chain, profile, graph, architecture, armorer, bootstrap, forge-config, forge-signals, forge-state, forge-api, pin, update, rollback, hook, posttool, formatter, assay, registry/rules |
239
+ | `scripts/registry/rules.mjs` | Anti-pattern rule registry (R1-R9 + custom rules desacopladas de detect.mjs) |
240
+ | `scripts/formatter.mjs` | Output formatter unificado (JSON, tabla, severidad coloreada, scoreBar, formatCheck, formatViolation) |
241
+ | `scripts/posttool.mjs` | PostToolUse hook — analiza archivos modificados tras escritura y reporta violaciones |
242
+ | `scripts/assay.mjs` | Motor de ensayo arquitectónico multi-persona (Bezos, Fowler, Hacker, PM, Arquitecta Senior) |
203
243
  | `templates/feature/` | Templates de feature (entity, repository, uc, controller, routes, schema, mapper) |
204
244
  | `templates/platform/` | Templates de platform (config, server, database, logger, http, di) |
205
245
  | `templates/shared/` | Templates de shared (errors, contracts, types, utils) |
206
246
  | `templates/infra/` | Templates de infra (prisma, mongodb, redis, mail) |
207
247
  | `command/forge.md` | Definición del comando `/forge` para opencode |
248
+
249
+ ### Tests
250
+
251
+ Forge incluye tests unitarios con `node:test` (sin dependencias externas).
252
+
253
+ ```bash
254
+ node --test .opencode/skills/forge/tests/core.test.mjs
255
+ ```
256
+
257
+ | Módulo | Tests | Descripción |
258
+ |--------|-------|-------------|
259
+ | `profile.mjs` | 8 | Detección de perfiles |
260
+ | `graph.mjs` | 1 | Grafo vacío |
261
+ | `armorer.mjs` | 1 | Ownership vacío |
262
+ | `forge-config.mjs` | 2 | Load/save state |
263
+ | `chain.mjs` | 1 | Grafo de dependencias vacío |
264
+ | `formatter.mjs` | 4 | Output format, colores, JSON |
265
+ | `registry/rules.mjs` | 4 | R1-R9, evaluación, custom rules |
266
+ | `detect.mjs` (inline ignores) | 5 | parseInlineIgnores, isIgnored |
267
+ | `posttool.mjs` | 1 | PostToolUse hook |
268
+ | `assay.mjs` | 4 | Personas, generateAssay, opiniones |
269
+
270
+ ### Flags adicionales
271
+
272
+ | Flag | Comando | Descripción |
273
+ |------|---------|-------------|
274
+ | `--fix` | `quench` | Auto-corrige violaciones WARNING/INFO (missing @injectable(), tsconfig, naming, container.resolve) |
275
+ | `--show-ignores` | `quench` | Muestra los inline ignores encontrados en el código |
276
+ | `--persona=<id>` | `assay` | Filtra ensayo por una persona (bezos, fowler, hacker, pm, senior) |
277
+ | `--save` | `assay` | Persiste ensayo en `.forge/assay/` |
278
+ | `--json` | `assay` | Salida JSON |
@@ -0,0 +1,107 @@
1
+ # Profile: Express + Drizzle ORM
2
+
3
+ ## Metadata
4
+
5
+ ```yaml
6
+ framework: Express
7
+ runtime: Node 20+
8
+ database: PostgreSQL / MySQL / SQLite
9
+ orm: Drizzle
10
+ di_strategy: manual
11
+ architecture: hexagonal-feature
12
+ ```
13
+
14
+ ## DI Strategy
15
+
16
+ DI manual. Sin contenedor externo. Las dependencias se inyectan por constructor y se cablean en `app.ts`.
17
+
18
+ ```typescript
19
+ // app.ts
20
+ import express from "express";
21
+ import { drizzle } from "drizzle-orm/node-postgres";
22
+ import { Pool } from "pg";
23
+
24
+ const app = express();
25
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
26
+ const db = drizzle(pool);
27
+
28
+ const creditRepo = new CreditRepository(db);
29
+ const addCredit = new AddCredit(creditRepo);
30
+ const creditController = new CreditController(addCredit);
31
+
32
+ app.use("/credits", creditRoutes(creditController));
33
+ app.listen(3000);
34
+ ```
35
+
36
+ ## Project Structure
37
+
38
+ ```
39
+ ├── src/
40
+ │ ├── db/
41
+ │ │ └── schema.ts # Drizzle schema definitions
42
+ │ ├── features/
43
+ │ │ └── <domain>/
44
+ │ │ ├── domain/
45
+ │ │ ├── application/
46
+ │ │ └── adapters/
47
+ │ │ ├── in/http/
48
+ │ │ └── out/persistence/
49
+ │ ├── shared/
50
+ │ ├── app.ts
51
+ │ └── server.ts
52
+ ```
53
+
54
+ ## Persistence (Drizzle)
55
+
56
+ ### Schema definition
57
+
58
+ ```typescript
59
+ // src/db/schema.ts
60
+ import { pgTable, serial, text, timestamp, integer } from "drizzle-orm/pg-core";
61
+
62
+ export const credits = pgTable("credits", {
63
+ id: serial("id").primaryKey(),
64
+ amount: integer("amount").notNull(),
65
+ userId: text("user_id").notNull(),
66
+ createdAt: timestamp("created_at").defaultNow(),
67
+ });
68
+ ```
69
+
70
+ ### Repository
71
+
72
+ ```typescript
73
+ import { eq } from "drizzle-orm";
74
+ import { credits } from "@/db/schema.js";
75
+
76
+ export class CreditRepository implements ICreditRepository {
77
+ constructor(private readonly db: DrizzleClient) {}
78
+
79
+ async create(data: CreditInput): Promise<Credit> {
80
+ const [record] = await this.db.insert(credits).values(data).returning();
81
+ return CreditMapper.toDomain(record);
82
+ }
83
+
84
+ async findById(id: number): Promise<Credit | null> {
85
+ const [record] = await this.db.select().from(credits).where(eq(credits.id, id));
86
+ return record ? CreditMapper.toDomain(record) : null;
87
+ }
88
+ }
89
+ ```
90
+
91
+ ### Migrations
92
+
93
+ ```bash
94
+ # Generate
95
+ npx drizzle-kit generate
96
+
97
+ # Apply
98
+ npx drizzle-kit migrate
99
+ ```
100
+
101
+ ## Testing Strategy
102
+
103
+ Unit: mocks de DrizzleClient. Integration: base de datos de test independiente.
104
+
105
+ ## Naming Conventions
106
+
107
+ Las tablas en Drizzle siguen camelCase en el esquema, snake_case en PostgreSQL.
@@ -0,0 +1,103 @@
1
+ # Profile: Fastify + MongoDB + Mongoose
2
+
3
+ ## Metadata
4
+
5
+ ```yaml
6
+ framework: Fastify
7
+ runtime: Node 20+
8
+ database: MongoDB
9
+ orm: Mongoose
10
+ di_strategy: manual
11
+ architecture: hexagonal-feature
12
+ ```
13
+
14
+ ## DI Strategy
15
+
16
+ DI manual. Sin contenedor. Cableado en `app.ts`.
17
+
18
+ ```typescript
19
+ // app.ts
20
+ import Fastify from "fastify";
21
+ import mongoose from "mongoose";
22
+
23
+ await mongoose.connect(process.env.MONGO_URI);
24
+
25
+ const app = Fastify({ logger: true });
26
+ const creditRepo = new CreditRepository(mongoose.connection);
27
+ const addCredit = new AddCredit(creditRepo);
28
+ const creditController = new CreditController(addCredit);
29
+
30
+ app.register(creditRoutes(creditController));
31
+ await app.listen({ port: 3000 });
32
+ ```
33
+
34
+ ## Project Structure
35
+
36
+ ```
37
+ ├── src/
38
+ │ ├── features/
39
+ │ │ └── <domain>/
40
+ │ │ ├── domain/
41
+ │ │ ├── application/
42
+ │ │ └── adapters/
43
+ │ │ ├── in/http/
44
+ │ │ └── out/persistence/
45
+ │ ├── shared/
46
+ │ ├── infrastructure/
47
+ │ │ ├── mongoose.ts # Mongoose connection
48
+ │ │ └── models/ # Mongoose schemas
49
+ │ ├── app.ts
50
+ │ └── server.ts
51
+ ```
52
+
53
+ ## Persistence (Mongoose)
54
+
55
+ ### Model schema
56
+
57
+ ```typescript
58
+ // infrastructure/models/credit.model.ts
59
+ import { Schema, model } from "mongoose";
60
+
61
+ const creditSchema = new Schema({
62
+ amount: { type: Number, required: true },
63
+ userId: { type: String, required: true },
64
+ }, { timestamps: true });
65
+
66
+ export const CreditModel = model("Credit", creditSchema);
67
+ ```
68
+
69
+ ### Repository
70
+
71
+ ```typescript
72
+ export class CreditRepository implements ICreditRepository {
73
+ async create(data: CreditInput): Promise<Credit> {
74
+ const doc = await CreditModel.create(data);
75
+ return CreditMapper.toDomain(doc.toObject());
76
+ }
77
+ }
78
+ ```
79
+
80
+ ## Routes & Controllers
81
+
82
+ Usar patrón Fastify plugin (ver `fastify-postgres`).
83
+
84
+ ## Testing Strategy
85
+
86
+ ```typescript
87
+ import { MongoMemoryServer } from "mongodb-memory-server";
88
+
89
+ let mongod: MongoMemoryServer;
90
+
91
+ beforeAll(async () => {
92
+ mongod = await MongoMemoryServer.create();
93
+ await mongoose.connect(mongod.getUri());
94
+ });
95
+ afterAll(async () => {
96
+ await mongoose.disconnect();
97
+ await mongod.stop();
98
+ });
99
+ ```
100
+
101
+ ## Naming Conventions
102
+
103
+ Mismas que `express-mongodb`. Colecciones en snake_case, campos en camelCase.
@@ -0,0 +1,81 @@
1
+ # Profile: Fastify + Prisma
2
+
3
+ ## Metadata
4
+
5
+ ```yaml
6
+ framework: Fastify
7
+ runtime: Node 20+
8
+ database: Cualquier RDBMS (PostgreSQL, MySQL, SQLite)
9
+ orm: Prisma
10
+ di_strategy: manual
11
+ architecture: hexagonal-feature
12
+ ```
13
+
14
+ ## DI Strategy
15
+
16
+ DI manual. Sin contenedor externo. Cableado explícito en `app.ts`.
17
+
18
+ ```typescript
19
+ // app.ts
20
+ import Fastify from "fastify";
21
+ import { PrismaClient } from "@prisma/client";
22
+
23
+ const app = Fastify({ logger: true });
24
+ const prisma = new PrismaClient();
25
+ const creditRepo = new CreditRepository(prisma);
26
+ const addCredit = new AddCredit(creditRepo);
27
+ const creditController = new CreditController(addCredit);
28
+
29
+ app.register(creditRoutes(creditController));
30
+ await app.listen({ port: 3000 });
31
+ ```
32
+
33
+ ## Project Structure
34
+
35
+ ```
36
+ ├── prisma/
37
+ │ └── schema.prisma
38
+ ├── src/
39
+ │ ├── features/
40
+ │ │ └── <domain>/
41
+ │ │ ├── domain/
42
+ │ │ ├── application/
43
+ │ │ └── adapters/
44
+ │ │ ├── in/http/
45
+ │ │ └── out/persistence/
46
+ │ ├── shared/
47
+ │ ├── infrastructure/
48
+ │ │ └── prisma.ts
49
+ │ ├── app.ts
50
+ │ └── server.ts
51
+ ```
52
+
53
+ ## Persistence
54
+
55
+ Idéntico al perfil `express-prisma`: repositorios Prisma con `PrismaClient` singleton, transacciones con `$transaction()`.
56
+
57
+ ## Routes & Controllers
58
+
59
+ Usar el patrón Fastify plugin como en `fastify-postgres`. Cada feature expone un plugin que recibe el controlador por parámetro.
60
+
61
+ ## Testing Strategy
62
+
63
+ ```typescript
64
+ import Fastify from "fastify";
65
+
66
+ const app = Fastify();
67
+ const mockRepo = { create: vi.fn() };
68
+ const useCase = new AddCredit(mockRepo);
69
+
70
+ app.register(creditRoutes(new CreditController(useCase)));
71
+
72
+ it("creates a credit", async () => {
73
+ mockRepo.create.mockResolvedValue({ id: "1" });
74
+ const res = await app.inject({ method: "POST", url: "/credits", payload: { amount: 100 } });
75
+ expect(res.statusCode).toBe(201);
76
+ });
77
+ ```
78
+
79
+ ## Naming Conventions
80
+
81
+ Mismas que `fastify-postgres`. Rutas en camelCase, servicios en PascalCase.