Engenharia de IA Aplicada à Programação Web
Aula 6 de 8
Navegar por módulos e aulas
  1. 01 Fundamentos da Web
  2. 02 JavaScript moderno
  3. 03 TypeScript, Git e qualidade
  4. 04 Angular
  5. 05 Node.js, NestJS e APIs
  1. 5.1 Introdução ao Node.js e NestJS
  2. 5.2 Módulos, controladores e provedores
  3. 5.3 REST, rotas e respostas HTTP
  4. 5.4 DTOs, pipes e validação
  5. 5.5 Erros, filtros e configuração
  6. 5.6 OpenAPI e documentação
  7. 5.7 Registros, interceptadores e testes
  8. 5.8 Compilação e projeto final

Módulo 5 · Aula 5.6

Aula 5.6 — OpenAPI e documentação

2 horas Teoria + laboratório Node.js, NestJS e APIs
Ver fonte Markdown

Identificação

  • Módulo: 5 — Node.js, NestJS e APIs
  • Duração: 2 horas
  • Tipo: teoria aplicada e laboratório
  • Entrega: contrato OpenAPI navegável da Knowledge API
  • Laboratório: ../exemplos/aula-5.6/index.html

Introdução

Uma API não é apenas código no servidor. Ela é um acordo entre quem oferece uma função e quem precisa utilizá-la. O Angular precisa saber qual endereço chamar, quais dados enviar, quais respostas esperar e como interpretar uma falha.

Escrever essas informações somente em mensagens ou na memória da equipe cria dúvidas. OpenAPI é uma especificação para descrever APIs HTTP de forma estruturada. O documento gerado pode alimentar uma página navegável, ferramentas de teste, geradores de clientes e verificações automáticas.

Swagger não é sinônimo de OpenAPI. OpenAPI é a especificação. Swagger UI é uma interface que lê um documento OpenAPI e apresenta operações, parâmetros e modelos. No NestJS, o pacote @nestjs/swagger integra esses recursos à aplicação.

Nesta aula responderemos:

  • documentação substitui validação?
  • Swagger UI é a própria API?
  • documentar uma resposta garante que o código a devolva?
  • a interface pode ficar pública em produção?
  • como descrever DTOs, parâmetros, exemplos, erros e autenticação?
  • como evitar que código e documentação contem histórias diferentes?

Objetivos

Ao concluir a aula, você será capaz de:

  1. diferenciar OpenAPI, Swagger UI e documentação manual;
  2. instalar e configurar @nestjs/swagger;
  3. gerar um documento a partir da aplicação NestJS;
  4. organizar operações com títulos, descrições e etiquetas;
  5. documentar DTOs, parâmetros, consultas e respostas;
  6. fornecer exemplos úteis sem inserir dados sensíveis;
  7. representar erros padronizados;
  8. declarar autenticação sem publicar credenciais;
  9. exportar o documento em JSON;
  10. revisar divergências entre implementação e contrato.

Pré-requisitos

  • aulas 5.1 a 5.5 concluídas;
  • endpoints REST de tarefas;
  • DTOs com validação;
  • respostas de erro padronizadas;
  • noção de prefixo global /api.

1. O que é um contrato de API?

Contrato é a descrição observável da comunicação:

Parte Exemplo
método e caminho POST /api/tasks
entrada CreateTaskDto
resposta de sucesso 201 com a tarefa criada
respostas de falha 400, 409 e 500
cabeçalhos Content-Type, correlação e autenticação
significado cria uma tarefa válida

O contrato não descreve como o serviço salva a tarefa. Isso pertence à implementação.

2. OpenAPI, Swagger e NestJS

decorators + tipos + configuração NestJS
                    ↓
          documento OpenAPI
             ↙             ↘
      Swagger UI          JSON/YAML
  • OpenAPI define a estrutura do documento;
  • @nestjs/swagger examina rotas e metadados;
  • Swagger UI apresenta o documento no navegador;
  • JSON ou YAML pode ser usado por outras ferramentas.

3. Instalação

No terminal aberto na pasta da API:

npm install @nestjs/swagger

Esse comando instala a integração. Ele não cria endpoints de negócio nem valida DTOs.

4. Configuração inicial

import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

const openApiConfig = new DocumentBuilder()
  .setTitle('Knowledge API')
  .setDescription('API de tarefas da plataforma Knowledge AI.')
  .setVersion('1.0.0')
  .addTag('tarefas', 'Operações de gerenciamento de tarefas.')
  .build();

const documentFactory = () =>
  SwaggerModule.createDocument(app, openApiConfig);

SwaggerModule.setup('docs', app, documentFactory, {
  jsonDocumentUrl: 'docs/openapi.json',
  customSiteTitle: 'Knowledge API | Documentação',
});

Com a API em http://localhost:3000:

  • interface: http://localhost:3000/docs;
  • documento: http://localhost:3000/docs/openapi.json.

