<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: William Queiroz</title>
    <description>The latest articles on DEV Community by William Queiroz (@wnqueiroz).</description>
    <link>https://dev.to/wnqueiroz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F275251%2F7acc69ba-0b05-4715-b1f5-9b930ce34745.jpg</url>
      <title>DEV Community: William Queiroz</title>
      <link>https://dev.to/wnqueiroz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wnqueiroz"/>
    <language>en</language>
    <item>
      <title>Drops #05: Meu guia para você aprender Go!</title>
      <dc:creator>William Queiroz</dc:creator>
      <pubDate>Tue, 13 Jun 2023 15:37:56 +0000</pubDate>
      <link>https://dev.to/wnqueiroz/drops-05-meu-guia-para-voce-aprender-go-5fj5</link>
      <guid>https://dev.to/wnqueiroz/drops-05-meu-guia-para-voce-aprender-go-5fj5</guid>
      <description>&lt;p&gt;&lt;em&gt;Foto de &lt;a href="https://unsplash.com/@framesbyfin?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Heidi Fin&lt;/a&gt; na &lt;a href="https://unsplash.com/pt-br/fotografias/M2Kxb80gqcc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;E ae dev, tudo bem com você?&lt;/p&gt;

&lt;p&gt;Nesses últimos meses eu passei boa parte do meu tempo aprendendo a linguagem criada pelo Google e queridinha pela comunidade de desenvolvedores (principalmente os apaixonados por CLIs 😅): Go!&lt;/p&gt;

&lt;p&gt;Foi um desafio e tanto, dado que eu tinha pouco tempo para isso e precisava entregar um projeto bem massa para outros desenvolvedores poderem utilizar e criar seus próprios projetos escritos em Go. No caminho encontrei barreiras e facilidades para quem busca aprender uma nova linguagem, pensando nisso, resolvi trazer um guia simples e objetivo para você orientar seus estudos e ter em mente alguns pontos para evitar algumas barreiras durante essa jornada de aprendizado! Bom, falei demais, a ideia desse "guia" é que ele seja vivo! A medida que eu for encontrando novos conteúdos vou atualizá-lo por aqui, btw.&lt;/p&gt;

&lt;p&gt;Bora pro post?&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumário
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Crie um plano: o que você quer construir com Go?&lt;/li&gt;
&lt;li&gt;Aprenda a testar seu código! Não subestime isso, ou ignore logo no início&lt;/li&gt;
&lt;li&gt;Cuidado com “a comunidade de Go não faz isso”&lt;/li&gt;
&lt;li&gt;
Indicações de conteúdos

&lt;ul&gt;
&lt;li&gt;Comunidades&lt;/li&gt;
&lt;li&gt;Cursos&lt;/li&gt;
&lt;li&gt;Outros&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Links úteis&lt;/li&gt;

&lt;li&gt;Finalizando...&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Crie um plano: o que você quer construir com Go?
&lt;/h2&gt;

&lt;p&gt;Antes de sair por ai buscando tutoriais pela internet e já sair colocando a mão na massa, pare um pouco, e reflita: o que você quer construir com Go? É muito fácil cairmos em um limbo onde não conseguimos visualizar a evolução do nosso aprendizado muito por conta de que se quer elaboramos um plano para isso! A pergunta é bem simples afinal, e com ela podemos até obter novas como: "O que dá para construirmos com Go?", "Por que raios o Google criou essa linguagem?", "Qual problema eles queriam resolver?". &lt;/p&gt;

&lt;p&gt;"Comece do começo": elabore um plano com objetivos que sejam fáceis de atingir, e assim que atingi-lo, adicione mais "requisitos" &lt;strong&gt;ainda no mesmo projeto&lt;/strong&gt;, e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quero construir uma API com 1 endpoint hello world com Go;&lt;/li&gt;
&lt;li&gt;Quero construir uma API com CRUD de TO-DOs com Go;&lt;/li&gt;
&lt;li&gt;Quero construir uma API conectada ao Postgres com Go;&lt;/li&gt;
&lt;li&gt;Quero adicionar testes na minha API com Go.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claro que isso são exemplos simples, não estou entrando no detalhe do que é um fato: de que você precisará entender e aprender as especificidades da linguagem. Mas isso será muito mais fácil se você tiver um objetivo e algo que seja tangível durante esse processo!&lt;/p&gt;

&lt;h2&gt;
  
  
  Aprenda a testar seu código! Não subestime isso, ou ignore logo no início
&lt;/h2&gt;

&lt;p&gt;Se você estiver vindo de outra linguagem, muito provavelmente (se você tiver o mínimo de preocupação com a qualidade e escalabilidade do seu projeto) você ficará curioso para entender como funcionam os testes no Go. Não caia na armadilha de pensar &lt;em&gt;“ah, isso aqui eu posso ver depois, preciso construir minha API!”&lt;/em&gt;: é muito tranquilo aprender Go já com testes, isso irá facilitar a construção do seu projeto (pelo &lt;em&gt;design e refactor&lt;/em&gt;), e também fará com que você tenha um código mais idiomático. Inclusive a recomendação desse tópico é pra esse excelente guia do &lt;a href="https://twitter.com/quii" rel="noopener noreferrer"&gt;Chris James&lt;/a&gt;: &lt;a href="https://quii.gitbook.io/learn-go-with-tests/" rel="noopener noreferrer"&gt;Learn Go with Tests&lt;/a&gt; (com a versão traduzida em pt-BR aqui: &lt;a href="https://larien.gitbook.io/aprenda-go-com-testes/" rel="noopener noreferrer"&gt;Aprenda Go com Testes&lt;/a&gt;). Apesar do guia estar utilizando a versão 1.16 do Go (e no momento em que eu escrevo esse artigo, já estamos na 1.20.5), não tive muitos problemas ao seguí-lo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cuidado com “a comunidade de Go não faz isso”
&lt;/h2&gt;

&lt;p&gt;Meu amigo, isso aqui sem dúvida algum foi uma barreira e tanto 🤣 Como se não bastasse a "pressão" que (eu não sei você, mas eu sou expert nisso) colocamos em nós mesmos, sempre haverá alguém para fazer isso ainda melhor! HAHAHA &lt;/p&gt;

&lt;p&gt;É &lt;em&gt;óbvio&lt;/em&gt; que cada tecnologia/linguagem terá um jeito adequado ou mais correto de lidar com um certo problema, mas pense comigo: isso é algo realmente necessário de nos preocuparmos logo no começo? O que eu mais ouvi sobre a comunidade de Go (isso, sobre, e não diretamente da comunidade) é de que "X coisa não é feita assim", "A comunidade prefere convencionar de Y jeito". O ponto aqui é que será fácil encontrar opiniões nesse sentido, o que você precisa é filtrar bem o conteúdo que encontra por ai... Em alguns momentos você terá uma sensação como se alguém estivesse falando pra uma criança: "Olha, cuidado pra você não tropeçar e cair", sendo que ela nem se quer começou a "engatinhar" 🤣&lt;/p&gt;

&lt;h2&gt;
  
  
  Indicações de conteúdos
&lt;/h2&gt;

&lt;p&gt;Aqui vou deixar alguns links de comunidades e cursos disponíveis na web que vão te ajudar muito! Nas comunidades é possível sanar dúvidas, buscar opiniões sobre um determinado assunto e acompanhar as novidades da linguagem da galera que está há mais tempo em contato com a linguagem (ou não hehehe).&lt;/p&gt;

&lt;h3&gt;
  
  
  Comunidades
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn: Go Developer Community&lt;/strong&gt;: &lt;a href="https://www.linkedin.com/groups/10541552/" rel="noopener noreferrer"&gt;https://www.linkedin.com/groups/10541552/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gophers: Slack oficial da comunidade Go&lt;/strong&gt;: &lt;a href="https://join.slack.com/t/gophers/shared_invite/zt-1x4z32nlf-QOO8r9eqA_C4kGa2YPlB2Q" rel="noopener noreferrer"&gt;https://join.slack.com/t/gophers/shared_invite/zt-1x4z32nlf-QOO8r9eqA_C4kGa2YPlB2Q&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cursos
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aprenda Go 🇧🇷&lt;/strong&gt;: Curso completo em português da linguagem Go construído pela &lt;a href="https://twitter.com/veekorbes" rel="noopener noreferrer"&gt;Ellen Korbes&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apesar do conteúdo já ter mais de 3 anos, a playlist do curso está gratuita no YouTube e conta com mais de 180 vídeos que explora a linguagem com diversos exercícios.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.youtube.com/playlist?list=PLCKpcjBB_VlBsxJ9IseNxFllf-UFEXOdg" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ytimg.com%2Fvi%2FWiGU_ZB-u0w%2Fhqdefault.jpg%3Fsqp%3D-oaymwEXCOADEI4CSFryq4qpAwkIARUAAIhCGAE%3D%26rs%3DAOn4CLDLII7U6SKcucPjEj2UuBM-Pxn4tg%26days_since_epoch%3D20010" height="auto" class="m-0"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.youtube.com/playlist?list=PLCKpcjBB_VlBsxJ9IseNxFllf-UFEXOdg" rel="noopener noreferrer" class="c-link"&gt;
          Aprenda Go 🇧🇷 - YouTube
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Curso completo em português da linguagem Go, de zero a ninja! 🇧🇷
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.youtube.com%2Fs%2Fdesktop%2Ffd504f58%2Fimg%2Ffavicon.ico"&gt;
        youtube.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Go 101&lt;/strong&gt;: Curso 100% gratuito do blog &lt;a href="https://aprendagolang.com.br/" rel="noopener noreferrer"&gt;Aprenda Golang&lt;/a&gt;, construído pelo Tiago Temporin.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.youtube.com/playlist?list=PLHPgIIn9ls6-1l7h8RUClMKPHi4NoKeQF&amp;amp;amp%3Bsi=p_lUYWmO6U0r-sFk" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ytimg.com%2Fvi%2FbOlnyWOjVIo%2Fhqdefault.jpg%3Fsqp%3D-oaymwEXCOADEI4CSFryq4qpAwkIARUAAIhCGAE%3D%26rs%3DAOn4CLAu-kEwkMdZfYMEXoMXvyZORJiMhw%26days_since_epoch%3D20010" height="auto" class="m-0"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.youtube.com/playlist?list=PLHPgIIn9ls6-1l7h8RUClMKPHi4NoKeQF&amp;amp;amp%3Bsi=p_lUYWmO6U0r-sFk" rel="noopener noreferrer" class="c-link"&gt;
          GO 101 - YouTube
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Curso completo e gratuito para quem está iniciando na linguagem Golang. Aqui você vai aprender tudo o que precisa para dar seus primeiros passos nessa lingua...
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.youtube.com%2Fs%2Fdesktop%2Ffd504f58%2Fimg%2Ffavicon.ico"&gt;
        youtube.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Outros
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Google I/O&lt;/strong&gt;: Apesar de não ser um conteúdo específico de Go, vou deixar a recomendação aqui para você acompanhar o Google I/O! &lt;/p&gt;

&lt;p&gt;O Google I/O é uma conferência de programadores que é organizada anualmente pela Google em São Francisco, Califórnia, Estados Unidos. O objetivo dessa conferência é orientar os programadores a melhorarem seus programas com técnicas que a Google demonstra (e geralmente tem o Go na jogada!). Aqui estão os links das últimas 3 edições disponíveis no YouTube:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PL590L5WQmH8dAqv03RCMbZrbzxqCn6W3O" rel="noopener noreferrer"&gt;Google I/O | 2023.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PL590L5WQmH8dUdwu3ZWuy5xh8j2iGgApr" rel="noopener noreferrer"&gt;Google I/O | 2022.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PL590L5WQmH8cmLG5BDnf334-eMhkmlvNE" rel="noopener noreferrer"&gt;Google I/O | 2021.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Gopher Academy: Talks!&lt;/strong&gt;: A Gopher Academy é a força criativa por trás da &lt;a href="https://www.gophercon.com" rel="noopener noreferrer"&gt;GopherCon&lt;/a&gt;, uma conferência que celebra todas as coisas do Go! Desde sua estreia em 2014, a GopherCon desenvolveu algumas das melhores programações da comunidade Go. A GopherCon até inspirou reuniões em países como Reino Unido, Índia, Brasil, Cingapura, Rússia e China, com novas conferências globais surgindo todos os anos!&lt;/p&gt;

&lt;p&gt;No canal do YouTube, você pode encontrar conteúdos mais específicos sobre Go, apresentados durante as edições da GopherCon. Aqui estão os links das últimas 3 edições disponíveis no YouTube:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PL2ntRZ1ySWBfiSJSt-zPRbVSMDfK0EwQC" rel="noopener noreferrer"&gt;GopherCon | 2022.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PL2ntRZ1ySWBfulCVQD6EaU8c-GM56aUU7" rel="noopener noreferrer"&gt;GopherCon | 2021.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PL2ntRZ1ySWBfGcmAccnsjqkYFHRn9XDjA" rel="noopener noreferrer"&gt;GopherCon | 2021 - Lightning Talks.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PL2ntRZ1ySWBfUint2hCE1JRxRWChloasB" rel="noopener noreferrer"&gt;GopherCon | 2020.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vale dizer que também temos a nossa edição BR, você pode encontrar mais detalhes aqui: &lt;a href="https://gopherconbr.org" rel="noopener noreferrer"&gt;https://gopherconbr.org&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links úteis
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;gobyexample.com&lt;/strong&gt; - uma introdução prática ao Go com vários exemplos: &lt;a href="https://gobyexample.com" rel="noopener noreferrer"&gt;https://gobyexample.com&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;gosamples.dev&lt;/strong&gt; - uma biblioteca de tutoriais e exemplos de Go que ajuda você a resolver problemas de código do dia a dia: &lt;a href="https://gosamples.dev" rel="noopener noreferrer"&gt;https://gosamples.dev&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;avelino/awesome-go&lt;/strong&gt; - uma lista com curadoria de incríveis frameworks, bibliotecas e software Go: &lt;a href="https://github.com/avelino/awesome-go" rel="noopener noreferrer"&gt;https://github.com/avelino/awesome-go&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Effective Go&lt;/strong&gt; - um guia construído pelos mantenedores do Go para entendermos a suas propriedades e expressões idiomáticas: &lt;a href="https://go.dev/doc/effective_go" rel="noopener noreferrer"&gt;https://go.dev/doc/effective_go&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 O documento "Effective Go" foi escrito para o lançamento do Go em 2009 e não foi atualizado significativamente desde então. Embora seja um bom guia para entender como usar a linguagem em si, graças à estabilidade da linguagem, fala pouco sobre as bibliotecas e nada sobre mudanças significativas no ecossistema Go desde que foi escrito, como o sistema de compilação, testes, módulos e polimorfismo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A tour of Go&lt;/strong&gt; - uma espécie de "tour" interativo construído pelos mantenedores do Go que cobre as características mais importantes da linguagem com diferentes lições: &lt;a href="https://go.dev/tour/list" rel="noopener noreferrer"&gt;https://go.dev/tour/list&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Finalizando...
&lt;/h2&gt;

&lt;p&gt;Bem, é isso, por hoje, é só!&lt;/p&gt;

&lt;p&gt;Quero te agradecer por chegar até aqui, e queria lhe pedir também para me encaminhar as suas dúvidas, comentários, críticas, correções ou sugestões sobre a publicação.&lt;/p&gt;

&lt;p&gt;Deixe seu ❤️ se gostou ou um 🦄 se esse post te ajudou de alguma maneira! Não se esqueça de ver os posts anteriores e me siga para maaaais conteúdos.&lt;/p&gt;

&lt;p&gt;Até!&lt;/p&gt;

</description>
      <category>go</category>
      <category>braziliandevs</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Refresh Tokens: equilibrando segurança e usabilidade em aplicações!</title>
      <dc:creator>William Queiroz</dc:creator>
      <pubDate>Fri, 17 Jun 2022 15:46:11 +0000</pubDate>
      <link>https://dev.to/wnqueiroz/refresh-tokens-equilibrando-seguranca-e-usabilidade-em-aplicacoes-c6c</link>
      <guid>https://dev.to/wnqueiroz/refresh-tokens-equilibrando-seguranca-e-usabilidade-em-aplicacoes-c6c</guid>
      <description>&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@flyd2069?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;FLY:D&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/unit-test?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumário
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introdução&lt;/li&gt;
&lt;li&gt;Problema&lt;/li&gt;
&lt;li&gt;
Solução: refresh tokens!

&lt;ul&gt;
&lt;li&gt;O que é um access token?&lt;/li&gt;
&lt;li&gt;O que é um refresh token?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Autenticação com refresh token&lt;/li&gt;

&lt;li&gt;Finalizando...&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;E ae dev, tudo bem com você?&lt;/p&gt;

&lt;p&gt;Hoje vamos falar especificamente de uma das camadas mais utilizadas num fluxo "moderno" de autenticação. Você já ouviu falar de Refresh Tokens? Em resumo, "tokens de atualização" são credenciais utilizadas para obter credenciais/tokens de acesso. Complicado?&lt;/p&gt;

