@saulwade/swl-ses 1.0.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 (702) hide show
  1. package/CLAUDE.md +238 -0
  2. package/README.md +560 -0
  3. package/_userland/agentes/.gitkeep +0 -0
  4. package/_userland/habilidades/.gitkeep +0 -0
  5. package/agentes/.evolved.json +9 -0
  6. package/agentes/accesibilidad-wcag-swl.md +692 -0
  7. package/agentes/arquitecto-swl.md +238 -0
  8. package/agentes/auto-evolucion-swl.md +854 -0
  9. package/agentes/backend-api-swl.md +470 -0
  10. package/agentes/backend-csharp-swl.md +418 -0
  11. package/agentes/backend-go-swl.md +388 -0
  12. package/agentes/backend-java-swl.md +279 -0
  13. package/agentes/backend-node-swl.md +477 -0
  14. package/agentes/backend-python-swl.md +608 -0
  15. package/agentes/backend-rust-swl.md +362 -0
  16. package/agentes/backend-workers-swl.md +480 -0
  17. package/agentes/cloud-infra-swl.md +485 -0
  18. package/agentes/consolidador-swl.md +539 -0
  19. package/agentes/datos-swl.md +584 -0
  20. package/agentes/depurador-swl.md +349 -0
  21. package/agentes/devops-ci-swl.md +374 -0
  22. package/agentes/disenador-ui-swl.md +558 -0
  23. package/agentes/documentador-swl.md +343 -0
  24. package/agentes/evals/arquitecto-swl.evals.json +56 -0
  25. package/agentes/evals/auto-evolucion-swl.evals.json +68 -0
  26. package/agentes/evals/implementador-swl.evals.json +56 -0
  27. package/agentes/evals/orquestador-swl.evals.json +60 -0
  28. package/agentes/evals/perfilador-usuario-swl.evals.json +60 -0
  29. package/agentes/evals/red-team-swl.evals.json +59 -0
  30. package/agentes/evals/revisor-codigo-swl.evals.json +59 -0
  31. package/agentes/frontend-angular-swl.md +627 -0
  32. package/agentes/frontend-css-swl.md +720 -0
  33. package/agentes/frontend-react-swl.md +696 -0
  34. package/agentes/frontend-swl.md +500 -0
  35. package/agentes/frontend-tailwind-swl.md +830 -0
  36. package/agentes/implementador-swl.md +328 -0
  37. package/agentes/investigador-swl.md +430 -0
  38. package/agentes/investigador-ux-swl.md +500 -0
  39. package/agentes/llm-apps-swl.md +276 -0
  40. package/agentes/migrador-swl.md +417 -0
  41. package/agentes/mobile-android-swl.md +509 -0
  42. package/agentes/mobile-cross-swl.md +539 -0
  43. package/agentes/mobile-ios-swl.md +500 -0
  44. package/agentes/mobile-testing-swl.md +300 -0
  45. package/agentes/notificador-swl.md +916 -0
  46. package/agentes/observabilidad-swl.md +436 -0
  47. package/agentes/orquestador-swl.md +884 -0
  48. package/agentes/pagos-swl.md +283 -0
  49. package/agentes/perfilador-usuario-swl.md +306 -0
  50. package/agentes/planificador-swl.md +402 -0
  51. package/agentes/producto-prd-swl.md +587 -0
  52. package/agentes/red-team-swl.md +216 -0
  53. package/agentes/release-manager-swl.md +568 -0
  54. package/agentes/rendimiento-swl.md +714 -0
  55. package/agentes/resolutor-build-swl.md +243 -0
  56. package/agentes/revisor-angular-swl.md +276 -0
  57. package/agentes/revisor-codigo-swl.md +348 -0
  58. package/agentes/revisor-csharp-swl.md +262 -0
  59. package/agentes/revisor-go-swl.md +257 -0
  60. package/agentes/revisor-java-swl.md +255 -0
  61. package/agentes/revisor-kotlin-swl.md +271 -0
  62. package/agentes/revisor-nextjs-swl.md +279 -0
  63. package/agentes/revisor-php-swl.md +269 -0
  64. package/agentes/revisor-react-swl.md +276 -0
  65. package/agentes/revisor-rust-swl.md +344 -0
  66. package/agentes/revisor-seguridad-swl.md +390 -0
  67. package/agentes/revisor-swift-swl.md +266 -0
  68. package/agentes/revisor-typescript-swl.md +344 -0
  69. package/agentes/sre-swl.md +265 -0
  70. package/agentes/tdd-qa-swl.md +354 -0
  71. package/agentes/ux-disenador-swl.md +501 -0
  72. package/bin/lib/bot-comandos.js +1030 -0
  73. package/bin/lib/bot-discovery.js +182 -0
  74. package/bin/lib/bot-git.js +142 -0
  75. package/bin/swl-ses.js +325 -0
  76. package/bin/swl-telegram-bot.js +442 -0
  77. package/bin/swl-telegram-bot.plist +21 -0
  78. package/bin/swl-telegram-bot.service +14 -0
  79. package/comandos/swl/.evolved.json +23 -0
  80. package/comandos/swl/actualizar.md +174 -0
  81. package/comandos/swl/adoptar-proyecto.md +207 -0
  82. package/comandos/swl/aprender.md +701 -0
  83. package/comandos/swl/auditar-deps.md +134 -0
  84. package/comandos/swl/autoresearch.md +170 -0
  85. package/comandos/swl/ayuda.md +224 -0
  86. package/comandos/swl/brainstorm.md +50 -0
  87. package/comandos/swl/checkpoint.md +330 -0
  88. package/comandos/swl/compactar.md +283 -0
  89. package/comandos/swl/configurar-ci.md +227 -0
  90. package/comandos/swl/contexto.md +112 -0
  91. package/comandos/swl/contribuir.md +233 -0
  92. package/comandos/swl/crear-skill.md +292 -0
  93. package/comandos/swl/cron.md +196 -0
  94. package/comandos/swl/dashboard.md +146 -0
  95. package/comandos/swl/discutir-fase.md +230 -0
  96. package/comandos/swl/ejecutar-fase.md +135 -0
  97. package/comandos/swl/evaluar-skill.md +487 -0
  98. package/comandos/swl/evolucion-estado.md +142 -0
  99. package/comandos/swl/evolucionar.md +259 -0
  100. package/comandos/swl/exportar-vault.md +189 -0
  101. package/comandos/swl/gateway.md +158 -0
  102. package/comandos/swl/inbox.md +116 -0
  103. package/comandos/swl/instalar.md +220 -0
  104. package/comandos/swl/instintos.md +86 -0
  105. package/comandos/swl/mapear-codebase.md +312 -0
  106. package/comandos/swl/mcp-status.md +175 -0
  107. package/comandos/swl/metricas.md +270 -0
  108. package/comandos/swl/modelo.md +102 -0
  109. package/comandos/swl/notificaciones.md +396 -0
  110. package/comandos/swl/nuevo-proyecto.md +154 -0
  111. package/comandos/swl/planear-fase.md +221 -0
  112. package/comandos/swl/plugins.md +256 -0
  113. package/comandos/swl/reflect-skills.md +125 -0
  114. package/comandos/swl/release.md +217 -0
  115. package/comandos/swl/revisar-impacto.md +206 -0
  116. package/comandos/swl/revisar.md +330 -0
  117. package/comandos/swl/salud.md +363 -0
  118. package/comandos/swl/sesiones.md +200 -0
  119. package/comandos/swl/skill-search.md +113 -0
  120. package/comandos/swl/verificar.md +585 -0
  121. package/comandos/swl/wiki.md +620 -0
  122. package/contextos/dev.md +32 -0
  123. package/contextos/research.md +30 -0
  124. package/contextos/review.md +31 -0
  125. package/habilidades/accesibilidad-a11y/SKILL.md +201 -0
  126. package/habilidades/accesibilidad-a11y/evals/evals.json +56 -0
  127. package/habilidades/accesibilidad-a11y/recursos/ejemplos-y-checklist-completo.md +441 -0
  128. package/habilidades/agent-browser/SKILL.md +218 -0
  129. package/habilidades/agentes-como-servicio/SKILL.md +218 -0
  130. package/habilidades/ai-runtime-security/SKILL.md +273 -0
  131. package/habilidades/angular-avanzado/SKILL.md +164 -0
  132. package/habilidades/angular-avanzado/recursos/ejemplos-avanzados.md +219 -0
  133. package/habilidades/angular-moderno/SKILL.md +186 -0
  134. package/habilidades/angular-moderno/evals/evals.json +45 -0
  135. package/habilidades/angular-moderno/recursos/ejemplos-avanzados.md +106 -0
  136. package/habilidades/api-rest-diseno/SKILL.md +191 -0
  137. package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
  138. package/habilidades/api-rest-diseno/recursos/referencia-api.md +140 -0
  139. package/habilidades/aprendizaje-continuo/SKILL.md +151 -0
  140. package/habilidades/aprendizaje-continuo/evals/evals.json +53 -0
  141. package/habilidades/aprendizaje-continuo/recursos/referencia-instintos.md +290 -0
  142. package/habilidades/async-python/SKILL.md +149 -0
  143. package/habilidades/async-python/evals/evals.json +47 -0
  144. package/habilidades/async-python/recursos/patrones-y-ejemplos-completos.md +292 -0
  145. package/habilidades/auth-patrones/.evolved.json +9 -0
  146. package/habilidades/auth-patrones/SKILL.md +413 -0
  147. package/habilidades/auth-patrones/recursos/implementaciones-completas.md +229 -0
  148. package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -0
  149. package/habilidades/auto-evolucion-protocolo/evals/evals.json +55 -0
  150. package/habilidades/auto-evolucion-protocolo/recursos/referencia-completa.md +145 -0
  151. package/habilidades/autoresearch/SKILL.md +268 -0
  152. package/habilidades/autoresearch/evals/evals.json +41 -0
  153. package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
  154. package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
  155. package/habilidades/azure-cloud/SKILL.md +308 -0
  156. package/habilidades/azure-cloud/recursos/aks.md +327 -0
  157. package/habilidades/backend-mcp-servidor/SKILL.md +270 -0
  158. package/habilidades/backend-production-resilience/SKILL.md +288 -0
  159. package/habilidades/brainstorming/SKILL.md +295 -0
  160. package/habilidades/brainstorming/recursos/componentes-html.md +247 -0
  161. package/habilidades/build-errors-cpp/SKILL.md +270 -0
  162. package/habilidades/build-errors-csharp/SKILL.md +265 -0
  163. package/habilidades/build-errors-go/SKILL.md +306 -0
  164. package/habilidades/build-errors-java/SKILL.md +278 -0
  165. package/habilidades/build-errors-kotlin/SKILL.md +303 -0
  166. package/habilidades/build-errors-nextjs/SKILL.md +312 -0
  167. package/habilidades/build-errors-php/SKILL.md +270 -0
  168. package/habilidades/build-errors-python/SKILL.md +292 -0
  169. package/habilidades/build-errors-rust/SKILL.md +284 -0
  170. package/habilidades/build-errors-swift/SKILL.md +272 -0
  171. package/habilidades/build-errors-typescript/SKILL.md +369 -0
  172. package/habilidades/checklist-calidad/SKILL.md +271 -0
  173. package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
  174. package/habilidades/checklist-seguridad/SKILL.md +285 -0
  175. package/habilidades/checkpoints-verificacion/SKILL.md +298 -0
  176. package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
  177. package/habilidades/ci-cd-pipelines/SKILL.md +157 -0
  178. package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
  179. package/habilidades/ci-cd-pipelines/recursos/pipelines-completos.md +487 -0
  180. package/habilidades/cloud-aws/SKILL.md +142 -0
  181. package/habilidades/cloud-aws/recursos/servicios-aws-referencia.md +321 -0
  182. package/habilidades/compactacion-contexto/SKILL.md +247 -0
  183. package/habilidades/contenedores-docker/SKILL.md +137 -0
  184. package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
  185. package/habilidades/contenedores-docker/recursos/ejemplos-y-configuraciones.md +327 -0
  186. package/habilidades/context-builder/SKILL.md +170 -0
  187. package/habilidades/control-profundidad/SKILL.md +128 -0
  188. package/habilidades/csharp-experto/SKILL.md +322 -0
  189. package/habilidades/csharp-patrones/SKILL.md +316 -0
  190. package/habilidades/csharp-testing/SKILL.md +286 -0
  191. package/habilidades/css-moderno/SKILL.md +166 -0
  192. package/habilidades/css-moderno/evals/evals.json +43 -0
  193. package/habilidades/css-moderno/recursos/ejemplos-y-patrones-completos.md +337 -0
  194. package/habilidades/datos-etl/SKILL.md +129 -0
  195. package/habilidades/datos-etl/recursos/implementaciones-completas.md +322 -0
  196. package/habilidades/dbml-experto/SKILL.md +339 -0
  197. package/habilidades/dbml-experto/evals/evals.json +56 -0
  198. package/habilidades/dependencias-auditoria/SKILL.md +320 -0
  199. package/habilidades/deprecacion-migracion/SKILL.md +169 -0
  200. package/habilidades/deprecacion-migracion/recursos/implementaciones-completas.md +220 -0
  201. package/habilidades/design-tokens/SKILL.md +158 -0
  202. package/habilidades/design-tokens/recursos/tokens-y-configuracion.md +363 -0
  203. package/habilidades/devsecops-pipeline-security/SKILL.md +309 -0
  204. package/habilidades/diagrama-arquitectura/SKILL.md +165 -0
  205. package/habilidades/diagrama-arquitectura/assets/template.html +276 -0
  206. package/habilidades/discutir-fase/SKILL.md +188 -0
  207. package/habilidades/diseno-herramientas-agente/SKILL.md +199 -0
  208. package/habilidades/diseno-responsivo/SKILL.md +186 -0
  209. package/habilidades/diseno-responsivo/recursos/ejemplos-layouts.md +156 -0
  210. package/habilidades/django-experto/SKILL.md +205 -0
  211. package/habilidades/django-experto/recursos/async-django.md +390 -0
  212. package/habilidades/django-experto/recursos/drf-patrones.md +438 -0
  213. package/habilidades/django-experto/recursos/orm-avanzado.md +382 -0
  214. package/habilidades/django-experto/recursos/referencia-completa.md +188 -0
  215. package/habilidades/django-experto/recursos/testing-django.md +415 -0
  216. package/habilidades/doc-sync/SKILL.md +280 -0
  217. package/habilidades/drift-detection/SKILL.md +179 -0
  218. package/habilidades/ejecutar-fase/SKILL.md +468 -0
  219. package/habilidades/estilo-sin-ai-isms/SKILL.md +775 -0
  220. package/habilidades/estilo-sin-ai-isms/evals/evals.json +63 -0
  221. package/habilidades/estilo-sin-ai-isms/scripts/detectar_aiisms.py +500 -0
  222. package/habilidades/estructura-proyecto-claude/SKILL.md +215 -0
  223. package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
  224. package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +176 -0
  225. package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +289 -0
  226. package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
  227. package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
  228. package/habilidades/evaluacion-agentes/SKILL.md +314 -0
  229. package/habilidades/event-driven/SKILL.md +153 -0
  230. package/habilidades/event-driven/recursos/implementaciones-completas.md +423 -0
  231. package/habilidades/extraccion-documentos/SKILL.md +221 -0
  232. package/habilidades/extractor-de-aprendizajes/.evolved.json +9 -0
  233. package/habilidades/extractor-de-aprendizajes/SKILL.md +311 -0
  234. package/habilidades/extractor-de-aprendizajes/evals/evals.json +55 -0
  235. package/habilidades/fastapi-experto/SKILL.md +221 -0
  236. package/habilidades/fastapi-experto/recursos/async-patterns.md +438 -0
  237. package/habilidades/fastapi-experto/recursos/dependency-injection.md +330 -0
  238. package/habilidades/fastapi-experto/recursos/referencia-completa.md +79 -0
  239. package/habilidades/fastapi-experto/recursos/testing-httpx.md +420 -0
  240. package/habilidades/filament-admin/SKILL.md +290 -0
  241. package/habilidades/frontend-avanzado/SKILL.md +257 -0
  242. package/habilidades/frontend-avanzado/recursos/apis-nativas-ejemplos.md +341 -0
  243. package/habilidades/gcp-cloud/SKILL.md +260 -0
  244. package/habilidades/gcp-cloud/recursos/gke.md +234 -0
  245. package/habilidades/gcp-cloud/recursos/terraform-gcp.md +307 -0
  246. package/habilidades/generacion-mermaid/SKILL.md +229 -0
  247. package/habilidades/git-worktrees-paralelo/SKILL.md +270 -0
  248. package/habilidades/go-experto/SKILL.md +305 -0
  249. package/habilidades/go-patrones/SKILL.md +299 -0
  250. package/habilidades/go-testing/SKILL.md +291 -0
  251. package/habilidades/graphql-experto/SKILL.md +323 -0
  252. package/habilidades/guardrail-semantico/SKILL.md +282 -0
  253. package/habilidades/harness-claude-code/SKILL.md +299 -0
  254. package/habilidades/iam-secretos/SKILL.md +265 -0
  255. package/habilidades/iam-secretos/recursos/implementaciones-completas.md +356 -0
  256. package/habilidades/infra-github-actions/SKILL.md +166 -0
  257. package/habilidades/instalar-sistema/.evolved.json +9 -0
  258. package/habilidades/instalar-sistema/SKILL.md +221 -0
  259. package/habilidades/java-experto/SKILL.md +290 -0
  260. package/habilidades/java-patrones/SKILL.md +275 -0
  261. package/habilidades/java-testing/SKILL.md +288 -0
  262. package/habilidades/kotlin-compose/SKILL.md +278 -0
  263. package/habilidades/kotlin-compose/recursos/animaciones-performance.md +93 -0
  264. package/habilidades/kotlin-experto/SKILL.md +318 -0
  265. package/habilidades/kotlin-testing/SKILL.md +267 -0
  266. package/habilidades/kotlin-testing/recursos/testing-avanzado.md +74 -0
  267. package/habilidades/kubernetes-orquestacion/SKILL.md +152 -0
  268. package/habilidades/kubernetes-orquestacion/recursos/manifiestos-completos.md +452 -0
  269. package/habilidades/langchain-langraph/SKILL.md +386 -0
  270. package/habilidades/langchain-langraph/recursos/evaluacion-rag.md +321 -0
  271. package/habilidades/langchain-langraph/recursos/rag-maturity-model.md +225 -0
  272. package/habilidades/langchain-langraph/recursos/vectorstores.md +306 -0
  273. package/habilidades/legacy-code-rescue/SKILL.md +267 -0
  274. package/habilidades/likec4-experto/SKILL.md +412 -0
  275. package/habilidades/likec4-experto/evals/evals.json +69 -0
  276. package/habilidades/manejo-errores/.evolved.json +9 -0
  277. package/habilidades/manejo-errores/SKILL.md +407 -0
  278. package/habilidades/manejo-errores/recursos/implementaciones-completas.md +248 -0
  279. package/habilidades/mapear-codebase/SKILL.md +275 -0
  280. package/habilidades/memoria-busqueda/SKILL.md +194 -0
  281. package/habilidades/memoria-busqueda/evals/evals.json +44 -0
  282. package/habilidades/meta-skills-estandar/SKILL.md +298 -0
  283. package/habilidades/meta-skills-estandar/recursos/anti-patrones-y-leyes.md +205 -0
  284. package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +107 -0
  285. package/habilidades/meta-skills-estandar/recursos/idiomas-framework.md +60 -0
  286. package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -0
  287. package/habilidades/microservicios/SKILL.md +155 -0
  288. package/habilidades/microservicios/recursos/patrones-y-ejemplos-completos.md +325 -0
  289. package/habilidades/mobile-flutter/SKILL.md +199 -0
  290. package/habilidades/mobile-flutter/recursos/ejemplos-completos.md +319 -0
  291. package/habilidades/mobile-react-native/SKILL.md +176 -0
  292. package/habilidades/mobile-react-native/recursos/ejemplos-completos.md +216 -0
  293. package/habilidades/mongodb-experto/SKILL.md +302 -0
  294. package/habilidades/monitoring-alertas/SKILL.md +201 -0
  295. package/habilidades/monitoring-alertas/recursos/instrumentacion-y-alertas.md +301 -0
  296. package/habilidades/nestjs-experto/SKILL.md +307 -0
  297. package/habilidades/nestjs-experto/recursos/guards-interceptors.md +339 -0
  298. package/habilidades/nestjs-experto/recursos/modulos-di.md +287 -0
  299. package/habilidades/nestjs-experto/recursos/testing-nestjs.md +354 -0
  300. package/habilidades/nextjs-experto/SKILL.md +335 -0
  301. package/habilidades/nextjs-patrones/SKILL.md +303 -0
  302. package/habilidades/nextjs-testing/SKILL.md +331 -0
  303. package/habilidades/node-experto/.evolved.json +9 -0
  304. package/habilidades/node-experto/SKILL.md +266 -0
  305. package/habilidades/node-experto/recursos/patrones-completos.md +283 -0
  306. package/habilidades/notificaciones-multicanal/SKILL.md +159 -0
  307. package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
  308. package/habilidades/notificaciones-multicanal/recursos/configuracion-y-templates.md +303 -0
  309. package/habilidades/nuevo-proyecto/SKILL.md +204 -0
  310. package/habilidades/orquestacion-async/SKILL.md +303 -0
  311. package/habilidades/paid-media-tracking/SKILL.md +269 -0
  312. package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +220 -0
  313. package/habilidades/paid-media-tracking/recursos/google-ads-api.md +215 -0
  314. package/habilidades/patrones-python/SKILL.md +228 -0
  315. package/habilidades/patrones-python/evals/evals.json +56 -0
  316. package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -0
  317. package/habilidades/patrones-python/recursos/referencia-completa.md +202 -0
  318. package/habilidades/perfil-usuario/SKILL.md +200 -0
  319. package/habilidades/perfil-usuario/evals/evals.json +55 -0
  320. package/habilidades/performance-baseline/SKILL.md +297 -0
  321. package/habilidades/php-experto/SKILL.md +291 -0
  322. package/habilidades/php-patrones/SKILL.md +306 -0
  323. package/habilidades/php-testing/SKILL.md +280 -0
  324. package/habilidades/planear-fase/SKILL.md +269 -0
  325. package/habilidades/postgresql-experto/SKILL.md +151 -0
  326. package/habilidades/postgresql-experto/evals/evals.json +53 -0
  327. package/habilidades/postgresql-experto/recursos/referencia-completa.md +215 -0
  328. package/habilidades/prevencion-racionalizacion/SKILL.md +175 -0
  329. package/habilidades/prevencion-sobreingenieria/SKILL.md +323 -0
  330. package/habilidades/privacy-memoria/SKILL.md +141 -0
  331. package/habilidades/privacy-memoria/evals/evals.json +43 -0
  332. package/habilidades/prompt-engineering/SKILL.md +518 -0
  333. package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +467 -0
  334. package/habilidades/rag-arquitectura/SKILL.md +338 -0
  335. package/habilidades/rails-experto/SKILL.md +237 -0
  336. package/habilidades/rails-experto/recursos/active-record.md +260 -0
  337. package/habilidades/rails-experto/recursos/hotwire-turbo.md +293 -0
  338. package/habilidades/rails-experto/recursos/testing-rspec.md +362 -0
  339. package/habilidades/react-experto/SKILL.md +209 -0
  340. package/habilidades/react-experto/evals/evals.json +55 -0
  341. package/habilidades/react-experto/recursos/patrones-y-ejemplos-completos.md +240 -0
  342. package/habilidades/react-optimizacion/SKILL.md +174 -0
  343. package/habilidades/react-optimizacion/recursos/patrones-avanzados.md +138 -0
  344. package/habilidades/redis-experto/SKILL.md +305 -0
  345. package/habilidades/release-semver/.evolved.json +9 -0
  346. package/habilidades/release-semver/SKILL.md +248 -0
  347. package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
  348. package/habilidades/rust-experto/SKILL.md +400 -0
  349. package/habilidades/rust-patrones/SKILL.md +296 -0
  350. package/habilidades/rust-testing/SKILL.md +311 -0
  351. package/habilidades/seguridad-skills-ia/SKILL.md +262 -0
  352. package/habilidades/sql-optimizacion/SKILL.md +200 -0
  353. package/habilidades/sql-optimizacion/evals/evals.json +54 -0
  354. package/habilidades/sql-optimizacion/recursos/patrones-sql-avanzados.md +131 -0
  355. package/habilidades/sre-patrones/SKILL.md +333 -0
  356. package/habilidades/sre-patrones/recursos/chaos-engineering.md +241 -0
  357. package/habilidades/sre-patrones/recursos/oncall-design.md +236 -0
  358. package/habilidades/stripe-pagos/SKILL.md +550 -0
  359. package/habilidades/stripe-pagos/recursos/errores-reintentos.md +390 -0
  360. package/habilidades/stripe-pagos/recursos/stripe-connect.md +290 -0
  361. package/habilidades/structured-outputs/SKILL.md +343 -0
  362. package/habilidades/swift-experto/SKILL.md +320 -0
  363. package/habilidades/swift-experto/recursos/keychain-y-wrappers.md +110 -0
  364. package/habilidades/swift-patrones/SKILL.md +313 -0
  365. package/habilidades/swift-patrones/recursos/tca-ejemplo-completo.md +113 -0
  366. package/habilidades/swift-testing/SKILL.md +254 -0
  367. package/habilidades/swift-testing/recursos/xcuitest-planes.md +143 -0
  368. package/habilidades/swl-dashboard/SKILL.md +370 -0
  369. package/habilidades/swl-markitdown/SKILL.md +285 -0
  370. package/habilidades/swl-markitdown/evals/evals.json +52 -0
  371. package/habilidades/swl-revisar-impacto/SKILL.md +233 -0
  372. package/habilidades/tailwind-experto/SKILL.md +240 -0
  373. package/habilidades/tailwind-experto/recursos/referencia-completa.md +184 -0
  374. package/habilidades/tdd-workflow/SKILL.md +293 -0
  375. package/habilidades/terraform-experto/SKILL.md +321 -0
  376. package/habilidades/testing-python/SKILL.md +340 -0
  377. package/habilidades/testing-python/recursos/ejemplos-completos.md +167 -0
  378. package/habilidades/threat-model-lite/SKILL.md +246 -0
  379. package/habilidades/tracing-processor/SKILL.md +212 -0
  380. package/habilidades/tracking-measurement/SKILL.md +239 -0
  381. package/habilidades/tracking-measurement/recursos/consent-mode.md +231 -0
  382. package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +216 -0
  383. package/habilidades/tracking-measurement/recursos/meta-capi.md +262 -0
  384. package/habilidades/typescript-avanzado/SKILL.md +144 -0
  385. package/habilidades/typescript-avanzado/evals/evals.json +55 -0
  386. package/habilidades/typescript-avanzado/recursos/patrones-y-ejemplos-completos.md +298 -0
  387. package/habilidades/typescript-diagnosticos/SKILL.md +513 -0
  388. package/habilidades/ux-diseno/SKILL.md +116 -0
  389. package/habilidades/ux-diseno/evals/evals.json +43 -0
  390. package/habilidades/ux-diseno/recursos/patrones-ux-referencia.md +214 -0
  391. package/habilidades/validacion-ci-sistema/SKILL.md +136 -0
  392. package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +369 -0
  393. package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
  394. package/habilidades/verificacion-evidencia/SKILL.md +160 -0
  395. package/habilidades/verificar-trabajo/SKILL.md +303 -0
  396. package/habilidades/verificar-trabajo/recursos/plantilla-verificacion.md +60 -0
  397. package/habilidades/wiki-conocimiento/SKILL.md +276 -0
  398. package/habilidades/wireframes-flujos/SKILL.md +212 -0
  399. package/habilidades/wireframes-flujos/recursos/referencia-completa.md +192 -0
  400. package/habilidades/workflow-claude-code/SKILL.md +260 -0
  401. package/habilidades/workflow-claude-code/recursos/referencia-completa.md +109 -0
  402. package/hooks/_run-hook.sh +57 -0
  403. package/hooks/actualizar-perfil-usuario.js +364 -0
  404. package/hooks/agente-lifecycle.js +71 -0
  405. package/hooks/aiisms-detector.js +173 -0
  406. package/hooks/audit-trail.js +204 -0
  407. package/hooks/auto-background.js +97 -0
  408. package/hooks/auto-consolidacion.js +178 -0
  409. package/hooks/auto-evolucion.js +666 -0
  410. package/hooks/auto-restaurar-settings.js +360 -0
  411. package/hooks/calidad-pre-commit.js +929 -0
  412. package/hooks/calidad-typescript.js +511 -0
  413. package/hooks/captura-feedback-usuario.js +148 -0
  414. package/hooks/check-update.js +211 -0
  415. package/hooks/clasificador-mensajes.js +271 -0
  416. package/hooks/degradacion-instintos.js +272 -0
  417. package/hooks/escaneo-secretos.js +389 -0
  418. package/hooks/extraccion-aprendizajes.js +763 -0
  419. package/hooks/grafo-contexto.js +129 -0
  420. package/hooks/graph-update.js +67 -0
  421. package/hooks/guardrail-modelo.js +247 -0
  422. package/hooks/inbox-aviso.js +75 -0
  423. package/hooks/inyeccion-contexto.js +246 -0
  424. package/hooks/lib/abort-registry.js +214 -0
  425. package/hooks/lib/agent-backend.js +210 -0
  426. package/hooks/lib/agent-comms.js +263 -0
  427. package/hooks/lib/agent-issue-codes.js +284 -0
  428. package/hooks/lib/agent-matcher.js +189 -0
  429. package/hooks/lib/async-hook-registry.js +252 -0
  430. package/hooks/lib/atomic-write.js +130 -0
  431. package/hooks/lib/auto-consolidator.js +335 -0
  432. package/hooks/lib/canary-skills.js +187 -0
  433. package/hooks/lib/consolidation-lock.js +291 -0
  434. package/hooks/lib/context-builder.js +430 -0
  435. package/hooks/lib/context-compressor.js +657 -0
  436. package/hooks/lib/convergence-detector.js +105 -0
  437. package/hooks/lib/delegation-tracker.js +198 -0
  438. package/hooks/lib/detectar-package-manager.js +423 -0
  439. package/hooks/lib/edit-accumulator.js +171 -0
  440. package/hooks/lib/error-classifier.js +308 -0
  441. package/hooks/lib/event-bus.js +112 -0
  442. package/hooks/lib/evolution-tracker.js +442 -0
  443. package/hooks/lib/execution-state.js +316 -0
  444. package/hooks/lib/fingerprint-id.js +135 -0
  445. package/hooks/lib/gateway-notify.js +116 -0
  446. package/hooks/lib/graph-security.js +75 -0
  447. package/hooks/lib/guardrail-metrics.js +202 -0
  448. package/hooks/lib/hook-circuit-breaker.js +206 -0
  449. package/hooks/lib/loop-detector.js +267 -0
  450. package/hooks/lib/mcp-health.js +184 -0
  451. package/hooks/lib/mcp-pool.js +436 -0
  452. package/hooks/lib/memory-search.js +506 -0
  453. package/hooks/lib/merkle-audit.js +96 -0
  454. package/hooks/lib/model-router.js +222 -0
  455. package/hooks/lib/normalize-error.js +324 -0
  456. package/hooks/lib/normalize-input.js +65 -0
  457. package/hooks/lib/nudge-tracker.js +306 -0
  458. package/hooks/lib/otlp-exporter.js +365 -0
  459. package/hooks/lib/performance-marks.js +239 -0
  460. package/hooks/lib/privacy-filter.js +128 -0
  461. package/hooks/lib/prompt-injection-scanner.js +209 -0
  462. package/hooks/lib/provenance-tracker.js +183 -0
  463. package/hooks/lib/rate-limit-tracker.js +253 -0
  464. package/hooks/lib/reflect-classifier.js +164 -0
  465. package/hooks/lib/resource-quota.js +122 -0
  466. package/hooks/lib/retry-jitter.js +165 -0
  467. package/hooks/lib/risk-engine.js +368 -0
  468. package/hooks/lib/run-log.js +408 -0
  469. package/hooks/lib/session-fts.js +379 -0
  470. package/hooks/lib/session-store.js +293 -0
  471. package/hooks/lib/singleton-guard.js +159 -0
  472. package/hooks/lib/skill-auditor.js +588 -0
  473. package/hooks/lib/sync-status.js +228 -0
  474. package/hooks/lib/taint-tracker.js +107 -0
  475. package/hooks/lib/task-service.js +295 -0
  476. package/hooks/lib/tech-skills-map.js +146 -0
  477. package/hooks/lib/telegram-cliente.js +159 -0
  478. package/hooks/lib/telegram-config.js +170 -0
  479. package/hooks/lib/token-budget.js +156 -0
  480. package/hooks/lib/token-estimator.js +420 -0
  481. package/hooks/lib/toon-compressor.js +245 -0
  482. package/hooks/lib/usage-model.js +183 -0
  483. package/hooks/lib/variable-resolver.js +230 -0
  484. package/hooks/linea-estado.js +324 -0
  485. package/hooks/metricas-evolucion.js +209 -0
  486. package/hooks/monitor-contexto.js +325 -0
  487. package/hooks/notificacion-sesion-stop.js +198 -0
  488. package/hooks/notificacion-telegram-notification.js +4 -0
  489. package/hooks/notificacion-telegram-subagent.js +4 -0
  490. package/hooks/notificacion-telegram.js +267 -0
  491. package/hooks/preservar-estado-pre-compact.js +150 -0
  492. package/hooks/proteccion-rutas.js +366 -0
  493. package/hooks/registro-turnos.js +209 -0
  494. package/hooks/resumen-sesion.js +249 -0
  495. package/hooks/risk-scoring.js +323 -0
  496. package/hooks/rotar-audit-auto.js +122 -0
  497. package/hooks/sugerir-regenerar-inventario.js +170 -0
  498. package/hooks/telemetria-agentes.js +167 -0
  499. package/hooks/tracking-costos.js +688 -0
  500. package/instintos/global.yaml +8 -0
  501. package/instintos/perfil-usuario.yaml +53 -0
  502. package/instintos/prompt-appendices.yaml +57 -0
  503. package/instintos/proyecto.yaml +372 -0
  504. package/manifiestos/gateway-config.json +77 -0
  505. package/manifiestos/handoff-context.json +223 -0
  506. package/manifiestos/hook-profiles.json +44 -0
  507. package/manifiestos/hooks-config.json +360 -0
  508. package/manifiestos/modulos.json +1173 -0
  509. package/manifiestos/perfiles.json +404 -0
  510. package/package.json +86 -0
  511. package/plantillas/ESTADO.md +109 -0
  512. package/plantillas/HOJA-RUTA.md +143 -0
  513. package/plantillas/PROYECTO.md +122 -0
  514. package/plantillas/REQUISITOS.md +132 -0
  515. package/plantillas/auditor-veto-template.md +105 -0
  516. package/plantillas/github-workflows/README.md +47 -0
  517. package/plantillas/github-workflows/release-please.yml +44 -0
  518. package/plantillas/github-workflows/swl-ci.yml +107 -0
  519. package/plantillas/github-workflows/swl-security.yml +51 -0
  520. package/plantillas/mcp-mineru.json +13 -0
  521. package/plantillas/research/ARQUITECTURA.md +220 -0
  522. package/plantillas/research/FUNCIONALIDADES.md +175 -0
  523. package/plantillas/research/RESUMEN.md +165 -0
  524. package/plantillas/research/STACK.md +233 -0
  525. package/plantillas/research/TRAMPAS.md +299 -0
  526. package/plantillas/skill-evals-template.json +44 -0
  527. package/plugin.json +343 -0
  528. package/reglas/accesibilidad.md +269 -0
  529. package/reglas/api-diseno.md +400 -0
  530. package/reglas/arquitectura.md +352 -0
  531. package/reglas/brevedad-output.md +124 -0
  532. package/reglas/cloud-infra.md +247 -0
  533. package/reglas/docs.md +245 -0
  534. package/reglas/estilo-codigo.md +201 -0
  535. package/reglas/git-workflow.md +245 -0
  536. package/reglas/gobernanza.md +271 -0
  537. package/reglas/harness-claude-code.md +213 -0
  538. package/reglas/hooks.md +186 -0
  539. package/reglas/lenguajes/csharp/estilo-codigo.md +231 -0
  540. package/reglas/lenguajes/csharp/hooks.md +281 -0
  541. package/reglas/lenguajes/csharp/patrones.md +226 -0
  542. package/reglas/lenguajes/csharp/seguridad.md +258 -0
  543. package/reglas/lenguajes/csharp/testing.md +176 -0
  544. package/reglas/lenguajes/go/estilo-codigo.md +195 -0
  545. package/reglas/lenguajes/go/hooks.md +249 -0
  546. package/reglas/lenguajes/go/patrones.md +249 -0
  547. package/reglas/lenguajes/go/seguridad.md +225 -0
  548. package/reglas/lenguajes/go/testing.md +272 -0
  549. package/reglas/lenguajes/java/estilo-codigo.md +217 -0
  550. package/reglas/lenguajes/java/hooks.md +251 -0
  551. package/reglas/lenguajes/java/patrones.md +226 -0
  552. package/reglas/lenguajes/java/seguridad.md +233 -0
  553. package/reglas/lenguajes/java/testing.md +238 -0
  554. package/reglas/lenguajes/kotlin/estilo-codigo.md +208 -0
  555. package/reglas/lenguajes/kotlin/hooks.md +245 -0
  556. package/reglas/lenguajes/kotlin/patrones.md +201 -0
  557. package/reglas/lenguajes/kotlin/seguridad.md +202 -0
  558. package/reglas/lenguajes/kotlin/testing.md +236 -0
  559. package/reglas/lenguajes/nextjs/estilo-codigo.md +175 -0
  560. package/reglas/lenguajes/nextjs/hooks.md +186 -0
  561. package/reglas/lenguajes/nextjs/patrones.md +225 -0
  562. package/reglas/lenguajes/nextjs/seguridad.md +216 -0
  563. package/reglas/lenguajes/nextjs/testing.md +193 -0
  564. package/reglas/lenguajes/php/estilo-codigo.md +228 -0
  565. package/reglas/lenguajes/php/hooks.md +165 -0
  566. package/reglas/lenguajes/php/patrones.md +233 -0
  567. package/reglas/lenguajes/php/seguridad.md +186 -0
  568. package/reglas/lenguajes/php/testing.md +205 -0
  569. package/reglas/lenguajes/rust/estilo-codigo.md +207 -0
  570. package/reglas/lenguajes/rust/hooks.md +240 -0
  571. package/reglas/lenguajes/rust/patrones.md +250 -0
  572. package/reglas/lenguajes/rust/seguridad.md +221 -0
  573. package/reglas/lenguajes/rust/testing.md +194 -0
  574. package/reglas/lenguajes/swift/estilo-codigo.md +238 -0
  575. package/reglas/lenguajes/swift/hooks.md +257 -0
  576. package/reglas/lenguajes/swift/patrones.md +235 -0
  577. package/reglas/lenguajes/swift/seguridad.md +248 -0
  578. package/reglas/lenguajes/swift/testing.md +242 -0
  579. package/reglas/markitdown.md +60 -0
  580. package/reglas/memoria-consolidada.md +209 -0
  581. package/reglas/patrones.md +225 -0
  582. package/reglas/performance.md +195 -0
  583. package/reglas/pruebas.md +159 -0
  584. package/reglas/seguridad-agentes.md +351 -0
  585. package/reglas/seguridad.md +151 -0
  586. package/reglas/skills-estandar.md +373 -0
  587. package/reglas/testing.md +193 -0
  588. package/schemas/agent-contract.json +176 -0
  589. package/schemas/agent-frontmatter.schema.json +149 -0
  590. package/schemas/agent-message.schema.json +53 -0
  591. package/schemas/agent-output-implementacion.schema.json +85 -0
  592. package/schemas/agent-output-planificacion.schema.json +113 -0
  593. package/schemas/agent-output-review.schema.json +78 -0
  594. package/schemas/diary-entry.schema.json +80 -0
  595. package/schemas/hook-profiles.schema.json +39 -0
  596. package/schemas/hooks-config.schema.json +74 -0
  597. package/schemas/instinct.schema.json +115 -0
  598. package/schemas/modulos.schema.json +29 -0
  599. package/schemas/perfiles.schema.json +28 -0
  600. package/schemas/plugin.schema.json +64 -0
  601. package/schemas/skill-evals.schema.json +95 -0
  602. package/schemas/skill-frontmatter.schema.json +170 -0
  603. package/scripts/actualizar.js +145 -0
  604. package/scripts/audit-skills.sh +78 -0
  605. package/scripts/auditar-agentes-gaps.js +149 -0
  606. package/scripts/auditar-cobertura-frameworks.js +241 -0
  607. package/scripts/auditar-skills-gaps.js +206 -0
  608. package/scripts/bootstrap-instintos.js +259 -0
  609. package/scripts/check-update.js +109 -0
  610. package/scripts/comandos/agents.js +105 -0
  611. package/scripts/comandos/info.js +108 -0
  612. package/scripts/comandos/install-asistido.js +186 -0
  613. package/scripts/comandos/skills.js +211 -0
  614. package/scripts/configurar-branch-protection.js +418 -0
  615. package/scripts/daemon-swl.py +388 -0
  616. package/scripts/desinstalar.js +130 -0
  617. package/scripts/doctor.js +559 -0
  618. package/scripts/field-report.js +199 -0
  619. package/scripts/generar-inventario.js +317 -0
  620. package/scripts/inbox-tmux-inject.js +161 -0
  621. package/scripts/inferir-herramientas-permitidas.js +586 -0
  622. package/scripts/inicializar.js +133 -0
  623. package/scripts/instalador.js +1031 -0
  624. package/scripts/instalar-git-hook.js +122 -0
  625. package/scripts/lib/agp-frontmatter.js +222 -0
  626. package/scripts/lib/append-con-marcadores.js +199 -0
  627. package/scripts/lib/artefactos-python.js +43 -0
  628. package/scripts/lib/audit-query.js +221 -0
  629. package/scripts/lib/autostart-linux.js +347 -0
  630. package/scripts/lib/autostart-macos.js +360 -0
  631. package/scripts/lib/autostart-windows.js +307 -0
  632. package/scripts/lib/budget-enforcer.js +252 -0
  633. package/scripts/lib/claude-sessions.js +285 -0
  634. package/scripts/lib/configurar-ci.js +380 -0
  635. package/scripts/lib/console-span-exporter.js +92 -0
  636. package/scripts/lib/contadores-inventario.js +217 -0
  637. package/scripts/lib/dashboard-widgets.js +290 -0
  638. package/scripts/lib/detectar-runtime.js +279 -0
  639. package/scripts/lib/detectar-stack.js +187 -0
  640. package/scripts/lib/diary-entry.js +234 -0
  641. package/scripts/lib/drift-detector.js +545 -0
  642. package/scripts/lib/estado.js +124 -0
  643. package/scripts/lib/gestor-componentes.js +243 -0
  644. package/scripts/lib/gitignore-manifest.js +305 -0
  645. package/scripts/lib/graph-analyze.py +556 -0
  646. package/scripts/lib/graph-builder.py +485 -0
  647. package/scripts/lib/graph-cluster.py +259 -0
  648. package/scripts/lib/health-row.js +168 -0
  649. package/scripts/lib/hooks-settings.js +789 -0
  650. package/scripts/lib/manifiestos.js +138 -0
  651. package/scripts/lib/mc-client.js +137 -0
  652. package/scripts/lib/notificaciones-telegram.js +1107 -0
  653. package/scripts/lib/npm-version.js +261 -0
  654. package/scripts/lib/paquetes-conocidos.js +50 -0
  655. package/scripts/lib/preservar-usuario.js +586 -0
  656. package/scripts/lib/prompt-builder.js +264 -0
  657. package/scripts/lib/resolver-externo.js +332 -0
  658. package/scripts/lib/schedule-parser.js +305 -0
  659. package/scripts/lib/scoring-instintos.js +240 -0
  660. package/scripts/lib/seguridad.js +160 -0
  661. package/scripts/lib/selector-interactivo.js +152 -0
  662. package/scripts/lib/semantic-search.js +242 -0
  663. package/scripts/lib/skill-discovery.js +234 -0
  664. package/scripts/lib/skill-metrics.js +246 -0
  665. package/scripts/lib/skill-normalizer.js +112 -0
  666. package/scripts/lib/skills-hub.js +340 -0
  667. package/scripts/lib/span-schema.js +134 -0
  668. package/scripts/lib/tool-cost-analyzer.js +255 -0
  669. package/scripts/lib/tracing-processor-interface.js +286 -0
  670. package/scripts/lib/transformadores/base.js +80 -0
  671. package/scripts/lib/transformadores/claude.js +124 -0
  672. package/scripts/lib/transformadores/codex.js +115 -0
  673. package/scripts/lib/transformadores/copilot.js +106 -0
  674. package/scripts/lib/transformadores/gemini.js +74 -0
  675. package/scripts/lib/transformadores/index.js +35 -0
  676. package/scripts/lib/transformadores/opencode.js +75 -0
  677. package/scripts/lib/ui.js +259 -0
  678. package/scripts/limpiar-artefactos-python.js +131 -0
  679. package/scripts/mcp-orchestrator.py +386 -0
  680. package/scripts/mcp-pool-manager.py +352 -0
  681. package/scripts/mcp-telemetry.py +378 -0
  682. package/scripts/poblar-evolvable.js +226 -0
  683. package/scripts/publicar.js +287 -0
  684. package/scripts/reflect-skills.js +403 -0
  685. package/scripts/rotar-audit-logs.js +185 -0
  686. package/scripts/run-skill-evals.js +242 -0
  687. package/scripts/smoke-test.js +374 -0
  688. package/scripts/token-analysis.py +471 -0
  689. package/scripts/validar-manifest.js +195 -0
  690. package/scripts/validar-memoria.js +321 -0
  691. package/scripts/validar-tests-aislamiento.js +184 -0
  692. package/scripts/validar-tokens-test.js +208 -0
  693. package/scripts/validar.js +147 -0
  694. package/scripts/validate-markdown.py +339 -0
  695. package/scripts/validate-skills.py +385 -0
  696. package/scripts/vendor/claude-usage/README.md +116 -0
  697. package/scripts/vendor/claude-usage/cli.py +334 -0
  698. package/scripts/vendor/claude-usage/dashboard.py +795 -0
  699. package/scripts/vendor/claude-usage/scanner.py +467 -0
  700. package/scripts/vendor/markitdown/cli.py +194 -0
  701. package/scripts/verificar-evolucion.js +289 -0
  702. package/scripts/verificar-release.js +494 -0