5. Ordem da inicialização

Registre prefixo, pipes e configuração antes de gerar o documento:

const app = await NestFactory.create(AppModule);

app.setGlobalPrefix('api');
app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));

configureOpenApi(app);

await app.listen(port);

O documento precisa refletir os caminhos realmente expostos.

6. O que o NestJS consegue descobrir?

O módulo reconhece rotas, métodos HTTP e tipos usados por decorators como:

  • @Body();
  • @Param();
  • @Query();
  • @Controller();
  • @Get(), @Post(), @Patch() e @Delete().

Nem toda intenção é inferida. Descrições, exemplos, respostas alternativas e regras de negócio precisam de metadados explícitos.

7. Etiquetas e operação

@ApiTags('tarefas')
@Controller('tasks')
export class TasksController {
  @Get()
  @ApiOperation({
    summary: 'Listar tarefas',
    description: 'Retorna tarefas filtradas por situação.',
  })
  list() {}
}

A etiqueta agrupa operações. O resumo deve começar com verbo e explicar a intenção.

8. DTO documentado

export class CreateTaskDto {
  @ApiProperty({
    description: 'Título visível da tarefa.',
    example: 'Documentar a Knowledge API',
    minLength: 3,
    maxLength: 80,
  })
  @IsString()
  @MinLength(3)
  @MaxLength(80)
  title!: string;

  @ApiPropertyOptional({
    description: 'Indica se a tarefa já foi concluída.',
    example: false,
    default: false,
  })
  @IsOptional()
  @IsBoolean()
  completed?: boolean;
}

@ApiProperty() documenta. class-validator valida em ambiente de execução. Uma função não substitui a outra.

9. Classe de resposta

Não use o DTO de entrada para tudo. A saída pode possuir campos criados pelo servidor:

export class TaskResponseDto {
  @ApiProperty({ example: 'task-001' })
  id!: string;

  @ApiProperty({ example: 'Documentar a Knowledge API' })
  title!: string;

  @ApiProperty({ example: false })
  completed!: boolean;

  @ApiProperty({ example: '2026-08-05T12:00:00.000Z' })
  createdAt!: string;
}

10. Respostas de sucesso

@Post()
@ApiCreatedResponse({
  description: 'Tarefa criada.',
  type: TaskResponseDto,
})
create(@Body() input: CreateTaskDto): TaskResponseDto {
  return this.tasksService.create(input);
}

Use o decorator específico quando ele tornar a intenção clara:

  • @ApiOkResponse() para 200;
  • @ApiCreatedResponse() para 201;
  • @ApiNoContentResponse() para 204;
  • @ApiNotFoundResponse() para 404.

11. Listas e matrizes

@ApiOkResponse({ type: TaskResponseDto, isArray: true })
list(): TaskResponseDto[] {}

Sem isArray, a documentação poderá exibir um objeto quando o código devolve uma lista.

12. Parâmetro de rota

@Get(':id')
@ApiParam({
  name: 'id',
  description: 'Identificador da tarefa.',
  example: 'task-001',
})
findOne(@Param('id') id: string) {}

O exemplo deve ser fictício, válido e coerente com o formato real.

13. Parâmetros de consulta

@ApiQuery({
  name: 'completed',
  required: false,
  type: Boolean,
  description: 'Filtra tarefas concluídas ou abertas.',
})

Também é possível usar uma classe de consulta. Isso concentra tipagem, validação e documentação em um contrato reaproveitável.

14. Erro padronizado

export class ApiErrorDto {
  @ApiProperty({ example: 404 })
  statusCode!: number;

  @ApiProperty({ example: 'TASK_NOT_FOUND' })
  code!: string;

  @ApiProperty({ example: 'Tarefa não encontrada.' })
  message!: string;

  @ApiProperty({ example: 'req-a81f' })
  correlationId!: string;
}
@ApiNotFoundResponse({
  description: 'Tarefa inexistente.',
  type: ApiErrorDto,
})

Documente os erros que o cliente precisa tratar. Não liste detalhes internos.

15. Exemplos seguros

Um exemplo bom:

  • possui formato válido;
  • explica o significado do campo;
  • não contém nome, e-mail ou credencial real;
  • não promete um valor que o servidor nunca devolve;
  • ajuda o aluno a montar uma requisição.

Nunca use token real, senha, chave de API ou conteúdo privado na documentação.

16. Autenticação

const config = new DocumentBuilder()
  .addBearerAuth()
  .build();
@ApiBearerAuth()
@Controller('tasks')
export class TasksController {}

Isso descreve o mecanismo. Não autentica ninguém e não substitui guardas. A autenticação será implementada no Módulo 7.

17. A documentação deve ficar pública?

Depende do produto:

Cenário Decisão possível
API pública documentação pública e versionada
API interna autenticação, rede restrita ou acesso controlado
produção sensível servir somente JSON controlado ou desabilitar a interface

