Appearance
Code Style Guide
Padrões obrigatórios herdados do
contrasync-nest-api. Em caso de conflito, esta página complementa, não substitui, o Code Style do nest-api.
1. Princípios Invioláveis
1.1 Nunca Comentários no Código
Sem comentários inline, JSDoc ou banners. Se o código precisa de explicação, refatore.
1.2 Nunca any
Use Record<string, unknown>, generics <T>, ou unknown com type guard.
1.3 Importações Absolutas via Path Aliases
typescript
// ❌ PROIBIDO
import { Logger } from '../../common/logger'
// ✅ CORRETO
import { Logger } from '@common/logger'Aliases disponíveis (configurados em tsconfig.json e vitest.config.ts):
@/*→src/*@common/*→src/common/*@domain/*→src/domain/*@helpers/*→src/helpers/*@services/*→src/services/*@handlers/*→src/handlers/*@adapters/*→src/adapters/*@infra/*→infra/*
1.4 Tipos, Interfaces e Constantes em domain/
Toda interface, type e const/enum reutilizável fica em src/domain/, nunca declarada dentro de handler, service ou adapter:
src/domain/
├── constants/ → BOT_COMMANDS, OFF_HOURS_MESSAGE, BOT_HOURS_OPEN/CLOSE
├── enums/ → BotState
└── interfaces/ → IncomingMessage, OutgoingTextMessage, SentMessageReceipt1.5 Sem try/catch Manual
Erros são tratados de forma centralizada em src/common/error-boundary.ts. Handlers e services apenas lançam BotError, ValidationError ou UnauthorizedError: a fronteira HTTP converte em response.
typescript
// ❌ PROIBIDO
async handle(event) {
try {
return await this.process(event)
} catch (e) {
return { statusCode: 500, body: '...' }
}
}
// ✅ CORRETO
async handle(event) {
return this.process(event)
}1.6 Sem return Type Anotado
O TypeScript infere o tipo de retorno. Tipos explícitos só em interfaces/contracts:
typescript
// ❌ PROIBIDO
sendText(message: OutgoingTextMessage): Promise<SentMessageReceipt> { ... }
// ✅ CORRETO
sendText(message: OutgoingTextMessage) { ... }Exceção: quando o contrato externo (ex.: interface explícita) exige.
1.7 Logger com warn Antes de throw
Sempre logar com nível warn (ou error) antes de propagar uma exceção, com contexto suficiente para investigação posterior.
2. Nomenclatura
| Tipo | Convenção | Exemplo |
|---|---|---|
| Classes | PascalCase | ZapiClient, BotRouterService |
| Métodos | camelCase | replyOffHours(), sendText() |
| Variáveis | camelCase | incoming, payload |
| Constantes | UPPER_SNAKE | OFF_HOURS_MESSAGE, BOT_HOURS_OPEN |
| Arquivos | kebab-case | inbound-webhook.handler.ts, business-hours.ts |
| Specs | kebab-case + .spec.ts | zapi.mapper.spec.ts |
| Interfaces | PascalCase | IncomingMessage, ZapiWebhookPayload |
| Enums | PascalCase | BotState |
3. Estrutura de Arquivos por Tipo
| Camada | Sufixo | Localização |
|---|---|---|
| Handler | .handler.ts | src/handlers/ |
| Service | .service.ts | src/services/ |
| Adapter (HTTP client) | .client.ts | src/adapters/<vendor>/ |
| Mapper | .mapper.ts | src/adapters/<vendor>/ |
| Types externos | .types.ts | src/adapters/<vendor>/ |
| Helper puro | kebab-case | src/helpers/ |
| Interface | .interface.ts | src/domain/interfaces/ |
| Enum | .enum.ts | src/domain/enums/ |
| Constante | .const.ts | src/domain/constants/ |
| Spec (teste) | .spec.ts | co-locado com o arquivo testado |
4. Regras de ESLint (herdadas)
- Proibido:
for,for...in,for...of(usar.map(),.filter(),.reduce(),.forEach()) - Proibido: comentários inline e
TODO/FIXME/HACK - Proibido: imports relativos profundos (usar
@/) - Limite: 4 níveis de aninhamento, 4 callbacks aninhados
- Aviso: funções > 80 linhas, > 5 parâmetros, complexidade > 15
5. Regras Específicas do Lambda
| Regra | Razão |
|---|---|
Bootstrap fora do handler | Inicialização (ZapiClient, services) acontece no module-level para reaproveitar contexto entre invocations |
Sem console.* direto | Sempre via Logger do @common/logger para garantir JSON estruturado |
process.env apenas em handler.ts ou infra/ | Services recebem config via construtor (DI manual) |
axios.create() por client | Nunca usar axios global facilita mock em testes |
IncomingMessage é imutável | Mapper devolve uma vez; downstream só lê |
Documento atualizado em Maio 2026