API Node.js + Express (Parte 2)
Documentando uma API Node.js + Express com Swagger
Este artigo foi desenvolvido para ser complementar ao projeto de API Node.JS com Express, desenvolvido no curso da Formação Node.js da DIO.
O repositório com a base do projeto (API) pode ser encontrado aqui no GitHub.
Se você caiu nesse artigo de para-quedas e não viu a parte 1 onde criamos a API, ela está disponível aqui.
Para a parte 2, iremos criar a documentação da API com o Swagger UI. O Swagger é uma ferramenta poderosa para documentar APIs, permitindo que você descreva a estrutura de suas endpoints de maneira interativa e legível.
Implementando o Swagger
1. Instalar as Dependências
Primeiramente, vamos instalar os pacotes necessários.
npm install swagger-ui-express swagger-jsdoc
npm install --save-dev @types/swagger-jsdoc @types/swagger-ui-express
2. Configurar o Swagger
Crie um arquivo swagger.ts
dentro da pasta src/config
para configurar o Swagger. Este arquivo definirá as especificações do Swagger para a sua API.
import swaggerJSDoc from 'swagger-jsdoc';
import swaggerUi from 'swagger-ui-express';
import { Express } from 'express';
const swaggerOptions = {
swaggerDefinition: {
openapi: '3.1.0',
info: {
title: 'Minha API',
version: '1.0.0',
description: 'Documentação da API',
},
servers: [
{
url: 'http://localhost:3333/api/v1',
},
],
},
// Caminho para os arquivos de rotas
apis: ['./src/routes.ts'],
};
const swaggerDocs = swaggerJSDoc(swaggerOptions);
const setupSwagger = (app: Express) => {
app.use('/api/v1/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));
};
export default setupSwagger;
3. Integrar o Swagger com o Express
No arquivo principal, app.ts
vamos importar a configuração do Swagger
import setupSwagger from './config/swagger'
// ... restante do código
setupSwagger(app)
app.listen(port, () => {
console.log('🔥 Server running')
console.log('Documentação disponível em http://localhost:3333/api/v1/docs')
})
4. Documentar as Rotas
No arquivo das rotas, adicione comentários seguindo o padrão do Swagger para documentar as suas endpoints.
import { Router } from "express"
import * as ClubController from './controllers/clubsController';
const router = Router()
/**
* @swagger
* tags:
* name: Players
* description: Operações relacionadas aos jogadores
*/
/**
* @swagger
* /players:
* get:
* summary: Retorna a lista de jogadores
* tags: [Players]
* responses:
* 200:
* description: Lista de jogadores
* content:
* application/json:
* schema:
* type: array
* items:
* type: object
* properties:
* id:
* type: number
* name:
* type: string
* club:
* type: string
* nationality:
* type: string
* position:
* type: string
* statistics:
* type: object
* properties:
* Overall:
* type: number
* Pace:
* type: number
* Shooting:
* type: number
* Passing:
* type: number
* Dribbling:
* type: number
* Defending:
* type: number
* Physical:
* type: number
*/
router.get('/players', PlayerController.getPlayer)
/**
* @swagger
* /players:
* post:
* summary: Cria um novo jogador
* tags: [Players]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* club:
* type: string
* nationality:
* type: string
* position:
* type: string
* statistics:
* type: object
* properties:
* Overall:
* type: number
* Pace:
* type: number
* Shooting:
* type: number
* Passing:
* type: number
* Dribbling:
* type: number
* Defending:
* type: number
* Physical:
* type: number
* responses:
* 201:
* description: Jogador criado com sucesso
* content:
* application/json:
* schema:
* type: object
* properties:
* id:
* type: number
* name:
* type: string
* club:
* type: string
* nationality:
* type: string
* position:
* type: string
* statistics:
* type: object
* properties:
* Overall:
* type: number
* Pace:
* type: number
* Shooting:
* type: number
* Passing:
* type: number
* Dribbling:
* type: number
* Defending:
* type: number
* Physical:
* type: number
*/
router.post('/players', PlayerController.createPlayer)
/**
* @swagger
* /players/{id}:
* get:
* summary: Retorna um jogador pelo ID
* tags: [Players]
* parameters:
* - in: path
* name: id
* schema:
* type: number
* required: true
* description: ID do jogador
* responses:
* 200:
* description: Dados do jogador
* content:
* application/json:
* schema:
* type: object
* properties:
* id:
* type: number
* name:
* type: string
* club:
* type: string
* nationality:
* type: string
* position:
* type: string
* statistics:
* type: object
* properties:
* Overall:
* type: number
* Pace:
* type: number
* Shooting:
* type: number
* Passing:
* type: number
* Dribbling:
* type: number
* Defending:
* type: number
* Physical:
* type: number
*/
router.get('/players/:id', PlayerController.getPlayerById)
/**
* @swagger
* /players/{id}:
* patch:
* summary: Atualiza um jogador pelo ID
* tags: [Players]
* parameters:
* - in: path
* name: id
* schema:
* type: number
* required: true
* description: ID do jogador
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* club:
* type: string
* nationality:
* type: string
* position:
* type: string
* statistics:
* type: object
* properties:
* Overall:
* type: number
* Pace:
* type: number
* Shooting:
* type: number
* Passing:
* type: number
* Dribbling:
* type: number
* Defending:
* type: number
* Physical:
* type: number
* responses:
* 200:
* description: Jogador atualizado com sucesso
* content:
* application/json:
* schema:
* type: object
* properties:
* id:
* type: number
* name:
* type: string
* club:
* type: string
* nationality:
* type: string
* position:
* type: string
* statistics:
* type: object
* properties:
* Overall:
* type: number
* Pace:
* type: number
* Shooting:
* type: number
* Passing:
* type: number
* Dribbling:
* type: number
* Defending:
* type: number
* Physical:
* type: number
*/
router.patch('/players/:id', PlayerController.updatePlayer)
/**
* @swagger
* /players/{id}:
* delete:
* summary: Deleta um jogador pelo ID
* tags: [Players]
* parameters:
* - in: path
* name: id
* schema:
* type: number
* required: true
* description: ID do jogador
* responses:
* 200:
* description: Jogador deletado com sucesso
*/
router.delete('/players/:id', PlayerController.deletePlayer)
export default router
5. Estrutura de Diretórios ATUALIZADA
| src/
├── config/
│ ├── swagger.ts
├── controllers/
│ ├── playersController.ts
├── models/
│ ├── playerModel.ts
│ └── httpResponseModel.ts
├── repositories/
│ └── playersRepository.ts
├── services/
│ └── playersService.ts
├── utils/
│ └── httpHelper.ts
├── routes.ts
├── app.ts
└── server.ts
└── package.json
└── tsconfig.json
| .env
| package.json
| tsconfig.json
Conclusão
Seguindo esses passos, você terá uma documentação interativa da sua API disponível em http://localhost:3333/api/v1/docs
.
Em resumo, instalamos as dependências e suas tipagens swagger-ui-express
e swagger-ui-express
. Depois criamos o arquivo swagger.ts
e configurando o Swagger. Importamos sua configuração no app.ts
e finalizamos com os comentários das rotas no arquivo router.ts
.
A parte 3 com a implementação de monitoramento ainda está em desenvolvimento.