A decisão precisa considerar exposição de rotas, modelos internos e superfície de ataque.

18. Documento não é teste

Este decorator:

@ApiOkResponse({ type: TaskResponseDto })

não obriga o método a devolver aquele formato. A documentação pode mentir. Testes de contrato e revisão são necessários para reduzir divergência.

19. Versão da API e versão do documento

  • versão do documento comunica evolução do contrato;
  • versão do pacote comunica evolução do código distribuído;
  • versão na URL, como /v1, é uma estratégia de roteamento;
  • essas decisões se relacionam, mas não são idênticas.

Não altere um contrato incompatível silenciosamente.

20. Exportação para arquivo

O documento retornado por createDocument() é serializável. Ele pode ser salvo durante uma tarefa controlada de compilação ou integração contínua:

const document = SwaggerModule.createDocument(app, config);
await writeFile(
  'artifacts/openapi.json',
  JSON.stringify(document, null, 2),
  'utf8',
);

Evite escrever arquivos inesperadamente a cada requisição.

21. Plugin da CLI

O plug-in do Swagger pode adicionar metadados durante a compilação e reduzir repetição. Ele é opcional. Mesmo com o plug-in:

  • mantenha validação em ambiente de execução;
  • escreva descrições quando a intenção não for óbvia;
  • forneça exemplos importantes;
  • revise o documento gerado.

22. Roteiro de implementação

  1. instalar @nestjs/swagger;
  2. criar configureOpenApi(app);
  3. definir título, descrição e versão;
  4. registrar a interface e o documento JSON;
  5. etiquetar controladores;
  6. documentar operações, entradas e respostas;
  7. incluir erros padronizados;
  8. revisar exemplos e informações sensíveis;
  9. abrir a interface e inspecionar o JSON;
  10. registrar como a documentação será protegida em produção.

23. Laboratório guiado

Abra o explorador de contrato OpenAPI.

Etapa 1 — Escolha uma operação

Compare listagem, consulta por ID, criação e atualização.

Etapa 2 — Inspecione o contrato

Observe método, caminho, parâmetros, corpo e possíveis respostas.

Etapa 3 — Valide a documentação

Ative e desative metadados. O painel indica campos ausentes e riscos de divergência.

Etapa 4 — Veja o documento

Alterne entre a visão amigável e um fragmento OpenAPI equivalente.

24. Erros comuns

Confundir documentação com execução

Swagger UI envia requisições, mas a regra continua na API.

Documentar somente o caminho feliz

O cliente também precisa conhecer 400, 404, 409 e falhas seguras.

Reutilizar entidade em toda resposta

Entidades podem conter campos internos. Use contratos de saída explícitos.

Inserir segredo no exemplo

Documentação pode ser copiada, armazenada em cache e publicada.

Declarar tipo diferente do retorno real

Isso cria integração frágil. Corrija o código ou o contrato.

Publicar interface sem decisão

Disponibilidade da documentação deve ser uma escolha de segurança.

25. Exercícios

  1. documente GET /api/health com resposta 200;
  2. documente GET /api/tasks/:id com 200 e 404;
  3. forneça exemplo seguro para CreateTaskDto;
  4. crie ApiErrorDto com correlação;
  5. explique por que @ApiProperty() não valida a entrada;
  6. exporte um fragmento JSON e identifique paths e components.

26. Desafio individual

Adicione uma operação PATCH /api/tasks/:id ao contrato:

  • parâmetro id;
  • corpo parcial;
  • resposta 200;
  • falhas 400 e 404;
  • exemplo de requisição;
  • exemplo de resposta;
  • nenhuma informação sensível.

27. Lista de verificação de conclusão

  • Diferencio OpenAPI e Swagger UI.
  • A documentação usa português claro.
  • Operações possuem intenção compreensível.
  • DTOs de entrada e saída estão separados.
  • Listas são documentadas como listas.
  • Parâmetros e consultas possuem exemplos.
  • Erros importantes estão representados.
  • Nenhum segredo aparece no documento.
  • Sei que documentação não substitui validação ou testes.
  • O JSON do contrato pode ser obtido de forma controlada.

28. Rubrica da entrega

Critério Pontos
Configuração do documento 20
Operações e organização 20
DTOs e modelos de resposta 20
Erros e exemplos 20
Segurança e coerência 20
Total 100

29. Resumo

  • OpenAPI descreve contratos HTTP de forma estruturada;
  • Swagger UI apresenta o documento no navegador;
  • @nestjs/swagger integra rotas e metadados do NestJS;
  • documentação, validação e teste possuem responsabilidades diferentes;
  • exemplos devem ser úteis, fictícios e seguros;
  • contrato e implementação precisam ser revisados em conjunto.

Próxima aula

Na Aula 5.7, adicionaremos registros estruturados, interceptadores de observação e uma suíte de testes unitários e de integração.

Fontes oficiais