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çDefinição da melhor abordagem para padronização de documentações parade APIs node.js comusando Swagger.o Swagger no âmbito da Superintendência de Tecnologia da Informação e Comunição - SETIC.

 

JUSTIFICATIVA

FoiAtualmente, identificadaas API's são documentadas usando o Postman que, como tem integração com a necessidade_rout_, debasta melhoriasapenas naalgumas marcações no código-fonte para que a documentação seja existente,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 dicionariodicionário de dados, exemplos de resposta variados abordando diversos casos e também a documentação de erros possíveis.veis, faz-se necessáro definir padrões de documentação que não polua o código excessivamente e de fácil manutenção/geração.

 
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; e,
  • Pouca poluição do código.
 
ENVOLVIDOS
  • Assessor:
    • Diego Gonçalves de Almeida.
  • Equipe Técnica:
    • Diego Barros de Oliveira;
    • Alef Carvalho da Silva; e,
    • Anderson Soares Cardoso.
  • Gerente de Desenvolvimento:
    • Janderson de Castro Thomaz.
  • Product Owner:
    • Jônatas Justiniano Lima.
  • Scrum Master:
    • Edson Masami Hiraçaka.

 

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

 

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

 

 

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.