Ir para o conteúdo principal

Swagger: melhores abordagens para documentação

Definição da melhor abordagem para utilização do Swagger em aplicações Node.js

OBJETIVO

Adequação de documentações para APIs node.js com Swagger.

 

JUSTIFICATIVA

Foi identificada a necessidade de melhorias na documentação já existente, visando a implementação de dicionario de dados, exemplos de resposta variados abordando diversos casos e também a documentação de erros possíveis.

 
RESULTADOS ESPERADOS

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.

Dentre as diversas bibliotecas Javascript de documentação que trabalham com swagger, optamos por utilizar uma que não polua o código excessivamente e de fácil manutenção, dentre as diversas opções escolhemos a routing-controller-openapi por sua compatibilidade com uma biblioteca que já usamos e também por sua:

  •  Simplicidade
  • Facilidade de implementação
  • Facilidade de manutenção
  • Pouca poluição do código
 
ENVOLVIDOS:IMPLEMENTAÇÃO:

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

 

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

 

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)
  }
}

 

  • Assessor:
    • Diego Gonçalves de Almeida
  • Equipe Técnica:
    • Diego Barros de Oliveira
    • Alef Carvalho da Silva
    • Anderson Soares Cardoso
  • Gerente de Desenvolvimento:
    • Janderson de Castro Thomaz
  • Product Owner:
    • Jônatas Justiniano Lima
  • Scrum Master:
    • Edson Masami Hiraçaka

 

GLOSSÁRIO
  • PostGreSql- Banco de Dados relacional openSource com mais de 30 anos de desenvolvimento ativo;

 

DESENVOLVIMENTO

....

 

CONCLUSÃO

Realizada a análise e os testes com o banco PostgreSQL no sistema Atualização Cadastral, foi possível prever e implementar no ambiente local do sistema o PostgreSQL. Sendo o passo-a-passo especificado nos tópicos acima. Foram identificados algumas possíveis alterações em tipos de dados, instalação de pacotes do PostgreSql nos sistemas, alteração do banco em código e alteração de connectionString nos ambientes. Estimando-se, um total de 6 pontos para a alteração em cada sistema proposto.

 

REFERÊNCIAS

[1] MICROSOFT. DATA TYPES. 2019. Disponível em: Tipos de dados (Transact-SQL) - SQL Server | Microsoft Docs.  Acesso em: 31 mai. 2021.

 

[2] POSTGRESQL. TIPOS DE DADOS (TRANSACT-SQL). 2020. Disponível em: PostgreSQL: Documentation: 9.6: Data Types.  Acesso em: 31 mai. 2021.

 

[3] POSTGRESQL. Npgsql Entity Framework Core Provider. 2019. Disponível em: Npgsql Entity Framework Core Provider | Npgsql Documentation.  Acesso em: 31 mai. 2021.

 

[4] POSTGRESQL. PostgreSQL Downloads. 2019. Disponível em: PostgreSQL: Documentation: 9.6: Data Types.  Acesso em: 31 mai. 2021.