Swagger: melhores abordagens para documentação
Data de elaboração | 18/08/2021 |
---|---|
Responsável pelo estudo |
|
Equipe do estudo | Esquadrão Suicida |
Alvo | Swagger |
Origem |
|
Objetivo | Definição da melhor abordagem para padronização de documentações de APIs node.js usando o Swagger no âmbito da Superintendência de Tecnologia da Informação e Comunicação - SETIC. Atualmente, as API's são documentadas usando o Postman que, como tem integração com a _rout_, basta apenas algumas marcações no código-fonte para que a documentação seja gerada. Todavia, com a mudança do Postman para o Swagger, aplicação adotada como padrão no âmbito da SETIC, visando a implementação de dicionário de dados, exemplos de resposta variados abordando diversos casos e também a documentação de erros possíveis, faz-se necessário definir padrões de documentação que não polua o código excessivamente e de fácil manutenção/geração. |
Documentação correlata (opcional) |
https://www.npmjs.com/package/swagger-ui-express https://www.npmjs.com/package/swagger-jsdoc https://dev.to/kabartolo/how-to-document-an-express-api-with-swagger-ui-and-jsdoc-50do |
Observações | Não possui. |
Glossário
- Swagger: é uma aplicação para auxilio no desenvolvimento de documentações
- OpenAPI: é uma especificação para documentação de API's Rest agnóstica a linguagem.
- Node.js - é um ambiente de execução JavaScript open-source que funciona utilizando o mecanismo Chrome V8.
- JavaScript - é uma linguagem de programação de alto nível que segue as especificações ECMAScript.
- TypeScript - é um superconjunto sintático estrito de Javascript, criado e mantido pela Microsoft.
- yarn - é um gerenciador de pacotes javascript.
- NPM - Node Package Manager.
1. Introdução
Maior produtividade na confecção da documentação com o uso de funções já existentes no Typescript, sem prejuízo da manutenção da aplicação, pois o código permanece 'limpo'. Com base nos estudos realizados decidimos utilizar o swagger, diversos times hoje usam esta ferramenta para documentação, logo, tonaria mais fácil a utilização para os mesmos.
2. Desenvolvimento
3. Desenvolvimento
2.1 Swagger UI Express:
Nos testes realizados constatamos que esta biblioteca serve como pilar para as demais que tramalham com Swagger, a configuração é simples porem a escrita de documentação exige muita escrita tornando a manutenção árdua e suscetível a erro, oferece a opção de documentação em forma de comentários no código mas que se prova inviável pois polui visualmente o documento tornando difícil a compreensão e manutenção do mesmo.
Exemplo de implementação Swagger UI Express
yarn add swagger-ui-express
const express = require('express');
const app = express();
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');
var options = {
swaggerOptions: {
validatorUrl: null
}
};
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, options));
/**
* @swagger
* /:
* get:
* summary: Lista de produtos
* description: Lista de produtos usada para popular a grid e produtos
* responses:
* 200:
* description: lista
* content:
* application/json:
* schema:
* type: array
* items:
* type: array
* items:
* type: object
* properties:
* id:
* type: string
* description: id do produto
* example: '0002321'
* categoria_id:
* type: string
* description: id da categoria
* example: '0254'
* ncm_id:
* type: string
* description: id do ncm
* example: '329'
* nome:
* type: string
* description: nome do produto
* example: Produto teste
* inativo?:
* type: number
* description: flag que indica se o produto esta ativo (1 ou null)
* example: 1
*/
route.get('/', (req, res) => {
...
})
2.2 Express jsdoc swagger:
Biblioteca que utiliza a 'swagger UI Express' citada anteriormente, segue a mesma premissa de documentação através de escrita de comentários no código e apresenta os mesmos problemas, poluição visual e dificuldade de manutenção.
2.3 Routing Controller Openapi:
Biblioteca que também utiliza a 'swagger UI Express', porem trás uma nova abordagem utilizando funções existentes no Typescript, usando decoradores podemos definir tipos de retornos, retornos múltiplos, casos onde ocorrem erros e exemplos de resposta, com o auxilio de outra biblioteca, 'class-validator-jsonschema', podemos definir schema de dados que nos ajuda a não repetir código e também oferecer um dicionário de dados.
Segue a baixo um exemplo de implementação com a routing-controllers-openapi em um ambiente de teste.
2.3.1 Instalação:
yarn add routing-controllers-openapi
# Dependências
yarn add class-validator-jsonschema # para criar dicionários de dados
yarn add swagger-ui-express # para servir a documentação no swagger
2.3.2 Configuração:
// importação das bibliotecas
import swagger from "swagger-ui-express";
import { routingControllersToSpec } from "routing-controllers-openapi";
import { validationMetadatasToSchemas } from "class-validator-jsonschema";
// configuração do class-validator-jsonschema
const schemas = validationMetadatasToSchemas({
refPointerPrefix: "#/components/schemas/",
});
// recupera metadata das rotas
const storage = getMetadataArgsStorage();
// gera as especificações da documentação no padrão OpenAPI
const spec = routingControllersToSpec(
storage,
{},
{
components: { schemas },
},
);
app.use("/doc", swagger.serve, swagger.setup(spec)); // cria uma rota para servir a documentação
2.3.3 Exemplo de implementação:
import { IsNumber, IsString } from "class-validator";
import { JSONSchema } from "class-validator-jsonschema";
const example1 = {
id: "001",
nome: "Example",
idade: 32,
};
const example2 = {
id: "001",
nome: "Example",
idade: null,
};
@JSONSchema({ examples: [example1, example2] })
export class User {
@IsString()
id!: string;
@IsString()
nome!: string;
@IsNumber()
idade?: number;
}
import { Body, Delete, Get, HttpCode, JsonController, Param, Post, Put } from "routing-controllers";
import { OpenAPI, ResponseSchema } from "routing-controllers-openapi";
import { ApplicationError } from "../error/ApplicationError";
import { UserService } from '../services/user.service';
import { User } from "../models/User.schema";
@JsonController("/users")
export class UserController {
@Get("/")
@ResponseSchema(User, { isArray: true })
@ResponseSchema(ApplicationError, { statusCode: 400 })
async list() {
return await UserService.list()
}
@Get("/:userId")
@ResponseSchema(User)
@ResponseSchema(ApplicationError, { statusCode: 400 })
async show(@Param("userId") userId: string): Promise<User> {
return await UserService.getUserById(userId)
}
@HttpCode(201)
@Post("/")
@ResponseSchema(User)
async store(@Body() user: User) {
return await UserService.createUser(user);
}
@Put("/:userId")
@ResponseSchema(User)
async edit(@Param("userId") userId: string, @Body() user: User) {
return user;
}
@Delete("/:userId")
@HttpCode(204)
@ResponseSchema("", { statusCode: 204 })
@ResponseSchema(ApplicationError, { statusCode: 404 })
async delete(@Param("userId") userId: string) {
return await UserService.deleteUserById(userId)
}
}
3. Conclusão
Dessa forma a utilização da 'routing-controller-openapi' se mostrou mais eficaz dado que:
- Simplicidade;
- Facilidade de implementação;
- Facilidade de manutenção; e,
- Pouca poluição do código.
- Uso de Typescript
Desta forma, usando a melhor abordagem, sera possível documentar qualquer endpoint usando swagger com 2 pontos de complexidade anti o 1 ponto usado no postman.
4. Referência
[1] SWAGGER UI EXPRESS. Disponível em: https://www.npmjs.com/package/swagger-ui-express. Acesso em: 18 ago. 2021.
[2] SWAGGER JSDOC. Disponível em: https://www.npmjs.com/package/swagger-jsdoc. Acesso em: 18 ago. 2021.
[3] How to Document an Express API with Swagger UI and JSDoc. 2020. Disponível em: https://dev.to/kabartolo/how-to-document-an-express-api-with-swagger-ui-and-jsdoc-50do. Acesso em: 18 ago. 2021.
[4] EXPRESS JSDOC SWAGGER. Disponível em: https://www.npmjs.com/package/express-jsdoc-swagger. Acesso em: 18 ago. 2021.
[5] ROUTING CONTROLLER OPENAPI. Disponível em: https://github.com/epiphone/routing-controllers-openapi. Acesso em: 18 ago. 2021.
Nenhum comentário