Skip to content

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, SentMessageReceipt

1.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 ​

TipoConvençãoExemplo
ClassesPascalCaseZapiClient, BotRouterService
MétodoscamelCasereplyOffHours(), sendText()
VariáveiscamelCaseincoming, payload
ConstantesUPPER_SNAKEOFF_HOURS_MESSAGE, BOT_HOURS_OPEN
Arquivoskebab-caseinbound-webhook.handler.ts, business-hours.ts
Specskebab-case + .spec.tszapi.mapper.spec.ts
InterfacesPascalCaseIncomingMessage, ZapiWebhookPayload
EnumsPascalCaseBotState

3. Estrutura de Arquivos por Tipo ​

CamadaSufixoLocalização
Handler.handler.tssrc/handlers/
Service.service.tssrc/services/
Adapter (HTTP client).client.tssrc/adapters/<vendor>/
Mapper.mapper.tssrc/adapters/<vendor>/
Types externos.types.tssrc/adapters/<vendor>/
Helper purokebab-casesrc/helpers/
Interface.interface.tssrc/domain/interfaces/
Enum.enum.tssrc/domain/enums/
Constante.const.tssrc/domain/constants/
Spec (teste).spec.tsco-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 ​

RegraRazão
Bootstrap fora do handlerInicialização (ZapiClient, services) acontece no module-level para reaproveitar contexto entre invocations
Sem console.* diretoSempre 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 clientNunca usar axios global facilita mock em testes
IncomingMessage é imutávelMapper devolve uma vez; downstream só lê

Documento atualizado em Maio 2026