jarvis-ai-framework 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.
- package/AGENTS.md +416 -0
- package/LICENSE +21 -0
- package/README.md +190 -0
- package/agents/AGENTS.md +234 -0
- package/agents/README.md +309 -0
- package/agents/engineering/data/eng.data-engineer.agent.md +309 -0
- package/agents/engineering/eng.agent.md +303 -0
- package/agents/engineering/eng.bug-hunter.md +386 -0
- package/agents/engineering/eng.cybersecurity.agent.md +503 -0
- package/agents/engineering/eng.dev-code-reviewer.md +148 -0
- package/agents/engineering/eng.docs-writer.md +152 -0
- package/agents/engineering/eng.frontend.agent.md +117 -0
- package/agents/engineering/eng.rpa.agent.md +215 -0
- package/agents/engineering/eng.tech-analyst.agent.md +102 -0
- package/agents/engineering/eng.ux-designer.agent.md +193 -0
- package/agents/engineering/qa/eng.qa.cypress-specialist.md +109 -0
- package/agents/engineering/qa/eng.qa.quality-champion-task-agent.md +85 -0
- package/agents/engineering/qa/eng.qa.quality-strategist.md +111 -0
- package/agents/engineering/qa/eng.qa.test-architect.md +400 -0
- package/agents/engineering/qa/eng.qa.test-planner.md +477 -0
- package/agents/engineering/qa/eng.qa.testing-engineer.md +339 -0
- package/agents/product/prod.pm-checker.md +52 -0
- package/bin/commands/docs-publish.js +184 -0
- package/bin/commands/docs-sync.js +139 -0
- package/bin/commands/info.js +87 -0
- package/bin/commands/init.js +237 -0
- package/bin/commands/install-rtk.js +90 -0
- package/bin/commands/list.js +48 -0
- package/bin/commands/qa-signoff.js +112 -0
- package/bin/commands/whoami.js +43 -0
- package/bin/jarvis.js +159 -0
- package/bin/lib/auth/session.js +56 -0
- package/bin/lib/config/constants.js +123 -0
- package/bin/lib/config/ide-config.js +233 -0
- package/bin/lib/core/scanner.js +124 -0
- package/bin/lib/core/sync-engine.js +551 -0
- package/bin/lib/docs/fetch-file.sh +41 -0
- package/bin/lib/docs/publish-file.sh +284 -0
- package/bin/lib/docs/validate-frontmatter.js +157 -0
- package/bin/lib/env-loader.js +198 -0
- package/bin/lib/tasks/comment.js +131 -0
- package/bin/lib/utils/git-parser.js +145 -0
- package/bin/lib/utils/logger.js +104 -0
- package/bin/lib/utils/npmrc-parser.js +106 -0
- package/bin/lib/utils/paths.js +55 -0
- package/bin/lib/utils/ui.js +59 -0
- package/bin/lib/vcs/api.js +312 -0
- package/bin/lib/vcs/create-issue.js +43 -0
- package/bin/lib/vcs/create-merge.js +43 -0
- package/bin/lib/vcs/fetch-raw.js +30 -0
- package/bin/postinstall.js +41 -0
- package/members.md +25 -0
- package/package.json +55 -0
- package/rules/AGENTS.md +205 -0
- package/rules/engineering/data/data-rules.md +200 -0
- package/rules/engineering/eng-rules.md +243 -0
- package/rules/engineering/eng-security-rules.md +186 -0
- package/rules/engineering/eng.breakdown-subtasks-rules.md +585 -0
- package/rules/engineering/eng.bump-rules.md +27 -0
- package/rules/engineering/eng.docs-scraping-rules.md +64 -0
- package/rules/engineering/eng.downstream-flow-rules.md +297 -0
- package/rules/engineering/eng.integrations-rules.md +73 -0
- package/rules/engineering/eng.plan-rules.md +333 -0
- package/rules/engineering/eng.pr-rules.md +359 -0
- package/rules/engineering/eng.pre-pr-rules.md +103 -0
- package/rules/engineering/eng.start-rules.md +246 -0
- package/rules/engineering/eng.tech-spec-rules.md +968 -0
- package/rules/engineering/eng.work-rules.md +312 -0
- package/rules/engineering/frontend/eng.frontend-rules.md +147 -0
- package/rules/engineering/qa/eng.qa.cypress-standards-rules.md +259 -0
- package/rules/engineering/qa/eng.qa.exploratory-session-rules.md +137 -0
- package/rules/engineering/qa/eng.qa.quality-gate-scoring-rules.md +181 -0
- package/rules/engineering/qa/eng.qa.tech-spec-validation-criteria-rules.md +120 -0
- package/rules/engineering/rpa/eng.rpa-rules.md +230 -0
- package/rules/product/README.md +24 -0
- package/rules/product/prod-rules.md +151 -0
- package/rules/rtk-rules.md +68 -0
- package/skills/AGENTS.md +290 -0
- package/skills/SKILLS-ROADMAP.md +333 -0
- package/skills/churn-audit/SKILL.md +385 -0
- package/skills/context-detect/SKILL.md +399 -0
- package/skills/context-detect/assets/context-profile-template.md +127 -0
- package/skills/docs-central/README.md +310 -0
- package/skills/docs-central/SKILL.md +423 -0
- package/skills/docs-index/SKILL.md +377 -0
- package/skills/eng-ai-engineer/SKILL.md +296 -0
- package/skills/eng-arch-c4/SKILL.md +358 -0
- package/skills/eng-arch-c4/assets/example-code.md +189 -0
- package/skills/eng-arch-c4/assets/example-component.md +105 -0
- package/skills/eng-arch-c4/assets/example-container.md +104 -0
- package/skills/eng-arch-c4/assets/example-context.md +81 -0
- package/skills/eng-backend/SKILL.md +776 -0
- package/skills/eng-browser-extension-builder/SKILL.md +385 -0
- package/skills/eng-cybersecurity/SKILL.md +645 -0
- package/skills/eng-data-bi/SKILL.md +199 -0
- package/skills/eng-data-debug/SKILL.md +307 -0
- package/skills/eng-data-engineer/SKILL.md +256 -0
- package/skills/eng-data-onboard/SKILL.md +310 -0
- package/skills/eng-data-orchestrator/SKILL.md +426 -0
- package/skills/eng-design-system/SKILL.md +619 -0
- package/skills/eng-docs-write/SKILL.md +312 -0
- package/skills/eng-frontend/SKILL.md +913 -0
- package/skills/eng-jira-comment/SKILL.md +17 -0
- package/skills/eng-microfrontend/SKILL.md +602 -0
- package/skills/eng-ms-trace/SKILL.md +469 -0
- package/skills/eng-nestjs/SKILL.md +791 -0
- package/skills/eng-performance-engineer/SKILL.md +312 -0
- package/skills/eng-pr/SKILL.md +339 -0
- package/skills/eng-qa-a11y-audit/SKILL.md +269 -0
- package/skills/eng-qa-bug-report/SKILL.md +1088 -0
- package/skills/eng-qa-bug-report/TASK_MANAGERS.md +138 -0
- package/skills/eng-qa-cypress-e2e/SKILL.md +177 -0
- package/skills/eng-qa-dev-guide/SKILL.md +164 -0
- package/skills/eng-qa-e2e/SKILL.md +400 -0
- package/skills/eng-qa-e2e-spec-writer/SKILL.md +322 -0
- package/skills/eng-qa-exploratory/SKILL.md +188 -0
- package/skills/eng-qa-gate/SKILL.md +370 -0
- package/skills/eng-qa-gate/assets/checklist-validacao.md +291 -0
- package/skills/eng-qa-graphql-contract/SKILL.md +256 -0
- package/skills/eng-qa-quality-report/SKILL.md +412 -0
- package/skills/eng-qa-test-plan/SKILL.md +466 -0
- package/skills/eng-qa-test-plan/assets/test-coverage-template.md +92 -0
- package/skills/eng-qa-test-plan/assets/test-patterns.md +178 -0
- package/skills/eng-qa-testsprite/SKILL.md +325 -0
- package/skills/eng-qa-testsprite/references/testsprite-mcp.md +224 -0
- package/skills/eng-qa-unit-test/SKILL.md +471 -0
- package/skills/eng-rabbitmq/SKILL.md +661 -0
- package/skills/eng-scraper/SKILL.md +683 -0
- package/skills/eng-scraper-robot-builder/SKILL.md +370 -0
- package/skills/eng-security-patch/SKILL.md +378 -0
- package/skills/eng-security-triage/SKILL.md +266 -0
- package/skills/eng-task-comment/SKILL.md +60 -0
- package/skills/eng-tech-analyst/SKILL.md +529 -0
- package/skills/eng-threat-model/SKILL.md +161 -0
- package/skills/init-jarvis/SKILL.md +1304 -0
- package/skills/init-jarvis/assets/mcp-configs.md +389 -0
- package/skills/init-jarvis/assets/onboarding-checklist.md +104 -0
- package/skills/init-jarvis/assets/setup-guide.md +360 -0
- package/skills/lovable-prompt-generator/SKILL.md +304 -0
- package/skills/prod-roadmap-report/README.md +303 -0
- package/skills/prod-roadmap-report/SKILL.md +198 -0
- package/skills/prod-roadmap-report/commands/status.compiled.single.team.md +23 -0
- package/skills/prod-roadmap-report/commands/status.list.projects.md +17 -0
- package/skills/prod-roadmap-report/commands/status.memory.md +192 -0
- package/skills/prod-roadmap-report/commands/status.roadmap.preview.md +94 -0
- package/skills/prod-roadmap-report/references/detailed-guide.md +236 -0
- package/skills/prod-roadmap-report/rules/detailed-guide.md +237 -0
- package/skills/prod-roadmap-report/rules/status-report-rules.md +44 -0
- package/skills/prod-roadmap-report/templates/template-multiple-teams-compiled-status.md +53 -0
- package/skills/prod-roadmap-report/templates/template-projects-list.md +23 -0
- package/skills/prod-roadmap-report/templates/template-single-team-compiled-status.md +60 -0
- package/skills/prod-roadmap-report/templates/template-single-team-status.md +49 -0
- package/skills/prod-specs/SKILL.md +108 -0
- package/skills/prod-specs/references/prod.spec.clarify.md +176 -0
- package/skills/prod-specs/references/prod.spec.epic.md +107 -0
- package/skills/prod-specs/references/prod.spec.frd.md +135 -0
- package/skills/prod-specs/references/prod.spec.issue.md +145 -0
- package/skills/prod-specs/references/prod.spec.prd.md +118 -0
- package/skills/prod-specs/rules/prod-spec-rules.md +186 -0
- package/skills/prod-specs/templates/prod-breakdown-template.md +136 -0
- package/skills/prod-specs/templates/prod-epic-template.md +76 -0
- package/skills/prod-specs/templates/prod-frd-template.md +172 -0
- package/skills/prod-specs/templates/prod-issue-template.md +68 -0
- package/skills/prod-specs/templates/prod-prd-full-template.md +159 -0
- package/skills/prod-specs/templates/prod-prd-template.md +173 -0
- package/skills/prod-specs-update/SKILL.md +272 -0
- package/skills/report-issue/SKILL.md +156 -0
- package/taxonomy.md +270 -0
- package/templates/AGENTS.md +189 -0
- package/templates/CDD aplicado a Prompts.md +182 -0
- package/templates/ENV-template.md +187 -0
- package/templates/engineering/AGENTS-template.md +71 -0
- package/templates/engineering/ARD-template.md +193 -0
- package/templates/engineering/CONTACTS-template.md +135 -0
- package/templates/engineering/PR-template.md +40 -0
- package/templates/engineering/RFC-Playbook.md +325 -0
- package/templates/engineering/RFC-template.md +199 -0
- package/templates/engineering/architecture-template.md +277 -0
- package/templates/engineering/breakdown-subtasks-template.md +582 -0
- package/templates/engineering/c4-model-template.md +516 -0
- package/templates/engineering/data-contract-template.md +135 -0
- package/templates/engineering/data-pipeline-template.md +163 -0
- package/templates/engineering/plan-template.md +255 -0
- package/templates/engineering/qa/eng.qa.quality-gate-examples-template.md +311 -0
- package/templates/engineering/qa/eng.qa.quality-gate-report-template.md +249 -0
- package/templates/engineering/qa/qa.cypress-test-template.md +172 -0
- package/templates/engineering/qa/qa.exploratory-session-template.md +148 -0
- package/templates/engineering/qa/qa.quality-report-template.md +130 -0
- package/templates/engineering/qa/qa.release-signoff-template.md +54 -0
- package/templates/engineering/qa/qa.sprint-plan-template.md +49 -0
- package/templates/engineering/swagger-template.md +145 -0
- package/templates/engineering/tech-spec-template.md +497 -0
- package/templates/engineering/work-progress-template.md +155 -0
- package/workflows/AGENTS.md +240 -0
- package/workflows/README.md +160 -0
- package/workflows/all-tools.md +11 -0
- package/workflows/engineering/data/data.contract.md +202 -0
- package/workflows/engineering/data/data.new-pipeline.md +234 -0
- package/workflows/engineering/eng.breakdown-subtasks.md +420 -0
- package/workflows/engineering/eng.bug-audit.md +591 -0
- package/workflows/engineering/eng.build-tech-spec.md +1116 -0
- package/workflows/engineering/eng.create-ard-from-code.md +259 -0
- package/workflows/engineering/eng.create-ard.md +382 -0
- package/workflows/engineering/eng.create-rfc.md +245 -0
- package/workflows/engineering/eng.debug.md +479 -0
- package/workflows/engineering/eng.docs.md +40 -0
- package/workflows/engineering/eng.light-arch.md +84 -0
- package/workflows/engineering/eng.plan.md +213 -0
- package/workflows/engineering/eng.pr.md +466 -0
- package/workflows/engineering/eng.pre-pr.md +167 -0
- package/workflows/engineering/eng.review.md +185 -0
- package/workflows/engineering/eng.rpa.robot.md +342 -0
- package/workflows/engineering/eng.security-audit.md +312 -0
- package/workflows/engineering/eng.security-incident.md +275 -0
- package/workflows/engineering/eng.security-pipeline.md +210 -0
- package/workflows/engineering/eng.security-review.md +235 -0
- package/workflows/engineering/eng.start.md +494 -0
- package/workflows/engineering/eng.work.md +558 -0
- package/workflows/engineering/frontend/eng.frontend-component.md +190 -0
- package/workflows/engineering/frontend/eng.frontend-perf-audit.md +375 -0
- package/workflows/engineering/frontend/eng.frontend-review.md +185 -0
- package/workflows/engineering/qa/eng.qa-dev-quality-guide.md +51 -0
- package/workflows/engineering/qa/eng.qa-e2e-test-generation.md +51 -0
- package/workflows/engineering/qa/eng.qa-exploratory-session.md +60 -0
- package/workflows/engineering/qa/eng.qa-quality-gate-validation.md +202 -0
- package/workflows/engineering/qa/eng.qa-quality-report.md +83 -0
- package/workflows/engineering/qa/eng.qa-refinement-entry.md +83 -0
- package/workflows/engineering/qa/eng.qa-release-signoff.md +170 -0
- package/workflows/engineering/qa/eng.qa-sprint-planning.md +100 -0
- package/workflows/engineering/ta/eng.ta.atendimento.md +93 -0
- package/workflows/product/prod.roadmap.preview.md +110 -0
- package/workflows/product/prod.spec.breakdown.md +163 -0
- package/workflows/product/prod.spec.clarify.md +178 -0
- package/workflows/product/prod.spec.epic.md +154 -0
- package/workflows/product/prod.spec.frd.md +96 -0
- package/workflows/product/prod.spec.issue.md +145 -0
- package/workflows/product/prod.spec.md +60 -0
- package/workflows/product/prod.spec.prd.md +100 -0
- package/workflows/taxonomy.md +92 -0
- package/workflows/warm-up.md +574 -0
|
@@ -0,0 +1,791 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eng-nestjs
|
|
3
|
+
description: >
|
|
4
|
+
Especialista em NestJS com domínio profundo em arquitetura de módulos, injeção de dependências,
|
|
5
|
+
guards, interceptors, pipes, middleware, testes com Jest/Supertest, TypeORM/Prisma e autenticação
|
|
6
|
+
com Passport/JWT. Inclui diagnóstico de erros de DI, decisões arquiteturais e padrões enterprise.
|
|
7
|
+
Trigger: Use para problemas ou features específicas do framework NestJS — módulos, DI, decorators,
|
|
8
|
+
ciclo de vida de requisição, configuração avançada, debugging de erros ou implementação de testes.
|
|
9
|
+
license: AGPL-3.0
|
|
10
|
+
compatibility: Designed for Claude Code (or similar products)
|
|
11
|
+
allowed-tools: Read Write Edit Glob Grep Bash
|
|
12
|
+
metadata:
|
|
13
|
+
author: jarvis-team
|
|
14
|
+
version: "2.0"
|
|
15
|
+
# Campos Claude Code-specific (não fazem parte da spec oficial agentskills.io):
|
|
16
|
+
argument-hint: "[módulo|guard|interceptor|pipe|teste|auth|config|erro] [contexto]"
|
|
17
|
+
disable-model-invocation: false
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Eng NestJS - Especialista em Framework NestJS
|
|
21
|
+
|
|
22
|
+
Você é um **especialista em NestJS** com domínio profundo em arquitetura de módulos, injeção de dependências, ciclo de vida de requisição, testing e padrões enterprise com Node.js e TypeScript.
|
|
23
|
+
|
|
24
|
+
## Objetivo
|
|
25
|
+
|
|
26
|
+
Resolver problemas específicos do framework NestJS e aplicar seus padrões avançados corretamente — desde a organização de módulos até debugging de erros de DI, configuração de guards, interceptors e testes.
|
|
27
|
+
|
|
28
|
+
## Entrada
|
|
29
|
+
|
|
30
|
+
- `$ARGUMENTS` - Problema, módulo ou feature NestJS a trabalhar (ex: `circular-dependency`, `guard-jwt`, `interceptor-logging`, `teste-service`, `configurar-config-module`)
|
|
31
|
+
|
|
32
|
+
## Recursos
|
|
33
|
+
|
|
34
|
+
- **ENV**: `$IDE/ENV.md` (variáveis de ambiente e stack do projeto)
|
|
35
|
+
- **Saída**: código TypeScript NestJS no repositório atual
|
|
36
|
+
- **Referência backend**: `$IDE/skills/eng-backend/SKILL.md` (para APIs, RabbitMQ, caching)
|
|
37
|
+
- **Guia de testes**: (guia de testes do projeto)
|
|
38
|
+
- **Guia de logs**: (guia de logs do projeto)
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Pré-requisito
|
|
43
|
+
|
|
44
|
+
Verificar setup do projeto antes de qualquer implementação:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Verificar se é projeto NestJS
|
|
48
|
+
test -f nest-cli.json && echo "NestJS CLI detectado"
|
|
49
|
+
grep "@nestjs/core" package.json
|
|
50
|
+
|
|
51
|
+
# Detectar ORM em uso
|
|
52
|
+
grep -E "@nestjs/typeorm|@prisma/client|@nestjs/mongoose" package.json
|
|
53
|
+
|
|
54
|
+
# Detectar autenticação configurada
|
|
55
|
+
grep -E "@nestjs/passport|@nestjs/jwt" package.json
|
|
56
|
+
|
|
57
|
+
# Verificar estrutura de módulos
|
|
58
|
+
find src -name "*.module.ts" | head -10
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Quando Usar
|
|
64
|
+
|
|
65
|
+
Use este skill quando:
|
|
66
|
+
- Resolver erros de injeção de dependências (`Nest can't resolve dependencies of...`)
|
|
67
|
+
- Configurar ou depurar guards, interceptors, pipes ou middleware
|
|
68
|
+
- Estruturar módulos e definir boundaries de domínio
|
|
69
|
+
- Implementar autenticação com Passport.js e JWT
|
|
70
|
+
- Configurar `ConfigModule` com validação e variáveis de ambiente
|
|
71
|
+
- Criar exception filters e tratamento de erros customizados
|
|
72
|
+
- Debugging de ciclo de vida, providers e módulos dinâmicos
|
|
73
|
+
- Implementar ou revisar testes unitários e de integração
|
|
74
|
+
|
|
75
|
+
**NÃO usar quando:**
|
|
76
|
+
- A tarefa é sobre design de APIs, paginação, RabbitMQ, caching → usar `eng-backend`
|
|
77
|
+
- A tarefa envolve scraping ou extração de dados → usar `eng-scraper`
|
|
78
|
+
- A tarefa é puramente de banco de dados (queries, migrations, schema) → usar `eng-database`
|
|
79
|
+
- Problema é de TypeScript puro (tipos, generics) → usar `typescript-type-expert`
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Validação de Entrada
|
|
84
|
+
|
|
85
|
+
Se `$ARGUMENTS` está vazio, solicitar ao usuário:
|
|
86
|
+
- Qual é o erro ou comportamento inesperado?
|
|
87
|
+
- Qual módulo/componente está envolvido?
|
|
88
|
+
- Qual versão do NestJS está em uso?
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Padrões Críticos
|
|
93
|
+
|
|
94
|
+
### Padrão 1: Sempre Ler o Código Antes de Sugerir
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Ver estrutura de módulos existentes
|
|
98
|
+
find src -name "*.module.ts" -type f | xargs grep -l "imports\|providers\|exports"
|
|
99
|
+
|
|
100
|
+
# Ver como DI está configurada para o contexto
|
|
101
|
+
grep -r "@Injectable\|@Module" src/ --include="*.ts" -l
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Padrão 2: Ordem de Execução do Ciclo de Requisição
|
|
105
|
+
|
|
106
|
+
Sempre que houver dúvida sobre guards, interceptors ou pipes:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Middleware → Guards → Interceptors (antes) → Pipes → Route Handler → Interceptors (depois) → Exception Filters
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Padrão 3: Diagnóstico de Erros de DI
|
|
113
|
+
|
|
114
|
+
Quando aparecer `Nest can't resolve dependencies of [Service] (?, +)`:
|
|
115
|
+
|
|
116
|
+
1. O `?` indica qual parâmetro no construtor está faltando
|
|
117
|
+
2. Contar os parâmetros do construtor na ordem para identificar qual está ausente
|
|
118
|
+
3. Verificar se o provider está em `providers[]` do módulo correto
|
|
119
|
+
4. Se cruza fronteiras de módulo, verificar `exports[]` do módulo de origem
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// ❌ Erro comum: exportar o módulo em vez do service
|
|
123
|
+
@Module({
|
|
124
|
+
exports: [UserModule] // ERRADO
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// ✅ Correto: exportar o service
|
|
128
|
+
@Module({
|
|
129
|
+
exports: [UserService] // CORRETO
|
|
130
|
+
})
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Padrão 4: Dependência Circular — Detectar e Resolver
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Detectar circular dependency no build
|
|
137
|
+
npm run build -- --watch=false 2>&1 | grep -i "circular"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**`forwardRef` é proibido neste projeto.** É uma má prática reconhecida pelo próprio framework — mascara problemas reais de design.
|
|
141
|
+
|
|
142
|
+
Soluções em ordem obrigatória de preferência:
|
|
143
|
+
1. **Refatorar a estrutura de módulos** — rever responsabilidades e boundaries
|
|
144
|
+
2. **Extrair lógica compartilhada para um terceiro módulo** (recomendado)
|
|
145
|
+
3. **Ajustar escopo do provider** — mudar para `TRANSIENT` ou `REQUEST` se apropriado
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// ✅ Solução correta: extrair para módulo compartilhado
|
|
149
|
+
@Module({
|
|
150
|
+
providers: [SharedService],
|
|
151
|
+
exports: [SharedService],
|
|
152
|
+
})
|
|
153
|
+
export class SharedModule {}
|
|
154
|
+
|
|
155
|
+
// AModule e BModule importam SharedModule em vez de dependerem um do outro
|
|
156
|
+
@Module({
|
|
157
|
+
imports: [SharedModule],
|
|
158
|
+
})
|
|
159
|
+
export class AModule {}
|
|
160
|
+
|
|
161
|
+
@Module({
|
|
162
|
+
imports: [SharedModule],
|
|
163
|
+
})
|
|
164
|
+
export class BModule {}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Padrão 5: Antes de Implementar Testes — Verificar Schematics
|
|
168
|
+
|
|
169
|
+
Antes de escrever qualquer teste (unitário ou de integração), verificar se existe um schematic com modelo:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Verificar schematics disponíveis no projeto
|
|
173
|
+
find . -name "*.schematic.json" -o -name "collection.json" 2>/dev/null | head -5
|
|
174
|
+
|
|
175
|
+
# Verificar se há templates de teste na CLI configurada
|
|
176
|
+
cat nest-cli.json | grep -i "schematic\|collection"
|
|
177
|
+
|
|
178
|
+
# Verificar se há arquivos *.spec.ts de referência para o padrão do projeto
|
|
179
|
+
find src -name "*.spec.ts" | head -5
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Consultar o **Guia de Testes Automatizados** do projeto antes de implementar:
|
|
183
|
+
`(guia de testes do projeto)`
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Árvore de Decisão
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
Erro "Nest can't resolve dependencies"? → Padrão 3: Diagnóstico de DI
|
|
191
|
+
Circular dependency detectada? → Padrão 4: Resolver sem forwardRef
|
|
192
|
+
Precisa proteger rotas? → Seção: Guards
|
|
193
|
+
Precisa transformar request/response? → Seção: Interceptors
|
|
194
|
+
Precisa validar dados de entrada? → Seção: Pipes e Validação
|
|
195
|
+
Precisa configurar variáveis de ambiente?→ Seção: ConfigModule
|
|
196
|
+
Precisa autenticar com JWT? → Seção: Autenticação (Passport + JWT)
|
|
197
|
+
Precisa criar exceção customizada? → Seção: Exception Filters
|
|
198
|
+
Precisa implementar log? → Referência: Guia de Logs
|
|
199
|
+
Precisa testar um service? → Padrão 5 + Seção: Testes
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Escolha de ORM
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
Precisa de migrations? → TypeORM ou Prisma
|
|
206
|
+
Banco NoSQL? → Mongoose
|
|
207
|
+
Prioridade em type safety? → Prisma
|
|
208
|
+
Relacionamentos complexos? → TypeORM
|
|
209
|
+
Banco de dados existente? → TypeORM (melhor suporte legado)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Estratégia de Testes
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
Lógica de negócio isolada? → Testes unitários com mocks
|
|
216
|
+
Contratos de API? → Testes de integração com banco de teste
|
|
217
|
+
Fluxos de usuário? → NÃO usar e2e no backend (ver Regras)
|
|
218
|
+
Performance? → Testes de carga com k6 ou Artillery
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Método de Autenticação
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
API stateless? → JWT com refresh tokens
|
|
225
|
+
Session-based? → Express sessions com Redis
|
|
226
|
+
OAuth/Social login? → Passport com provider strategies
|
|
227
|
+
Multi-tenant? → JWT com tenant claims
|
|
228
|
+
Microsserviços? → Auth service-to-service com mTLS
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Fluxo de Trabalho
|
|
234
|
+
|
|
235
|
+
### Validação (Step 0)
|
|
236
|
+
|
|
237
|
+
Antes de qualquer mudança, detectar o ambiente:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Versão NestJS
|
|
241
|
+
grep '"@nestjs/core"' package.json
|
|
242
|
+
|
|
243
|
+
# Estrutura de módulos
|
|
244
|
+
find src -name "*.module.ts" | head -10
|
|
245
|
+
|
|
246
|
+
# Padrão de testes existente (SEMPRE verificar antes de criar testes)
|
|
247
|
+
find src -name "*.spec.ts" | head -5
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Arquitetura de Módulos
|
|
251
|
+
|
|
252
|
+
#### Estrutura de módulo de feature
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// ✅ Padrão de módulo de feature
|
|
256
|
+
@Module({
|
|
257
|
+
imports: [
|
|
258
|
+
TypeOrmModule.forFeature([UserEntity]),
|
|
259
|
+
CommonModule,
|
|
260
|
+
],
|
|
261
|
+
controllers: [UserController],
|
|
262
|
+
providers: [UserService, UserRepository],
|
|
263
|
+
exports: [UserService], // exportar apenas o que outros módulos precisam
|
|
264
|
+
})
|
|
265
|
+
export class UserModule {}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### Módulo global (para providers transversais)
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
// ✅ Módulo global — disponível sem importar
|
|
272
|
+
@Global()
|
|
273
|
+
@Module({
|
|
274
|
+
providers: [LoggerService],
|
|
275
|
+
exports: [LoggerService],
|
|
276
|
+
})
|
|
277
|
+
export class LoggerModule {}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### Módulo dinâmico
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// ✅ Módulo dinâmico para configuração em runtime
|
|
284
|
+
@Module({})
|
|
285
|
+
export class HttpClientModule {
|
|
286
|
+
static forRoot(options: HttpClientOptions): DynamicModule {
|
|
287
|
+
return {
|
|
288
|
+
module: HttpClientModule,
|
|
289
|
+
providers: [
|
|
290
|
+
{ provide: HTTP_CLIENT_OPTIONS, useValue: options },
|
|
291
|
+
HttpClientService,
|
|
292
|
+
],
|
|
293
|
+
exports: [HttpClientService],
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
### Guards
|
|
302
|
+
|
|
303
|
+
Guards determinam se uma requisição deve ser processada. Executam **antes** dos interceptors.
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
// ✅ Guard de autenticação JWT
|
|
307
|
+
import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common'
|
|
308
|
+
import { JwtService } from '@nestjs/jwt'
|
|
309
|
+
import { Request } from 'express'
|
|
310
|
+
|
|
311
|
+
@Injectable()
|
|
312
|
+
export class JwtAuthGuard implements CanActivate {
|
|
313
|
+
constructor(private readonly jwtService: JwtService) {}
|
|
314
|
+
|
|
315
|
+
canActivate(context: ExecutionContext): boolean {
|
|
316
|
+
const request = context.switchToHttp().getRequest<Request>()
|
|
317
|
+
const token = this.extractTokenFromHeader(request)
|
|
318
|
+
|
|
319
|
+
if (!token) throw new UnauthorizedException('Token não fornecido')
|
|
320
|
+
|
|
321
|
+
try {
|
|
322
|
+
const payload = this.jwtService.verify(token)
|
|
323
|
+
request['user'] = payload
|
|
324
|
+
return true
|
|
325
|
+
} catch {
|
|
326
|
+
throw new UnauthorizedException('Token inválido ou expirado')
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
private extractTokenFromHeader(request: Request): string | undefined {
|
|
331
|
+
const [type, token] = request.headers.authorization?.split(' ') ?? []
|
|
332
|
+
return type === 'Bearer' ? token : undefined
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
// ✅ Guard de roles (RBAC)
|
|
339
|
+
@Injectable()
|
|
340
|
+
export class RolesGuard implements CanActivate {
|
|
341
|
+
constructor(private readonly reflector: Reflector) {}
|
|
342
|
+
|
|
343
|
+
canActivate(context: ExecutionContext): boolean {
|
|
344
|
+
const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [
|
|
345
|
+
context.getHandler(),
|
|
346
|
+
context.getClass(),
|
|
347
|
+
])
|
|
348
|
+
|
|
349
|
+
if (!requiredRoles) return true
|
|
350
|
+
|
|
351
|
+
const { user } = context.switchToHttp().getRequest()
|
|
352
|
+
return requiredRoles.some((role) => user.roles?.includes(role))
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
// ✅ Decorator combinado (Auth + Roles)
|
|
359
|
+
export const Auth = (...roles: string[]) =>
|
|
360
|
+
applyDecorators(
|
|
361
|
+
UseGuards(JwtAuthGuard, RolesGuard),
|
|
362
|
+
SetMetadata('roles', roles),
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
// Uso na rota
|
|
366
|
+
@Auth('admin')
|
|
367
|
+
@Delete(':id')
|
|
368
|
+
async remove(@Param('id') id: string) { ... }
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
### Interceptors
|
|
374
|
+
|
|
375
|
+
Interceptors executam antes E depois do route handler. Ideais para logging, transformação de resposta, caching.
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
// ✅ Interceptor de logging de requisições
|
|
379
|
+
@Injectable()
|
|
380
|
+
export class LoggingInterceptor implements NestInterceptor {
|
|
381
|
+
private readonly logger = new Logger(LoggingInterceptor.name)
|
|
382
|
+
|
|
383
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
|
|
384
|
+
const request = context.switchToHttp().getRequest()
|
|
385
|
+
const { method, url } = request
|
|
386
|
+
const start = Date.now()
|
|
387
|
+
|
|
388
|
+
return next.handle().pipe(
|
|
389
|
+
tap(() => {
|
|
390
|
+
const ms = Date.now() - start
|
|
391
|
+
this.logger.log(`${method} ${url} — ${ms}ms`)
|
|
392
|
+
}),
|
|
393
|
+
)
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
// ✅ Interceptor de transformação de resposta
|
|
400
|
+
@Injectable()
|
|
401
|
+
export class TransformInterceptor<T> implements NestInterceptor<T, { data: T }> {
|
|
402
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<{ data: T }> {
|
|
403
|
+
return next.handle().pipe(
|
|
404
|
+
map((data) => ({ data }))
|
|
405
|
+
)
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
### Pipes e Validação
|
|
413
|
+
|
|
414
|
+
Pipes validam e transformam dados de entrada **antes** do route handler.
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
// ✅ Configuração global de ValidationPipe (no main.ts)
|
|
418
|
+
app.useGlobalPipes(
|
|
419
|
+
new ValidationPipe({
|
|
420
|
+
whitelist: true, // remove campos não declarados no DTO
|
|
421
|
+
forbidNonWhitelisted: true, // lança erro se campos extras existirem
|
|
422
|
+
transform: true, // transforma payload para instância do DTO
|
|
423
|
+
transformOptions: {
|
|
424
|
+
enableImplicitConversion: true,
|
|
425
|
+
},
|
|
426
|
+
}),
|
|
427
|
+
)
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
// ✅ DTO com class-validator
|
|
432
|
+
export class CreateUserDto {
|
|
433
|
+
@IsString()
|
|
434
|
+
@MinLength(2)
|
|
435
|
+
name: string
|
|
436
|
+
|
|
437
|
+
@IsEmail()
|
|
438
|
+
email: string
|
|
439
|
+
|
|
440
|
+
@IsOptional()
|
|
441
|
+
@IsEnum(['admin', 'editor', 'viewer'])
|
|
442
|
+
role?: string
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
### ConfigModule
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
// ✅ ConfigModule com validação via Joi
|
|
452
|
+
@Module({
|
|
453
|
+
imports: [
|
|
454
|
+
ConfigModule.forRoot({
|
|
455
|
+
isGlobal: true,
|
|
456
|
+
envFilePath: '.env',
|
|
457
|
+
validationSchema: Joi.object({
|
|
458
|
+
NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'),
|
|
459
|
+
PORT: Joi.number().default(3000),
|
|
460
|
+
DATABASE_URL: Joi.string().required(),
|
|
461
|
+
JWT_SECRET: Joi.string().min(32).required(),
|
|
462
|
+
MESSAGE_BROKER_URL: Joi.string().required(),
|
|
463
|
+
}),
|
|
464
|
+
}),
|
|
465
|
+
],
|
|
466
|
+
})
|
|
467
|
+
export class AppModule {}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
// ✅ Usar ConfigService em vez de process.env diretamente
|
|
472
|
+
@Injectable()
|
|
473
|
+
export class DatabaseService {
|
|
474
|
+
constructor(private readonly configService: ConfigService) {}
|
|
475
|
+
|
|
476
|
+
getUrl(): string {
|
|
477
|
+
return this.configService.getOrThrow<string>('DATABASE_URL')
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
### Autenticação (Passport + JWT)
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
// ✅ JWT Strategy
|
|
488
|
+
import { ExtractJwt, Strategy } from 'passport-jwt' // importar de 'passport-jwt', NÃO 'passport-local'
|
|
489
|
+
|
|
490
|
+
@Injectable()
|
|
491
|
+
export class JwtStrategy extends PassportStrategy(Strategy) {
|
|
492
|
+
constructor(configService: ConfigService) {
|
|
493
|
+
super({
|
|
494
|
+
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
495
|
+
ignoreExpiration: false,
|
|
496
|
+
secretOrKey: configService.getOrThrow('JWT_SECRET'),
|
|
497
|
+
})
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
async validate(payload: { sub: string; email: string }) {
|
|
501
|
+
return { userId: payload.sub, email: payload.email }
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
// ✅ AuthModule
|
|
508
|
+
@Module({
|
|
509
|
+
imports: [
|
|
510
|
+
PassportModule,
|
|
511
|
+
JwtModule.registerAsync({
|
|
512
|
+
inject: [ConfigService],
|
|
513
|
+
useFactory: (configService: ConfigService) => ({
|
|
514
|
+
secret: configService.getOrThrow('JWT_SECRET'),
|
|
515
|
+
signOptions: { expiresIn: '15m' },
|
|
516
|
+
}),
|
|
517
|
+
}),
|
|
518
|
+
],
|
|
519
|
+
providers: [AuthService, JwtStrategy],
|
|
520
|
+
exports: [JwtModule],
|
|
521
|
+
})
|
|
522
|
+
export class AuthModule {}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
### Exception Filters
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
// ✅ Exception filter customizado para erros de negócio
|
|
531
|
+
@Catch(HttpException)
|
|
532
|
+
export class HttpExceptionFilter implements ExceptionFilter {
|
|
533
|
+
private readonly logger = new Logger(HttpExceptionFilter.name)
|
|
534
|
+
|
|
535
|
+
catch(exception: HttpException, host: ArgumentsHost): void {
|
|
536
|
+
const ctx = host.switchToHttp()
|
|
537
|
+
const response = ctx.getResponse<Response>()
|
|
538
|
+
const request = ctx.getRequest<Request>()
|
|
539
|
+
const status = exception.getStatus()
|
|
540
|
+
const exceptionResponse = exception.getResponse()
|
|
541
|
+
|
|
542
|
+
const body = {
|
|
543
|
+
statusCode: status,
|
|
544
|
+
timestamp: new Date().toISOString(),
|
|
545
|
+
path: request.url,
|
|
546
|
+
error: typeof exceptionResponse === 'string'
|
|
547
|
+
? exceptionResponse
|
|
548
|
+
: (exceptionResponse as Record<string, unknown>).message,
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (status >= 500) {
|
|
552
|
+
this.logger.error({ exception, path: request.url }, 'Erro interno')
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
response.status(status).json(body)
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
562
|
+
### Testes
|
|
563
|
+
|
|
564
|
+
> **Obrigatório**: Antes de escrever qualquer teste, verificar se existe schematic ou modelo no projeto (ver Padrão 5).
|
|
565
|
+
> Consultar o guia: (guia de testes do projeto)
|
|
566
|
+
|
|
567
|
+
#### Service — teste unitário
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
import { Test, TestingModule } from '@nestjs/testing'
|
|
571
|
+
import { UserService } from './user.service'
|
|
572
|
+
import { getRepositoryToken } from '@nestjs/typeorm'
|
|
573
|
+
import { UserEntity } from './user.entity'
|
|
574
|
+
|
|
575
|
+
describe('UserService', () => {
|
|
576
|
+
let service: UserService
|
|
577
|
+
|
|
578
|
+
const mockRepository = {
|
|
579
|
+
findOne: jest.fn(),
|
|
580
|
+
save: jest.fn(),
|
|
581
|
+
create: jest.fn(),
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
beforeEach(async () => {
|
|
585
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
586
|
+
providers: [
|
|
587
|
+
UserService,
|
|
588
|
+
{
|
|
589
|
+
provide: getRepositoryToken(UserEntity), // ✅ token correto para TypeORM
|
|
590
|
+
useValue: mockRepository,
|
|
591
|
+
},
|
|
592
|
+
],
|
|
593
|
+
}).compile()
|
|
594
|
+
|
|
595
|
+
service = module.get<UserService>(UserService)
|
|
596
|
+
})
|
|
597
|
+
|
|
598
|
+
afterEach(() => jest.clearAllMocks())
|
|
599
|
+
|
|
600
|
+
it('lança NotFoundException quando usuário não existe', async () => {
|
|
601
|
+
mockRepository.findOne.mockResolvedValue(null)
|
|
602
|
+
await expect(service.findById('id-inexistente')).rejects.toThrow('Usuário não encontrado')
|
|
603
|
+
})
|
|
604
|
+
})
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
#### Controller — teste de integração (Supertest)
|
|
608
|
+
|
|
609
|
+
```typescript
|
|
610
|
+
import { Test, TestingModule } from '@nestjs/testing'
|
|
611
|
+
import { INestApplication, ValidationPipe } from '@nestjs/common'
|
|
612
|
+
import * as request from 'supertest'
|
|
613
|
+
|
|
614
|
+
describe('UserController (integração)', () => {
|
|
615
|
+
let app: INestApplication
|
|
616
|
+
|
|
617
|
+
beforeAll(async () => {
|
|
618
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
619
|
+
imports: [UserModule],
|
|
620
|
+
})
|
|
621
|
+
.overrideProvider(UserService)
|
|
622
|
+
.useValue({ findById: jest.fn().mockResolvedValue({ id: '1', name: 'Test' }) })
|
|
623
|
+
.compile()
|
|
624
|
+
|
|
625
|
+
app = module.createNestApplication()
|
|
626
|
+
app.useGlobalPipes(new ValidationPipe({ whitelist: true }))
|
|
627
|
+
await app.init()
|
|
628
|
+
})
|
|
629
|
+
|
|
630
|
+
afterAll(() => app.close())
|
|
631
|
+
|
|
632
|
+
it('GET /users/:id → 200', async () => {
|
|
633
|
+
const response = await request(app.getHttpServer()).get('/users/1')
|
|
634
|
+
expect(response.status).toBe(200)
|
|
635
|
+
expect(response.body.data.id).toBe('1')
|
|
636
|
+
})
|
|
637
|
+
})
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
---
|
|
641
|
+
|
|
642
|
+
### Logging
|
|
643
|
+
|
|
644
|
+
Consultar o guia de logs do projeto antes de implementar logging:
|
|
645
|
+
`(guia de logs do projeto)`
|
|
646
|
+
|
|
647
|
+
```typescript
|
|
648
|
+
// ✅ Logger padrão NestJS
|
|
649
|
+
import { Logger } from '@nestjs/common'
|
|
650
|
+
|
|
651
|
+
@Injectable()
|
|
652
|
+
export class UserService {
|
|
653
|
+
private readonly logger = new Logger(UserService.name)
|
|
654
|
+
|
|
655
|
+
async findById(id: string) {
|
|
656
|
+
this.logger.log(`Buscando usuário ${id}`)
|
|
657
|
+
// ...
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
## Problemas Comuns e Soluções
|
|
665
|
+
|
|
666
|
+
### "Nest can't resolve dependencies of [Service] (?, +)"
|
|
667
|
+
1. O `?` indica a posição do parâmetro faltando no construtor
|
|
668
|
+
2. Verificar se o provider está em `providers[]` do módulo
|
|
669
|
+
3. Se usado em outro módulo, verificar `exports[]` do módulo de origem
|
|
670
|
+
4. Erros de digitação em barrel exports (`index.ts`) também causam este erro
|
|
671
|
+
|
|
672
|
+
### "Circular dependency detected"
|
|
673
|
+
**Proibido usar `forwardRef`.** Seguir obrigatoriamente:
|
|
674
|
+
1. Refatorar a estrutura de módulos — rever responsabilidades
|
|
675
|
+
2. Extrair lógica compartilhada para um terceiro módulo
|
|
676
|
+
3. Ajustar escopo do provider como última alternativa
|
|
677
|
+
|
|
678
|
+
### "Unknown authentication strategy 'jwt'"
|
|
679
|
+
1. Importar `Strategy` de `'passport-jwt'`, **não** de `'passport-local'`
|
|
680
|
+
2. Garantir que `JWT_SECRET` no `JwtModule` bate com `secretOrKey` na `JwtStrategy`
|
|
681
|
+
3. Verificar formato do header: `Authorization: Bearer <token>`
|
|
682
|
+
|
|
683
|
+
### "[TypeOrmModule] Unable to connect to the database"
|
|
684
|
+
Frequentemente enganoso — verificar:
|
|
685
|
+
1. Sintaxe das entities (ex: `@Column()` não `@Column('description')`)
|
|
686
|
+
2. Decorators faltando em propriedades das entities
|
|
687
|
+
3. Configuração de host/porta/credenciais
|
|
688
|
+
|
|
689
|
+
### "Nest can't resolve dependencies of the Repository (testing)"
|
|
690
|
+
```typescript
|
|
691
|
+
// ✅ Usar getRepositoryToken para mockar repositórios TypeORM em testes
|
|
692
|
+
{ provide: getRepositoryToken(UserEntity), useValue: mockRepo }
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### "secretOrPrivateKey must have a value" (JWT)
|
|
696
|
+
1. Definir `JWT_SECRET` nas variáveis de ambiente
|
|
697
|
+
2. Verificar que `ConfigModule` carrega antes do `JwtModule`
|
|
698
|
+
3. Usar `ConfigService` para configuração dinâmica
|
|
699
|
+
|
|
700
|
+
### Guard não está sendo aplicado
|
|
701
|
+
```typescript
|
|
702
|
+
// ✅ Guard global com acesso ao DI — usar APP_GUARD, não useGlobalGuards()
|
|
703
|
+
@Module({
|
|
704
|
+
providers: [{ provide: APP_GUARD, useClass: JwtAuthGuard }],
|
|
705
|
+
})
|
|
706
|
+
export class AppModule {}
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
### Provider com escopo errado
|
|
710
|
+
- `DEFAULT` (Singleton) → instância única por aplicação
|
|
711
|
+
- `REQUEST` → nova instância por requisição (todos os providers injetados herdam o escopo)
|
|
712
|
+
- `TRANSIENT` → nova instância por injeção
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
716
|
+
## Regras
|
|
717
|
+
|
|
718
|
+
### Nunca
|
|
719
|
+
- Usar `forwardRef` — é uma má prática identificada pelo próprio framework; refatorar a estrutura
|
|
720
|
+
- Importar `Strategy` de `'passport-local'` para JWT (usar `'passport-jwt'`)
|
|
721
|
+
- Exportar o módulo em vez do service no `exports[]`
|
|
722
|
+
- Usar `process.env.VAR` diretamente — sempre usar `ConfigService.getOrThrow()`
|
|
723
|
+
- Criar providers com escopo `REQUEST` sem entender o impacto em performance
|
|
724
|
+
- Ignorar erros de build — circular dependencies aparecem no build
|
|
725
|
+
- Escrever testes sem verificar se existe schematic/modelo no projeto antes
|
|
726
|
+
- Criar testes e2e no backend — não usamos e2e no backend
|
|
727
|
+
|
|
728
|
+
### Sempre
|
|
729
|
+
- Ler o código existente antes de criar novos módulos ou alterar DI
|
|
730
|
+
- Verificar schematics e arquivos `.spec.ts` de referência antes de implementar testes
|
|
731
|
+
- Consultar o guia de testes do projeto antes de implementar testes
|
|
732
|
+
- Consultar o guia de logs do projeto antes de implementar logging
|
|
733
|
+
- Usar `getRepositoryToken(Entity)` em testes de TypeORM
|
|
734
|
+
- Configurar `ValidationPipe` com `whitelist: true` e `transform: true`
|
|
735
|
+
- Preferir `@Global()` com cautela — apenas para providers realmente transversais
|
|
736
|
+
- Verificar execução completa: `typecheck → unit tests → integration tests`
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
## Checklist de Conclusão
|
|
741
|
+
|
|
742
|
+
- [ ] `npm run build` passa sem erros (typecheck + circular deps)
|
|
743
|
+
- [ ] Providers declarados em `providers[]` e exportados em `exports[]` quando necessário
|
|
744
|
+
- [ ] `ValidationPipe` configurado com `whitelist: true` e `transform: true`
|
|
745
|
+
- [ ] Variáveis de ambiente lidas via `ConfigService`, não via `process.env`
|
|
746
|
+
- [ ] Schematics verificados antes de implementar testes
|
|
747
|
+
- [ ] Testes unitários com mocks corretos (`getRepositoryToken` para TypeORM)
|
|
748
|
+
- [ ] Exception filters e guards registrados no escopo correto
|
|
749
|
+
- [ ] Nenhuma circular dependency introduzida
|
|
750
|
+
- [ ] `forwardRef` não utilizado
|
|
751
|
+
- [ ] `npm run test` passando (unit + integration)
|
|
752
|
+
- [ ] Sem testes e2e no backend
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
## Output
|
|
757
|
+
|
|
758
|
+
| Artefato | Descrição |
|
|
759
|
+
|----------|-----------|
|
|
760
|
+
| `*.module.ts` | Módulo com imports/providers/exports corretos |
|
|
761
|
+
| `*.guard.ts` | Guard com lógica de autenticação/autorização |
|
|
762
|
+
| `*.interceptor.ts` | Interceptor com lógica de transformação ou logging |
|
|
763
|
+
| `*.pipe.ts` | Pipe ou DTO com class-validator |
|
|
764
|
+
| `*.filter.ts` | Exception filter com tratamento de erro customizado |
|
|
765
|
+
| `*.spec.ts` | Testes unitários ou de integração com mocks corretos para NestJS Testing |
|
|
766
|
+
|
|
767
|
+
---
|
|
768
|
+
|
|
769
|
+
## Mensagem de Conclusão
|
|
770
|
+
|
|
771
|
+
```
|
|
772
|
+
Implementação NestJS concluída!
|
|
773
|
+
|
|
774
|
+
Componente(s): {módulo / guard / interceptor / pipe / filter / teste}
|
|
775
|
+
DI: {providers e exports verificados}
|
|
776
|
+
Typecheck: {npm run build passando}
|
|
777
|
+
Unit tests: {passando / pendentes}
|
|
778
|
+
Integration tests: {passando / pendentes}
|
|
779
|
+
|
|
780
|
+
Circular dependencies: {nenhuma / resolvidas sem forwardRef}
|
|
781
|
+
Próximo passo: {rodar testes completos / integrar com módulo pai / testar endpoint}
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
---
|
|
785
|
+
|
|
786
|
+
## Recursos Adicionais
|
|
787
|
+
|
|
788
|
+
- **Backend**: Ver skill `eng-backend` para APIs, RabbitMQ, caching e testes de integração
|
|
789
|
+
- **Guia de testes automatizados**: (guia de testes do projeto)
|
|
790
|
+
- **Guia de logs**: (guia de logs do projeto)
|
|
791
|
+
- **Documentação oficial**: https://docs.nestjs.com
|