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

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 ComuniçComunicação - SETIC.

 

JUSTIFICATIVA

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árorio 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.

 

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.

 

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.

 

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.

 

Escolha:

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: é uma aplicação para auxilio no desenvolvimento de documentações
  • PostGreSql-OpenAPI: Bancoé uma especificação para documentação de DadosAPI's relacionalRest openSourceagnóstica coma maislinguagem.
  • Node.js - é um ambiente de 30execução anosJavaScript open-source que funciona utilizando o mecanismo Chrome V8.
  • JavaScript - é uma linguagem de desenvolvimentoprogramação ativo;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.

 

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

    RealizadaApos ao análisetime entrar em acordo, optamos pela utilização da 'routing-controller-openapi' pela sua fácil integração as tecnologias utilizadas que utilizamos e osfácil testes com o banco PostgreSQL no sistema Atualizaçmanutençã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.o.

     

    REFERÊNCIAS

    [1] MICROSOFT.SWAGGER DATAUI TYPESEXPRESS. 2019. Disponível em: https://www.npmjs.com/package/swagger-ui-express.Tipos de dados (Transact-SQL) - SQL Server | Microsoft Docs Acesso em: 3118 mai.ago. 2021.

     

    [2] POSTGRESQL.SWAGGER JSDOC.TIPOS DE DADOS (TRANSACT-SQL). 2020. Disponível em: https://www.npmjs.com/package/swagger-jsdocPostgreSQL: Documentation: 9.6: Data Types.  Acesso em: 3118 mai.ago. 2021.

     

    [3] POSTGRESQL.How Npgsqlto EntityDocument Frameworkan CoreExpress ProviderAPI with Swagger UI and JSDoc. 2019.2020. Disponível em: Npgsql Entity Framework Core Provider | Npgsql Documentationhttps://dev.to/kabartolo/how-to-document-an-express-api-with-swagger-ui-and-jsdoc-50do.  Acesso em: 3118 mai.ago. 2021.

     

    [4] POSTGRESQL.EXPRESS PostgreSQLJSDOC DownloadsSWAGGER. 2019. Disponível em: PostgreSQL: Documentation: 9.6: Data Typeshttps://www.npmjs.com/package/express-jsdoc-swagger.  Acesso em: 3118 mai.ago. 2021.

     

    [5] ROUTING CONTROLLER OPENAPI. Disponível em: https://github.com/epiphone/routing-controllers-openapi.  Acesso em: 18 ago. 2021.