@@ -0,0 +1,307 @@
1
+ ---
2
+ name: nestjs-experto
3
+ description: >
4
+ NestJS con TypeScript: módulos, controladores, servicios, DTOs con class-validator,
5
+ guards JWT, interceptors, TypeORM y Prisma. Cargar cuando se implementen APIs
6
+ NestJS, módulos con inyección de dependencias, autenticación JWT/Passport,
7
+ endpoints REST o GraphQL con NestJS, o configuración de pipes y guards.
8
+ version: "1.0.0"
9
+ herramientasPermitidas: [Read]
10
+ exclusiones:
11
+ - "No cargar para APIs Express o Fastify sin NestJS — la DI, los decoradores y el sistema de módulos son exclusivos de NestJS; para Node.js sin framework opinionado cargar `node-experto`."
12
+ - "No cargar para el frontend Next.js aunque comparten TypeScript — Next.js y NestJS son backends distintos con modelos de rendering y lifecycle diferentes; cargar `nextjs-experto`."
13
+ - "No cargar para la configuración de TypeORM o Prisma independientemente de NestJS — si la pregunta es sobre migraciones o queries del ORM en un proyecto no-NestJS, cargar el skill del ORM directamente."
14
+ - "No cargar para errores de compilación TypeScript en proyectos NestJS — esos son errores TS genéricos; cargar `build-errors-typescript` o `typescript-diagnosticos`."
15
+ evolvable: true # default para skill estandar
16
+ ---
17
+ # NestJS Experto — APIs TypeScript de Producción
18
+
19
+ ## Cuándo NO cargar
20
+
21
+ - El proyecto usa Express o Fastify sin NestJS — para Node.js sin framework opinionado cargar `node-experto`.
22
+ - La app es Next.js frontend — NestJS y Next.js son backends distintos; cargar `nextjs-experto`.
23
+ - Los errores son de tsconfig o tsc — cargar `build-errors-typescript`.
24
+
25
+ ## Estructura de proyecto
26
+
27
+ ```
28
+ src/
29
+ ├── app.module.ts
30
+ ├── main.ts
31
+ ├── common/
32
+ │ ├── decorators/
33
+ │ ├── filters/
34
+ │ ├── guards/
35
+ │ ├── interceptors/
36
+ │ └── pipes/
37
+ ├── config/
38
+ │ └── configuration.ts # ConfigModule con validación Joi/Zod
39
+ └── modules/
40
+ └── users/
41
+ ├── users.module.ts
42
+ ├── users.controller.ts
43
+ ├── users.service.ts
44
+ ├── dto/
45
+ │ ├── create-user.dto.ts
46
+ │ └── update-user.dto.ts
47
+ └── entities/
48
+ └── user.entity.ts
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Regla idiomática crítica: SIEMPRE constructor injection
54
+
55
+ ```typescript
56
+ // NUNCA — field injection
57
+ @Injectable()
58
+ export class UsersService {
59
+ @InjectRepository(User)
60
+ private usersRepository: Repository<User>; // MAL: dificulta testing y viola DI explícita
61
+ }
62
+
63
+ // SIEMPRE — constructor injection
64
+ @Injectable()
65
+ export class UsersService {
66
+ constructor(
67
+ @InjectRepository(User)
68
+ private readonly usersRepository: Repository<User>,
69
+ ) {}
70
+ }
71
+ ```
72
+
73
+ ---
74
+
75
+ ## DTO con class-validator y class-transformer
76
+
77
+ ```typescript
78
+ import { IsEmail, IsString, MinLength, IsOptional } from 'class-validator';
79
+ import { Transform } from 'class-transformer';
80
+ import { ApiProperty } from '@nestjs/swagger';
81
+
82
+ export class CreateUserDto {
83
+ @ApiProperty({ example: 'usuario@ejemplo.com' })
84
+ @IsEmail({}, { message: 'El correo no es válido' })
85
+ @Transform(({ value }: { value: unknown }) => {
86
+ if (typeof value === 'string') return value.toLowerCase().trim();
87
+ return value;
88
+ })
89
+ email!: string;
90
+
91
+ @ApiProperty({ example: 'contraseñaSegura123', minLength: 8 })
92
+ @IsString()
93
+ @MinLength(8, { message: 'La contraseña debe tener mínimo 8 caracteres' })
94
+ password!: string;
95
+
96
+ @ApiProperty({ required: false })
97
+ @IsOptional()
98
+ @IsString()
99
+ nombre?: string;
100
+ }
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Controller con Swagger y decoradores correctos
106
+
107
+ ```typescript
108
+ import {
109
+ Controller, Get, Post, Body, Param, HttpCode, HttpStatus, UseGuards,
110
+ } from '@nestjs/common';
111
+ import {
112
+ ApiTags, ApiBearerAuth, ApiCreatedResponse, ApiOkResponse,
113
+ ApiNotFoundResponse, ApiBadRequestResponse,
114
+ } from '@nestjs/swagger';
115
+ import { ParseUUIDPipe } from '@nestjs/common';
116
+ import { JwtAuthGuard } from '../common/guards/jwt-auth.guard';
117
+ import { UsersService } from './users.service';
118
+ import { CreateUserDto } from './dto/create-user.dto';
119
+ import { UserResponseDto } from './dto/user-response.dto';
120
+
121
+ @ApiTags('usuarios')
122
+ @ApiBearerAuth()
123
+ @UseGuards(JwtAuthGuard)
124
+ @Controller('usuarios')
125
+ export class UsersController {
126
+ constructor(private readonly usersService: UsersService) {}
127
+
128
+ @Post()
129
+ @HttpCode(HttpStatus.CREATED)
130
+ @ApiCreatedResponse({ type: UserResponseDto, description: 'Usuario creado' })
131
+ @ApiBadRequestResponse({ description: 'Datos de entrada inválidos' })
132
+ async crear(@Body() dto: CreateUserDto): Promise<UserResponseDto> {
133
+ return this.usersService.crear(dto);
134
+ }
135
+
136
+ @Get(':id')
137
+ @ApiOkResponse({ type: UserResponseDto })
138
+ @ApiNotFoundResponse({ description: 'Usuario no encontrado' })
139
+ async obtener(
140
+ @Param('id', ParseUUIDPipe) id: string,
141
+ ): Promise<UserResponseDto> {
142
+ return this.usersService.obtenerPorId(id);
143
+ }
144
+ }
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Service con manejo de errores tipado
150
+
151
+ ```typescript
152
+ import {
153
+ Injectable, NotFoundException, ConflictException,
154
+ } from '@nestjs/common';
155
+ import { InjectRepository } from '@nestjs/typeorm';
156
+ import { Repository } from 'typeorm';
157
+ import * as bcrypt from 'bcrypt';
158
+ import { User } from './entities/user.entity';
159
+ import { CreateUserDto } from './dto/create-user.dto';
160
+
161
+ @Injectable()
162
+ export class UsersService {
163
+ constructor(
164
+ @InjectRepository(User)
165
+ private readonly usersRepository: Repository<User>,
166
+ ) {}
167
+
168
+ async crear(dto: CreateUserDto): Promise<User> {
169
+ const existe = await this.usersRepository.findOneBy({ email: dto.email });
170
+ if (existe) {
171
+ throw new ConflictException('El correo ya está registrado');
172
+ }
173
+ const hashedPassword = await bcrypt.hash(dto.password, 12);
174
+ const usuario = this.usersRepository.create({
175
+ ...dto,
176
+ password: hashedPassword,
177
+ });
178
+ return this.usersRepository.save(usuario);
179
+ }
180
+
181
+ async obtenerPorId(id: string): Promise<User> {
182
+ const usuario = await this.usersRepository.findOneBy({ id });
183
+ if (!usuario) {
184
+ throw new NotFoundException(`Usuario ${id} no encontrado`);
185
+ }
186
+ return usuario;
187
+ }
188
+ }
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Module con exports correctos
194
+
195
+ ```typescript
196
+ import { Module } from '@nestjs/common';
197
+ import { TypeOrmModule } from '@nestjs/typeorm';
198
+ import { JwtModule } from '@nestjs/jwt';
199
+ import { ConfigService } from '@nestjs/config';
200
+ import { User } from './entities/user.entity';
201
+ import { UsersController } from './users.controller';
202
+ import { UsersService } from './users.service';
203
+ import { JwtStrategy } from '../common/guards/jwt.strategy';
204
+
205
+ @Module({
206
+ imports: [
207
+ TypeOrmModule.forFeature([User]),
208
+ JwtModule.registerAsync({
209
+ inject: [ConfigService],
210
+ useFactory: (config: ConfigService) => ({
211
+ secret: config.getOrThrow<string>('JWT_SECRET'),
212
+ signOptions: { expiresIn: '7d' },
213
+ }),
214
+ }),
215
+ ],
216
+ controllers: [UsersController],
217
+ providers: [UsersService, JwtStrategy],
218
+ exports: [UsersService], // Exportar solo lo que otros módulos necesitan
219
+ })
220
+ export class UsersModule {}
221
+ ```
222
+
223
+ ---
224
+
225
+ ## GlobalPipe y configuración de main.ts
226
+
227
+ ```typescript
228
+ import { NestFactory } from '@nestjs/core';
229
+ import { ValidationPipe } from '@nestjs/common';
230
+ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
231
+ import { AppModule } from './app.module';
232
+ import { HttpExceptionFilter } from './common/filters/http-exception.filter';
233
+
234
+ async function bootstrap(): Promise<void> {
235
+ const app = await NestFactory.create(AppModule);
236
+
237
+ app.useGlobalPipes(
238
+ new ValidationPipe({
239
+ whitelist: true, // Elimina propiedades no declaradas en DTO
240
+ forbidNonWhitelisted: true, // Lanza error si llegan propiedades extra
241
+ transform: true, // Transforma strings a tipos correctos
242
+ transformOptions: { enableImplicitConversion: true },
243
+ }),
244
+ );
245
+
246
+ app.useGlobalFilters(new HttpExceptionFilter());
247
+ app.enableCors({
248
+ origin: process.env['CORS_ORIGIN']?.split(',') ?? [],
249
+ credentials: true,
250
+ });
251
+
252
+ const config = new DocumentBuilder()
253
+ .setTitle('API')
254
+ .setVersion('1.0')
255
+ .addBearerAuth()
256
+ .build();
257
+ const document = SwaggerModule.createDocument(app, config);
258
+ SwaggerModule.setup('docs', app, document);
259
+
260
+ const port = process.env['PORT'] ?? 3000;
261
+ await app.listen(port);
262
+ }
263
+
264
+ void bootstrap();
265
+ ```
266
+
267
+ ---
268
+
269
+ ## MUST DO / MUST NOT DO
270
+
271
+ **MUST DO:**
272
+ - Constructor injection siempre (nunca field injection)
273
+ - Validar inputs con class-validator en todos los DTOs
274
+ - `whitelist: true` y `forbidNonWhitelisted: true` en ValidationPipe global
275
+ - Tipos explícitos en todas las funciones — cero `any`
276
+ - `getOrThrow` en ConfigService para variables de entorno requeridas
277
+ - Lanzar excepciones tipadas de `@nestjs/common`: NotFoundException, ConflictException, UnauthorizedException, ForbiddenException
278
+ - Documentar endpoints con @ApiTags, @ApiOperation, @ApiResponse
279
+
280
+ **MUST NOT DO:**
281
+ - Field injection con @Inject sin constructor
282
+ - `any` como tipo — usar `unknown` + type guards
283
+ - Lógica de negocio en controllers
284
+ - Hardcodear secrets — usar ConfigModule con validación al arranque
285
+ - Circular dependencies entre módulos — usar forwardRef() solo si es inevitable
286
+ - Olvidar `exports` en módulos cuando otro módulo necesita el servicio
287
+ - Omitir `readonly` en dependencias inyectadas del constructor
288
+
289
+ ---
290
+
291
+ ## Gotchas / Errores comunes no obvios
292
+
293
+ **Dependencia circular silenciosa entre módulos**: cuando el módulo A importa al módulo B y viceversa, NestJS no lanza un error claro — la aplicación arranca pero algunas dependencias son `undefined`. Causa: NestJS no puede resolver el orden de inicialización en un ciclo. Fix: extraer la dependencia compartida a un módulo C que ambos importen, o usar `forwardRef(() => ModuloB)` + `@Inject(forwardRef(() => ServicioB))` en el constructor si el ciclo es inevitable.
294
+
295
+ **`@InjectRepository` fuera del módulo que declara `TypeOrmModule.forFeature`**: el servicio arranca pero falla con `No repository for "Entidad" was found` en runtime. Causa: `@InjectRepository(Entidad)` requiere que `TypeOrmModule.forFeature([Entidad])` esté en el mismo módulo o que el módulo que lo incluye esté en `exports`. Fix: verificar que el módulo que usa el repositorio tiene `TypeOrmModule.forFeature([Entidad])` en sus `imports`, o que lo importa de otro módulo que lo exporta.
296
+
297
+ **`ConfigService.get()` retorna `undefined` en guards y middlewares**: ocurre cuando el guard se registra globalmente con `APP_GUARD` antes de que `ConfigModule` termine de inicializar. Causa: orden de inicialización en el contenedor DI. Fix: usar `ConfigService.getOrThrow()` para detectarlo temprano, y verificar que `ConfigModule.forRoot({ isGlobal: true })` está en `AppModule` como primer import.
298
+
299
+ **ValidationPipe con `transform: true` no convierte tipos en `@Param`**: el parámetro `id` llega como `string` aunque el DTO declare `@IsNumber()`. Causa: `@Param('id')` extrae strings del path — `transform: true` convierte con `class-transformer` pero el valor del path ya es string y no se convierte a number automáticamente sin `@Type(() => Number)`. Fix: agregar `@Type(() => Number)` en el DTO, o usar `ParseIntPipe` / `ParseUUIDPipe` directamente en el decorador `@Param`.
300
+
301
+ ## Tabla de referencias
302
+
303
+ | Tema | Archivo |
304
+ |------|---------|
305
+ | Módulos avanzados, DI circular, forwardRef, scopes, dynamic modules | recursos/modulos-di.md |
306
+ | Guards JWT, interceptors de logging/caché, exception filters, throttling | recursos/guards-interceptors.md |
307
+ | Testing con Jest, Test.createTestingModule, mocks de repositorios, e2e | recursos/testing-nestjs.md |
@@ -0,0 +1,339 @@
1
+ # Guards, Interceptors, Filters y Pipes Avanzados en NestJS
2
+
3
+ ## JwtAuthGuard con @Public() decorator
4
+
5
+ El patrón con Reflector permite marcar rutas públicas sin quitar el guard global.
6
+
7
+ ```typescript
8
+ // common/decorators/public.decorator.ts
9
+ import { SetMetadata } from '@nestjs/common';
10
+
11
+ export const IS_PUBLIC_KEY = 'isPublic';
12
+ export const Public = (): MethodDecorator & ClassDecorator =>
13
+ SetMetadata(IS_PUBLIC_KEY, true);
14
+
15
+ // common/guards/jwt-auth.guard.ts
16
+ import { Injectable, ExecutionContext } from '@nestjs/common';
17
+ import { Reflector } from '@nestjs/core';
18
+ import { AuthGuard } from '@nestjs/passport';
19
+ import { IS_PUBLIC_KEY } from '../decorators/public.decorator';
20
+
21
+ @Injectable()
22
+ export class JwtAuthGuard extends AuthGuard('jwt') {
23
+ constructor(private readonly reflector: Reflector) {
24
+ super();
25
+ }
26
+
27
+ canActivate(context: ExecutionContext): boolean | Promise<boolean> {
28
+ const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
29
+ context.getHandler(),
30
+ context.getClass(),
31
+ ]);
32
+ if (isPublic) return true;
33
+ // La llamada a super activa la estrategia Passport
34
+ return super.canActivate(context) as boolean | Promise<boolean>;
35
+ }
36
+ }
37
+
38
+ // Registro global en app.module.ts o main.ts
39
+ app.useGlobalGuards(new JwtAuthGuard(reflector));
40
+
41
+ // Uso en controllers
42
+ @Public()
43
+ @Post('auth/login')
44
+ async login(@Body() dto: LoginDto): Promise<TokenResponseDto> {
45
+ return this.authService.login(dto);
46
+ }
47
+ ```
48
+
49
+ ---
50
+
51
+ ## RolesGuard con @Roles() decorator
52
+
53
+ ```typescript
54
+ // common/decorators/roles.decorator.ts
55
+ import { SetMetadata } from '@nestjs/common';
56
+
57
+ export type AppRole = 'ADMIN' | 'EDITOR' | 'LECTOR';
58
+
59
+ export const ROLES_KEY = 'roles';
60
+ export const Roles = (...roles: AppRole[]): MethodDecorator & ClassDecorator =>
61
+ SetMetadata(ROLES_KEY, roles);
62
+
63
+ // common/guards/roles.guard.ts
64
+ import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
65
+ import { Reflector } from '@nestjs/core';
66
+ import { ROLES_KEY, AppRole } from '../decorators/roles.decorator';
67
+
68
+ interface AuthenticatedRequest extends Request {
69
+ user: { id: string; email: string; rol: AppRole };
70
+ }
71
+
72
+ @Injectable()
73
+ export class RolesGuard implements CanActivate {
74
+ constructor(private readonly reflector: Reflector) {}
75
+
76
+ canActivate(context: ExecutionContext): boolean {
77
+ const rolesRequeridos = this.reflector.getAllAndOverride<AppRole[]>(
78
+ ROLES_KEY,
79
+ [context.getHandler(), context.getClass()],
80
+ );
81
+ if (!rolesRequeridos || rolesRequeridos.length === 0) return true;
82
+
83
+ const request = context.switchToHttp().getRequest<AuthenticatedRequest>();
84
+ const { user } = request;
85
+
86
+ if (!rolesRequeridos.includes(user.rol)) {
87
+ throw new ForbiddenException(
88
+ `Se requiere uno de los roles: ${rolesRequeridos.join(', ')}`,
89
+ );
90
+ }
91
+ return true;
92
+ }
93
+ }
94
+
95
+ // Uso combinado en controller
96
+ @UseGuards(JwtAuthGuard, RolesGuard)
97
+ @Roles('ADMIN')
98
+ @Delete(':id')
99
+ async eliminar(@Param('id', ParseUUIDPipe) id: string): Promise<void> {
100
+ return this.usersService.eliminar(id);
101
+ }
102
+ ```
103
+
104
+ ---
105
+
106
+ ## LoggingInterceptor con tiempo de ejecución
107
+
108
+ ```typescript
109
+ // common/interceptors/logging.interceptor.ts
110
+ import {
111
+ Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger,
112
+ } from '@nestjs/common';
113
+ import { Observable } from 'rxjs';
114
+ import { tap } from 'rxjs/operators';
115
+
116
+ @Injectable()
117
+ export class LoggingInterceptor implements NestInterceptor {
118
+ private readonly logger = new Logger(LoggingInterceptor.name);
119
+
120
+ intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
121
+ const request = context.switchToHttp().getRequest<{
122
+ method: string;
123
+ url: string;
124
+ }>();
125
+ const { method, url } = request;
126
+ const inicio = Date.now();
127
+
128
+ return next.handle().pipe(
129
+ tap({
130
+ next: () => {
131
+ const duracionMs = Date.now() - inicio;
132
+ this.logger.log(`${method} ${url} — ${duracionMs}ms`);
133
+ },
134
+ error: (error: unknown) => {
135
+ const duracionMs = Date.now() - inicio;
136
+ const mensaje = error instanceof Error ? error.message : 'Error desconocido';
137
+ this.logger.error(`${method} ${url} — ${duracionMs}ms — ${mensaje}`);
138
+ },
139
+ }),
140
+ );
141
+ }
142
+ }
143
+ ```
144
+
145
+ ---
146
+
147
+ ## TransformInterceptor — envolver responses en { data, metadata }
148
+
149
+ ```typescript
150
+ // common/interceptors/transform.interceptor.ts
151
+ import {
152
+ Injectable, NestInterceptor, ExecutionContext, CallHandler,
153
+ } from '@nestjs/common';
154
+ import { Observable } from 'rxjs';
155
+ import { map } from 'rxjs/operators';
156
+
157
+ export interface ApiResponse<T> {
158
+ data: T;
159
+ timestamp: string;
160
+ path: string;
161
+ }
162
+
163
+ @Injectable()
164
+ export class TransformInterceptor<T>
165
+ implements NestInterceptor<T, ApiResponse<T>>
166
+ {
167
+ intercept(
168
+ context: ExecutionContext,
169
+ next: CallHandler<T>,
170
+ ): Observable<ApiResponse<T>> {
171
+ const request = context.switchToHttp().getRequest<{ url: string }>();
172
+
173
+ return next.handle().pipe(
174
+ map((data) => ({
175
+ data,
176
+ timestamp: new Date().toISOString(),
177
+ path: request.url,
178
+ })),
179
+ );
180
+ }
181
+ }
182
+
183
+ // Registro global en main.ts
184
+ app.useGlobalInterceptors(new TransformInterceptor());
185
+ ```
186
+
187
+ ---
188
+
189
+ ## HttpExceptionFilter — formato de error estandarizado
190
+
191
+ ```typescript
192
+ // common/filters/http-exception.filter.ts
193
+ import {
194
+ ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus, Logger,
195
+ } from '@nestjs/common';
196
+ import type { Request, Response } from 'express';
197
+
198
+ interface ErrorResponse {
199
+ statusCode: number;
200
+ timestamp: string;
201
+ path: string;
202
+ method: string;
203
+ message: string | string[];
204
+ error: string;
205
+ }
206
+
207
+ @Catch()
208
+ export class HttpExceptionFilter implements ExceptionFilter {
209
+ private readonly logger = new Logger(HttpExceptionFilter.name);
210
+
211
+ catch(exception: unknown, host: ArgumentsHost): void {
212
+ const ctx = host.switchToHttp();
213
+ const response = ctx.getResponse<Response>();
214
+ const request = ctx.getRequest<Request>();
215
+
216
+ let statusCode: number;
217
+ let message: string | string[];
218
+ let error: string;
219
+
220
+ if (exception instanceof HttpException) {
221
+ statusCode = exception.getStatus();
222
+ const responseBody = exception.getResponse();
223
+ if (typeof responseBody === 'object' && responseBody !== null) {
224
+ const body = responseBody as Record<string, unknown>;
225
+ message = (body['message'] as string | string[]) ?? exception.message;
226
+ error = (body['error'] as string) ?? exception.name;
227
+ } else {
228
+ message = exception.message;
229
+ error = exception.name;
230
+ }
231
+ } else {
232
+ statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
233
+ message = 'Error interno del servidor';
234
+ error = 'InternalServerError';
235
+ // Log completo solo para errores no esperados
236
+ this.logger.error(
237
+ `Error no controlado: ${exception instanceof Error ? exception.message : String(exception)}`,
238
+ exception instanceof Error ? exception.stack : undefined,
239
+ );
240
+ }
241
+
242
+ const errorResponse: ErrorResponse = {
243
+ statusCode,
244
+ timestamp: new Date().toISOString(),
245
+ path: request.url,
246
+ method: request.method,
247
+ message,
248
+ error,
249
+ };
250
+
251
+ response.status(statusCode).json(errorResponse);
252
+ }
253
+ }
254
+ ```
255
+
256
+ ---
257
+
258
+ ## Throttler guard — rate limiting
259
+
260
+ ```typescript
261
+ // Instalación: npm install @nestjs/throttler
262
+ // app.module.ts
263
+ import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
264
+ import { APP_GUARD } from '@nestjs/core';
265
+
266
+ @Module({
267
+ imports: [
268
+ ThrottlerModule.forRootAsync({
269
+ inject: [ConfigService],
270
+ useFactory: (config: ConfigService) => ([{
271
+ name: 'global',
272
+ ttl: config.get<number>('THROTTLE_TTL_MS') ?? 60_000,
273
+ limit: config.get<number>('THROTTLE_LIMIT') ?? 100,
274
+ }]),
275
+ }),
276
+ ],
277
+ providers: [
278
+ // Guard global — aplica a todos los endpoints
279
+ { provide: APP_GUARD, useClass: ThrottlerGuard },
280
+ ],
281
+ })
282
+ export class AppModule {}
283
+
284
+ // Sobrescribir límite en un endpoint específico
285
+ import { Throttle, SkipThrottle } from '@nestjs/throttler';
286
+
287
+ @Throttle({ default: { ttl: 60_000, limit: 5 } })
288
+ @Post('auth/login')
289
+ async login(@Body() dto: LoginDto): Promise<TokenResponseDto> {
290
+ return this.authService.login(dto);
291
+ }
292
+
293
+ @SkipThrottle()
294
+ @Get('health')
295
+ health(): { status: string } {
296
+ return { status: 'ok' };
297
+ }
298
+ ```
299
+
300
+ ---
301
+
302
+ ## ValidationPipe avanzado con mensajes personalizados
303
+
304
+ ```typescript
305
+ // common/pipes/validation.pipe.ts
306
+ import { ValidationPipe, UnprocessableEntityException } from '@nestjs/common';
307
+ import { ValidationError } from 'class-validator';
308
+
309
+ type FieldErrors = Record<string, string[]>;
310
+
311
+ function extraerErrores(errores: ValidationError[], prefijo = ''): FieldErrors {
312
+ return errores.reduce<FieldErrors>((acum, error) => {
313
+ const campo = prefijo ? `${prefijo}.${error.property}` : error.property;
314
+
315
+ if (error.constraints) {
316
+ acum[campo] = Object.values(error.constraints);
317
+ }
318
+ if (error.children && error.children.length > 0) {
319
+ Object.assign(acum, extraerErrores(error.children, campo));
320
+ }
321
+ return acum;
322
+ }, {});
323
+ }
324
+
325
+ export const globalValidationPipe = new ValidationPipe({
326
+ whitelist: true,
327
+ forbidNonWhitelisted: true,
328
+ transform: true,
329
+ transformOptions: { enableImplicitConversion: true },
330
+ exceptionFactory: (errores: ValidationError[]) => {
331
+ const campos = extraerErrores(errores);
332
+ return new UnprocessableEntityException({
333
+ message: 'Error de validación',
334
+ error: 'UnprocessableEntity',
335
+ campos,
336
+ });
337
+ },
338
+ });
339
+ ```