&lt;p&gt;Calma fica comigo, pega um café e garanta sua leitura!&lt;/p&gt;

&lt;p&gt;Bora pro post?&lt;/p&gt;

&lt;h2&gt;
  
  
  Problema
&lt;/h2&gt;

&lt;p&gt;Vamos criar uma cenário hipotético mas muito comum para quem está lidando com autenticação de aplicações. Imagine que um usuário queira acessar uma aplicação. Essa aplicação por sua vez possui uma tela de login onde o usuário precisará se autenticar para então acessar toda a parte interna da aplicação: dashboards, meu perfil, e etc.&lt;/p&gt;

&lt;p&gt;Por questões de segurança, no momento em que o usuário se autenticou, foi definido que o tempo de sessão mínimo seja de apenas 5 minutos. O usuário então (sempre que expira a sua sessão) perde o acesso ao sistema, e deve inserir suas credenciais novamente para continuar navegando.&lt;/p&gt;

&lt;p&gt;É evidente que o nosso usuário acaba tendo uma péssima experiência ao utilizar o nosso sistema...&lt;/p&gt;

&lt;p&gt;Tendo isso em vista, conversamos com o time de segurança sobre aumentarmos o tempo de duração da sessão, mas isso implicaria em deixarmos a nossa aplicação menos segura para o nosso usuário...&lt;/p&gt;

&lt;p&gt;Sendo assim, como evitar que os usuários tenham que realizar o login sempre que a sessão expire? Como equilibrar a segurança e a usabilidade na nossa aplicação?&lt;/p&gt;

&lt;h2&gt;
  
  
  Solução: refresh tokens!
&lt;/h2&gt;

&lt;p&gt;Primeiro, vamos entender um pouco do fluxo de autenticação que temos até então.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpci8m7u9yv0i5e01tgm4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpci8m7u9yv0i5e01tgm4.png" alt="Basic authentication flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O &lt;em&gt;Client&lt;/em&gt; envia um usuário e senha para o servidor de autorização, as credenciais estando válidas o servidor devolve um &lt;em&gt;access_token&lt;/em&gt; para o &lt;em&gt;Client&lt;/em&gt;. O Client pode (e deve) utilizar o &lt;em&gt;access_token&lt;/em&gt; nas requisições protegidas para as APIs. As APIs protegidas validam o &lt;em&gt;access_token&lt;/em&gt; e devolvem o recurso solicitado pelo &lt;em&gt;Client&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Com o fluxo atual, é inevitável que o usuário tenha a experiência que falamos antes. Isto porque as APIs protegidas verificam sempre se o access_token é válido, para então devolver o recurso pro usuário.&lt;/p&gt;

&lt;p&gt;Precisamos melhorar esse fluxo, incluindo o mecanismo de &lt;em&gt;refresh_token&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;Vamos primeiro entender qual é a diferença entre um &lt;code&gt;access_token&lt;/code&gt; e de um &lt;code&gt;refresh_token&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que é um access token?
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;access token&lt;/em&gt; é um JWT (JSON Web Tokens) que é utilizado pelo usuário para acessar as aplicações e os recursos protegidos. Esse token é codificado (não encriptado) e carrega algumas informações presentes no &lt;em&gt;Header&lt;/em&gt;, &lt;em&gt;Payload&lt;/em&gt; e &lt;em&gt;Signature&lt;/em&gt; (seções que compõe a estrutura base de um token JWT).&lt;/p&gt;

&lt;p&gt;Geralmente ele possui um tempo de vida útil &lt;strong&gt;curto&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;a href="https://jwt.io/" rel="noopener noreferrer"&gt;jwt.io&lt;/a&gt;: &lt;em&gt;JSON Web Tokens are an open, industry standard &lt;a href="https://tools.ietf.org/html/rfc7519" rel="noopener noreferrer"&gt;RFC 7519&lt;/a&gt; method for representing claims securely between two parties.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  O que é um refresh token?
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;refresh token&lt;/em&gt; é um token utilizado para "renovar a sessão" de um usuário. Através dele podemos solicitar ao servidor de autorização para que seja gerado um novo &lt;em&gt;access token&lt;/em&gt; sem ter que pedir ao usuário que ele se logue novamente (desde que o token de atualização seja válido e não tenha expirado).&lt;/p&gt;

&lt;p&gt;É importante entender que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ele possui um &lt;strong&gt;tempo de vida útil maior&lt;/strong&gt; do que o &lt;code&gt;access_token&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;É um token apenas para gerar um novo token de acesso. Não pode ser utilizado para acessar a aplicação. Porém, se expirado, o usuário deve realizar o login novamente;&lt;/li&gt;
&lt;li&gt;Alguns IdPs (&lt;a href="https://en.wikipedia.org/wiki/Identity_provider" rel="noopener noreferrer"&gt;Identity Providers&lt;/a&gt;) utilizam o &lt;em&gt;refresh token&lt;/em&gt; pra revogar as sessões ativas do usuário.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Estando claras as diferenças, vamos adaptar o nosso fluxo de autenticação!&lt;/p&gt;

&lt;h2&gt;
  
  
  Autenticação com refresh token
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0387hi6n712sy33trglv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0387hi6n712sy33trglv.png" alt="Basic authentication flow: with refresh tokens"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No novo fluxo o &lt;em&gt;Client&lt;/em&gt;, toda vez que tiver uma solicitação rejeitada pela API protegida, deve solicitar ao servidor de autorização um novo token de acesso (utilizando o &lt;em&gt;refresh token&lt;/em&gt; na solicitação). O servidor de autorização valida a solicitação (verificando se o &lt;em&gt;refresh token&lt;/em&gt; está válido e não expirado) e concede ao &lt;em&gt;Client&lt;/em&gt; o token de acesso.&lt;/p&gt;

