Pular para o conteúdo
Bruno Dórea
Todos os posts

26 mins de leitura


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.