&lt;p&gt;Verificando as alterações no novo fluxo de autenticação:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Além de retornar o &lt;code&gt;access_token&lt;/code&gt;, também retornamos o &lt;code&gt;refresh_token&lt;/code&gt; durante o login do usuário (no &lt;code&gt;POST /auth/login&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;Adicionamos um nova rota no &lt;em&gt;Authorization Server&lt;/em&gt; para possibilitar que o &lt;em&gt;Client&lt;/em&gt; possa renovar a sua sessão (o &lt;code&gt;POST /auth/refresh&lt;/code&gt;);&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Finalizando...
&lt;/h2&gt;

&lt;p&gt;Bem, é isso, por hoje, é só!&lt;/p&gt;

&lt;p&gt;Quero te agradecer por chegar até aqui, e queria lhe pedir também para me encaminhar as suas dúvidas, comentários, críticas, correções ou sugestões sobre a publicação.&lt;/p&gt;

&lt;p&gt;Deixe seu ❤️ se gostou ou um 🦄 se esse post te ajudou de alguma maneira! Não se esqueça de ver os posts anteriores e me siga para maaaais conteúdos.&lt;/p&gt;

&lt;p&gt;Até!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>security</category>
      <category>ux</category>
    </item>
    <item>
      <title>Testes Unitários: Fundamentos e Qualidade de Software!</title>
      <dc:creator>William Queiroz</dc:creator>
      <pubDate>Fri, 11 Mar 2022 12:41:38 +0000</pubDate>
      <link>https://dev.to/wnqueiroz/testes-unitarios-fundamentos-e-qualidade-de-software-5af0</link>
      <guid>https://dev.to/wnqueiroz/testes-unitarios-fundamentos-e-qualidade-de-software-5af0</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@flowforfrank?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Ferenc Almasi&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/unit-test?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumário
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introdução&lt;/li&gt;
&lt;li&gt;Qualidade de Software&lt;/li&gt;
&lt;li&gt;Por que eu devo testar meu código?&lt;/li&gt;
&lt;li&gt;Tipos de testes&lt;/li&gt;
&lt;li&gt;
Testes Unitários

&lt;ul&gt;
&lt;li&gt;Dicas para escrever bons testes unitários&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

O que são Test Doubles

&lt;ul&gt;
&lt;li&gt;Dummies, Fakes, Spies, Stubs e Mocks&lt;/li&gt;
&lt;li&gt;Diferenças entre Mocks e Stubs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

TDD: Test Driven Development

&lt;ul&gt;
&lt;li&gt;TDD vs Escrever o teste depois&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Análise de Qualidade de Software

&lt;ul&gt;
&lt;li&gt;SonarQube&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Finalizando...&lt;/li&gt;

&lt;li&gt;Referências e Links&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;E ae dev, tudo bem com você?&lt;/p&gt;

&lt;p&gt;Hoje eu vim trazer um tema que eu gosto beeem pouco (sou apaixonado) que é sobre Testes Unitários e Qualidade de Software!&lt;/p&gt;

&lt;p&gt;O post dessa vez está mais teórico que o normal por aqui, mas fica comigo, pega um café e garanta sua leitura!&lt;/p&gt;

&lt;p&gt;Bora pro post?&lt;/p&gt;

&lt;h2&gt;
  
  
  Qualidade de Software
&lt;/h2&gt;

&lt;p&gt;Antes de falarmos sobre testes, precisamos entender o que é que define a qualidade de um software. Da perspectiva de produto e negócios, do nosso "cliente", um software de qualidade é aquele que atende os requisitos funcionais, expectativa e necessidades do usuário final. E qual é a perspectiva do desenvolvedor quanto à qualidade?&lt;/p&gt;

&lt;p&gt;Em 1977, James A. McCall propôs um modelo que define critérios de qualidade de software dividido em 3 pontos de vista distintos, sendo eles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Operação&lt;/strong&gt;: que são características relativas ao uso do produto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revisão&lt;/strong&gt;: que é a capacidade do produto ser modificado e evoluído.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transição&lt;/strong&gt;: que remete a adaptabilidade à novos ambientes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tais critérios, são elencados a partir de cada ponto de vista:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operação&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Corretitude&lt;/strong&gt;: medida na qual o software satisfaz as especificações e objetivos visados pelo cliente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confiabilidade&lt;/strong&gt;: medida que se pode esperar que um programa execute sua função com a precisão exigida.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eficiência&lt;/strong&gt;: é a quantidade de recursos computacionais exigidos para que um programa execute sua função, visando realizar a operação de forma 100% segura e performática.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integridade&lt;/strong&gt;: medida na qual, controla-se o acesso ao software e aos dados, bloqueando assim o acesso de pessoas não autorizadas, para que não ocorra perda de dados ou de código.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usabilidade&lt;/strong&gt;: mede a facilidade para a utilização do software.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Revisão:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manutenção&lt;/strong&gt;: mede o esforço exigido para localizar e reparar erros em um programa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibilidade&lt;/strong&gt;: analisa o esforço utilizado para realizar uma alteração no software, isto é, qual o grau de facilidade que o software oferece para a sua alteração.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testabilidade&lt;/strong&gt;: analisa se é possível testar o funcionamento do software, não só por vias automatizadas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Transição:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Portabilidade&lt;/strong&gt;: mede a facilidade com que um produto pode ser movido para outra plataforma ou ambiente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusabilidade&lt;/strong&gt;: medida na qual o software, ou parte dele, poder ser reusado em outros softwares, em outras palavras, o código do software deve ser reaproveitável.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperabilidade&lt;/strong&gt;: capacidade do software ser acoplado à outro.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dito isso, qualidade de software da perspectiva do desenvolvedor é uma área que visa garantir a qualidade do software por meio de normatizações e definições de processos de desenvolvimento. Testar é apenas &lt;strong&gt;uma das maneiras&lt;/strong&gt; que temos para garantir a qualidade do nosso software. Ainda assim, vamos responder a seguinte pergunta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que eu devo testar meu código?
&lt;/h2&gt;

&lt;p&gt;Você em algum momento da sua carreira deve ter se perguntado: "&lt;em&gt;será que se eu alterar isso aqui, isso ainda vai continuar funcionando?&lt;/em&gt; 🤔”. Já sentiu aquela insegurança na hora de fazer aquela &lt;em&gt;feature&lt;/em&gt; ou &lt;em&gt;refactor&lt;/em&gt;? Seu código/projeto não trazia nenhuma &lt;strong&gt;confiança&lt;/strong&gt; quando estava tomando proporções maiores?&lt;/p&gt;

&lt;p&gt;Pois é… e como saber se aquilo que você implementou funciona &lt;strong&gt;em conjunto&lt;/strong&gt; com aquilo já foi implementado? A melhor maneira de saber se algo funciona é: &lt;strong&gt;testando&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ao testar o seu projeto, você garante mais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confiabilidade;&lt;/li&gt;
&lt;li&gt;Integridade, evolução e melhorias no código;&lt;/li&gt;
&lt;li&gt;Velocidade nas entregas e demandas (uma vez que um código existente já possui testes, a preocupação nas mudanças e implementações futuras é menor, podendo-se ter mais agilidade e previsão ao decorrer do desenvolvimento); Isso vem em contrapartida de que se eu implementar testes durante a entrega eu vou levar mais tempo. Isso é gradual, à medida em que o software é contemplado com mais testes, mais demandas com qualidade são entregues.&lt;/li&gt;
&lt;li&gt;Qualidade no software (fácil manutenção, flexível a alterações, testabilidade e etc, tudo que falamos na introdução);&lt;/li&gt;
&lt;li&gt;Redução no tempo ao encontrar bugs;&lt;/li&gt;
&lt;li&gt;Implementações mais objetivas e códigos mais limpos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora que você já sabe os motivos pelos quais você deve implementar testes, vamos conhecer alguns dos &lt;strong&gt;tipos de testes&lt;/strong&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Tipos de testes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frholti3x70gzpso27o7o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frholti3x70gzpso27o7o.png" alt="Pirâmide de Testes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fonte: &lt;a href="https://martinfowler.com/articles/practical-test-pyramid.html" rel="noopener noreferrer"&gt;https://martinfowler.com/articles/practical-test-pyramid.html&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A maioria das pessoas conhecem essa pirâmide graças à Mike Cohn que a descreveu no seu livro de 2009, &lt;a href="https://www.amazon.com.br/Succeeding-Agile-Software-Development-Using/dp/0321579364/ref=sr_1_1?__mk_pt_BR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;amp;keywords=Succeeding+with+Agile&amp;amp;qid=1646232183&amp;amp;sr=8-1&amp;amp;ufe=app_do%3Aamzn1.fos.25548f35-0de7-44b3-b28e-0f56f3f96147" rel="noopener noreferrer"&gt;Succeeding with Agile&lt;/a&gt;. No livro ele faz referência à &lt;em&gt;"Test Automation Pyramid"&lt;/em&gt; (pirâmide de automação de testes) que popularmente ficou conhecida apenas como &lt;em&gt;"Test Pyramid"&lt;/em&gt; (pirâmide de testes).&lt;/p&gt;

&lt;p&gt;Ela é constituída por 3 camadas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Testes Unitários&lt;/li&gt;
&lt;li&gt;Testes de Serviço&lt;/li&gt;
&lt;li&gt;Testes de Interface do Usuário&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pode-se observar que, à medida em que chegamos ao topo da pirâmide, menor é quantidade de testes que teremos e mais "caros" eles serão (pensando em processamento). Quanto menor é o isolamento, mais rápido será a execução dos nossos testes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Recebi uma excelente recomendação do &lt;a href="https://github.com/pauloGoncalvesBH/" rel="noopener noreferrer"&gt;Paulo Gonçalves&lt;/a&gt;, membro do &lt;a href="https://agiletesters.com.br/" rel="noopener noreferrer"&gt;Agile Testers&lt;/a&gt; de alternativas e materiais complementares à pirâmide de testes. Um deles é o artigo &lt;em&gt;"Abordagem de testes"&lt;/em&gt; e a talk &lt;em&gt;"AT Talks: Triângulos de Teste, Não Mais"&lt;/em&gt; da &lt;a href="https://samantacicilia.medium.com/" rel="noopener noreferrer"&gt;Samanta Cicilia&lt;/a&gt;. Os links você encontra na seção Referências e Links.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Testes Unitários
&lt;/h2&gt;

&lt;p&gt;Estando na base da pirâmide, os testes unitários além de ser a fundamentação, eles são responsáveis por testar a menor unidade do nosso software de maneira isolada. "Tá, mas qual é a menor unidade do software?”: podem ser métodos/funções, classes, módulos, etc. Esses testes validam o comportamento esperado de um método/função: dada uma determinada execução &lt;strong&gt;espera-se&lt;/strong&gt; uma saída.&lt;/p&gt;

&lt;p&gt;Como testamos as funções do software, podemos ter diversos comportamentos a cada execução com determinadas condições e, consequentemente, vários testes. O teste unitário nos possibilita criar um código mais objetivo, com métodos limpos e com uma única e determinada funcionalidade (daí, associa-se também o conceito de "unidade”), sendo possível ser testado de maneira isolada.&lt;/p&gt;

&lt;p&gt;Vamos ver um exemplo de teste unitário com JavaScript! Imagine que temos uma calculadora, e que centralizamos as funções das operações em um arquivo. Precisamos testar o comportamento esperado de cada uma dessas funções. No exemplo, espera-se que a função &lt;code&gt;sum&lt;/code&gt; retorne a soma de &lt;code&gt;a&lt;/code&gt; e &lt;code&gt;b&lt;/code&gt;. Como seria o nosso teste?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// calculator.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// calculator.spec.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./calculator.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calculator.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return the sum of a and b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Na descrição do nosso teste, montamos o cenário de teste de acordo com a especificidade da função.&lt;/p&gt;

&lt;p&gt;Você precisa ter a seguinte reflexão quando for escrever os seus testes unitários: "essa função/método deve fazer &lt;strong&gt;isso&lt;/strong&gt; quando &lt;strong&gt;aquilo&lt;/strong&gt;”. Ou seja, para um determinado &lt;strong&gt;comportamento&lt;/strong&gt;, é necessária uma &lt;strong&gt;condição&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dicas para escrever bons testes unitários
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Escolha as melhores asserções para cada momento.&lt;/li&gt;
&lt;li&gt;Evite ruídos e dependências entre os testes, garanta o &lt;strong&gt;isolamento&lt;/strong&gt;. Se o seu teste depender de quaisquer fatores externos ele &lt;strong&gt;não é mais um teste unitário&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Utilize do teste unitário para definir o &lt;strong&gt;design do seu código&lt;/strong&gt;. Durante a escrita dos testes, é comum identificarmos a necessidade de refatorar o código para melhorar o seu uso (e também isolá-lo). Aproveite desses momentos.&lt;/li&gt;
&lt;li&gt;Por último, mas não menos importante: evite "estressar" camadas que excedam a barreira de unidade: banco de dados, 3rd party APIs... Os testes unitários sempre superarão os testes das camadas superiores da pirâmide. Garanta que a execução dos testes unitários seja rápida, use &lt;em&gt;Test Doubles&lt;/em&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por falar nisso, você sabe o que são &lt;em&gt;Test Doubles?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O que são Test Doubles
&lt;/h2&gt;

&lt;p&gt;Segundo Martin Fowler, "&lt;em&gt;Test Doubles”&lt;/em&gt; é um termo genérico para qualquer caso que você queira substituir um objeto de produção para fins de teste. Pense em "dublê", aqueles de cinema mesmo, que "simulam” a aparência e o comportamento dos atores em um filme. Você provavelmente deve conhecer o conceito de maneira generalizada como "mockar" ou pela palavra "Mock". O fato é que Mock é apenas um dos tipos de "dublês" que temos disponíveis.&lt;/p&gt;

&lt;p&gt;Além dele temos Dummies, Fakes, Spies e Stubs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dummies, Fakes, Spies, Stubs e Mocks
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Dummies&lt;/strong&gt;: são objetos ou dados fictícios que substituem dados reais mas que não utilizados nos testes geralmente. São usados para satisfazer parâmetros. Com o uso deles é possível diminuir a complexidade dos testes, focando no que importa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fakes&lt;/strong&gt;: são objetos reais que implementam um comportamento que os torna inviável para serem utilizados em produção (um &lt;a href="https://aws.amazon.com/pt/nosql/in-memory/" rel="noopener noreferrer"&gt;In-Memory Database&lt;/a&gt;, por exemplo).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spies&lt;/strong&gt;: são "espiões” para registrar as informações de uma determinada função. Pode ser usado para dizer se um específico método importante no escopo da função que está sendo testada foi chamado, quantas vezes, com quais argumentos e etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stubs&lt;/strong&gt;: são semelhantes aos spies porém, ele consegue substituir toda a implementação de um específico método, mudando o seu comportamento. São úteis para simular uma possível exceção, evitar estresse na camada de serviço: persistência de dados (evitando de gravar um registro no banco de dados, por exemplo); chamada à uma API ou integração a outros serviços possibilitando a diminuição no tempo de execução do teste.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mocks&lt;/strong&gt;: São similares ao stub porém, é a camada mais alta para tornar um comportamento falso, geralmente, são usados para emular um banco de dados, um &lt;em&gt;output&lt;/em&gt; de dados ou até mesmo uma dependência, a diferença é que, com um stub, é possível testar diversas ramificações do seu código, já com o mock, é possível testar diversos comportamentos de uma só vez. Os Mocks tem expectativas sobre o jeito que ele deve ser chamado e, caso não seja chamado da forma correta, o teste deve falhar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diferenças entre Mocks e Stubs
&lt;/h3&gt;

&lt;p&gt;Para entender a diferença entre mocks e stubs vamos imaginar que toda vez que um usuário criar uma conta no nosso software, um e-mail é disparado com uma mensagem de boas-vindas e dados referente à sua conta. No nosso cenário de testes não queremos enviar esse e-mail. Podemos usar mocks ou stubs, mas afinal... qual é a diferença?&lt;/p&gt;

&lt;p&gt;Observemos a implementação abaixo retirada do artigo "&lt;em&gt;Mocks Aren't Stubs”&lt;/em&gt; do Martin Fowler (sim, em Java mesmo hahaha). Criamos um stub que implementa o método &lt;code&gt;send&lt;/code&gt; apenas com um contador (adicionando a mensagem para ser enviada na lista &lt;code&gt;messages&lt;/code&gt;), ou seja, deixaremos de enviar o e-mail propriamente:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;MailService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MailServiceStub&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MailService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;numberSent&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Com nosso stub, podemos usar a verificação de estado no teste:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderStateTester&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

 &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testOrderSendsMailIfUnfilled&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TALISKER&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;MailServiceStub&lt;/span&gt; &lt;span class="n"&gt;mailer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MailServiceStub&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setMailer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mailer&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;warehouse&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;numberSent&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A verificação de estado ocorre através da asserção e utilização do método &lt;code&gt;numberSent&lt;/code&gt; do nosso stub.&lt;/p&gt;

&lt;p&gt;Usando mocks, nosso teste ficará um pouco diferente:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderInteractionTester&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testOrderSendsMailIfUnfilled&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TALISKER&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Mock&lt;/span&gt; &lt;span class="n"&gt;warehouse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Warehouse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Mock&lt;/span&gt; &lt;span class="n"&gt;mailer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MailService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setMailer&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;MailService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;mailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="n"&gt;mailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;expects&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;once&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"send"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;warehouse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;expects&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;once&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hasInventory"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withAnyArguments&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;will&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;returnValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;Warehouse&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;warehouse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Lembra que falamos que os mocks tem expectativas sobre o jeito que ele deve ser chamado? Aqui criamos as expectativas (espera-se que o método &lt;code&gt;mailer.send&lt;/code&gt; deve ser chamado ao menos 1 vez e o método &lt;code&gt;warehouse.hasInventory&lt;/code&gt; seja chamado ao menos uma vez, com qualquer argumento e retornará &lt;code&gt;false&lt;/code&gt; quando chamado. Se por ventura alguma dessas expectativas não forem atendidas, nosso teste falhará.&lt;/p&gt;

&lt;p&gt;Em ambos os casos usamos &lt;em&gt;Test Doubles&lt;/em&gt; ao invés do nosso serviço de e-mail (evitando o estresse externo). A principal diferença é que com stub utilizamos a &lt;strong&gt;verificação por estado&lt;/strong&gt; e com o mock usamos a &lt;strong&gt;verificação do comportamento&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TDD: Test Driven Development
&lt;/h2&gt;

&lt;p&gt;Agora que tivemos uma introdução ao universo dos testes unitários, vamos conhecer um método muito comum atualmente para a construção de testes unitários: o TDD!&lt;/p&gt;

&lt;p&gt;TDD é uma sigla para "&lt;em&gt;Test Driven Development",&lt;/em&gt; em português "Desenvolvimento Orientado à Testes. A técnica foi criada/descoberta em 2003 pelo engenheiro de software americano &lt;a href="https://en.wikipedia.org/wiki/Kent_Beck" rel="noopener noreferrer"&gt;Kent Beck&lt;/a&gt; (um dos pais do &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Extreme_programming" rel="noopener noreferrer"&gt;eXtreme Programming&lt;/a&gt;&lt;/em&gt; ou simplesmente, XP) e declara que o TDD é um método que encoraja designs de código simples e inspira confiança.&lt;/p&gt;

&lt;p&gt;O método se baseia em ciclos ou etapas de desenvolvimento que visam que uma implementação permita que um teste tenha um resultado positivo. Confuso não?&lt;/p&gt;

&lt;p&gt;Calma que eu explico!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekwjd4rss2bjnw1cav1b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekwjd4rss2bjnw1cav1b.png" alt="Ciclos do TDD"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fonte: &lt;a href="https://www.rcelebrone.com/2021/03/podcast-teste-unitario-automatizado-tdd.html" rel="noopener noreferrer"&gt;https://www.rcelebrone.com/2021/03/podcast-teste-unitario-automatizado-tdd.html&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Como mencionei, a ideia do TDD é que você trabalhe em ciclos. Iniciando a partir da escrita de um teste para a sua solução. O TDD é composto em 3 ciclos, aplicados na seguinte ordem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Red&lt;/strong&gt;: escreva um teste que irá falhar. Isso mesmo! Pense em como você teria um teste caso o seu código estivesse implementado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Green&lt;/strong&gt;: a partir disso, implemente o código que satisfaça as condições do seu teste. O intuito nessa fase é que o código implementado, faça com que o teste criado no ciclo anterior passe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactor&lt;/strong&gt;: na fase anterior, você precisava apenas fazer com que o teste passasse, nesse ciclo você deve focar em melhorar os pontos que não eram uma preocupação: legibilidade, reuso, duplicidade. Deixando-o funcional, e mais limpo. Consequentemente (e é comum), o seu teste criado no primeiro ciclo, pode vir a falhar com a refatoração. No próximo ciclo, você deve fazer com que o teste passe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O ciclos são iterativos até que os testes e a implementação satisfaça as especificidades solução.&lt;/p&gt;

&lt;h3&gt;
  
  
  TDD vs Escrever o teste depois
&lt;/h3&gt;

&lt;p&gt;Ressaltando que o TDD é uma metodologia para desenvolvimento e escrita de código, você deve estar se perguntando: "Po, mas o que eu ganho escrevendo o teste antes? Será que vale a pena?”&lt;/p&gt;

&lt;p&gt;O que irá manter a qualidade do nosso software será a quantidade de testes produzidos durante a prática do TDD, como qualquer outra metodologia, você só conseguirá ver os reais ganhos colocando-a em prática, é no dia-a-dia que isso acaba ficando mais claro.&lt;/p&gt;

&lt;p&gt;Uma das principais vantagens do uso de TDD é que o desenvolvedor acabar tendo mais feedback dos testes, e a quantidades de feedbacks também é maior!&lt;/p&gt;

&lt;p&gt;Pense comigo: é melhor implementar testes em um sistema "legado" (onde a quantidade de código é muito maior para ser testado) ou aplicar TDD no inicio do projeto onde a base de código ainda é pequena? Quanto maior é a quantidade de código escrito, maior será o &lt;strong&gt;custo da mudança&lt;/strong&gt;. Ao aplicar o TDD, o desenvolvedor recebe o feedback em um momento onde as mudanças ainda são baratas!&lt;/p&gt;

&lt;h2&gt;
  
  
  Análise de Qualidade de Software
&lt;/h2&gt;

&lt;p&gt;Falamos muito sobre testes e qualidade de software, mas mais do que garantir, como podemos mensurar e analisar como anda a qualidade do nosso código-fonte?&lt;/p&gt;

&lt;p&gt;Existem ferramentas poderosíssimas que podem nos auxiliar à deixar um código mais limpo e mais seguro para ir para produção. É comum as empresas adotarem táticas para evitar que um projeto com pouca qualidade (isso envolve segurança e todos os outros quesitos mencionados na introdução desse artigo) seja implantado no ambiente produtivo. Afinal é muito melhor prevenir do que remediar.&lt;/p&gt;

&lt;p&gt;Uma excelente ferramenta utilizada amplamente no mercado é o SonarQube!&lt;/p&gt;

&lt;h3&gt;
  
  
  SonarQube
&lt;/h3&gt;

&lt;p&gt;O SonarQube é uma ferramenta de revisão automática de código para detectar bugs, vulnerabilidades, falta de cobertura de teste e &lt;a href="https://refactoring.guru/pt-br/refactoring/smells" rel="noopener noreferrer"&gt;&lt;em&gt;code smells&lt;/em&gt;&lt;/a&gt; em seu código. Ele pode ser integrado em esteiras de &lt;a href="https://www.redhat.com/pt-br/topics/devops/what-is-ci-cd" rel="noopener noreferrer"&gt;CI/CD&lt;/a&gt; para permitir a inspeção contínua de código em todas as &lt;a href="https://git-scm.com/book/pt-br/v2/Branches-no-Git-Branches-em-poucas-palavras" rel="noopener noreferrer"&gt;&lt;em&gt;branchs&lt;/em&gt;&lt;/a&gt; do projeto e &lt;em&gt;&lt;a href="https://docs.github.com/pt/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests" rel="noopener noreferrer"&gt;pull requests&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O fluxo de análise do projeto é baseado no seguinte:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O desenvolvedor abre um Pull Request com o código novo criado e testado.&lt;/li&gt;
&lt;li&gt;Num workflow de CI/CD, a &lt;a href="https://www.redhat.com/pt-br/topics/devops/what-cicd-pipeline" rel="noopener noreferrer"&gt;pipeline&lt;/a&gt; de CI é acionada a partir do PR criado.&lt;/li&gt;
&lt;li&gt;A pipeline de CI executa os comandos do projeto para realizar a execução dos testes e extrair a cobertura do código.&lt;/li&gt;
&lt;li&gt;A pipeline de CI envia os metadados coletados para o SonarQube a partir de uma integração.&lt;/li&gt;
&lt;li&gt;O SonarQube recebe os metadados e disponibiliza uma dashboard com um overview completo sobre o seu projeto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhdedvbz0l5gz1uhcz42b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhdedvbz0l5gz1uhcz42b.png" alt="SonarQube Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Existem diversas outras ferramentas e serviços (como &lt;a href="https://coveralls.io/" rel="noopener noreferrer"&gt;Coveralls&lt;/a&gt; e &lt;a href="https://about.codecov.io/" rel="noopener noreferrer"&gt;Codecov&lt;/a&gt;), cabe você avaliar o que faz mais sentido utilizar no momento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalizando...
&lt;/h2&gt;

&lt;p&gt;Bem, é isso, por hoje, é só!&lt;/p&gt;

&lt;p&gt;Quero te agradecer por chegar até aqui, e queria lhe pedir também para me encaminhar as suas dúvidas, comentários, críticas, correções ou sugestões sobre a publicação.&lt;/p&gt;

&lt;p&gt;Deixe seu ❤️ se gostou ou um 🦄 se esse post te ajudou de alguma maneira! Não se esqueça de ver os posts anteriores e me siga para maaaais conteúdos.&lt;/p&gt;

&lt;p&gt;Até!&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências e Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/articles/mocksArentStubs.html" rel="noopener noreferrer"&gt;Mocks Aren't Stubs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.devmedia.com.br/test-driven-development-tdd-simples-e-pratico/18533" rel="noopener noreferrer"&gt;Test Driven Development: TDD Simples e Prático&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.treinaweb.com.br/blog/afinal-o-que-e-tdd" rel="noopener noreferrer"&gt;Afinal, o que é TDD?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Kent_Beck" rel="noopener noreferrer"&gt;Kent Beck - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Extreme_programming" rel="noopener noreferrer"&gt;Extreme programming - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.sonarqube.org/latest/" rel="noopener noreferrer"&gt;SonarQube Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://refactoring.guru/pt-br/refactoring/smells" rel="noopener noreferrer"&gt;Code Smells&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.redhat.com/pt-br/topics/devops/what-is-ci-cd" rel="noopener noreferrer"&gt;O que é CI/CD?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/assertqualityassurance/abordagem-de-testes-212b6238f0c3" rel="noopener noreferrer"&gt;Abordagem de testes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=QSZYrVLcfto" rel="noopener noreferrer"&gt;AT Talks: Triângulos de Teste, Não Mais&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>braziliandevs</category>
      <category>qualityassurance</category>
    </item>
    <item>
      <title>Drops #04: Desmistificando ponteiros no Golang!</title>
      <dc:creator>William Queiroz</dc:creator>
      <pubDate>Sun, 04 Jul 2021 21:13:14 +0000</pubDate>
      <link>https://dev.to/wnqueiroz/drops-04-desmistificando-ponteiros-no-golang-3kj9</link>
      <guid>https://dev.to/wnqueiroz/drops-04-desmistificando-ponteiros-no-golang-3kj9</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;E ae dev, tudo bem com você?&lt;/p&gt;

&lt;p&gt;Agora que FINALMENTE finalizei o MBA, aproveitei o tempo livre para dedicá-lo aos estudos do &lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;Golang&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Confesso que eu estou apaixonado pela linguagem - ainda dando os primeiros passos claro - mas creio que já dá pra compartilhar uma parada muito massa da linguagem (e como ela implementa) que são os ponteiros!&lt;/p&gt;

&lt;p&gt;Bora pro post?&lt;/p&gt;

&lt;p&gt;Ah! mas antes disso... Esse post faz parte de uma série de artigos "drops" que tenho aqui! Veja a lista:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-01-corrigindo-vulnerabilidades-em-dependencias-com-yarn-ou-quase-2e2p"&gt;Drops #01: Corrigindo vulnerabilidades em dependências com Yarn! (ou quase)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-02-como-alterar-o-autor-do-commit-depois-do-push-2mgg"&gt;Drops #02: Como alterar o autor do commit depois do push&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-03-usando-aliases-para-importacao-de-modulos-em-typescript-1fe9"&gt;Drops #03: Usando aliases para importação de módulos em TypeScript!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-04-desmistificando-ponteiros-no-golang-3kj9"&gt;Drops #04: Desmistificando ponteiros no Golang!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Afinal, o que é um ponteiro?
&lt;/h2&gt;

&lt;p&gt;Um ponteiro (ou apontador) nada mais é do que uma variável que, ao invés de armazenar um valor (true, "hello world"), ela armazena um endereço que está alocado na memória.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memória
&lt;/h2&gt;

&lt;p&gt;Vamos entender a imagem a seguir:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flett8q04nv0fmxt2nljq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flett8q04nv0fmxt2nljq.png" alt="Representação da Memória"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basicamente, bem a grosso modo, a memória é constituída por elementos que armazenam informações.&lt;/p&gt;

&lt;p&gt;O endereço é uma posição onde os dados serão colocados (geralmente expressos em números hexadecimais). Eles podem conter apenas uma única informação.&lt;/p&gt;

&lt;p&gt;O dado, por sua vez, é a informação presente em cada posição na memória.&lt;/p&gt;

&lt;p&gt;Quando criamos uma variável, ela recebe um endereçamento na memória e através dessa variável podemos armazenar valores que serão alocados nesse endereço:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqmkyw516ell7v88kop3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqmkyw516ell7v88kop3.png" alt="Criação de variável x memória"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aqui podemos ler o seguinte: &lt;/p&gt;

&lt;p&gt;A variável &lt;code&gt;a&lt;/code&gt; que possui o endereço de memória &lt;code&gt;0xc000192020&lt;/code&gt; está armazenando o dado &lt;code&gt;10&lt;/code&gt; na posição deste endereço.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ponteiros no Go
&lt;/h2&gt;

&lt;p&gt;É muito simples definir um ponteiro, basta adicionar o &lt;code&gt;*&lt;/code&gt; junto ao tipo do ponteiro que estamos criando:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// output: &amp;lt;nil&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 O tipo do ponteiro indica qual é o tipo de dado que esse ponteiro irá manipular. No caso acima, criamos um ponteiro que pode "apontar" para endereços na memória de variáveis que armazenam dados do tipo inteiro.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No Go temos o conceito de &lt;em&gt;zero value&lt;/em&gt; que, ao definir uma variável sem atribuir um valor para ela, o Go irá atribuir um valor padrão para essa variável. Cada tipo possui o seu valor padrão (&lt;code&gt;0&lt;/code&gt; para &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt; para &lt;code&gt;bool&lt;/code&gt;...), no caso do nosso ponteiro, o &lt;em&gt;zero value&lt;/em&gt; será &lt;code&gt;nil&lt;/code&gt; dado que não atribuímos nenhum valor para ele. Ou melhor dizendo: nenhum endereço!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;E como podemos definir um endereço para o ponteiro?&lt;/em&gt; 🤔&lt;/p&gt;

&lt;p&gt;Primeiro, criaremos outra variável no nosso código, e então, vamos atribuir o endereço dela para o ponteiro dessa forma:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;

    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;

    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="c"&gt;// atribuindo o endereço de i para o ponteiro&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// output: algo como 0xc000192020&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 O &lt;code&gt;&amp;amp;&lt;/code&gt; usado antes da variável, indica que queremos obter o endereço na memória daquela variável.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A representação gráfica do que fizemos aqui está na imagem a seguir:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9faqss4csmdj27fl2n0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9faqss4csmdj27fl2n0q.png" alt="Atribuição de endereço"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Note que o ponteiro que criamos, também possui o seu próprio endereço na memória!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Beleza, entendi! Até aqui o ponteiro já tá "apontando" pra um endereço... mas como eu faço pra saber o que esse endereço aí tá armazenando?&lt;/em&gt; 🤔&lt;/p&gt;

&lt;p&gt;Basta utilizar o operador &lt;code&gt;*&lt;/code&gt; junto ao ponteiro (&lt;code&gt;*p&lt;/code&gt;). Esse é o processo de &lt;a href="https://en.wikipedia.org/wiki/Dereference_operator" rel="noopener noreferrer"&gt;desreferenciar&lt;/a&gt; o ponteiro para que, ao invés dele retornar o endereço armazenado, ele ir lá naquele endereço e a partir de lá retornar o valor:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;

    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;

    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// output: 0xc000192020&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// output: 10&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Uma vez que desreferenciamos o ponteiro, podemos manipular o dado que está armazenado naquele endereço:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;

    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;

    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// output: 0xc000192020&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// output: 10&lt;/span&gt;

    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// output: 20&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// output: 20&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A representação gráfica do que fizemos aqui está na imagem a seguir:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7ndqq0217ebgz0lc5jb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7ndqq0217ebgz0lc5jb.png" alt="Manipulando dado pelo ponteiro"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usar ponteiros?
&lt;/h2&gt;

&lt;p&gt;No Go, por padrão, tudo é &lt;em&gt;Pass By Value&lt;/em&gt;. Isso significa que, quando passamos uma variável como parâmetro de uma função, essa variável é "duplicada" na memória e o que fazemos dentro do escopo da função acontece &lt;strong&gt;apenas no escopo da função&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// output: 11&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;

    &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// output: 10&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Como é realizada uma "cópia" da variável na memória, isso tem um custo, que pode se tornar problemático quando lidamos com um grande volume de dados nessa variável. Para economizarmos essa operação, é possível trabalhar com &lt;em&gt;Pass By Reference&lt;/em&gt; com a ajuda de ponteiros: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// output: 11&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// output: 0xc0000180b0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;

    &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// output: 11&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// output: 0xc0000180b0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Perceba que a função &lt;code&gt;increment&lt;/code&gt; não retorna mais o valor manipulado e que além disso, passou a exigir um ponteiro/endereço de memória como parâmetro (&lt;code&gt;a *int&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Dessa maneira, o parâmetro da função &lt;code&gt;increment&lt;/code&gt; não foi duplicado na memória e passamos a trabalhar com a referência da variável &lt;code&gt;x&lt;/code&gt; (que está fora do escopo da função &lt;code&gt;increment&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;A grosso modo, podemos trabalhar com ponteiros uma vez que lidamos com um volume grande de dados ou simplesmente querer trabalhar com &lt;em&gt;Pass By Reference&lt;/em&gt; ao invés de &lt;em&gt;Pass By Value&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;É importante entender que existem pontos positivos e negativos ao trabalhar com ponteiros. Nós podemos e devemos usá-los mas precisamos ter certeza do que estamos fazendo.&lt;/p&gt;

&lt;p&gt;Ou seja: depende! HAHA Cabe a você avaliar os melhores cenários.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalizando...
&lt;/h2&gt;

&lt;p&gt;Bem, é isso, por hoje, é só!&lt;/p&gt;

&lt;p&gt;Quero te agradecer por chegar até aqui, e queria lhe pedir também para me encaminhar as suas dúvidas, comentários, críticas, correções ou sugestões sobre a publicação.&lt;/p&gt;

&lt;p&gt;Deixe seu ❤️ se gostou ou um 🦄 se esse post te ajudou de alguma maneira! Não se esqueça de ver os posts anteriores e me siga para maaaais conteúdos.&lt;/p&gt;

&lt;p&gt;Até!&lt;/p&gt;

</description>
      <category>go</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Configurando e publicando aplicações NodeJS no Nexus Repository Manager 3</title>
      <dc:creator>William Queiroz</dc:creator>
      <pubDate>Mon, 01 Feb 2021 20:59:31 +0000</pubDate>
      <link>https://dev.to/wnqueiroz/configurando-e-publicando-aplicacoes-nodejs-no-nexus-repository-manager-3-2m0l</link>
      <guid>https://dev.to/wnqueiroz/configurando-e-publicando-aplicacoes-nodejs-no-nexus-repository-manager-3-2m0l</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;E ae dev, tudo bem com você?&lt;/p&gt;

&lt;p&gt;Fazia um tempo que não publicava nada por aqui, eis então que surgiu uma oportunidade de falar sobre o &lt;a href="https://help.sonatype.com/repomanager3" rel="noopener noreferrer"&gt;Nexus Repository Manager 3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;O Nexus é um gerenciador de repositórios e artefatos! Ele possibilita termos nosso próprio &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt; e &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;NPM&lt;/a&gt; privados!&lt;/p&gt;

&lt;p&gt;Hoje vou mostrar como configurá-lo para publicar suas aplicações NodeJS, e compartilhá-las entre projetos.&lt;/p&gt;

&lt;p&gt;Ao final deste artigo, você irá:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configurar um contêiner Nexus para publicação de projetos NodeJS.&lt;/li&gt;
&lt;li&gt;Configurar aplicações para publicação no Nexus.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bora pro post?&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumário
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Criando um contêiner Docker com o Nexus

&lt;ul&gt;
&lt;li&gt;Obtendo a senha do usuário padrão&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Configurando o Nexus

&lt;ul&gt;
&lt;li&gt;Criando um usuário para publicação de pacotes&lt;/li&gt;
&lt;li&gt;Configurando um armazenamento Blob&lt;/li&gt;
&lt;li&gt;Criando um repositório privado (hosted)&lt;/li&gt;
&lt;li&gt;Criando proxy para NPM público e agrupamento de repositórios&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Configurando aplicação para publicação no Nexus

&lt;ul&gt;
&lt;li&gt;Habilitando Realm NPM de autenticação no Nexus&lt;/li&gt;
&lt;li&gt;Realizando a publicação da aplicação no Nexus&lt;/li&gt;
&lt;li&gt;Salvando configurações de login no projeto (basic)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Instalando dependências a partir do Nexus&lt;/li&gt;

&lt;li&gt;Finalizando...&lt;/li&gt;

&lt;li&gt;

FAQ

&lt;ul&gt;
&lt;li&gt;Devo versionar o arquivo .npmrc contendo as credenciais do Nexus no projeto?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Criando um contêiner Docker com o Nexus
&lt;/h2&gt;

&lt;p&gt;Bom, inicialmente, precisaremos configurar o Nexus localmente para realizarmos as configurações para habilitar o nosso "NPM privado". Felizmente, a &lt;a href="https://www.sonatype.com/company/" rel="noopener noreferrer"&gt;Sonatype&lt;/a&gt; disponibiliza uma imagem Docker pronta para executarmos!&lt;/p&gt;

&lt;p&gt;Vamos começar subindo um contêiner docker com o seguinte comando:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8081:8081 &lt;span class="nt"&gt;--name&lt;/span&gt; nexus sonatype/nexus3:3.29.2


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Em seguida vamos visualizar os logs desse contêiner:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;docker logs nexus &lt;span class="nt"&gt;-f&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Como o processo de inicialização desse contêiner é demorado, aguarde até visualizar a seguinte saída nos logs:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nt"&gt;-------------------------------------------------&lt;/span&gt;

Started Sonatype Nexus OSS 3.29.2-02

&lt;span class="nt"&gt;-------------------------------------------------&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Veja mais em: &lt;a href="https://help.sonatype.com/repomanager3/installation/installation-methods#InstallationMethods-InstallingwithDocker" rel="noopener noreferrer"&gt;https://help.sonatype.com/repomanager3/installation/installation-methods#InstallationMethods-InstallingwithDocker&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Após isso, acesse a URL &lt;a href="http://localhost:8081/" rel="noopener noreferrer"&gt;http://localhost:8081/&lt;/a&gt;, você visualizará a tela inicial do Nexus:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fabup4104f579yu9757hx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fabup4104f579yu9757hx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Obtendo a senha do usuário padrão
&lt;/h3&gt;

&lt;p&gt;No canto inferior direito, clique em &lt;strong&gt;Sign in&lt;/strong&gt;. Você visualizará essa tela:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpi3v87ceq9mkfjw6afci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpi3v87ceq9mkfjw6afci.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perceba que aqui, temos que obter a senha do usuário padrão (admin), em &lt;code&gt;/nexus-data/admin.password&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos acessar o contêiner e obter a senha com os comandos:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; nexus /bin/bash

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /nexus-data/admin.password&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="c"&gt;# d9f3e86b-1a5d-45f8-a851-afcba3d05fdb&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Copie a saída do segundo comando e realize o login.&lt;/p&gt;

&lt;p&gt;Avance na janela de configuração exibida, e defina uma nova senha. Em seguida, marque a opção &lt;em&gt;&lt;strong&gt;Disable anonymous access&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Isso fará com que apenas usuários logados possam navegar no nosso Nexus.&lt;/p&gt;

&lt;p&gt;Saia do contêiner digitando &lt;code&gt;exit&lt;/code&gt; no terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurando o Nexus
&lt;/h2&gt;

&lt;p&gt;Antes de sermos capazes de armazenar nossos projetos no Nexus, é necessário realizar algumas configurações.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando um usuário para publicação de pacotes
&lt;/h3&gt;

&lt;p&gt;Vamos no painel, na barra superior e clique no símbolo de engrenagem e navegue em &lt;code&gt;Security / Users&lt;/code&gt;. Clique em &lt;strong&gt;Create local user&lt;/strong&gt; e crie o usuário com as seguintes informações:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Campo&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Valor&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ID&lt;/td&gt;
&lt;td&gt;npmuser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First name&lt;/td&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Last name&lt;/td&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:npmuser@company.com"&gt;npmuser@company.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Password&lt;/td&gt;
&lt;td&gt;npmuser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Confirm Password&lt;/td&gt;
&lt;td&gt;npmuser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Status&lt;/td&gt;
&lt;td&gt;Active&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Granted&lt;/td&gt;
&lt;td&gt;nx-admin&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Configurando um armazenamento Blob
&lt;/h3&gt;

&lt;p&gt;Aqui criaremos uma partição lógica que queremos impor para nossos diferentes tipos de projeto, ou seja, queremos segregar nossos binários NPM e binários Maven, por exemplo, para evitar quaisquer conflitos (de nome ou outros).&lt;br&gt;
Internamente, o Nexus apenas cria pastas diferentes para cada armazenamento de &lt;em&gt;Blob&lt;/em&gt; que criamos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Veja mais em: &lt;a href="https://help.sonatype.com/repomanager3/high-availability/configuring-blob-stores#ConfiguringBlobStores-WhatisaBlobStore" rel="noopener noreferrer"&gt;https://help.sonatype.com/repomanager3/high-availability/configuring-blob-stores#ConfiguringBlobStores-WhatisaBlobStore&lt;/a&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Navegue em &lt;code&gt;Repository / Blob Stores&lt;/code&gt;, clique em &lt;strong&gt;Create blob store&lt;/strong&gt; e crie o &lt;em&gt;blob store&lt;/em&gt; com as seguintes as informações:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Campo&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Valor&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Path&lt;/td&gt;
&lt;td&gt;/nexus-data/blobs/NPM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Qualquer pacote que enviarmos agora (para esse Blob) será persistido no volume sob a pasta associada à ele.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando um repositório privado (hosted)
&lt;/h3&gt;

&lt;p&gt;Esse repositório será responsável por manter todos os nossos projetos privados que enviamos ao Nexus.&lt;/p&gt;

&lt;p&gt;Navegue em &lt;code&gt;Repository / Repositories&lt;/code&gt;, clique em &lt;strong&gt;Create repository&lt;/strong&gt;. O Nexus trará uma lista de &lt;em&gt;recipes&lt;/em&gt; disponíveis para configuração. Selecione &lt;strong&gt;npm (hosted)&lt;/strong&gt; e crie o repositório com as seguintes informações:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Campo&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Valor&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;npm-private&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blob store&lt;/td&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment Policy&lt;/td&gt;
&lt;td&gt;Allow redeploy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Aqui, em &lt;em&gt;Blob store&lt;/em&gt;, selecionamos aquele que criamos anteriormente. É interessante falar que, em &lt;em&gt;Deployment Policy&lt;/em&gt;, estamos habilitando o "redeploy" para ser possível sobrescrever a mesma versão do pacote que é enviado.&lt;/p&gt;

&lt;p&gt;Note que aqui isso é configurando apenas pro nosso exemplo. Essa estratégia deve ser analisada juntamente com o time responsável que realizará a manutenção dos projetos mantidos no Nexus.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando proxy para NPM público e agrupamento de repositórios
&lt;/h3&gt;

&lt;p&gt;O repositório &lt;code&gt;proxy&lt;/code&gt; realiza o proxy (duh!) de todas as nossas solicitações de leitura para o registro público do NPM (&lt;a href="https://registry.npmjs.org" rel="noopener noreferrer"&gt;https://registry.npmjs.org&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Já o repositório &lt;code&gt;group&lt;/code&gt; combina o repositório &lt;code&gt;proxy&lt;/code&gt; e o &lt;code&gt;hosted&lt;/code&gt; para possibilitar a instalação de bibliotecas de terceiros (NPM) quanto as privadas (npm-private).&lt;/p&gt;

&lt;p&gt;Ainda em &lt;code&gt;Repository / Repositories&lt;/code&gt;, clique em &lt;strong&gt;Create repository&lt;/strong&gt;. Selecione &lt;strong&gt;npm (proxy)&lt;/strong&gt; e crie o repositório com as seguintes as informações:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Campo&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Valor&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;npm-proxy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote Storage&lt;/td&gt;
&lt;td&gt;&lt;a href="https://registry.npmjs.org" rel="noopener noreferrer"&gt;https://registry.npmjs.org&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blob store&lt;/td&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Voltando para &lt;code&gt;Repository / Repositories&lt;/code&gt;, clique em &lt;strong&gt;Create repository&lt;/strong&gt;. Selecione &lt;strong&gt;npm (group)&lt;/strong&gt; e crie o repositório com as seguintes as informações:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Campo&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Valor&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;npm-group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blob store&lt;/td&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Members&lt;/td&gt;
&lt;td&gt;npm-proxy, npm-private&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Configurando aplicação para publicação no Nexus
&lt;/h2&gt;

&lt;p&gt;Afim de agilizar o processo de configuração, eu já deixei um projeto pré-configurado para brincarmos aqui. Baixe o projeto com o comando abaixo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/wnqueiroz/nodejs-nexus-repository-setup.git


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;O nosso objetivo aqui será publicar a &lt;code&gt;application-a&lt;/code&gt; no Nexus, e realizar a instalação dela na &lt;code&gt;application-b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Acesse o projeto &lt;code&gt;application-a&lt;/code&gt;, e abra o &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note que lá temos uma configuração de publicação:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"publishConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"registry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8081/repository/npm-private/"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ou seja, toda vez que executarmos o comando &lt;code&gt;npm publish&lt;/code&gt;, o NPM irá utilizar o repositório privado (que criamos lá atrás, &lt;code&gt;npm-private&lt;/code&gt;) como registry de publicação.&lt;/p&gt;

&lt;p&gt;A mesma configuração está disponível na &lt;code&gt;application-b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Em um terminal, na &lt;code&gt;application-a&lt;/code&gt;, vamos tentar realizar a publicação do projeto. Execute o comando:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;npm publish


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Perceba que não foi possível realizar a publicação, pois ainda não estamos logados na CLI do NPM:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm ERR! code E401
npm ERR! Unable to authenticate, need: BASIC &lt;span class="nv"&gt;realm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Sonatype Nexus Repository Manager"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Vamos realizar o login no repositório privado, usando o usuário de publicação que criamos em &lt;em&gt;Criando um usuário para publicação de pacotes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Execute o comando abaixo informando as crendenciais de acesso:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;npm login &lt;span class="nt"&gt;--registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8081/repository/npm-private/


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Em seguida, tente realizar a publicação novamente:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;npm publish


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Veja que, mesmo logados, ainda temos o mesmo problema:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm ERR! code E401
npm ERR! Unable to authenticate, need: BASIC &lt;span class="nv"&gt;realm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Sonatype Nexus Repository Manager"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Isso acontece por que precisamos dizer ao Nexus, que ele aceite esse tipo de publicação (logados localmente através da CLI). Para fazer isso, vamos habilitar um dos &lt;em&gt;Realms&lt;/em&gt; do Nexus, precisamente o &lt;code&gt;npm Bearer Token Realm&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Habilitando Realm NPM de autenticação no Nexus
&lt;/h3&gt;

&lt;p&gt;Os &lt;em&gt;Realms&lt;/em&gt; no Nexus, nada mais são de que um mecanismo de segurança para segregar os tipos de autenticação permitidas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Veja mais em: &lt;a href="https://help.sonatype.com/repomanager3/system-configuration/access-control/realms" rel="noopener noreferrer"&gt;https://help.sonatype.com/repomanager3/system-configuration/access-control/realms&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Voltando à interface do Nexus, na seção de configuração, acesse &lt;code&gt;Security / Realms&lt;/code&gt;. Selecione &lt;code&gt;npm Bearer Token Realm&lt;/code&gt; em &lt;strong&gt;Available&lt;/strong&gt;, e adicione na guia &lt;strong&gt;Active&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F78kw574odghhqinal8up.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F78kw574odghhqinal8up.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clique em &lt;strong&gt;Save&lt;/strong&gt; para finalizar a configuração.&lt;/p&gt;

&lt;h3&gt;
  
  
  Realizando a publicação da aplicação no Nexus
&lt;/h3&gt;

&lt;p&gt;Voltando ao terminal na &lt;code&gt;application-a&lt;/code&gt;, vamos tentar realizar novamente a publicação do projeto. Execute o comando:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;npm publish


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Veja que agora conseguimos realizar a publicação! 🚀🎉&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm notice
npm notice 📦  application-a@1.0.0
npm notice &lt;span class="o"&gt;===&lt;/span&gt; Tarball Contents &lt;span class="o"&gt;===&lt;/span&gt;
npm notice 39B  src/index.js
npm notice 321B package.json
npm notice &lt;span class="o"&gt;===&lt;/span&gt; Tarball Details &lt;span class="o"&gt;===&lt;/span&gt;
npm notice name:          application-a
npm notice version:       1.0.0
npm notice package size:  368 B
npm notice unpacked size: 360 B
npm notice shasum:        f40f2d6547110507a8d72481be0614eab3e9b659
npm notice integrity:     sha512-Aw1e784PXCFUT[...]BQKZZEnlJ61Yg&lt;span class="o"&gt;==&lt;/span&gt;
npm notice total files:   2
npm notice
+ application-a@1.0.0


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Salvando configurações de login no projeto (basic)
&lt;/h3&gt;

&lt;p&gt;Em alguns casos, não podemos utilizar a CLI do NPM para realizar o login (usando STDIN e STDOUT), como por exemplo, em um ambiente de CI. Podemos configurar o nosso projeto para utilizar uma autenticação básica (um pouco diferente da autenticação através do Realm e Login).&lt;/p&gt;

&lt;p&gt;Na raiz do projeto, crie um arquivo &lt;code&gt;.npmrc&lt;/code&gt; com o seguinte conteúdo:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;npmuser@company.com
always-auth&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="nv"&gt;_auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;BASE_64_TOKEN&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Em um terminal, gere o Base64 do usuário e senha que criamos em &lt;em&gt;Criando um usuário para publicação de pacotes&lt;/em&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'npmuser:npmuser'&lt;/span&gt; | openssl &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="c"&gt;# bnBtdXNlcjpucG11c2Vy&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Substitua &lt;code&gt;&amp;lt;BASE_64_TOKEN&amp;gt;&lt;/code&gt; no &lt;code&gt;.npmrc&lt;/code&gt; com o Base64 gerado. Seu arquivo deve estar com o seguinte conteúdo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;npmuser@company.com
always-auth&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="nv"&gt;_auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bnBtdXNlcjpucG11c2Vy


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Agora vamos validar a configuração realizando o logout da CLI do NPM e publicando o pacote novamente. Em um terminal, na &lt;code&gt;application-a&lt;/code&gt;, execute os comandos:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;logout&lt;/span&gt; &lt;span class="nt"&gt;--registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8081/repository/npm-private/
&lt;span class="nv"&gt;$ &lt;/span&gt;npm publish


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Aqui, como habilitamos o "redeploy" em &lt;em&gt;Criando um repositório privado (hosted)&lt;/em&gt;, é possível sobrescrevermos a versão 1.0.0, publicada anteriormente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Veja que agora conseguimos realizar a publicação sem realizarmos o login na CLI do NPM! 🚀🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalando dependências a partir do Nexus
&lt;/h2&gt;

&lt;p&gt;Agora vamos configurar a &lt;code&gt;application-b&lt;/code&gt; para instalarmos a &lt;code&gt;application-a&lt;/code&gt; no projeto.&lt;/p&gt;

&lt;p&gt;Vamos copiar o conteúdo do &lt;code&gt;.npmrc&lt;/code&gt; criado na &lt;code&gt;application-a&lt;/code&gt; e vamos criar um &lt;code&gt;.npmrc&lt;/code&gt; na &lt;code&gt;application-b&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;npmuser@company.com
always-auth&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="nv"&gt;_auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bnBtdXNlcjpucG11c2Vy


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Aqui também vamos adicionar o &lt;code&gt;registry&lt;/code&gt; com o &lt;code&gt;npm-group&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8081/repository/npm-group/


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Usamos o repositório &lt;code&gt;npm-group&lt;/code&gt; para conseguirmos obter tanto as aplicações públicas (direto do NPM registry, através do repositório &lt;code&gt;npm-proxy&lt;/code&gt;) tanto quanto as aplicações privadas (através do repositório &lt;code&gt;npm-private&lt;/code&gt;). E como dito anteriormente, isso só é possível pois agrupamos esses repositórios no &lt;code&gt;npm-group&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ao final, seu arquivo deverá conter o seguinte:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;npmuser@company.com
always-auth&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="nv"&gt;_auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bnBtdXNlcjpucG11c2Vy
&lt;span class="nv"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8081/repository/npm-group/


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Vamos testar a configuração realizando a instalação da &lt;code&gt;application-a&lt;/code&gt; na &lt;code&gt;application-b&lt;/code&gt;. Em um terminal, na &lt;code&gt;application-b&lt;/code&gt;, execute o comando:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;application-a


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Aqui já conseguimos instalar aplicações em outros projetos a partir do Nexus.&lt;/p&gt;

&lt;p&gt;Agora, vamos instalar o &lt;code&gt;axios&lt;/code&gt; para testar se conseguimos instalar aplicações públicas, direto do registry do NPM:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;axios


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Finalizamos todas as nossa configurações! 🚀🎉&lt;/p&gt;

&lt;p&gt;Caso tenha alguma dúvida, ou tenha deixado passar alguma configuração, no projeto base existe uma &lt;em&gt;branch&lt;/em&gt; com toda a configuração realizada até aqui:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wnqueiroz/nodejs-nexus-repository-setup/tree/final-setup" rel="noopener noreferrer"&gt;https://github.com/wnqueiroz/nodejs-nexus-repository-setup/tree/final-setup&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalizando...
&lt;/h2&gt;

&lt;p&gt;Bem, é isso, por hoje, é só!&lt;/p&gt;

&lt;p&gt;Quero te agradecer por chegar até aqui, e queria lhe pedir também para me encaminhar as suas dúvidas, comentários, críticas, correções ou sugestões sobre a publicação.&lt;/p&gt;

&lt;p&gt;Deixe seu ❤️ se gostou ou um 🦄 se esse post te ajudou de alguma maneira! Não se esqueça de ver os posts anteriores e me siga para maaaais conteúdos.&lt;/p&gt;

&lt;p&gt;Até!&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Devo versionar o arquivo .npmrc contendo as credenciais do Nexus no projeto?
&lt;/h3&gt;

&lt;p&gt;Bem, idealmente, nenhum arquivo contendo informações sensíveis devem ser "versionados" no SCM. Toda e qualquer informação inerente à ambiente, devem estar disponíveis através de variáveis de ambiente. Entretanto, a CLI do NPM não nos permite realizar o login sem ser através de STDIN e STDOUT (de maneira não interativa). O CircleCI por exemplo, sugere para inserirmos o token &lt;code&gt;_auth&lt;/code&gt; no arquivo &lt;code&gt;.npmrc&lt;/code&gt; em tempo de execução na própria pipeline (obtendo o token através de uma variável de ambiente), algo como:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"_auth=&lt;/span&gt;&lt;span class="nv"&gt;$NPM_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .npmrc


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A variável &lt;code&gt;$NPM_TOKEN&lt;/code&gt; deve conter o token de autenticação.&lt;/p&gt;

&lt;p&gt;Alternativamente, existem algumas soluções como a &lt;a href="https://www.npmjs.com/package/npm-cli-login" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/npm-cli-login&lt;/a&gt;, que possibilita realizar o login no NPM através de variáveis de ambiente.&lt;/p&gt;

&lt;p&gt;A decisão é dada através de um alinhamento com todo o time para que não só a esteira de CI funcione, mas também a possibilidade do desenvolvedor ter mais flexibilidade quando for atuar nos projetos privados.&lt;/p&gt;

&lt;p&gt;Pessoalmente, eu crio um usuário "devops" com específicas permissões e mantenho o arquivo &lt;code&gt;.npmrc&lt;/code&gt; com o &lt;code&gt;_auth&lt;/code&gt;. O combinado não sai caro! 😏&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>node</category>
      <category>npm</category>
    </item>
    <item>
      <title>Drops #03: Usando aliases para importação de módulos em TypeScript!</title>
      <dc:creator>William Queiroz</dc:creator>
      <pubDate>Thu, 22 Oct 2020 21:09:45 +0000</pubDate>
      <link>https://dev.to/wnqueiroz/drops-03-usando-aliases-para-importacao-de-modulos-em-typescript-1fe9</link>
      <guid>https://dev.to/wnqueiroz/drops-03-usando-aliases-para-importacao-de-modulos-em-typescript-1fe9</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;E ae dev, tudo bem com você?&lt;/p&gt;

&lt;p&gt;Você já deve ter trabalhado com projetos onde as importações de arquivos e módulos eram (ou ficaram) cada vez mais aninhadas. Em um determinado momento você se perde a cada "ponto, ponto, barra, ponto, ponto, barra" (e ainda espera um pouquinho pra ver se o editor de texto ajuda a completar o caminho, pra onde você realmente quer ir (profundo, não?).&lt;/p&gt;

&lt;p&gt;Seria muito mágico se houvesse uma maneira de alterar isso:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyClass&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../../deep/module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Pra isso:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyClass&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/deep/module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Pois é, e TEM!&lt;/p&gt;

&lt;p&gt;Bora pro post?&lt;/p&gt;

&lt;p&gt;Ah! mas antes disso... Esse post faz parte de uma série de artigos "drops" que tenho aqui! Veja a lista:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-01-corrigindo-vulnerabilidades-em-dependencias-com-yarn-ou-quase-2e2p"&gt;Drops #01: Corrigindo vulnerabilidades em dependências com Yarn! (ou quase)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-02-como-alterar-o-autor-do-commit-depois-do-push-2mgg"&gt;Drops #02: Como alterar o autor do commit depois do push&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-03-usando-aliases-para-importacao-de-modulos-em-typescript-1fe9"&gt;Drops #03: Usando aliases para importação de módulos em TypeScript!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-04-desmistificando-ponteiros-no-golang-3kj9"&gt;Drops #04: Desmistificando ponteiros no Golang!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Iniciando o projeto
&lt;/h2&gt;

&lt;p&gt;Vamos começar criando um projeto e inicializando o nosso &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;mkdir &lt;/span&gt;ts-module-aliases &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;ts-module-aliases &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn init &lt;span class="nt"&gt;-y&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Em seguida, vamos adicionar algumas dependências de desenvolvimento, sendo elas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O TypeScript (duh!);&lt;/li&gt;
&lt;li&gt;O &lt;a href="https://github.com/whitecolor/ts-node-dev" rel="noopener noreferrer"&gt;ts-node-dev&lt;/a&gt; (que será responsável por rodar o nosso código em modo de desenvolvimento);&lt;/li&gt;
&lt;li&gt;O &lt;a href="https://github.com/facebook/jest" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; (precisaremos configurar algumas coisas no Jest para que ele interprete os caminhos absolutos que usaremos no nosso código);&lt;/li&gt;
&lt;li&gt;O &lt;a href="https://www.npmjs.com/package/tsconfig-paths" rel="noopener noreferrer"&gt;tsconfig-paths&lt;/a&gt; (esse carinha será responsável por viabilizar o uso dos aliases).&lt;/li&gt;
&lt;li&gt;O &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; (ficará encarregado de realizar a construção do nosso projeto, interpretando os aliases e &lt;em&gt;transpilando&lt;/em&gt; o código com os caminhos respectivos).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Execute o comando:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

yarn add typescript@4.0.3 ts-node-dev@1.0.0 jest@26.6.0 ts-jest@26.4.1 @types/jest@26.0.15 tsconfig-paths@3.9.0 @babel/core@7.12.3 @babel/cli@7.12.1 @babel/node@7.12.1 @babel/preset-env@7.12.1 @babel/preset-typescript@7.12.1 babel-plugin-module-resolver@4.0.0 &lt;span class="nt"&gt;-D&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Note que aqui foram fixadas as versões de cada dependência. Apenas para que a minha configuração e a sua sejam feitas com as mesmas versões dos pacotes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Depois de instalar as dependências vamos iniciar as configurações!&lt;/p&gt;
&lt;h2&gt;
  
  
  Configurando o TypeScript
&lt;/h2&gt;

&lt;p&gt;Na raiz do projeto, crie um arquivo &lt;code&gt;tsconfig.json&lt;/code&gt; com a seguinte configuração:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2017"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"es6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dom"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rootDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/lib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"declarationDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/@types"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"declaration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"removeComments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resolveJsonModule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src/**/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"**/*.spec.ts"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Criando a base do projeto
&lt;/h3&gt;

&lt;p&gt;Depois de configurar o Typescript, vamos criar alguns arquivos partindo da raiz do projeto, dentro da pasta &lt;code&gt;src&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/services/BarService.ts&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BarService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hi! I'm bar method from BarService :)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;src/controllers/FooController.ts&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BarService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../services/BarService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FooController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;barService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BarService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;barService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BarService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;barService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;src/index.ts&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FooController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./controllers/FooController&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fooController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FooController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;fooController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Para finalizar, vamos adicionar o script no &lt;code&gt;package.json&lt;/code&gt; que executa o nosso código em modo de desenvolvimento:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ts-node-dev --no-notify src/index.ts"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Perceba que até aqui, ainda não temos um bom exemplo de arquivos SUPER aninhados. Será possível visualizar isso ao criarmos os nossos arquivos de testes!&lt;/p&gt;
&lt;h2&gt;
  
  
  Configurando o Jest
&lt;/h2&gt;

&lt;p&gt;Na raiz do projeto, crie um arquivo &lt;code&gt;jest.config.js&lt;/code&gt; com a seguinte configuração:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// For a detailed explanation regarding each configuration property, visit:&lt;/span&gt;
&lt;span class="c1"&gt;// https://jestjs.io/docs/en/configuration.html&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;clearMocks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;coverageDirectory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__tests__/coverage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;coverageProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;v8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;preset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts-jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;testEnvironment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;testMatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;**/__tests__/**/*.spec.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;NOTA: os testes da nossa aplicação, ficarão na raiz do projeto, dentro da pasta &lt;code&gt;__tests__&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vamos então criar os nossos arquivos de testes. Partindo da raiz do projeto, dentro da pasta &lt;code&gt;__tests__&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__tests__/unit/controllers/FooController.spec.ts&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FooController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../src/controllers/FooController&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BarService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../src/services/BarService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unit: FooController&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;fooController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FooController&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fooController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FooController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should call bar method from BarService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BarService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="nx"&gt;fooController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeCalled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;__tests__/unit/services/BarService.spec.ts&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BarService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../src/services/BarService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unit: BarService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;barService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BarService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;barService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BarService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should call console.log&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;log&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="nx"&gt;barService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hi! I'm bar method from BarService :)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Olha ai, os benditos "ponto, ponto, barra, ponto, ponto, barra"!&lt;/p&gt;
&lt;h2&gt;
  
  
  Configurando os aliases no projeto
&lt;/h2&gt;

&lt;p&gt;Vamos adicionar a configuração abaixo no &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./src/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Esse mapeamento, fará com que todo &lt;code&gt;@/*&lt;/code&gt; seja um alias para &lt;code&gt;./src/*&lt;/code&gt; (com o &lt;code&gt;baseUrl&lt;/code&gt; sendo a raiz do nosso projeto).&lt;/p&gt;

&lt;p&gt;Vamos agora, fazer com que o &lt;code&gt;ts-node-dev&lt;/code&gt; seja capaz de entender os nossos aliases. Adicione no script de dev (no &lt;code&gt;package.json&lt;/code&gt;), O trecho &lt;code&gt;-r tsconfig-paths/register&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="gd"&gt;- "dev": "ts-node-dev --no-notify src/index.ts"
&lt;/span&gt;&lt;span class="gi"&gt;+ "dev": "ts-node-dev -r tsconfig-paths/register --no-notify src/index.ts"
&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;A partir daqui, podemos alterar as importações! Altere isso:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FooController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../src/controllers/FooController&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BarService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../src/services/BarService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Para isso:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FooController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/controllers/FooController&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BarService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/services/BarService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;NOTA: Altere todas as importações para usarmos o alias ao invés dos &lt;code&gt;../&lt;/code&gt; ou &lt;code&gt;./&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ao executarmos o comando &lt;code&gt;yarn dev&lt;/code&gt;, já podemos utilizar os aliases durante o desenvolvimento, porém, ao executarmos o &lt;code&gt;yarn test&lt;/code&gt;, o Jest ainda não é capaz de entender os caminhos que estamos utilizando...&lt;/p&gt;

&lt;p&gt;Vamos adicionar a propriedade &lt;code&gt;moduleNameMapper&lt;/code&gt; no arquivo &lt;code&gt;jest.config.js&lt;/code&gt; e fazer a seguinte configuração:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pathsToModuleNameMapper&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts-jest/utils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;compilerOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./tsconfig.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// (...)&lt;/span&gt;
  &lt;span class="na"&gt;moduleNameMapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pathsToModuleNameMapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compilerOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;rootDir&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Com isso, já é possível utilizarmos os aliases nas nossas importações!&lt;/p&gt;
&lt;h2&gt;
  
  
  O problema
&lt;/h2&gt;

&lt;p&gt;Até aqui, conseguimos configurar os aliases e utilizá-los tanto nos arquivos de testes quanto no source do projeto. Entretanto, precisamos ainda configurar o comando de construção do nosso projeto, somente assim ele estará pronto para publicarmos e utilizarmos no ambiente produtivo.&lt;/p&gt;

&lt;p&gt;Vamos configurar o comando &lt;code&gt;yarn build&lt;/code&gt; para construir o nosso projeto, e o comando &lt;code&gt;yarn start&lt;/code&gt; para executar a o pacote construído.&lt;/p&gt;

&lt;p&gt;Adicione os scripts no &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node dist/lib/src/index.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;A seguir, execute o comando:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

yarn build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn start


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Você perceberá que o projeto não pode ser executado, por conta do seguinte erro:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

❯ yarn start
yarn run v1.22.5
&lt;span class="nv"&gt;$ &lt;/span&gt;node dist/lib/src/index.js
internal/modules/cjs/loader.js:968
  throw err&lt;span class="p"&gt;;&lt;/span&gt;
  ^

Error: Cannot find module &lt;span class="s1"&gt;'@/controllers/FooController'&lt;/span&gt;
Require stack:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Isso ocorre por que o &lt;code&gt;tsc&lt;/code&gt; não é capaz de entender esses aliases, inclusive, para nossa versão de produção, pouco importa se estamos usando aliases ou caminhos relativos, o que importa é que funcione!&lt;/p&gt;

&lt;p&gt;Outro problema também, é que se notarmos os arquivos que foram construídos na nossa pasta &lt;code&gt;dist&lt;/code&gt; vamos encontrar todos os nossos arquivos de testes! O que não faz sentido algum ir pro ambiente de produção, não é mesmo?&lt;/p&gt;

&lt;p&gt;Precisamos então:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fazer com que o comando de build gere um pacote funcional.&lt;/li&gt;
&lt;li&gt;Fazer com que o comando de build empacote apenas o código que irá para produção (e remover os arquivos de testes de lá).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos fazer tudo isso com a substituição do &lt;code&gt;tsc&lt;/code&gt; pelo &lt;code&gt;babel&lt;/code&gt;!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTA: O babel será responsável por alterar os nossos aliases, para os respectivos caminhos no projeto&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Configurando o Babel
&lt;/h3&gt;

&lt;p&gt;Como já adicionamos as dependências do Babel no inicio do artigo, vamos começar o arquivo &lt;code&gt;babel.config.js&lt;/code&gt; na raiz do projeto, com a seguinte configuração:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;presets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;current&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/preset-typescript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module-resolver&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^@/(.+)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;**/*.spec.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Com isso o babel irá alterar todo &lt;code&gt;^@/(.+)&lt;/code&gt; para &lt;code&gt;./src/\\1&lt;/code&gt;, e.g.: &lt;code&gt;@/services/BarService&lt;/code&gt; para &lt;code&gt;../services/BarService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos agora criar o arquivo &lt;code&gt;tsconfig.build.json&lt;/code&gt; que irá herdar todas as configurações do nosso &lt;code&gt;tsconfig.json&lt;/code&gt; e será usado apenas para criar os arquivos de declaração de tipos do projeto (dentro da pasta &lt;code&gt;dist/@types&lt;/code&gt;). Isso é necessário, pois o Babel não fará esse trabalho. Adicione o seguinte no arquivo:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./tsconfig.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rootDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"**/*.spec.ts"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Em seguida, altere o script &lt;code&gt;start&lt;/code&gt; (não precisaremos mais do &lt;code&gt;src&lt;/code&gt; ali) e o de &lt;code&gt;build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Adicione também o script &lt;code&gt;postbuild&lt;/code&gt; no &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node dist/lib/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"babel src --extensions &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;.js,.ts&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; --out-dir dist/lib --copy-files --no-copy-ignored"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postbuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc -p tsconfig.build.json --emitDeclarationOnly"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Vamos apagar a pasta &lt;code&gt;dist&lt;/code&gt; gerada anteriormente, construir o projeto com o Babel, e então rodar o comando de produção:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; dist &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn start


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

yarn run v1.22.5
&lt;span class="nv"&gt;$ &lt;/span&gt;babel src &lt;span class="nt"&gt;--extensions&lt;/span&gt; &lt;span class="s2"&gt;".js,.ts"&lt;/span&gt; &lt;span class="nt"&gt;--out-dir&lt;/span&gt; dist/lib &lt;span class="nt"&gt;--copy-files&lt;/span&gt; &lt;span class="nt"&gt;--no-copy-ignored&lt;/span&gt;
Successfully compiled 3 files with Babel &lt;span class="o"&gt;(&lt;/span&gt;704ms&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;tsc &lt;span class="nt"&gt;-p&lt;/span&gt; tsconfig.build.json &lt;span class="nt"&gt;--emitDeclarationOnly&lt;/span&gt;
✨  Done &lt;span class="k"&gt;in &lt;/span&gt;3.74s.
yarn run v1.22.5
&lt;span class="nv"&gt;$ &lt;/span&gt;node dist/lib/index.js
Hi! I&lt;span class="s1"&gt;'m bar method from BarService :)
✨  Done in 0.35s.


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  E Voilà!
&lt;/h2&gt;

&lt;p&gt;Foi bastante coisa feita aqui! Espero que você tenha conseguido usar essa funcionalidade massa nos seus projetos, e entendido cada detalhe da configuração. No final desse artigo eu deixo o exemplo completo que desenvolvemos juntos!&lt;/p&gt;
&lt;h2&gt;
  
  
  Finalizando…
&lt;/h2&gt;

&lt;p&gt;Bem, é isso, por hoje é só!&lt;/p&gt;

&lt;p&gt;Quero agradecer a você que chegou até aqui, e queria lhe pedir também para encaminhar-me as suas dúvidas, comentários, críticas, correções ou sugestões sobre a postagem.&lt;/p&gt;

&lt;p&gt;Deixe seu ❤️ se gostou ou um 🦄 se esse post te ajudou de alguma maneira! Não se esqueça de ver os posts anteriores e me siga para maaaais conteúdos.&lt;/p&gt;

&lt;p&gt;Até!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/wnqueiroz" rel="noopener noreferrer"&gt;
        wnqueiroz
      &lt;/a&gt; / &lt;a href="https://github.com/wnqueiroz/typescript-tsconfig-paths" rel="noopener noreferrer"&gt;
        typescript-tsconfig-paths
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An example project on how to configure tsconfig-paths
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>typescript</category>
      <category>node</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Criando e automatizando o versionamento semântico de projetos NodeJS</title>
      <dc:creator>William Queiroz</dc:creator>
      <pubDate>Tue, 11 Aug 2020 14:53:07 +0000</pubDate>
      <link>https://dev.to/wnqueiroz/criando-e-automatizando-o-versionamento-semantico-de-projetos-nodejs-3ogj</link>
      <guid>https://dev.to/wnqueiroz/criando-e-automatizando-o-versionamento-semantico-de-projetos-nodejs-3ogj</guid>
      <description>&lt;p&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@jdubs?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Johnson Wang&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/stack?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;E ae dev, tudo bem com você?&lt;/p&gt;

&lt;p&gt;Desde que eu comecei a trabalhar com JavaScript do lado do servidor, e a utilizar as mais diversas bibliotecas lá do NPM, sempre me questionei como elas eram mantidas... Desde as suas versões publicadas, padrões dos projetos que podem ser seguidos por um ou mais desenvolvedores, ou até mesmo por uma equipe dedicada apenas nisso.&lt;/p&gt;

&lt;p&gt;A questão que mais me intrigava era: como saber quais versões DEVEM ser publicadas, quando uma alteração é feita?&lt;/p&gt;

&lt;p&gt;Bom, com base nisso, nos últimos dias dediquei os estudos a explorar os mais variados repositórios no GitHub, e as bibliotecas mais populares no momento no NPM. Identifiquei alguns padrões que podem facilitar a manutenção dos projetos com automatização de processos!&lt;/p&gt;

&lt;p&gt;Ao final deste artigo, você irá:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entender a importância de padronizar um projeto, antes de desenvolver.&lt;/li&gt;
&lt;li&gt;Entender como funciona um versionamento semântico.&lt;/li&gt;
&lt;li&gt;Entender o que são commits semânticos.&lt;/li&gt;
&lt;li&gt;Aprender a automatizar a publicação/distribuição do seu projeto com base no versionamento.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bora pro post?&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumário
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;O problema&lt;/li&gt;
&lt;li&gt;Entendendo o versionamento semântico&lt;/li&gt;
&lt;li&gt;
Entendendo o que são commits semânticos

&lt;ul&gt;
&lt;li&gt;Especificação Conventional Commits&lt;/li&gt;
&lt;li&gt;Por que usar?&lt;/li&gt;
&lt;li&gt;Como isso se relaciona com o SemVer?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Hands-On

&lt;ul&gt;
&lt;li&gt;Iniciando o projeto&lt;/li&gt;
&lt;li&gt;Habilitando a padronização de commits semânticos&lt;/li&gt;
&lt;li&gt;Instalando o husky e integrando-o ao commitlint&lt;/li&gt;
&lt;li&gt;Facilitando a criação de commits padronizados&lt;/li&gt;
&lt;li&gt;Gerando versões semânticas e CHANGELOG&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Workflow de desenvolvimento&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  O problema
&lt;/h2&gt;

&lt;p&gt;Imagine que você esteja trabalhando com o cenário, onde as versões do seu projeto precisam ser coerentes com cada ajuste que você precise fazer, isto é, as versões devem indicar aquilo que foi feito. Seja uma implementação de uma nova funcionalidade, uma correção de um bug, ou até mesmo um &lt;em&gt;breaking change&lt;/em&gt; por remover uma &lt;em&gt;feature&lt;/em&gt; ou mudar completamente a integração do seu projeto, com os demais projetos que o utilizam.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A coerência com as versões do seu projeto irá auxiliar na manutenção do projeto como um todo!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O &lt;strong&gt;SemVer&lt;/strong&gt; está aqui para nos ajudar!&lt;/p&gt;

&lt;h2&gt;
  
  
  Entendendo o versionamento semântico
&lt;/h2&gt;

&lt;p&gt;Vamos entender melhor como funciona a especificação SemVer!&lt;/p&gt;

&lt;p&gt;Ela aborda um conjunto simples de regras e requisitos que determinam como os números da versão são atribuídos e por sua vez, incrementados.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Sob esse esquema, os números da versão e a maneira como eles mudam transmitem &lt;strong&gt;significado&lt;/strong&gt; sobre o código subjacente e o que foi modificado de uma versão para a seguinte".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Em resumo, dado o número de versão &lt;code&gt;MAJOR&lt;/code&gt;.&lt;code&gt;MINOR&lt;/code&gt;.&lt;code&gt;PATCH&lt;/code&gt;, deve-se incrementá-las seguindo as seguintes regras:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MAJOR&lt;/strong&gt;: quando você realizar alterações incompatíveis da API;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MINOR&lt;/strong&gt;: quando você adicionar funcionalidades compatíveis com versões anteriores;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PATCH&lt;/strong&gt;: quando você corrigir erros compatíveis com versões anteriores.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para a nossa configuração, o essencial está nesse resumo. Você pode ler mais sobre a especificação em: &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;https://semver.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recomendo também a leitura da seção &lt;em&gt;FAQ&lt;/em&gt; disponível no site, lá você encontrará respostas para dúvidas do tipo: &lt;em&gt;"Como sei quando lançar a 1.0.0?"&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A especificação SemVer foi originalmente criada por &lt;a href="https://en.wikipedia.org/wiki/Tom_Preston-Werner" rel="noopener noreferrer"&gt;Tom Preston-Werner&lt;/a&gt;, inventor do &lt;a href="https://en.wikipedia.org/wiki/Gravatar" rel="noopener noreferrer"&gt;Gravatar&lt;/a&gt; e co-fundador do &lt;a href="https://en.wikipedia.org/wiki/GitHub" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Entendendo o que são commits semânticos
&lt;/h2&gt;

&lt;p&gt;Você em algum momento já se questionou como deveria escrever uma mensagem de commit (se deveria colocar muitos detalhes, descrever melhor o que fez no corpo do commit, usar algum prefixo, e etc.).&lt;/p&gt;

&lt;p&gt;Seria mágico termos algum padrão para usarmos no nosso projeto, que siga uma maneira consistente e coesa de escrever os commits, e que informe exatamente o que foi feito ali, não é mesmo?&lt;/p&gt;

&lt;p&gt;Pois é, e TEM!&lt;/p&gt;

&lt;h3&gt;
  
  
  Especificação Conventional Commits
&lt;/h3&gt;

&lt;p&gt;A especificação &lt;em&gt;Conventional Commits&lt;/em&gt; é inspirada e baseada fortemente no &lt;a href="https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines" rel="noopener noreferrer"&gt;guideline de commits do Angular&lt;/a&gt;. É uma convenção bem simples para seguir ao escrever commits e que oferece um conjunto fácil de regras para manter um histórico de commits mais explícito e facilmente compreendido.&lt;/p&gt;

&lt;p&gt;Em resumo, para seguir a especificação, um commit deve ser estruturado da seguinte maneira:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;type&amp;gt;[optional scope]: &amp;lt;description&amp;gt;

[optional body]

[optional footer(s)]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;O commit pode conter alguns elementos estruturais, que comunicam a intenção aos "consumidores" do seu projeto:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;fix&lt;/strong&gt;: um commit "do tipo" &lt;em&gt;fix&lt;/em&gt; indica que aquela alteração corrige algum bug no projeto (isso se correlaciona ao &lt;code&gt;PATCH&lt;/code&gt; do SemVer);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;feat&lt;/strong&gt;: um commit "do tipo" &lt;em&gt;feat&lt;/em&gt; indica que aquela alteração adiciona alguma nova funcionalidade ao projeto (isso se correlaciona ao &lt;code&gt;MINOR&lt;/code&gt; do SemVer);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BREAKING CHANGE&lt;/strong&gt;: um commit que possui um rodapé com &lt;em&gt;BREAKING CHANGE&lt;/em&gt; ou está diretamente na mensagem com &lt;code&gt;!&lt;/code&gt; depois do &lt;em&gt;type&lt;/em&gt; ou &lt;em&gt;scope&lt;/em&gt;, indica que aquela alteração, muda a compatibilidade da sua API com os "consumidores" (isso se correlaciona com o &lt;code&gt;MAJOR&lt;/code&gt; do SemVer). Um &lt;em&gt;BREAKING CHANGE&lt;/em&gt; pode fazer parte de commits de qualquer &lt;em&gt;type&lt;/em&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Outros tipos além de &lt;code&gt;feat&lt;/code&gt; e &lt;code&gt;fix&lt;/code&gt; também são permitidos.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Um &lt;em&gt;scope&lt;/em&gt; pode ser fornecido ao &lt;em&gt;type&lt;/em&gt; do commit, para fornecer informações contextuais adicionais e pode ser encontrado entre parênteses na mensagem, e.g.:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

feat(parser): add ability to parse arrays.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Você pode ler a especificação completa em: &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/#specification" rel="noopener noreferrer"&gt;https://www.conventionalcommits.org/en/v1.0.0/#specification&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Por que usar?
&lt;/h3&gt;

&lt;p&gt;Ao adotar os padrões no seu projeto, você poderá:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Determinar automaticamente o &lt;em&gt;bump&lt;/em&gt; das versões (de maneira semântica, com base nos tipos dos commits criados);&lt;/li&gt;
&lt;li&gt;Comunicar com clareza a natureza das alterações (seja aos colegas de equipe ou ao público);&lt;/li&gt;
&lt;li&gt;Automatizar o processo de &lt;em&gt;build&lt;/em&gt; e publicação/distribuição do projeto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gerar CHANGELOGs automaticamente.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Outro ganho é que os desenvolvedores serão encorajados a &lt;strong&gt;granularizar&lt;/strong&gt; os commits, uma vez que os padrões adotados visam contextualizar melhor a alteração feita (com tipos, escopos, e etc.). Isso é muito bom ao trabalhar com &lt;em&gt;Code Review&lt;/em&gt; e &lt;em&gt;Pull Requests&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Como isso se relaciona com o SemVer?
&lt;/h3&gt;

&lt;p&gt;Como vimos, os tipos dos commits se relacionam com cada "acrônimo" da especificação SemVer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;fix:&lt;/em&gt; deve ser traduzido em liberações de &lt;em&gt;PATCH&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;feat:&lt;/em&gt; deve ser traduzido em liberações &lt;em&gt;MINOR&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;BREAKING CHANGE:&lt;/em&gt; deve ser traduzido, independentemente do tipo, em liberações &lt;em&gt;MAJOR&lt;/em&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hands-On
&lt;/h2&gt;

&lt;p&gt;Bom, agora que já entendemos como o versionamento e os commits semânticos funcionam, vamos criar um projeto com as configurações ideais para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Realizar o incremento automático de versões (coesas, através da análise dos commits);&lt;/li&gt;
&lt;li&gt;Realizar a geração automática do arquivo &lt;code&gt;CHANGELOG.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Realizar a distribuição/publicação da versão gerada (com a ajuda de CI/CD).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;TL;DR: O arquivo &lt;code&gt;CHANGELOG.md&lt;/code&gt;, na raiz do projeto, contém o descritivo de todas as alterações (pertintentes) feitas naquele específico projeto. A razão para criar e manter um &lt;em&gt;changelog&lt;/em&gt; é simples: quando um colaborador ou usuário final deseja verificar se alguma alteração foi feita em um software, ele pode fazer isso com facilidade e precisão lendo o registro de alterações. Tudo o que eles precisam fazer é ir para o &lt;em&gt;changelog&lt;/em&gt; e ele mostrará o que e quando as alterações foram feitas entre as diferentes versões ou lançamentos daquele software.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Iniciando o projeto
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Vamos criar um novo projeto NodeJS e criar o &lt;code&gt;package.json&lt;/code&gt;, com o seguinte comando:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-project &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;my-project &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn init &lt;span class="nt"&gt;-y&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Posteriormente, usaremos um hook do Git para que a cada vez que realizarmos um commit, seja feita uma análise do commit em questão para identificar se ele está ou não no padrão especificado pelo &lt;em&gt;Conventional Commits&lt;/em&gt;. Então, vamos inicialiazar o git no projeto:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git init


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Habilitando a padronização de commits semânticos
&lt;/h3&gt;

&lt;p&gt;Para realizar a análise dos commits criados, precisamos de uma ferramenta que fará esse trabalho e nos auxiliará a adotar os padrões que vimos anteriormente. Vamos então instalar e configurar o &lt;a href="https://commitlint.js.org/#/" rel="noopener noreferrer"&gt;commitlint&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Comece instalando os pacotes &lt;code&gt;cli&lt;/code&gt; e &lt;code&gt;config-conventional&lt;/code&gt; do commitlint nas dependências de desenvolvimento:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; @commitlint/&lt;span class="o"&gt;{&lt;/span&gt;config-conventional,cli&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Vamos criar o arquivo de configuração &lt;code&gt;commitlint.config.js&lt;/code&gt; na raiz do projeto com o trecho abaixo:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@commitlint/config-conventional&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Valide as configurações com o comando:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'foo: bar'&lt;/span&gt; | yarn commitlint


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Você deverá visualizar no terminal algo como:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

⧗   input: foo: bar
✖   Please add rules to your &lt;span class="sb"&gt;`&lt;/span&gt;commitlint.config.js&lt;span class="sb"&gt;`&lt;/span&gt;
    - Getting started guide: https://git.io/fhHij
    - Example config: https://git.io/fhHip &lt;span class="o"&gt;[&lt;/span&gt;empty-rules]

✖   found 1 problems, 0 warnings
ⓘ   Get &lt;span class="nb"&gt;help&lt;/span&gt;: https://github.com/conventional-changelog/commitlint/#what-is-commitlint


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Instalando o husky e integrando-o ao commitlint
&lt;/h3&gt;

&lt;p&gt;Bom, até aqui, apenas configuramos a ferramenta que realiza análise dos nossos commits. Para que ela seja usada, a cada novo commit, precisaremos instalar o &lt;a href="https://www.npmjs.com/package/husky" rel="noopener noreferrer"&gt;husky&lt;/a&gt; e configurá-lo com o &lt;code&gt;commitlint&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Comece instalando o &lt;code&gt;husky&lt;/code&gt; como dependência de desenvolvimento:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; husky


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Vamos agora habilitar o hook &lt;code&gt;commit-msg&lt;/code&gt; criando um arquivo &lt;code&gt;.huskyrc&lt;/code&gt; (na raiz do projeto) com o trecho abaixo:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commit-msg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commitlint -E HUSKY_GIT_PARAMS"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Valide a configuração criando um commit, no seguinte formato:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"foo: bar"&lt;/span&gt; &lt;span class="nt"&gt;--allow-empty&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Você deverá visualizar no terminal algo como:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

husky &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; commit-msg &lt;span class="o"&gt;(&lt;/span&gt;node v12.16.1&lt;span class="o"&gt;)&lt;/span&gt;
⧗   input: foo: bar
✖   Please add rules to your &lt;span class="sb"&gt;`&lt;/span&gt;commitlint.config.js&lt;span class="sb"&gt;`&lt;/span&gt;
    - Getting started guide: https://git.io/fhHij
    - Example config: https://git.io/fhHip &lt;span class="o"&gt;[&lt;/span&gt;empty-rules]

✖   found 1 problems, 0 warnings
ⓘ   Get &lt;span class="nb"&gt;help&lt;/span&gt;: https://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; commit-msg hook failed &lt;span class="o"&gt;(&lt;/span&gt;add &lt;span class="nt"&gt;--no-verify&lt;/span&gt; to bypass&lt;span class="o"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Perceba que o &lt;code&gt;husky&lt;/code&gt; habilitou o &lt;em&gt;hook&lt;/em&gt; &lt;strong&gt;commit-msg&lt;/strong&gt;, o &lt;code&gt;commitlint&lt;/code&gt;, por sua vez, foi executado e fez a análise do que escrevemos. Com isso os nossos commits serão analisados antes de serem criados!&lt;/p&gt;

&lt;p&gt;Para que haja sucesso na criação do commit, ele deve estar padronizado seguindo a especificação.&lt;/p&gt;

&lt;h3&gt;
  
  
  Facilitando a criação de commits padronizados
&lt;/h3&gt;

&lt;p&gt;Imagine que você esteja realizando um commit, e por ventura não se lembre de algum tipo que esteja na especificação, ou até mesmo não lembre do formato específico que comunique um &lt;em&gt;breaking change&lt;/em&gt;, por exemplo. O Commitizen disponibiliza uma CLI que nos auxilia na criação de commits padronizados.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Essa configuração, é opcional, mas é bem interessante tê-la aqui para os futuros colaboradores terem mais facilidade e entendimento quanto aos padrões do projeto.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Comece configurando a CLI no repositório com o comando:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;npx commitizen init cz-conventional-changelog &lt;span class="nt"&gt;--yarn&lt;/span&gt; &lt;span class="nt"&gt;--dev&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Será adicionado ao &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commitizen"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./node_modules/cz-conventional-changelog"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;A seguir, vamos adicionar um script ao &lt;code&gt;package.json&lt;/code&gt; para iniciar a CLI:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git-cz"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Execute o comando &lt;code&gt;yarn commit --allow-empty&lt;/code&gt;. Você verá a ferramenta entrar em ação!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A flag &lt;code&gt;--allow-empty&lt;/code&gt;, apesar de intuitiva vale a pena informar que ela possibilita a criação de commits sem ser necessário adicionar uma modificação em &lt;em&gt;staged&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;br&gt;
    &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhbujbz2nii62b9yxxqt3.png" alt="commitzen-git-cz.png"&gt;&lt;br&gt;
  

&lt;blockquote&gt;
&lt;p&gt;É possível definir o commitizen como padrão ao executar &lt;code&gt;git commit&lt;/code&gt; no terminal, veja mais em: &lt;a href="https://github.com/commitizen/cz-cli#optional-running-commitizen-on-git-commit" rel="noopener noreferrer"&gt;https://github.com/commitizen/cz-cli#optional-running-commitizen-on-git-commit&lt;/a&gt;&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;Extra: se o seu projeto for &lt;strong&gt;open-source&lt;/strong&gt;, com essa configuração, é possível adicionar a &lt;em&gt;badge&lt;/em&gt; "commitizen friendly" no &lt;code&gt;README.md&lt;/code&gt; do repositório:&lt;/p&gt;



&lt;p&gt;&lt;a href="http://commitizen.github.io/cz-cli/" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2Fcommitizen-friendly-brightgreen.svg" alt="Commitizen friendly"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;![Commitizen friendly&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://img.shields.io/badge/commitizen-friendly-brightgreen.svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;](http://commitizen.github.io/cz-cli/)&lt;span class="sb"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Gerando versões semânticas e CHANGELOG
&lt;/h3&gt;

&lt;p&gt;Até aqui, já podemos gerar os commits semânticos. Através deles, utilizaremos uma ferramenta que realiza a análise dos commits novos (adicionados desde a última versão do projeto) e determina qual será essa nova versão para a distribuição. Por padrão, ela também criará o CHANGELOG.md automaticamente de acordo com a análise feita.&lt;/p&gt;

&lt;p&gt;Vamos configurar o projeto com o &lt;a href="https://github.com/conventional-changelog/standard-version" rel="noopener noreferrer"&gt;standard-version&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Comece instale o &lt;code&gt;standard-version&lt;/code&gt; como dependência de desenvolvimento:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; standard-version


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Em seguida, adicione o script abaixo no &lt;code&gt;package.json&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"standard-version"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ao executar o comando &lt;code&gt;yarn release&lt;/code&gt; (ou &lt;code&gt;npm rum release&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faev8aczwuiw7i5xxq5cw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faev8aczwuiw7i5xxq5cw.gif" alt="cmd-yarn-release.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Será realizada a análise dos commits feitos após o último &lt;em&gt;release&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Será incrementada a versão do projeto no &lt;code&gt;package.json&lt;/code&gt;, com base na análise dos commits.&lt;/li&gt;
&lt;li&gt;Será gerado o &lt;code&gt;CHANGELOG.md&lt;/code&gt;, incluindo os detalhes da nova versão.&lt;/li&gt;
&lt;li&gt;Será criada uma &lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging" rel="noopener noreferrer"&gt;tag&lt;/a&gt; com base na versão do &lt;code&gt;package.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Para remover o prefixo "v" da tag, basta adicionar a flag &lt;code&gt;-t&lt;/code&gt; sem nenhum valor no script criado, e.g.: &lt;code&gt;standard-version -t \"\"&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Depois de executar o comando, você pode publicar o projeto com o &lt;code&gt;npm publish&lt;/code&gt; e enviar a &lt;em&gt;tag&lt;/em&gt; gerada para o repositório remoto com &lt;code&gt;git push --follow-tags origin master&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow de desenvolvimento
&lt;/h2&gt;

&lt;p&gt;Com ajuda de uma esteira de &lt;em&gt;CI/CD&lt;/em&gt;, é possível automatizar o processo de publicação/distribuição de novas versões, para que a cada nova modificação na branch &lt;code&gt;master&lt;/code&gt;, sejam executados os comandos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Gerando uma nova versão: &lt;code&gt;yarn release&lt;/code&gt; (ou nom &lt;code&gt;run release&lt;/code&gt;);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publicando a nova versão: &lt;code&gt;npm publish&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enviando a tag gerada para o repositório: &lt;code&gt;git push --follow-tags origin master&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mas para que isso seja possível, deve-se seguir o seguinte fluxo de desenvolvimento:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffk46e2v3d6t2ted2xj69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffk46e2v3d6t2ted2xj69.png" alt="development-workflow.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Criar uma nova &lt;em&gt;feature branch&lt;/em&gt; a partir da branch principal (master);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Realizar as alterações e "commitá-las" nos padrões estabelecidos pelas especificações;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mesclar as alterações na branch principal via &lt;em&gt;Pull Request&lt;/em&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A esteira de CI/CD deve ser acionada assim que houver uma nova alteração na branch principal, e (além de executar outros passos durante o processo, como testes, coleta de cobertura, lint, e etc.) incluir os comandos mencionados anteriormente.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Finalizando...
&lt;/h2&gt;

&lt;p&gt;Bem, é isso, por hoje, é só!&lt;/p&gt;

&lt;p&gt;Quero te agradecer por chegar até aqui, e queria lhe pedir também para me encaminhar as suas dúvidas, comentários, críticas, correções ou sugestões sobre a publicação.&lt;/p&gt;

&lt;p&gt;Deixe seu ❤️ se gostou ou um 🦄 se esse post te ajudou de alguma maneira! Não se esqueça de ver os posts anteriores e me siga para maaaais conteúdos.&lt;/p&gt;

&lt;p&gt;Até!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>git</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Drops #02: Como alterar o autor do commit depois do push</title>
      <dc:creator>William Queiroz</dc:creator>
      <pubDate>Mon, 06 Jul 2020 19:07:18 +0000</pubDate>
      <link>https://dev.to/wnqueiroz/drops-02-como-alterar-o-autor-do-commit-depois-do-push-2mgg</link>
      <guid>https://dev.to/wnqueiroz/drops-02-como-alterar-o-autor-do-commit-depois-do-push-2mgg</guid>
      <description>&lt;p&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@yancymin?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Yancy Min&lt;/a&gt; on &lt;a href="https://unsplash.com/@yancymin?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;E ae dev, tudo bem com você?&lt;/p&gt;

&lt;p&gt;Semana passada eu finalmente comecei a usar o dev.to, inaugurando-o com um post que eu havia escrito originalmente lá no Medium, se você ainda não leu, já salva pra ler mais tarde: &lt;a href="https://dev.to/wnqueiroz/drops-01-corrigindo-vulnerabilidades-em-dependencias-com-yarn-ou-quase-2e2p"&gt;Drops #01: Corrigindo vulnerabilidades em dependências com Yarn! (ou quase)&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bom, continuando essa série &lt;em&gt;"drops"&lt;/em&gt; com dicas e truques que eu uso no dia-a-dia...&lt;/p&gt;

&lt;p&gt;Quem nunca subiu um código para o repositório depois de ter "comitado" com o usuário que você usa na empresa, não é mesmo? HAHAHA&lt;/p&gt;

&lt;p&gt;Calma, isso é mais comum do que você imagina. Ainda mais se costuma utilizar uma única máquina tanto para o seu trabalho, quanto para aqueles projetos pessoais que você costuma publicar no Github.&lt;/p&gt;

&lt;p&gt;A dica de hoje é de como alterar o autor do commit depois de já tê-lo enviado ao seu repositório remoto.&lt;/p&gt;

&lt;p&gt;Bora pro post?&lt;/p&gt;

&lt;p&gt;Ah! mas antes disso... Esse post faz parte de uma série de artigos "drops" que tenho aqui! Veja a lista:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-01-corrigindo-vulnerabilidades-em-dependencias-com-yarn-ou-quase-2e2p"&gt;Drops #01: Corrigindo vulnerabilidades em dependências com Yarn! (ou quase)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-02-como-alterar-o-autor-do-commit-depois-do-push-2mgg"&gt;Drops #02: Como alterar o autor do commit depois do push&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-03-usando-aliases-para-importacao-de-modulos-em-typescript-1fe9"&gt;Drops #03: Usando aliases para importação de módulos em TypeScript!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-04-desmistificando-ponteiros-no-golang-3kj9"&gt;Drops #04: Desmistificando ponteiros no Golang!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Alterando o usuário do repositório
&lt;/h2&gt;

&lt;p&gt;Antes de realizarmos as alterações nos commits, vamos definir o usuário que, &lt;strong&gt;daqui pra frente&lt;/strong&gt;, será o autor dos commits futuros.&lt;/p&gt;

&lt;p&gt;Para isso, abra um terminal na pasta do seu &lt;strong&gt;repositório&lt;/strong&gt;, e execute os comandos abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user.email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;GIT_EMAIL&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--replace-all&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user.name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;GIT_USER&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--replace-all&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTA: a flag &lt;code&gt;--replace-all&lt;/code&gt; irá substituir todas as configurações anteriores.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Altere &lt;code&gt;&amp;lt;GIT_EMAIL&amp;gt;&lt;/code&gt; e &lt;code&gt;&amp;lt;GIT_USER&amp;gt;&lt;/code&gt; para os seus respectivos valores.&lt;/p&gt;

&lt;p&gt;Opcional:&lt;/p&gt;

&lt;p&gt;Eu costumo armazenar as credenciais usando o helper &lt;strong&gt;store&lt;/strong&gt;, essa configuração evita que uma janela de credenciais seja aberta a cada interação com o repositório remoto.&lt;/p&gt;

&lt;p&gt;Caso você queira usar a mesma configuração, execute o comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;credential.helper&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Veja mais em: &lt;a href="https://git-scm.com/docs/git-credential-store"&gt;https://git-scm.com/docs/git-credential-store&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note que todos os comandos, servirão apenas para o repositório atual, caso queira essa configuração em outros repositórios, basta repetir o processo nos repositórios desejados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selecionando os commits para alteração
&lt;/h2&gt;

&lt;p&gt;O &lt;a href="https://git-scm.com/docs/git-rebase"&gt;git-rebase&lt;/a&gt; é uma ferramenta poderosíssima, que nos permite alterar a linha do tempo sem ser necessário gerar novas ramificações. Com isso é possível juntar commits, reordenar, removê-los, e um bocado de outras coisas. &lt;/p&gt;

&lt;p&gt;Vamos utilizá-lo para selecionar os commits!&lt;/p&gt;

&lt;p&gt;Se você quer alterar todos os commits, desde o primeiro, basta executar o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;rebase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--root&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Caso queira alterar apenas os 3 ou N últimos commits, basta utilizar o comando &lt;code&gt;git rebase -i HEAD~3&lt;/code&gt; ou &lt;code&gt;git rebase -i HEAD~n&lt;/code&gt;, sendo &lt;code&gt;n&lt;/code&gt; o número de commits que deseja alterar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Isso abrirá um arquivo chamado &lt;code&gt;git-rebase-todo&lt;/code&gt;, que é exatamente ali onde informaremos o que queremos fazer com os commits, e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;pick&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;687f049&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;foo:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;pick&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;25a798a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fooz:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;barz&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Rebase f157872..25a798a onto f157872 (2 commands)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Commands:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# p, pick &amp;lt;commit&amp;gt; = use commit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# e, edit &amp;lt;commit&amp;gt; = use commit, but stop for amending&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# s, squash &amp;lt;commit&amp;gt; = use commit, but meld into previous commit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# f, fixup &amp;lt;commit&amp;gt; = like "squash", but discard this commit's log message&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# x, exec &amp;lt;command&amp;gt; = run command (the rest of the line) using shell&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# b, break = stop here (continue rebase later with 'git rebase --continue')&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# d, drop &amp;lt;commit&amp;gt; = remove commit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# l, label &amp;lt;label&amp;gt; = label current HEAD with a name&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# t, reset &amp;lt;label&amp;gt; = reset HEAD to a label&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# m, merge [-C &amp;lt;commit&amp;gt; | -c &amp;lt;commit&amp;gt;] &amp;lt;label&amp;gt; [# &amp;lt;oneline&amp;gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# .       create a merge commit using the original merge commit's&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# .       message (or the oneline, if no original merge commit was&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# .       specified). Use -c &amp;lt;commit&amp;gt; to reword the commit message.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# These lines can be re-ordered; they are executed from top to bottom.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# If you remove a line here THAT COMMIT WILL BE LOST.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# However, if you remove everything, the rebase will be aborted.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Note that empty commits are commented out&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No nosso caso, iremos substituir &lt;code&gt;pick&lt;/code&gt; por &lt;code&gt;edit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- pick 687f049 foo: bar
&lt;/span&gt;&lt;span class="gi"&gt;+ edit 687f049 foo: bar
&lt;/span&gt;&lt;span class="gd"&gt;- pick 25a798a fooz: barz
&lt;/span&gt;&lt;span class="gi"&gt;+ edit 25a798a fooz: barz
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos então, salvar a edição do arquivo, e fechá-lo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alterando o autor
&lt;/h2&gt;

&lt;p&gt;No terminal, veremos a seguinte saída após fechar o arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;You can amend the commit now, with

  git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; 

Once you are satisfied with your changes, run

  git rebase &lt;span class="nt"&gt;--continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beleza! Estamos prontos.&lt;/p&gt;

&lt;p&gt;Para cada um dos commits, iremos alterar o autor, com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--amend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;GIT_USER&amp;gt; &amp;lt;&amp;lt;GIT_EMAIL&amp;gt;&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--no-edit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# e.g.: git commit --amend --author="Lorem Ipsum &amp;lt;lorem@ipsum.com&amp;gt;" --no-edit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Altere &lt;code&gt;&amp;lt;GIT_EMAIL&amp;gt;&lt;/code&gt; e &lt;code&gt;&amp;lt;GIT_USER&amp;gt;&lt;/code&gt; para os seus respectivos valores.&lt;/p&gt;

&lt;p&gt;Após isso, você deve continuar para o próximo commit, que selecionou na edição do &lt;code&gt;git-rebase-todo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;rebase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--continue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse processo ocorre para cada commit. Quando finalizado, o &lt;em&gt;rebasing&lt;/em&gt; é concluído.&lt;/p&gt;

&lt;p&gt;Aqui é importante observar que, você não conseguirá enviar de volta os commits modificados com apenas o comando &lt;code&gt;git push&lt;/code&gt;. Isso porque estamos reescrevendo a nossa linha do tempo, isso significa que devemos substituir a branch atual que existe lá no remoto.&lt;/p&gt;

&lt;p&gt;Para isso, devemos usar a flag &lt;code&gt;--force&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--force&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  E Voilà!
&lt;/h2&gt;

&lt;p&gt;Alteramos o autor dos commits lá do repositório e ainda garantimos que os próximos commits sejam criados com o usuário correto!&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalizando…
&lt;/h2&gt;

&lt;p&gt;Bem, é isso, por hoje, é só!&lt;/p&gt;

&lt;p&gt;Quero agradecer a você que chegou até aqui, e queria lhe pedir também para encaminhar-me as suas dúvidas, comentários, críticas, correções ou sugestões sobre a postagem.&lt;/p&gt;

&lt;p&gt;Deixe seu ❤️ se gostou ou um 🦄 se esse post te ajudou de alguma maneira! Não se esqueça de ver os posts anteriores e me siga para maaaais conteúdos.&lt;/p&gt;

&lt;p&gt;Até!&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Drops #01: Corrigindo vulnerabilidades em dependências com Yarn! (ou quase)</title>
      <dc:creator>William Queiroz</dc:creator>
      <pubDate>Thu, 02 Jul 2020 20:03:20 +0000</pubDate>
      <link>https://dev.to/wnqueiroz/drops-01-corrigindo-vulnerabilidades-em-dependencias-com-yarn-ou-quase-2e2p</link>
      <guid>https://dev.to/wnqueiroz/drops-01-corrigindo-vulnerabilidades-em-dependencias-com-yarn-ou-quase-2e2p</guid>
      <description>&lt;p&gt;&lt;em&gt;Photo by Alexander Sinn on &lt;a href="https://unsplash.com/photos/KgLtFCgfC28" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;E ae dev, tudo bem com você?&lt;/p&gt;

&lt;p&gt;Esse post foi originado lá no meu &lt;a href="https://medium.com/@wnqueiroz" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;, estou migrando-o para cá, pois adotarei o &lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt; por diversas vantagens em relação ao Medium (o suporte ao Markdown me venceu heauehau).&lt;/p&gt;

&lt;p&gt;Bora pro post?&lt;/p&gt;

&lt;p&gt;Ah! mas antes disso... Esse post faz parte de uma série de artigos "drops" que tenho aqui! Veja a lista:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-01-corrigindo-vulnerabilidades-em-dependencias-com-yarn-ou-quase-2e2p"&gt;Drops #01: Corrigindo vulnerabilidades em dependências com Yarn! (ou quase)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-02-como-alterar-o-autor-do-commit-depois-do-push-2mgg"&gt;Drops #02: Como alterar o autor do commit depois do push&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-03-usando-aliases-para-importacao-de-modulos-em-typescript-1fe9"&gt;Drops #03: Usando aliases para importação de módulos em TypeScript!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/wnqueiroz/drops-04-desmistificando-ponteiros-no-golang-3kj9"&gt;Drops #04: Desmistificando ponteiros no Golang!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Fala pessoal!! Quanto tempo!&lt;/p&gt;

&lt;p&gt;Alguns dias atrás, acessei o repositório de um exemplo que usei no post: &lt;a href="https://medium.com/reactbrasil/entendendo-a-context-api-do-react-criando-um-componente-de-loading-a84f84007dc7" rel="noopener noreferrer"&gt;Entendendo a Context API do React: criando um componente de loading&lt;/a&gt; e me deparei com isso:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzii4aerv2j5a3ljaz853.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzii4aerv2j5a3ljaz853.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eu precisava então atualizar as dependências desse projeto lá no meu &lt;a href="https://github.com/wnqueiroz" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. E como tenho utilizado o &lt;a href="https://classic.yarnpkg.com/en/" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt; como gerenciador de pacotes principal, quis fazer o processo de correção com ele.&lt;/p&gt;

&lt;p&gt;Até aí, BELEZA.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuxw30r4x1poig3rmzerm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuxw30r4x1poig3rmzerm.gif" alt="PLOT TWIST!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Entretanto, notei que o Yarn até possui um script para executar a auditoria das dependências do projeto, porém, não inclui a atualização &lt;strong&gt;automática&lt;/strong&gt; e &lt;strong&gt;transparente&lt;/strong&gt; delas (assim como o NPM faz com o &lt;code&gt;npm audit fix&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Se você executar no seu terminal o script &lt;code&gt;yarn audit --help&lt;/code&gt;, verá que de fato não existe um script que corrija automaticamente as dependências com vulnerabilidades…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Você pode ler mais sobre o comando audit do Yarn em: &lt;a href="https://classic.yarnpkg.com/en/docs/cli/audit" rel="noopener noreferrer"&gt;https://classic.yarnpkg.com/en/docs/cli/audit&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Existem algumas &lt;em&gt;issues&lt;/em&gt; no repositório do Yarn, solicitando o recurso e etc. Não vou entrar tanto em detalhes, mas você pode dar uma olhada começando por aqui: &lt;a href="https://github.com/yarnpkg/yarn/issues/5808" rel="noopener noreferrer"&gt;https://github.com/yarnpkg/yarn/issues/5808&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Troubleshoot
&lt;/h2&gt;

&lt;p&gt;A ideia aqui é aproveitar o script do NPM, e ainda assim continuar utilizando o Yarn como o gerenciador principal dos seus pacotes.&lt;/p&gt;

&lt;p&gt;Inicialmente, vamos obter apenas &lt;code&gt;package-lock.json&lt;/code&gt; que o NPM gera ao instalar as dependências (mais à frente explicarei o porque disso):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--package-lock-only&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Então utilizaremos o script &lt;code&gt;npm audit fix&lt;/code&gt;. Ele utilizará o &lt;code&gt;package-lock.json&lt;/code&gt; gerado:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fix&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;O comando atualizará a dependências &lt;strong&gt;passíveis de atualização&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;E o que eu quero dizer com isso? O comando é capaz de identificar possíveis &lt;em&gt;breaking changes&lt;/em&gt; que impactam diretamente o seu projeto. Você talvez veja na saída do terminal algo como:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"x" vulnerabilities required manual review and could not be updated&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Você pode usar a flag &lt;code&gt;-- force&lt;/code&gt;, porém, o NPM irá avisá-lo: &lt;strong&gt;&lt;em&gt;I sure hope you know what you are doing&lt;/em&gt;&lt;/strong&gt; HAHA &lt;br&gt;&lt;br&gt; Veja mais sobre em: &lt;a href="https://docs.npmjs.com/cli/audit" rel="noopener noreferrer"&gt;https://docs.npmjs.com/cli/audit&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ainda não terminamos! Até então, temos o arquivo &lt;code&gt;package-lock.json&lt;/code&gt; criado e, possivelmente, o &lt;code&gt;package.json&lt;/code&gt; modificado no projeto. O &lt;em&gt;lock&lt;/em&gt; de dependências de um projeto que utiliza o Yarn como gerenciador, é o arquivo &lt;code&gt;yarn.lock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O que faremos aqui, é gerar esse arquivo a partir do nosso &lt;code&gt;package-lock.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F313f22g1gc11tpp5r29i.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F313f22g1gc11tpp5r29i.gif" alt="PLOT TWIST!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Antes de executar o comando a seguir, remova o arquivo &lt;code&gt;yarn.lock&lt;/code&gt; para não termos algum problema na criação do novo arquivo com o &lt;code&gt;yarn import&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;yarn.lock&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;yarn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;import&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Veja mais sobre em: &lt;a href="https://classic.yarnpkg.com/en/docs/cli/import/" rel="noopener noreferrer"&gt;https://classic.yarnpkg.com/en/docs/cli/import/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  E Voilà!
&lt;/h2&gt;

&lt;p&gt;Temos o &lt;code&gt;yarn.lock&lt;/code&gt; fresquinho, com as correções feitas pelo NPM, e prontinho para ser versionado!&lt;/p&gt;

&lt;p&gt;Ah! Não esqueça de remover o &lt;code&gt;package-lock.json&lt;/code&gt; gerado lá no início.&lt;/p&gt;

&lt;h1&gt;
  
  
  Finalizando…
&lt;/h1&gt;

&lt;p&gt;Bem, é isso, por hoje, é só!&lt;/p&gt;

&lt;p&gt;Quero agradecer a você que chegou até aqui, e queria lhe pedir também para encaminhar-me as suas dúvidas, comentários, críticas, correções ou sugestões sobre a postagem.&lt;/p&gt;

&lt;p&gt;Deixe seu ❤️ se gostou e me siga para mais conteúdos.&lt;/p&gt;

&lt;p&gt;Até!&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>security</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
