<?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: Jorge Soares</title>
    <description>The latest articles on DEV Community by Jorge Soares (@kurybr).</description>
    <link>https://dev.to/kurybr</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%2F162223%2F093d8d26-e57d-4fc6-8771-51e0129d1692.png</url>
      <title>DEV Community: Jorge Soares</title>
      <link>https://dev.to/kurybr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kurybr"/>
    <language>en</language>
    <item>
      <title>Entendendo o Padrão RRULE do iCalendar com JavaScript</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Wed, 18 Sep 2024 18:56:14 +0000</pubDate>
      <link>https://dev.to/kurybr/entendendo-o-padrao-rrule-do-icalendar-com-javascript-ip0</link>
      <guid>https://dev.to/kurybr/entendendo-o-padrao-rrule-do-icalendar-com-javascript-ip0</guid>
      <description>&lt;p&gt;Fala pessoas, tudo bem? &lt;/p&gt;

&lt;p&gt;Hoje vamos mergulhar em um assunto que pode parecer meio obscuro à primeira vista, mas que é super útil quando falamos de agendas e calendários: o padrão RRULE do iCalendar. E, claro, vamos ver como podemos aplicar isso usando JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o iCalendar e o RRULE?
&lt;/h2&gt;

&lt;p&gt;Vamos começar do começo: o que é esse tal de iCalendar? O iCalendar, também conhecido como RFC 5545, é um padrão para o intercâmbio de dados de calendário e agendamento. Em outras palavras, é uma forma padronizada de representar eventos, tarefas, informações de disponibilidade, etc., de modo que diferentes sistemas possam entender e processar essas informações.&lt;/p&gt;

&lt;p&gt;Isso permite que aplicativos como Google Calendar, Apple Calendar, Outlook e muitos outros possam importar e exportar eventos e agendas sem que você tenha que fazer nenhum malabarismo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Por que o iCalendar é importante?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Interoperabilidade: Como é um padrão amplamente adotado, usar o iCalendar garante que sua aplicação possa se comunicar com uma variedade de outros sistemas e serviços.&lt;/li&gt;
&lt;li&gt;Padronização: Evita a necessidade de criar formatos proprietários ou customizados para lidar com dados de calendário.&lt;/li&gt;
&lt;li&gt;Flexibilidade: Suporta uma ampla gama de funcionalidades, desde eventos simples até regras complexas de recorrência.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Onde entra o RRULE?
&lt;/h2&gt;

&lt;p&gt;O que torna o iCalendar realmente poderoso é a capacidade de definir regras de recorrência usando o RRULE (Recurrence Rule). Isso permite que você especifique eventos que se repetem de acordo com padrões específicos, como “toda segunda quarta-feira do mês” ou “a cada dois dias”.&lt;/p&gt;

&lt;p&gt;Imagina que você está criando uma aplicação de agenda e quer que ela seja compatível com outros serviços. Usar o RRULE garante que as regras de recorrência que você define serão entendidas por outros sistemas que também suportam o iCalendar.&lt;/p&gt;

&lt;p&gt;Além disso, lidar com eventos recorrentes manualmente pode ser um pesadelo. O RRULE simplifica isso ao permitir que você defina uma regra que gera todas as ocorrências para você.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como funciona o RRULE?
&lt;/h2&gt;

&lt;p&gt;O RRULE é basicamente uma string que segue um formato específico para descrever a recorrência. Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FREQ=DAILY;COUNT=5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso significa que o evento se repete diariamente por 5 vezes.&lt;/p&gt;

&lt;p&gt;Principais parâmetros do RRULE:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FREQ: Frequência da recorrência (DAILY, WEEKLY, MONTHLY, YEARLY)&lt;/li&gt;
&lt;li&gt;INTERVAL: Intervalo entre as recorrências&lt;/li&gt;
&lt;li&gt;COUNT: Número total de ocorrências&lt;/li&gt;
&lt;li&gt;UNTIL: Data final da recorrência&lt;/li&gt;
&lt;li&gt;BYDAY: Dias da semana em que o evento ocorre&lt;/li&gt;
&lt;li&gt;BYMONTHDAY: Dias do mês em que o evento ocorre&lt;/li&gt;
&lt;li&gt;BYMONTH: Meses em que o evento ocorre&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Exemplos de RRULE&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Evento semanal às segundas e quartas por 10 ocorrências:&lt;/span&gt;
&lt;span class="nv"&gt;FREQ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;WEEKLY&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;BYDAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;MO,WE&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10
&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;&lt;span class="c"&gt;# Evento anual no dia 25 de dezembro até 2025:&lt;/span&gt;
&lt;span class="nv"&gt;FREQ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YEARLY&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;BYMONTH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;12&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;BYMONTHDAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;25&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;UNTIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20251225T000000Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usando o RRULE com JavaScript
&lt;/h2&gt;

&lt;p&gt;Agora, vamos ver como podemos manipular o RRULE em uma aplicação JavaScript. Para isso, podemos usar bibliotecas como a rrule.js.&lt;/p&gt;

&lt;h3&gt;
  
  
  Instalando a biblioteca
&lt;/h3&gt;

&lt;p&gt;Se você estiver usando Node.js, pode instalar com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;rrule
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Exemplo Prático
&lt;/h3&gt;

&lt;p&gt;Digamos que queremos criar um evento que ocorre toda terça e quinta às 10h, pelos próximos 2 meses.&lt;br&gt;
&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;RRule&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="s1"&gt;rrule&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Definindo a regra&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rule&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;RRule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RRule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WEEKLY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;byweekday&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RRule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TU&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RRule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TH&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;dtstart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="na"&gt;until&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Obtendo as datas das ocorrências&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&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="nx"&gt;dates&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse código vai gerar todas as datas em que o evento ocorre, respeitando a regra que definimos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Convertendo para String RRULE
&lt;/h3&gt;

&lt;p&gt;Se você precisar da string RRULE para, por exemplo, salvar no banco de dados ou enviar para outro serviço, pode fazer:&lt;br&gt;
&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="nx"&gt;rruleString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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="nx"&gt;rruleString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso vai retornar algo como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,TH;UNTIL=20231217T100000Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Interpretando uma String RRULE
&lt;/h3&gt;

&lt;p&gt;Se você receber uma string RRULE e quiser interpretá-la em JavaScript, também é possível:&lt;br&gt;
&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;RRule&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="s1"&gt;rrule&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;rruleString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FREQ=DAILY;COUNT=5&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;rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;RRule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rruleString&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;dates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&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="nx"&gt;dates&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integrando com outros Serviços
&lt;/h3&gt;

&lt;p&gt;Uma vez que você tem a string RRULE, pode integrá-la com APIs que suportam o iCalendar. Por exemplo, ao criar um evento no Google Calendar via API, você pode incluir a regra de recorrência.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo com Google Calendar API&lt;/strong&gt;&lt;br&gt;
&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="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Reunião Semanal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023-10-01T10:00:00-03:00&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;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023-10-01T11:00:00-03:00&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;recurrence&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="s1"&gt;RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20231231T235959Z&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="c1"&gt;// Código para inserir o evento usando a API do Google Calendar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Considerações Finais
&lt;/h2&gt;

&lt;p&gt;Compreender o padrão iCalendar e, em especial, o &lt;strong&gt;RRULE&lt;/strong&gt;, é um passo fundamental para quem desenvolve aplicações que lidam com calendários e agendamento. Além de facilitar a interoperabilidade entre diferentes sistemas, você oferece aos usuários uma experiência mais consistente e integrada.&lt;/p&gt;

&lt;p&gt;Ao incorporar o RRULE em suas aplicações JavaScript, você não apenas simplifica o gerenciamento de eventos recorrentes, mas também garante que suas soluções sejam escaláveis e compatíveis com padrões amplamente aceitos no mercado.&lt;/p&gt;

&lt;p&gt;Seja você um desenvolvedor iniciante ou experiente, explorar e dominar esses padrões pode abrir portas para projetos mais complexos e interessantes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Links de Referência
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tools.ietf.org/html/rfc5545" rel="noopener noreferrer"&gt;Documentação Oficial do iCalendar (RFC 5545)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jakubroztocil/rrule" rel="noopener noreferrer"&gt;Biblioteca rrule.js no GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/calendar/api/concepts/events-calendars#recurring_events" rel="noopener noreferrer"&gt;Uso do RRULE na API do Google Calendar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html" rel="noopener noreferrer"&gt;Exemplos de RRULE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Espero que este artigo tenha ajudado a esclarecer o uso do RRULE no iCalendar. Se tiver alguma dúvida ou sugestão, fique à vontade para deixar um comentário!&lt;/p&gt;

&lt;p&gt;Até a próxima! 👋&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>rrule</category>
      <category>icalendar</category>
      <category>kurybr</category>
    </item>
    <item>
      <title>Usando Robo3t (robomongo) no Ubuntu 23.04</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Fri, 13 Oct 2023 12:21:36 +0000</pubDate>
      <link>https://dev.to/kurybr/usando-robo3t-robomongo-no-ubuntu-2304-1mf6</link>
      <guid>https://dev.to/kurybr/usando-robo3t-robomongo-no-ubuntu-2304-1mf6</guid>
      <description>&lt;p&gt;Criei um script para conseguir usar o Robo3T (legado) no Ubuntu, pois estava enfrentado problemas com o Studio 3t.&lt;/p&gt;

&lt;p&gt;Vou postar aqui apenas para guardar isso para o futuro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://github.com/Studio3T/robomongo/releases/download/v1.4.4/robo3t-1.4.4-linux-x86_64-e6ac9ec.tar.gz
&lt;span class="nb"&gt;sudo &lt;/span&gt;wget https://dashboard.snapcraft.io/site_media/appmedia/2018/09/logo-256x256.png &lt;span class="nt"&gt;-O&lt;/span&gt; /opt/robo3t-1.4.4-linux-x86_64-e6ac9ec/icon.png
&lt;span class="nb"&gt;sudo tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; robo3t-1.4.4-linux-x86_64-e6ac9ec.tar.gz &lt;span class="nt"&gt;-C&lt;/span&gt; /opt
&lt;span class="nb"&gt;rm &lt;/span&gt;robo3t-1.4.4-linux-x86_64-e6ac9ec.tar.gz
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; /opt/robo3t-1.4.4-linux-x86_64-e6ac9ec/lib/BKP/
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /opt/robo3t-1.4.4-linux-x86_64-e6ac9ec/lib/libstdc++&lt;span class="k"&gt;*&lt;/span&gt; /opt/robo3t-1.4.4-linux-x86_64-e6ac9ec/lib/BKP/
&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /opt/robo3t-1.4.4-linux-x86_64-e6ac9ec/bin/robo3t /usr/bin/robo3t
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.local/share/applications/robo3t.desktop &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOL&lt;/span&gt;&lt;span class="sh"&gt;
[Desktop Entry]
Encoding=UTF-8
Name=Robo3T
Icon=/opt/robo3t-1.4.4-linux-x86_64-e6ac9ec/icon.png
Exec=robo3t
Terminal=false
Type=Application
Categories=Development;
&lt;/span&gt;&lt;span class="no"&gt;EOL
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>robo3t</category>
      <category>robomongo</category>
      <category>studio3t</category>
      <category>kurybr</category>
    </item>
    <item>
      <title>Configurando o OpenVPN 2.4.7 no Ubuntu 23.04</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Tue, 10 Oct 2023 18:35:27 +0000</pubDate>
      <link>https://dev.to/kurybr/configurando-o-openvpn-247-no-ubuntu-2304-3aie</link>
      <guid>https://dev.to/kurybr/configurando-o-openvpn-247-no-ubuntu-2304-3aie</guid>
      <description>&lt;p&gt;Olá, pessoal! Hoje vou compartilhar um método eficaz para configurar o OpenVPN 2.4.7 no Ubuntu 20.04. Vamos lá? 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalação Manual
&lt;/h2&gt;

&lt;p&gt;Desinstalando a versão atual do OpenVPN (se instalada):&lt;br&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;sudo &lt;/span&gt;apt remove OpenVPN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Instalando o binário libssl1.1:
&lt;/h3&gt;

&lt;p&gt;Acesse o &lt;a href="https://launchpad.net/ubuntu/focal/amd64/libssl1.1/1.1.1f-1ubuntu2.12"&gt;link&lt;/a&gt;&lt;br&gt;
Baixe o arquivo &lt;strong&gt;libssl1.1_1.1.1f-1ubuntu2.12_amd64.deb&lt;/strong&gt; na seção "Downloadable files"&lt;br&gt;
Dê um duplo clique no arquivo e abra com o Software Install (GUI)&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Instalando o OpenVPN 2.4.7:
&lt;/h3&gt;

&lt;p&gt;Acesse o &lt;a href="https://launchpad.net/ubuntu/focal/amd64/openvpn/2.4.7-1ubuntu2.20.04.4"&gt;link&lt;/a&gt;&lt;br&gt;
Baixe o arquivo &lt;strong&gt;openvpn_2.4.7-1ubuntu2.20.04.4_amd64.deb&lt;/strong&gt; na seção "Downloadable files"&lt;br&gt;
Dê um duplo clique no arquivo e abra com o Software Install (GUI)&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Reinstalando o NetworkManager OpenVPN GUI:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;network-manager-openvpn-gnome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Nota: As etapas 1 e 4 devem ser executadas como um comando no terminal. Isso requer que você tenha as permissões adequadas e deve conhecer o nome de usuário e senha da sua máquina local.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Além disso, para as etapas 2 e 3, após baixar os pacotes .deb, você pode dar um duplo clique neles no Nautilus/gerenciador de arquivos e selecionar "Software Install" como a opção necessária para abrir o pacote.&lt;/p&gt;

&lt;p&gt;Por último, mas não menos importante, é fundamental seguir estas etapas na ordem em que são apresentadas, caso contrário, o processo falhará.&lt;/p&gt;



&lt;p&gt;Espero que este guia tenha sido útil para você. Fique à vontade para compartilhar suas experiências nos comentários abaixo e até a próxima! 😊&lt;/p&gt;

&lt;p&gt;Este artigo foi baseado em uma resposta no Stackoverflow que pode ser encontrada aqui &lt;a href="https://askubuntu.com/a/1406472"&gt;https://askubuntu.com/a/1406472&lt;/a&gt;&lt;br&gt;
traduzido para o português.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Artigo editado pelo ChatGPT&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: Update&lt;br&gt;
Pra facilitar fiz um script para não precisar fazer manualmente esse processo&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt remove openvpn -y
curl -O https://launchpad.net/~ubuntu-security-proposed/+archive/ubuntu/ppa/+build/23493657/+files/openvpn_2.4.7-1ubuntu2.20.04.4_amd64.deb
sudo dpkg -i openvpn_2.4.7-1ubuntu2.20.04.4_amd64.deb
rm openvpn_2.4.7-1ubuntu2.20.04.4_amd64.deb
sudo apt install network-manager-openvpn-gnome  -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>openvpn</category>
      <category>vpn</category>
      <category>kurybr</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Nginx, SSL e mTLS: Um Guia Prático para Criar um Ambiente mais seguro</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Mon, 25 Sep 2023 17:28:11 +0000</pubDate>
      <link>https://dev.to/kurybr/nginx-e-ssl-um-guia-pratico-para-criar-um-ambiente-https-local-parte-1-56hg</link>
      <guid>https://dev.to/kurybr/nginx-e-ssl-um-guia-pratico-para-criar-um-ambiente-https-local-parte-1-56hg</guid>
      <description>&lt;p&gt;Olaaaaaa pessoas, muito boa tarde/manhã/noite, espero que vocês estejam bem. &lt;/p&gt;

&lt;p&gt;Trilha sonora enquanto eu escrevia esse artigo: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://open.spotify.com/intl-pt/track/5dpDnd3Nnw5dRql80RcI7M?si=41eec3a4d5eb45e9" rel="noopener noreferrer"&gt;https://open.spotify.com/intl-pt/track/5dpDnd3Nnw5dRql80RcI7M?si=41eec3a4d5eb45e9&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Neste artigo, vamos fornecer um combo de informações. Aprenderemos desde a configuração de um servidor HTTPS usando o Nginx, passando pela criação de um certificado autoassinado e, por fim, configuraremos o mesmo servidor para ser um Mutual TLS ou apenas mTLS. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: Nesta primeira parte, aprenderemos como configurar um ambiente HTTPS usando o Nginx.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para este tutorial, estou usando o Docker com o Docker Compose para orquestrar nosso ambiente local, facilitando assim o processo de configuração do ambiente. Afinal, em 2023, ninguém mais configura um servidor Nginx diretamente na máquina.&lt;/p&gt;

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

&lt;p&gt;Começaremos criando nosso diretório de projeto:&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;projeto-mtls


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

&lt;/div&gt;

&lt;p&gt;Dentro da pasta, criaremos um arquivo docker-compose.yaml e uma pasta nginx que conterá tudo relacionado ao nosso servidor:&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;cd &lt;/span&gt;projeto-mtls
&lt;span class="nb"&gt;touch &lt;/span&gt;docker-compose.yaml &lt;span class="c"&gt;# Arquivo do ambiente docker nosso.&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;nginx &lt;span class="c"&gt;# Pasta que vai guardar tudo relacionado ao nginx&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;nginx/certs &lt;span class="c"&gt;# Pasta que vai guardar nossos certificados.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Feito isso, agora começaremos a configurar nosso servidor.&lt;/p&gt;

&lt;p&gt;Vamos criar um arquivo nginx.conf:&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;touch &lt;/span&gt;nginx.conf


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

&lt;/div&gt;

&lt;p&gt;Nele, configuraremos um servidor "simples" que retornará uma página HTML quando acessado em &lt;a href="http://localhost:" rel="noopener noreferrer"&gt;http://localhost:&lt;/a&gt;&lt;/p&gt;

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

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="nc"&gt;text/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;!DOCTYPE&lt;/span&gt; &lt;span class="s"&gt;html&amp;gt;&amp;lt;h2&amp;gt;Hello&lt;/span&gt; &lt;span class="s"&gt;World!&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;n"&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;Agora, para testarmos se tudo está funcionando, configuraremos nosso docker-compose.yaml da seguinte forma:&lt;/p&gt;

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

&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;proxy-mtls&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/nginx.conf:/etc/nginx/conf.d/default.conf&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/certs:/etc/nginx/certs&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sandbox&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sandbox&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Mapearemos a pasta nginx para dentro do container, para que as configurações e certificados sejam acessíveis no servidor:&lt;/p&gt;

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

docker-compose up &lt;span class="c"&gt;# Inicializa os containers do Docker Compose.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Com o servidor ativo, acesse &lt;a href="http://localhost:" rel="noopener noreferrer"&gt;http://localhost:&lt;/a&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%2Fuploads%2Farticles%2Fyix64mg6hbknhmxzpvzp.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%2Fyix64mg6hbknhmxzpvzp.png" alt="Página HTML, com o texto "&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Agora que temos nosso servidor HTTP, precisamos configurar o SSL para começarmos a usar HTTPS nas requisições.&lt;/p&gt;

&lt;p&gt;Para isso, precisamos gerar um certificado autoassinado.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: Um certificado digital normalmente requer uma autoridade de certificação (CA) para validar sua autenticidade. No entanto, em casos de desenvolvimento, podemos atuar como a própria CA e assinar nosso próprio certificado, conhecido como "certificado autoassinado". Esse tipo de certificado não é válido em produção, mas é suficiente para ambientes de desenvolvimento.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Gerando a chave privada do certificado
&lt;/h3&gt;

&lt;p&gt;Para gerar nosso certificado, usaremos o utilitário OpenSSL, amplamente utilizado para criptografia e segurança. Utilizaremos o comando a seguir para gerar uma chave privada:&lt;/p&gt;

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

openssl genpkey &lt;span class="nt"&gt;-algorithm&lt;/span&gt; RSA &lt;span class="nt"&gt;-out&lt;/span&gt; certs/localhost.key


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

&lt;/div&gt;

&lt;p&gt;Este comando utiliza o algoritmo RSA, amplamente empregado em sistemas de segurança, como SSL/TLS, para criptografar comunicações na web. O resultado será salvo em certs/localhost.key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gerando a Solicitação de Assinatura de Certificado (CSR)
&lt;/h3&gt;

&lt;p&gt;Agora, usaremos o OpenSSL para gerar uma Solicitação de Assinatura de Certificado (CSR):&lt;/p&gt;

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

openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; certs/localhost.key &lt;span class="nt"&gt;-out&lt;/span&gt; certs/localhost.csr


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

&lt;/div&gt;

&lt;p&gt;Essa solicitação contém informações necessárias para emitir nosso certificado. Informamos a chave privada a ser usada (certs/localhost.key) e o arquivo de saída (certs/localhost.csr).&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%2Fgh46x2opxaxv52r4sw0u.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%2Fgh46x2opxaxv52r4sw0u.png" alt="Tela do terminal, com as informações necessárias para gerar um CSR"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ao executar esse comando, você precisará fornecer várias informações sobre a autoridade do certificado e detalhes de contato, que serão enviados à CA para autenticar o certificado da empresa.&lt;/p&gt;

&lt;h4&gt;
  
  
  Dica bonus sobre geração de CSR
&lt;/h4&gt;

&lt;p&gt;
  Ver dica
  &lt;p&gt;Se você precisa gerar vários certificados ou deseja ter um "modelo" para facilitar a geração de certificados no futuro, pode criar um arquivo de configuração contendo configurações padrão. Isso agilizará o processo de geração de certificados.&lt;/p&gt;

&lt;p&gt;Vamos criar um arquivo chamado template.csr.conf para ser nosso modelo:&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;touch &lt;/span&gt;template.csr.conf


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

&lt;/div&gt;
&lt;p&gt;Dentro deste arquivo, colocaremos as seguintes informações:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;

[&lt;span class="n"&gt;req&lt;/span&gt;]
&lt;span class="n"&gt;default_bits&lt;/span&gt; = &lt;span class="m"&gt;2048&lt;/span&gt;
&lt;span class="n"&gt;default_keyfile&lt;/span&gt; = &lt;span class="n"&gt;localhost&lt;/span&gt;.&lt;span class="n"&gt;key&lt;/span&gt;
&lt;span class="n"&gt;distinguished_name&lt;/span&gt; = &lt;span class="n"&gt;req_distinguished_name&lt;/span&gt;
&lt;span class="n"&gt;req_extensions&lt;/span&gt; = &lt;span class="n"&gt;req_ext&lt;/span&gt;
&lt;span class="n"&gt;x509_extensions&lt;/span&gt; = &lt;span class="n"&gt;v3_ca&lt;/span&gt;
&lt;span class="n"&gt;req_extensions&lt;/span&gt; = &lt;span class="n"&gt;v3_req&lt;/span&gt;

[&lt;span class="n"&gt;req_distinguished_name&lt;/span&gt;]
&lt;span class="n"&gt;countryName&lt;/span&gt; = &lt;span class="n"&gt;Country&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; (&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;)
&lt;span class="n"&gt;countryName_default&lt;/span&gt; = &lt;span class="n"&gt;BR&lt;/span&gt;
&lt;span class="n"&gt;stateOrProvinceName&lt;/span&gt; = &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;Province&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; (&lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;)
&lt;span class="n"&gt;stateOrProvinceName_default&lt;/span&gt; = &lt;span class="n"&gt;Sao&lt;/span&gt; &lt;span class="n"&gt;Paulo&lt;/span&gt;
&lt;span class="n"&gt;localityName&lt;/span&gt; = &lt;span class="n"&gt;Locality&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; (&lt;span class="n"&gt;eg&lt;/span&gt;, &lt;span class="n"&gt;city&lt;/span&gt;)
&lt;span class="n"&gt;localityName_default&lt;/span&gt; = &lt;span class="n"&gt;Sao&lt;/span&gt; &lt;span class="n"&gt;Paulo&lt;/span&gt;
&lt;span class="n"&gt;organizationName&lt;/span&gt; = &lt;span class="n"&gt;Organization&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; (&lt;span class="n"&gt;eg&lt;/span&gt;, &lt;span class="n"&gt;company&lt;/span&gt;)
&lt;span class="n"&gt;organizationName_default&lt;/span&gt; = &lt;span class="n"&gt;Localhost&lt;/span&gt; &lt;span class="n"&gt;Ltda&lt;/span&gt;
&lt;span class="n"&gt;organizationalUnitName&lt;/span&gt; = &lt;span class="n"&gt;organizationalunit&lt;/span&gt;
&lt;span class="n"&gt;organizationalUnitName_default&lt;/span&gt; = &lt;span class="n"&gt;Development&lt;/span&gt;
&lt;span class="n"&gt;commonName&lt;/span&gt; = &lt;span class="n"&gt;Common&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; (&lt;span class="n"&gt;e&lt;/span&gt;.&lt;span class="n"&gt;g&lt;/span&gt;. &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;FQDN&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;YOUR&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;)
&lt;span class="n"&gt;commonName_default&lt;/span&gt; = &lt;span class="n"&gt;localhost&lt;/span&gt;
&lt;span class="n"&gt;commonName_max&lt;/span&gt; = &lt;span class="m"&gt;64&lt;/span&gt;

[&lt;span class="n"&gt;req_ext&lt;/span&gt;]
&lt;span class="n"&gt;subjectAltName&lt;/span&gt; = @&lt;span class="n"&gt;alt_names&lt;/span&gt;

[&lt;span class="n"&gt;v3_ca&lt;/span&gt;]
&lt;span class="n"&gt;subjectAltName&lt;/span&gt; = @&lt;span class="n"&gt;alt_names&lt;/span&gt;

[&lt;span class="n"&gt;v3_req&lt;/span&gt;]
&lt;span class="n"&gt;basicConstraints&lt;/span&gt; = &lt;span class="n"&gt;CA&lt;/span&gt;:&lt;span class="n"&gt;FALSE&lt;/span&gt;
&lt;span class="n"&gt;keyUsage&lt;/span&gt; = &lt;span class="n"&gt;nonRepudiation&lt;/span&gt;, &lt;span class="n"&gt;digitalSignature&lt;/span&gt;, &lt;span class="n"&gt;keyEncipherment&lt;/span&gt;
&lt;span class="n"&gt;subjectAltName&lt;/span&gt; = @&lt;span class="n"&gt;alt_names&lt;/span&gt;

[&lt;span class="n"&gt;alt_names&lt;/span&gt;]
&lt;span class="n"&gt;DNS&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt; = &lt;span class="m"&gt;127&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;DNS&lt;/span&gt;.&lt;span class="m"&gt;2&lt;/span&gt; = &lt;span class="n"&gt;localhost&lt;/span&gt;


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

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Nota: Eu não vou explicar aqui detalhes sobre esse arquivo, mas um ponto legal é que você pode configurar vários endereços no &lt;code&gt;[alt_names]&lt;/code&gt; para que esse certificado suporte vários dominios.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Agora, execute o comando novamente, mas desta vez passando o arquivo de configuração:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; certs/localhost.key &lt;span class="nt"&gt;-out&lt;/span&gt; certs/localhost.csr &lt;span class="nt"&gt;-config&lt;/span&gt; template.csr.conf


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

&lt;/div&gt;
&lt;p&gt;Observe que, mesmo pedindo que você preencha informações, os dados pré-definidos são os que definimos no nosso modelo, economizando tempo durante o processo.&lt;/p&gt;



&lt;/p&gt;

&lt;h3&gt;
  
  
  Gerando o Certificado Autoassinado
&lt;/h3&gt;

&lt;p&gt;Após criar a chave privada e a solicitação de assinatura de certificado, chegou a hora de atuar como CA e assinar o certificado. Use o seguinte comando:&lt;/p&gt;

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

openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="nt"&gt;-in&lt;/span&gt; certs/localhost.csr &lt;span class="nt"&gt;-signkey&lt;/span&gt; certs/localhost.key &lt;span class="nt"&gt;-out&lt;/span&gt;  certs/localhost.crt


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

&lt;/div&gt;

&lt;p&gt;Este comando gera o certificado a partir da solicitação de assinatura de certificado (CSR). O certificado terá validade de 1 ano e será salvo em certs/localhost.crt.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Entenda o comando: x509 é usado para manipular certificados digitais. -req indica que estamos trabalhando com uma solicitação de assinatura de certificado. -days 365 define a validade do certificado em 1 ano. Os próximos três argumentos (-in, -signkey, -out) especificam o caminho da solicitação de assinatura de certificado, da chave privada e do arquivo de saída.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Testando o SSL
&lt;/h2&gt;

&lt;p&gt;Após gerar o certificado, precisamos testá-lo. Para isso, faremos algumas alterações no nosso arquivo nginx.conf para indicar o uso de HTTPS em vez de HTTP:&lt;/p&gt;

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

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$host$request_uri&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="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/certs/localhost.crt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/certs/localhost.key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="nc"&gt;text/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;!DOCTYPE&lt;/span&gt; &lt;span class="s"&gt;html&amp;gt;&amp;lt;h2&amp;gt;Hello&lt;/span&gt; &lt;span class="s"&gt;World&lt;/span&gt; &lt;span class="s"&gt;with&lt;/span&gt; &lt;span class="s"&gt;HTTPS&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;n"&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;Agora, qualquer requisição para &lt;a href="http://localhost" rel="noopener noreferrer"&gt;http://localhost&lt;/a&gt; será redirecionada para &lt;a href="https://localhost" rel="noopener noreferrer"&gt;https://localhost&lt;/a&gt;. Observe que estamos usando os atributos ssl_certificate e ssl_certificate_key para apontar o certificado e a chave do nosso servidor.&lt;/p&gt;

&lt;p&gt;Salve as alterações e reinicie o servidor:&lt;/p&gt;

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

docker-compose down
docker-compose up


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

&lt;/div&gt;

&lt;p&gt;Ao acessar &lt;a href="https://localhost" rel="noopener noreferrer"&gt;https://localhost&lt;/a&gt;, você receberá um aviso do navegador informando que o certificado de autoridade é inválido.&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%2F2jqnp0gp4uwjhislamd4.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%2F2jqnp0gp4uwjhislamd4.png" alt="Aviso de SSL inválido no navegador Chrome."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isso é esperado, uma vez que nós mesmos assinamos o certificado. Para continuar, clique em "Avançado" e depois em "Prosseguir para localhost (não seguro)".&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%2Fpgisrm99vq0lyvdvxdsj.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%2Fpgisrm99vq0lyvdvxdsj.png" alt="Aviso de SSL inválido"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pronto, agora temos nosso servidor HTTPS funcionando:&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%2F8pj9u4p86lad5ozjldjk.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%2F8pj9u4p86lad5ozjldjk.png" alt="Tela do Chrome, escrita Hello World with HTTPS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Até este ponto, já temos um servidor HTTPS funcionando perfeitamente. Agora, vamos para a parte do Mutual TLS ou mTLS.&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Fechando as Portas com mTLS
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: O mTLS, ou Mutual Transport Layer Security, é uma extensão do protocolo TLS que autentica tanto o cliente quanto o servidor durante a comunicação na internet. Isso é feito por meio da troca de certificados digitais, onde cada parte verifica a identidade da outra. Esse nível adicional de autenticação reforça a segurança da comunicação, especialmente em ambientes sensíveis à segurança, como serviços bancários online e sistemas corporativos, protegendo contra ataques de intermediários mal-intencionados e garantindo uma conexão confiável e criptografada.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para começar, criaremos um certificado para o cliente, seguindo os mesmos passos que fizemos para criar o certificado do servidor:&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;nginx/certs/clients &lt;span class="c"&gt;# Vai guardar o certificado do nosso cliente&lt;/span&gt;


&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;

openssl genpkey &lt;span class="nt"&gt;-algorithm&lt;/span&gt; RSA &lt;span class="nt"&gt;-out&lt;/span&gt; certs/clients/certificado-do-cliente.key
openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; certs/clients/certificado-do-cliente.key &lt;span class="nt"&gt;-out&lt;/span&gt; certs/clients/certificado-do-cliente.csr &lt;span class="nt"&gt;-config&lt;/span&gt; template.csr.conf
openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="nt"&gt;-in&lt;/span&gt; certs/clients/certificado-do-cliente.csr &lt;span class="nt"&gt;-signkey&lt;/span&gt; certs/clients/certificado-do-cliente.key &lt;span class="nt"&gt;-out&lt;/span&gt;  certs/clients/certificado-do-cliente.crt


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

&lt;/div&gt;

&lt;p&gt;Após gerar o certificado do cliente, precisaremos configurar nosso servidor Nginx para trabalhar com mTLS. Para isso, faremos algumas atualizações em nosso arquivo de configuração:&lt;/p&gt;

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


&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/certs/localhost.crt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/certs/localhost.key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_ciphers&lt;/span&gt; &lt;span class="s"&gt;'ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_client_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/certs/clients/certificado-do-cliente.crt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_verify_client&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="nc"&gt;text/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;!DOCTYPE&lt;/span&gt; &lt;span class="s"&gt;html&amp;gt;&amp;lt;h2&amp;gt;Hello&lt;/span&gt; &lt;span class="s"&gt;World&lt;/span&gt; &lt;span class="s"&gt;Secury&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;n"&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;Agora, adicionamos algumas configurações adicionais ao nosso proxy. ssl_client_certificate especifica o certificado do cliente (que o cliente deve usar ao fazer chamadas para o nosso serviço), e ssl_verify_client ativa a verificação.&lt;/p&gt;

&lt;p&gt;Com essa pequena mudança, garantimos que apenas o cliente que possua este certificado conseguirá fazer requisições para nosso ambiente.&lt;/p&gt;

&lt;p&gt;Requisições sem o certificado resultarão em um erro:&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%2Fghnjyhy4u5729y7tr8o2.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%2Fghnjyhy4u5729y7tr8o2.png" alt="Requisição no Postman, sem fechar o MTLS, informando que não foi possível finalizar a chamada"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora, ao passar o certificado na requisição, a chamada será bem-sucedida:&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%2F96lfi9bifx5s33rt9mdr.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%2F96lfi9bifx5s33rt9mdr.png" alt="Página html, escrito Hello World with mTLS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Considerações finais
&lt;/h3&gt;

&lt;p&gt;Espero que este artigo seja útil para quem deseja estudar configurações de ambientes e segurança.&lt;/p&gt;

&lt;p&gt;Até a próxima.&lt;/p&gt;

&lt;p&gt;Se tiver alguma dúvida ou comentário, deixe-os aqui, e vamos compartilhar conhecimento.&lt;/p&gt;

</description>
      <category>ssl</category>
      <category>https</category>
      <category>kurybr</category>
      <category>nginx</category>
    </item>
    <item>
      <title>Draw.io + PlantUML - Como tornar mais fácil o processo de documentação</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Wed, 01 Feb 2023 12:11:15 +0000</pubDate>
      <link>https://dev.to/kurybr/drawio-plantuml-como-tornar-mais-facil-o-processo-de-documentacao-85e</link>
      <guid>https://dev.to/kurybr/drawio-plantuml-como-tornar-mais-facil-o-processo-de-documentacao-85e</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Nota pessoal: A trilha sonora que ouvi enquanto escrevia esse artigo.&lt;br&gt;
&lt;a href="https://open.spotify.com/playlist/0n81ha8dSdYLDVc8VpCPsd?si=70347c8542f44a84" rel="noopener noreferrer"&gt;https://open.spotify.com/playlist/0n81ha8dSdYLDVc8VpCPsd?si=70347c8542f44a84&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;small&gt;Resumo: Nesse artigo, você vai entender um pouco sobre o que é UML, também o que é diagrama de sequencia e por fim veremos um exemplo de como utilizar a ferramenta plantUML junto com o Draw.io para facilitar nossas documentações&lt;/small&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Fala pessoal, a documentação é uma parte fundamental de todo projeto de desenvolvimento, embora nem sempre seja fácil ou divertida. &lt;/p&gt;

&lt;p&gt;Recentemente, descobri que o &lt;a href="https://app.diagrams.net/" rel="noopener noreferrer"&gt;draw.io&lt;/a&gt; possui uma integração com o &lt;a href="https://plantuml.com/" rel="noopener noreferrer"&gt;plantUML&lt;/a&gt;, que pode ser muito útil na criação de Diagramas UML. &lt;/p&gt;

&lt;p&gt;Por isso, resolvi escrever esse artigo para começar uma série sobre como facilitar a documentação de projetos.&lt;/p&gt;

&lt;p&gt;Mas antes de continuar, vamos dar alguns passos para trás e entender um pouco mais sobre o que é UML.&lt;/p&gt;

&lt;p&gt;A UML (do inglês Unified Modeling Language) é a Linguagem de Modelagem Unificada, é uma linguagem-padrão para a elaboração da estrutura de projetos de software. &lt;/p&gt;

&lt;p&gt;É adequada para a modelagem de sistemas, incluindo sistemas corporativos, aplicações baseadas na web e sistemas complexos embutidos em tempo real. &lt;/p&gt;

&lt;p&gt;A UML é uma linguagem expressiva que cobre todas as visões necessárias ao desenvolvimento e implantação de sistemas de software complexos.&lt;/p&gt;

&lt;p&gt;Em resumo, UML é um padrão de escrita para criar diagramas, que tem como objetivo ajudar na documentação e no entendimento das regras de negócio de um projeto no futuro. &lt;/p&gt;

&lt;p&gt;É importante notar que um modelo UML e um diagrama UML são coisas diferentes, o segundo é uma representação gráfica do primeiro.&lt;/p&gt;

&lt;p&gt;Eu adoro ver coisas representadas visualmente, é mais fácil entender um processo ou regra de negócio na minha opinião, quanto mais claro, menos complicado será a hora de colocarmos a ideia em prática.&lt;/p&gt;

&lt;p&gt;Mas conceitos a parte vamos para a parte mais prática.&lt;/p&gt;

&lt;p&gt;Na animação abaixo eu mostro um exemplo &lt;strong&gt;bem&lt;/strong&gt; simples de criação de "fluxo" de autenticação no draw.io, onde o usuário faz o login e logo em seguida ele mostra a tela de boas vindas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fzkhf2o0o97xr0dutu5zf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzkhf2o0o97xr0dutu5zf.gif" alt="Animação mostrando uma criação de fluxo simples" width="1634" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como nós podemos representar esse fluxo utilizando um diagrama de sequencia? &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: O diagrama de sequência é uma ferramenta visual que mostra como diferentes componentes de um sistema se relacionam e comunicam entre si ao longo do tempo. Ele ajuda a entender o fluxo de mensagens entre objetos ou componentes, mostrando quem envia a mensagem, quem a recebe e em que ordem isso acontece. É uma forma simples de ilustrar a ordem de eventos em um processo, e pode ser útil para esclarecer dúvidas sobre a lógica de um sistema ou de um negócio. É como um mapa mental que ajuda a visualizar o funcionamento de algo e a identificar pontos onde pode haver melhorias. Em resumo, o diagrama de sequência é uma ferramenta eficaz para ajudar a compreender o funcionamento de um sistema de maneira visual e fácil de entender.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A imagem abaixo representa como seria esse mesmo fluxo porém em um diagrama de Sequencia perceba que ele é mais detalhado mostrando como que o sistema deve se comportar para que o login do usuário aconteça apesar de ser um diagrama de sequencia ainda é superficial pois nesse caso não informamos quais as informações que devem ser encaminhadas de um ponto ao outro.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fwp4uye89kloky9h57y0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fwp4uye89kloky9h57y0i.png" alt="Animação de um fluxo de diagrama de sequencia simples" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora na imagem abaixo vemos esse mesmo diagrama, porém um pouco mais especificado onde nós conseguimos saber quais os métodos que serão executados em cada momento e quais informações eles devem passar&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fceaxne6ar2bpwargp2o8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fceaxne6ar2bpwargp2o8.png" alt="Animação de um fluxo de diagrama de sequencia complexo" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por exemplo observando a imagem a cima, eu sei que caso no passo &lt;strong&gt;6&lt;/strong&gt; não retorne um usuário &lt;code&gt;( User === null )&lt;/code&gt; ele deve acusar um erro e com isso chamar o metodo &lt;code&gt;HTTPResponse&lt;/code&gt; que irá encaminhar  uma resposta com código 401, e a mensagem "credencial inválida" para a tela de login.&lt;/p&gt;

&lt;p&gt;Perceba que dessa forma a pessoa que for realizar o desenvolvimento desse fluxo consegue de forma clara saber o que está acontecendo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota pessoal: Eu particularmente não gosto de chegar nesse nível de detalhamento, pois na 'vida real' o código é vivo e se altera muito, então acaba tornado obsoleto esse nível de detalhamento muito rápido, e o trade-off começa a ficar caro para manter atualizado a documentação. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pois bem, depois dessa breve explicação da idéia de diagrama de sequência, vamos voltar ao &lt;strong&gt;draw.io&lt;/strong&gt; e como nós podemos construir diagramas de forma simples e rápida nele.&lt;/p&gt;

&lt;p&gt;Para isso iremos usar o &lt;strong&gt;PlantUML&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: O PlantUML é uma ferramenta de geração de diagramas UML (Unified Modeling Language) baseada em texto. É uma forma simples e fácil de representar diagramas UML usando uma sintaxe de marcação simples, e permite a geração automática de diagramas a partir do código. Além de suportar diagramas de classes, sequência, casos de uso, estados, objetos e componentes, PlantUML também suporta vários outros diagramas técnicos e de negócios, tornando-se uma ferramenta versátil e útil para modelagem de sistemas e processos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para acessar o PlantUML dentro do draw.io siga os seguintes passos: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No menu superior vá na opção Arrange&lt;/li&gt;
&lt;li&gt;Logo em seguida Insert&lt;/li&gt;
&lt;li&gt;Depois Advanced&lt;/li&gt;
&lt;li&gt;e por vim Clique em PlantUML&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F850ee42e02jmev27di4m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F850ee42e02jmev27di4m.gif" alt="Figura representado os passos acima" width="1692" height="961"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ao fazer isso irá abrir uma janela com um exemplo de diagrama, clique em "Insert"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F8rjdxcxmolluosw6b1pd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8rjdxcxmolluosw6b1pd.gif" alt="Figura representado os passos acima" width="1692" height="973"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feito isso será renderizado aquele exemplo de diagrama dentro do draw.io.&lt;/p&gt;

&lt;p&gt;Para editar basta clicar duas vezes sobre a imagem e a janela para edição irá abrir novamente. &lt;/p&gt;

&lt;p&gt;Coloque o trecho de código abaixo na janela de edição e clique em "Apply"&lt;br&gt;
&lt;/p&gt;

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

actor       Usuario        as User
boundary    Login          as Login
control     Servidor       as System
database    Banco_de_Dados as DB


User -&amp;gt; Login : document.ready()
Login -&amp;gt; Login : valida_login()

alt user.access_token !== null
    Login -[#green]x Login: redirect()
    note right: Redireciona o usuário para tela de login    
end

User -&amp;gt; Login: autenticar(email: string, senha: string)
Login -&amp;gt; System : usuario_controladora(email: string, senha: string): User
System -&amp;gt; DB: buscar_usuario(email: string, senha: string): User

alt User === null
    rnote over System #FFAAAA: Usuário não foi encontrado\ne deve retornar uma mensagem\nde erro para o usuário.
    DB -[#red]&amp;gt; System: new Error("Usuário não encontrado")
    System -[#red]x Login: HTTPResponse(401, "Credencial inválida")
else
    DB --[#green]&amp;gt; System:
    System -[#green]&amp;gt; Login: HTTPResponse(200, "Usuário lgoado com sucesso")
    note over Login: Usuário deve ser redirecionado para tela de Boas vindas
    Login -[#green]x Login: redirect()
end

@enduml

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

&lt;/div&gt;



&lt;p&gt;O resultado que você terá é o diagrama que foi mostrado ali em cima 😉 &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F2oon9kurzeb8exzctxds.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2oon9kurzeb8exzctxds.gif" alt="Animação de homem simbolizando a cabeça explodindo" width="400" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesse caso o PlantUML serve quase que como uma linguagem de marcação que facilita e MUITO criarmos diagramas com um custo de manutenção muito menor, afinal por ser uma "linguagem" conseguimos editar e utilizar sua sintaxe ao nosso favor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dica bonus:
&lt;/h3&gt;

&lt;p&gt;Existem várias extensões que você pode usar no seu editor de código favorito que ajuda na hora de escrever as descrições no PlantUML como por exemplo para o VSCode encontrei &lt;a href="https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml" rel="noopener noreferrer"&gt;esse aqui&lt;/a&gt; que permite você visualizar uma preview em tempo real enquanto você está escrevendo e caso queira também utilizar o Draw.io dentro do VSCode você pode utilizando esse &lt;a href="https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio" rel="noopener noreferrer"&gt;plugin aqui&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Material de apoio: &lt;br&gt;
&lt;a href="https://plantuml.com/sequence-diagram" rel="noopener noreferrer"&gt;https://plantuml.com/sequence-diagram&lt;/a&gt;&lt;br&gt;
&lt;a href="https://plantuml.com/faq" rel="noopener noreferrer"&gt;https://plantuml.com/faq&lt;/a&gt;&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/PlantUML" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/PlantUML&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pt.wikipedia.org/wiki/Diagrama_de_sequ%C3%AAncia" rel="noopener noreferrer"&gt;https://pt.wikipedia.org/wiki/Diagrama_de_sequ%C3%AAncia&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.lucidchart.com/pages/pt/o-que-e-uml" rel="noopener noreferrer"&gt;https://www.lucidchart.com/pages/pt/o-que-e-uml&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pt.wikipedia.org/wiki/UML" rel="noopener noreferrer"&gt;https://pt.wikipedia.org/wiki/UML&lt;/a&gt;&lt;br&gt;
&lt;a href="https://abapinho.com/2017/09/plantuml-finalmente-o-uml-da-para-usar/" rel="noopener noreferrer"&gt;https://abapinho.com/2017/09/plantuml-finalmente-o-uml-da-para-usar/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>uml</category>
      <category>kurybr</category>
      <category>softwareenginner</category>
      <category>plantuml</category>
    </item>
    <item>
      <title>Keycloak 19.0.1 + Mysql + Docker - Configuração simples de um docker-compose.yaml</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Fri, 29 Jul 2022 20:33:39 +0000</pubDate>
      <link>https://dev.to/kurybr/keycloak-1901-mysql-dockercompose-como-configurar-3an9</link>
      <guid>https://dev.to/kurybr/keycloak-1901-mysql-dockercompose-como-configurar-3an9</guid>
      <description>&lt;p&gt;Oi Pessoal, para configurar uma imagem simples do Keycloak com Mysql vou deixar um exemplo de &lt;code&gt;docker-compose.yaml&lt;/code&gt; para facilitar a vida de vocês&lt;/p&gt;

&lt;p&gt;docker-compose.yaml&lt;/p&gt;

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

&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db_mysql&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:latest&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MYSQL_ROOT_PASSWORD=root_pwd&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MYSQL_USER=admin&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MYSQL_PASSWORD=pa55word&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3306:3306"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.docker/db/mysql:/var/lib/mysql&lt;/span&gt;
  &lt;span class="na"&gt;keycloak&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keycloak&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;quay.io/keycloak/keycloak:19.0.1&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;KEYCLOAK_ADMIN=admin&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;KEYCLOAK_ADMIN_PASSWORD=admin&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;KC_DB=mysql&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;KC_DB_USERNAME=admin&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;KC_DB_PASSWORD=pa55word&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;KC_DB_URL_HOST=db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;KC_DB_URL_PORT=3306&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;KC_DB_SCHEMA=keycloak&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8080:8080&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;start-dev&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Ao subir a imagem do mysql crie um banco chamado &lt;code&gt;keycloak&lt;/code&gt; ele será usado pelo container do Keycloak para salvar as configurações do sistema.&lt;/p&gt;

&lt;p&gt;Caso na primeira vez que subir os containers der o seguinte erro no container do Keycloak  &lt;code&gt;Unknown database 'keycloak'&lt;/code&gt; significa que o keycloak tentou acessar o schema mas ele ainda não tinha sido criado.&lt;/p&gt;

&lt;p&gt;Nesse caso só certifique-se de ter criado o schema no Mysql e rode novamente. &lt;/p&gt;

&lt;p&gt;Se tudo der certo, conseguirá acessar &lt;a href="http://localhost:8080/" rel="noopener noreferrer"&gt;http://localhost:8080/&lt;/a&gt; e agora é só se divertir desbravando.&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%2F1sohzsvrfn4gxi0ulnsi.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%2F1sohzsvrfn4gxi0ulnsi.png" alt="Tela de acesso do Keycloak"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>keycloak</category>
      <category>mysql</category>
      <category>docker</category>
      <category>kurybr</category>
    </item>
    <item>
      <title>Javascript - Prototypes</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Fri, 26 Feb 2021 11:44:13 +0000</pubDate>
      <link>https://dev.to/kurybr/javascript-prototypes-f8g</link>
      <guid>https://dev.to/kurybr/javascript-prototypes-f8g</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Muito provavelmente você já deve ter ouvido falar em algum lugar que &lt;em&gt;"Tudo no javascript é objeto!"&lt;/em&gt;, mas por que isso ? &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Isso se dá porque praticamente tudo dentro do javascript tem descendência do &lt;code&gt;Object&lt;/code&gt; e com isso possuem todos os métodos herdados de &lt;code&gt;Object.prototype&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mas afinal o que é esse &lt;em&gt;prototype&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;O &lt;em&gt;prototype&lt;/em&gt; é um objeto que possui um conjunto de métodos que são originais de um tipo, por exemplo o &lt;code&gt;map()&lt;/code&gt; ou &lt;code&gt;toString()&lt;/code&gt;, que mesmo você não declarando eles na criação da sua variável, ao se deparar com um Array por exemplo eles existem, isso acontece porque quando você declara uma nova variável, você herda as funções do prototype dela.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&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="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&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="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&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="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&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="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você pode perceber que mesmo não declarando essas funções &lt;code&gt;forEach&lt;/code&gt; ou &lt;code&gt;map&lt;/code&gt; na criação do nosso Array mesmo assim elas existem, isso porque essas funções são herdadas do &lt;code&gt;Array.prototype&lt;/code&gt;; Mas ao olhar dentro do &lt;code&gt;Array.prototype&lt;/code&gt; ainda não encontramos o método &lt;code&gt;hasOwnProperty&lt;/code&gt;, mas então porque mesmo assim ele existe?&lt;/p&gt;

&lt;p&gt;Ele existe porque temos algo chamado &lt;em&gt;Prototype Chain&lt;/em&gt;  que é o encadeamento de protótipos até o Objeto original.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Quando se trata de herança, o JavaScript tem somente um construtor: objetos. Cada objeto tem um link interno para um outro objeto chamado prototype. Esse objeto prototype também tem um atributo prototype, e assim por diante até o que o valor null seja encontrado como sendo o seu prototype. null que, por definição, não tem prototype, e age como um link final nesta cadeia de protótipos  (&lt;small&gt;&lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain"&gt;MDN Web Docs - Herança e cadeia de protótipos (prototype chain)&lt;/a&gt;&lt;/small&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;De forma prática, ao declarar nossa variável &lt;code&gt;arr&lt;/code&gt; no exemplo acima nós informamos que o tipo dela é Array, e com isso temos os métodos nativos do &lt;em&gt;Array&lt;/em&gt;, que tem um link através do atributo &lt;code&gt;__proto__&lt;/code&gt; para o tipo Object.&lt;br&gt;
&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;// Exemplificando&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__proto__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__proto__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__proto__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// nosso objeto -&amp;gt; prototype do array -&amp;gt; prototype do object. &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando usamos o método &lt;code&gt;hasOwnProperty&lt;/code&gt; internamente o javascript começa procurar na primeira cadeia de protótipo da nossa variável, ao não encontrar, ele sobe um degrau nessa cadeia, e assim de forma subsequente, até ele encontrar o método ou chegar no tipo primário, se ao chegar no tipo primário ele ainda não encontrar, então é retornado &lt;code&gt;null&lt;/code&gt;&lt;br&gt;
&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="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;findFunction&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__proto__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;findFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__proto__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;findFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// arr.hasOwnProperty  - na nossa declaração existe ?&lt;/span&gt;
&lt;span class="c1"&gt;// arr.__proto__.hasOwnProperty - No tipo array existe ?&lt;/span&gt;
&lt;span class="c1"&gt;// arr.__proto__.__proto__.hasOwnProperty - No tipo Object existe ? &lt;/span&gt;
&lt;span class="c1"&gt;// Se na cadeia acima não existir, então ele retorna null, pois o object é o tipo primário.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"Ah OK, Jorge eu entendi, mas como eu posso tirar proveito do prototype" ?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Existem vários exemplos na internet mostrando como manipular o prototype de uma função que você criou, como exemplo "Carro" ou o clássico exemplo de animais, mas o que eu vou trazer para vocês é um exemplo de manipulação de um Tipo de variável já existente. O que eu mais gosto é o &lt;code&gt;toCapitalize&lt;/code&gt;, que não existe nativamente no tipo String, e em nenhum outro, porém muitas vezes precisamos adicionar um capitalize pelo javascript em algum lugar. &lt;/p&gt;

&lt;p&gt;Então como funcionaria isso ?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;String&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="nx"&gt;toCapitalize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&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;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;words&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;word&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;firstLetter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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;otherLetters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;firstLetter&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;otherLetters&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simples assim, você cria uma novo método que vai ser vinculado a todos os tipos &lt;em&gt;String&lt;/em&gt; do seu código de forma global. (sem que você precise sempre redeclarar essa função);&lt;/p&gt;

&lt;p&gt;Mas como eu utilizo? &lt;/p&gt;

&lt;p&gt;Ao criar uma variável do tipo array, ela já vai possuir esse método nativamente, daí é só chama-lo da forma abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;estou no dev.to&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toCapitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// Estou No Dev.to&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com esse exemplo, conseguimos ver uma forma "turbinamos" os tipos nativos do Javascript.&lt;/p&gt;

&lt;h1&gt; !! ATENÇÃO !! &lt;/h1&gt;

&lt;p&gt;Apesar de ter dado esse exemplo de manipulação de um tipo nativo, tenha muito cuidado, manipular ou sobrescrever métodos de tipo nativos como &lt;em&gt;Array&lt;/em&gt;, &lt;em&gt;String&lt;/em&gt;, &lt;em&gt;Number&lt;/em&gt; etc..., pode gerar confusão na cabeça dos outros desenvolvedores que fizerem parte do projeto que você está implementando. Então, lembre sempre de documentar de forma clara essas mudanças para não ter problemas no futuro.&lt;/p&gt;

&lt;p&gt;Espero ter ajudado a esclarecer um pouco mais sobre os mistérios desse mundo do Javascript.&lt;/p&gt;

&lt;p&gt;Até a próxima&lt;/p&gt;

&lt;p&gt;Referências&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain"&gt;MDN Web Docs - Herança e cadeia de protótipos (prototype chain)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/pt-BR/docs/conflicting/Web/JavaScript/Reference/Global_Objects/Object"&gt;MDN Web Docs - Object.prototype&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>prototype</category>
      <category>dev</category>
      <category>kurybr</category>
    </item>
    <item>
      <title>Docker - Comandos do docker congelando como resolver?</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Tue, 22 Dec 2020 18:23:33 +0000</pubDate>
      <link>https://dev.to/kurybr/docker-comando-do-docker-congelando-46ap</link>
      <guid>https://dev.to/kurybr/docker-comando-do-docker-congelando-46ap</guid>
      <description>&lt;p&gt;Recentemente eu venho passando por alguns problemas de Congelamento do &lt;code&gt;docker&lt;/code&gt;, o que signfica, que ele simplesmente trava.&lt;/p&gt;

&lt;p&gt;A melhor solução que encontrei para resolve esse problema foi apagar todas as imagens e containers do computador. &lt;/p&gt;

&lt;p&gt;No meu caso como uso o Linux, resolvi o problema com os seguintes comandos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo rm -rf /var/lib/containerd
sudo rm -rf /var/lib/docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;É uma solução rádical&lt;/strong&gt;, porém foi a unica que funcionou no meu caso; pois nenhum comando do docker estava respondendo. Inclusive tentei executar o stop do serviço do docker no computador, e também não obtive &lt;br&gt;
uma solução. &lt;/p&gt;

&lt;p&gt;Eu espero que de alguma forma possa ajudar vocês. &lt;/p&gt;

&lt;p&gt;Até uma próxima ! &lt;/p&gt;

</description>
      <category>docker</category>
      <category>containers</category>
      <category>node</category>
      <category>kurybr</category>
    </item>
    <item>
      <title>GCloud + Docker problema de unauthorized</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Sun, 18 Oct 2020 15:35:20 +0000</pubDate>
      <link>https://dev.to/kurybr/gcloud-docker-problema-de-unauthorized-2d4i</link>
      <guid>https://dev.to/kurybr/gcloud-docker-problema-de-unauthorized-2d4i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;unauthorized: You don't have the needed permissions to perform this operation, and you may have invalid credentials. To authenticate your request, follow the steps in: &lt;a href="https://cloud.google.com/container-registry/docs/advanced-authentication"&gt;https://cloud.google.com/container-registry/docs/advanced-authentication&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eu estava com problema para fazer deploy para o Google Container.&lt;br&gt;
Por algum motivo meu Docker no Windows não estava conseguindo se conectar ao GCloud para fazer o push das imagens.&lt;/p&gt;

&lt;p&gt;Depois de tentar de várias formas, a solução prática e rápida que encontrei foi usar esse comando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud docker &lt;span class="nt"&gt;--&lt;/span&gt; pull gcr.io/image:tag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Documentação:  &lt;a href="https://cloud.google.com/sdk/gcloud/reference/docker"&gt;https://cloud.google.com/sdk/gcloud/reference/docker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ao rodar esse comando, ele usa as credenciais do Gcloud para se autenticar com o docker e fazer tanto o Push quanto o Pull das imagens.&lt;/p&gt;

</description>
      <category>gcloud</category>
      <category>docker</category>
      <category>google</category>
    </item>
    <item>
      <title>Javascript - Promise ou Observable</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Sun, 16 Aug 2020 01:52:23 +0000</pubDate>
      <link>https://dev.to/kurybr/promise-ou-observable-misterios-do-javascript-4f70</link>
      <guid>https://dev.to/kurybr/promise-ou-observable-misterios-do-javascript-4f70</guid>
      <description>&lt;p&gt;Existem dois termos que são aplicados quando falamos desses conceitos; Eles são, Eager e Lazy ( ansioso e preguiçoso ) e a principal diferença entre os dois, são respectivamente as definições desse termos.&lt;/p&gt;

&lt;p&gt;Como assim? Vou explicar logo abaixo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eager &amp;amp; Lazy
&lt;/h2&gt;

&lt;p&gt;Vamos começar com o seguinte exemplo de Promise&lt;br&gt;
&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="nx"&gt;greetingEager&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;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dentro da promise as coisas acontecem de forma anciosa.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Olá, Prazer em te conhece.&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="nx"&gt;greetingEager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Saudação na Promisse: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo acima conseguimos ver como ela é ansiosa, porque ao declarar a Promise o conteudo dela já é executado imediatamente, sem mesmo esperar ser invocada através do &lt;code&gt;then&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Se você executar esse código acima verá que a mensagem do &lt;code&gt;console.log&lt;/code&gt; dentro da Promise é executada antes mesmo de você chamar o &lt;code&gt;then&lt;/code&gt; da função.&lt;/p&gt;

&lt;p&gt;Ao contrário de um Observer, que por essência é preguiçoso.&lt;br&gt;
&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;//https://rxjs-dev.firebaseapp.com/guide/overview&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;Observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rxjs&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;greetingLazy&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;Observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observer&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dentro de um observer as coisas acontecem de forma preguiçosa.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Olá, fique a vontade.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Antes de começar inscreva-se no Observer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;greetingLazy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;complete&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fim da conversa.&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;Quando você cria um Observable, você precisa fornecer uma função de retorno de chamada através do atributo &lt;em&gt;next&lt;/em&gt;, que será invocada sempre que for executado o next dentro do observer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Para entender um pouco mais sobre isso, tem um post sobre &lt;a href="https://dev.to/kurybr/entendendo-javascript-generators-em-3-minutos-235m"&gt;Generator&lt;/a&gt; que pode te ajudar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No exemplo acima a mensagem "&lt;em&gt;Antes de começar inscreva-se no Observer&lt;/em&gt;" vai aparecer antes do console.log de dentro do Observable.&lt;/p&gt;

&lt;blockquote&gt;
Um exemplo seria um cenário onde você quer obter uma informação sobre o cardápio de um restaurante.

A promise, seria um menu na sua mesa. onde ao chegar o menu já está disponível para você.

Enquanto o Observable, o menu só irá vir até você quando você pedir para um garçom trazer.
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Sync &amp;amp; Async
&lt;/h1&gt;

&lt;p&gt;Uma outra diferença é o tipo de execução um observable pode ser síncrono ou assíncrono dependendo do contexto, enquanto a Promise sempre vai ser assíncrona, mesmo que seja resolvida imediatamente após sua execução.&lt;br&gt;
&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="nx"&gt;greeting&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;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Olá, prazer em te conhecer.&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Antes de chamar a Promise&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Saudação da Promisse: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;res&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Depois de chamar o then na Promise provando que ela inicia sempre de maneira assíncrona.&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;No exemplo acima, apesar da execução dessa promise ser imediata, você vai perceber ao rodar o código, que a mensagem de dentro da Promise aparecerá por ultimo. Isso porque uma vez que é declarada a Promise  a chamada dela é adicionada a fila de microtasks, ela será só executada no fim da microtask atual.&lt;br&gt;
&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;Observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rxjs&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;greeting&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;Observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observer&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;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Olá, Estou muito feliz em ver você&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Antes de chamar o subscribe do Observable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;complete&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fim da saudação&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Depois de chamar o subscribe do Observable, provando que ele pode ser executado de forma síncrona&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;No exemplo a cima, a ordem das mensagem serão mantidas. por seguir uma ordem de processos de execução de tasks.&lt;/p&gt;

&lt;p&gt;Porém, podemos executar coisas dentro do Observable de forma assíncrona também, como no código a seguir.&lt;br&gt;
&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="nx"&gt;tiredGreeting&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;Observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observer&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;setTimeout&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;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ah, hey, prazer em te conhecer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;2000&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Antes de chamar o subscribe do Observable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;tiredGreeting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;next&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;complete&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fim da saudação&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Depois de chamar o subscribe do Observable, provando que ele pode ser executado de forma assíncrona&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;h1&gt;
  
  
  Valores
&lt;/h1&gt;

&lt;p&gt;Um Observable pode emitir vários valores/resultados para enquanto estiver inscrito.&lt;/p&gt;

&lt;p&gt;Enquanto a Promise retorna apenas um resultado, independente de quantas vezes você chame aquela mesma promise.&lt;br&gt;
&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;Observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rxjs&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;notifications$&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;Observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observer&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;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&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;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Nova Noticia.&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="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&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;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;notifications$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&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;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo de cima, enquanto não há uma desinscrição do Observable, ele ficará emitindo valores.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Como no exemplo do restaurante. A Promise é o menu, ele sempre estará lá, da mesma forma. Enquanto no observable, toda vez que chega alguém novo, o Garçom pode chegar com o Menu, ou com outra informação ao cliente que ele achar relevante.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recapitulando. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Promise são ansiosas, enquanto Observable são preguiçosos.&lt;/li&gt;
&lt;li&gt;Promise sempre são assíncronas, enquanto Observable pode ser tanto síncronas quanto assíncronas.&lt;/li&gt;
&lt;li&gt;Promise sempre retornam o mesmo valor, enquanto Observable pode retornar um fluxo de valores, de nenhum a vários.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;small&gt;Nota de rodapé&lt;/small&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;O Observable, pode ser aprimorado usando outras ferramentas dentro do RxJS, para tornar ele ainda mais poderoso, conseguindo definir fluxos sobre medida.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Nota de tradução
&lt;/h3&gt;

&lt;p&gt;Esse texto é uma adaptação do texto original &lt;a href="https://medium.com/javascript-everyday/javascript-theory-promise-vs-observable-d3087bc1239a"&gt;JavaScript Theory: Promise vs Observable&lt;/a&gt; em Inglês no Medium.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>promise</category>
      <category>observable</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>Javascript - Entendendo Generators em 3 Minutos</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Thu, 09 Jul 2020 02:05:11 +0000</pubDate>
      <link>https://dev.to/kurybr/entendendo-javascript-generators-em-3-minutos-235m</link>
      <guid>https://dev.to/kurybr/entendendo-javascript-generators-em-3-minutos-235m</guid>
      <description>&lt;p&gt;Geralmente não se fala tanto sobre o &lt;strong&gt;generators&lt;/strong&gt;. Isso ocorre porque existem poucos cenários em que você realmente deseja usá-lo. &lt;/p&gt;

&lt;p&gt;No entanto, isso não nega a utilidade do recurso - porque quando esses cenários acabam surgindo, você ficará feliz em ter o &lt;strong&gt;generator&lt;/strong&gt; em seu currículo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Como a maioria das coisas em programação, o &lt;code&gt;generator&lt;/code&gt; é apenas uma ferramenta; Nesse caso, uma ferramenta especializada.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vamos dar uma olhada em um exemplo de &lt;code&gt;generator&lt;/code&gt; em ação e percorrer cada etapa e ver como está funcionando:&lt;br&gt;
&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;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;firstGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; 
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nx"&gt;i&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="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;i&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;Aqui está um &lt;code&gt;generator&lt;/code&gt; definido.&lt;br&gt;
Você perceberá que é muito semelhante a uma função normal, exceto pelo fato de termos um &lt;code&gt;*&lt;/code&gt; e &lt;code&gt;yield&lt;/code&gt;. &lt;br&gt;
O &lt;code&gt;*&lt;/code&gt; informa ao JavaScript que esta é uma função geradora. &lt;/p&gt;

&lt;p&gt;Discutiremos o &lt;code&gt;yield&lt;/code&gt; em um minuto. &lt;/p&gt;

&lt;p&gt;Primeiro, vamos mostrar um exemplo do gerador em ação:&lt;br&gt;
&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;let&lt;/span&gt; &lt;span class="nx"&gt;iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;firstGenerator&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="nx"&gt;iterator&lt;/span&gt; &lt;span class="c1"&gt;// Object [Generator] {}&lt;/span&gt;
&lt;span class="nx"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// { value: 1, done: false }       &lt;/span&gt;
&lt;span class="nx"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// { value: 2, done: false }       &lt;/span&gt;
&lt;span class="nx"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// { value: 3, done: false }       &lt;/span&gt;
&lt;span class="nx"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// { value: undefined, done: true }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nosso &lt;code&gt;firstGenerator&lt;/code&gt; retornou um &lt;code&gt;iterator&lt;/code&gt;, dando acesso a um próximo método.&lt;/p&gt;

&lt;p&gt;Cada vez que chamamos o &lt;code&gt;next&lt;/code&gt;, nossa função executará o código até encontrar uma declaração de rendimento (&lt;code&gt;yield&lt;/code&gt;). Quando encontramos uma declaração de rendimento, interromperemos a execução até que a próxima seja chamada novamente. Quando o &lt;code&gt;someGenerator&lt;/code&gt; terminar a execução, na próxima vez que chamarmos &lt;code&gt;next&lt;/code&gt;, Nós receberemos um objeto que tenha uma chave &lt;code&gt;done&lt;/code&gt; com um valor definido como &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Bem maneiro né? &lt;/p&gt;

&lt;p&gt;Bem, o retorno do &lt;code&gt;iterator&lt;/code&gt; realmente nos permite fazer mais do que apenas isso. &lt;br&gt;
Também temos acesso a instruções como  &lt;code&gt;for… of&lt;/code&gt;, bem como a outros métodos de iteração, como o operador &lt;code&gt;spread&lt;/code&gt;:&lt;br&gt;
&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;let&lt;/span&gt; &lt;span class="nx"&gt;iterator2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;firstGenerator&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="k"&gt;for&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;item&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;iterator2&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="nx"&gt;item&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;Agora que sabemos o básico sobre o uso de geradores, vamos ver alguns casos de uso.&lt;/p&gt;

&lt;p&gt;Um caso de uso comum seria manter o estado de um gerador de ID baseado em um índice.&lt;/p&gt;

&lt;p&gt;Digamos que temos um &lt;code&gt;map/object&lt;/code&gt; de itens e queremos expor uma função que permita que um usuário&lt;br&gt;
adicione um item a esse mapa, cada item deve ter um ID exclusivo com base na ordem que foi inserido.&lt;/p&gt;

&lt;p&gt;Podemos gerar essa instrução de Geração de IDs usando &lt;code&gt;generators&lt;/code&gt;&lt;br&gt;
&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;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;idGenerator&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; 
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&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="p"&gt;{&lt;/span&gt; 
        &lt;span class="nx"&gt;i&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="k"&gt;yield&lt;/span&gt; &lt;span class="s2"&gt;`id-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&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;ourItems&lt;/span&gt; &lt;span class="o"&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;ourIdGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;idGenerator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ourIdGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;ourItems&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;addItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;valor a ser guardado&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;Outro exemplo seria abstrair o &lt;strong&gt;UX Flow&lt;/strong&gt; em uma única função. &lt;/p&gt;

&lt;blockquote&gt;

    Esse exemplo é de longe o que eu mais gosto.
&lt;small&gt;
&lt;/small&gt;
&lt;br&gt;
    &lt;small&gt;- Nota do tradutor&lt;/small&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine que temos um design de UX; Um usuário clica em um botão, depois fazemos alguns cálculos; depois que os cálculos terminam, queremos mostrar outro botão; depois de clicar nesse botão, fazemos mais alguns cálculos e então atualizamos a janela.&lt;/p&gt;

&lt;p&gt;Poderíamos colocar tudo isso em uma única função, mas pode ficar bem confuso. &lt;/p&gt;

&lt;p&gt;Em vez disso, como sabemos a ordem na qual nosso design flui, podemos usar &lt;code&gt;generators&lt;/code&gt;:&lt;br&gt;
&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;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;UXDesignFlow&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; 
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;showFirstButton&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;showSecondButton&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mainApp&lt;/span&gt;&lt;span class="p"&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;uxIterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UXDesignFlow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;uxIterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;firstButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&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="nx"&gt;uxIterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;secondButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&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="nx"&gt;uxIterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&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;No exemplo acima, isolamos com êxito nosso fluxo de design e nossa lógica. &lt;br&gt;
Isso facilita o teste, a legibilidade e, consequentemente, a manutenção. &lt;/p&gt;

&lt;p&gt;Cada vez que concluímos nossos cálculos, mostramos a próxima etapa na interface do usuário.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Na maioria das vezes você não vai precisar de geradores, mas, quando precisa ficará feliz em ter isso na sua stack, Ele ajuda a abstrair interações e fornecem uma solução limpa para quando é necessário uma execução mais lenta dos valores solicitados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão do Tradutor.
&lt;/h3&gt;

&lt;p&gt;Esse artigo é uma tradução quase que direta do &lt;a href="https://medium.com/swlh/understand-javascripts-generators-in-3-minutes-8af75c9c4f5f"&gt;Artigo Original&lt;/a&gt; em inglês no medium.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>generators</category>
      <category>node</category>
      <category>advanced</category>
    </item>
    <item>
      <title>Javascript - Entendendo o toLocaleDateString</title>
      <dc:creator>Jorge Soares</dc:creator>
      <pubDate>Tue, 24 Mar 2020 02:58:08 +0000</pubDate>
      <link>https://dev.to/kurybr/javascript-entendendo-o-tolocaledatestring-261k</link>
      <guid>https://dev.to/kurybr/javascript-entendendo-o-tolocaledatestring-261k</guid>
      <description>&lt;p&gt;Fala pessoal, a um tempo atrás descobri uma coisa bem legal do Javascript e queria compartilhar com vocês.&lt;/p&gt;

&lt;p&gt;Quem usa o &lt;a href="https://momentjs.com/"&gt;moment&lt;/a&gt; ou então outra lib apenas para dar aquela formatada básica, para o padrão da sua região, tem um jeito que é bem simples, e extremamente leve, que é usando uma função nativa da Classe &lt;code&gt;Date&lt;/code&gt;, que é o &lt;code&gt;toLocaleDateString&lt;/code&gt;&lt;br&gt;
&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="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;03-22-2020&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 22/03/2020&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ou&lt;br&gt;
&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="nx"&gt;option&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;weekday&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&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;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// domingo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um exemplo completo de uso para o uso dessa função seria algo mais ou menos assim:&lt;br&gt;
&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="nx"&gt;option&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;month&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="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;weekday&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="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;minute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;second&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;era&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="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;timeZoneName&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="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// domingo, 22 de março de 2020 depois de Cristo 18:56:20 Horário Padrão de Brasília&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Só com isso já conseguimos perceber a força que essa função tem na hora de fazer a formatação de uma data não é mesmo ? &lt;/p&gt;

&lt;p&gt;Se eu quisesse passar para a linguagem americana, russa, ou de qualquer outra região do mundo; Apenas trocando o &lt;code&gt;locale&lt;/code&gt;, já estaria retornando na lingua.&lt;br&gt;
&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="nx"&gt;option&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;weekday&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;minute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;second&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;era&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timeZoneName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Português Brasil&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// domingo, 22 de março de 2020 depois de Cristo 18:56:20 Horário Padrão de Brasília&lt;/span&gt;

&lt;span class="c1"&gt;// Africano&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;af&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 'Maandag 23 Maart 2020 na Christus 22:30:43 Brasilia-standaardtyd'&lt;/span&gt;

&lt;span class="c1"&gt;// Arabe - Libia&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ar-ly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 'الاثنين، 23 مارس 2020 ميلادي 10:31:46 م توقيت برازيليا الرسمي'&lt;/span&gt;

&lt;span class="c1"&gt;// Alemão - Alemanha&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;de-de&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Montag, 23. März 2020 n. Chr., 22:33:09 Brasília-Normalzeit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;small&gt; &lt;em&gt;Vou deixar no fim do artigo um link para a lista de Localidades que você pode usar.&lt;/em&gt; &lt;small&gt;&lt;/small&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Agora queria detalhar um pouco mais o uso de alguns atributos dentro das opções disponíveis, até para entender o quão poderoso é essa função;&lt;/p&gt;

&lt;p&gt;Além dos parametros básicos que fazem a formatação de uma data:&lt;br&gt;
&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;let&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;     
    &lt;span class="na"&gt;second&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="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="na"&gt;minute&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="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;hour&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="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="na"&gt;day&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="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="na"&gt;weekday&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="s1"&gt;narrow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;month&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="s1"&gt;narrow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;year&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="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;era&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="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;timeZoneName&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="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Temos alguns &lt;code&gt;alias&lt;/code&gt; para facilitar a formação de datas sem precisar passar essa quantidade imensa de parametros acima.&lt;br&gt;
&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;let&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;     
    &lt;span class="na"&gt;dateStyle&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="s1"&gt;full&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="na"&gt;timeStyle&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="s1"&gt;full&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// new Date().toLocaleDateString('pt-Br',{ dateStyle: 'full' } )&lt;/span&gt;
&lt;span class="c1"&gt;// "domingo, 22 de março de 2020"&lt;/span&gt;
&lt;span class="c1"&gt;// new Date().toLocaleDateString('pt-Br',{ dateStyle: 'long' } )&lt;/span&gt;
&lt;span class="c1"&gt;// "22 de março de 2020"&lt;/span&gt;
&lt;span class="c1"&gt;// new Date().toLocaleDateString('pt-Br',{ dateStyle: 'medium' } )&lt;/span&gt;
&lt;span class="c1"&gt;// "22 de mar. de 2020"&lt;/span&gt;
&lt;span class="c1"&gt;// new Date().toLocaleDateString('pt-Br',{ dateStyle: 'short' } )&lt;/span&gt;
&lt;span class="c1"&gt;// "22/03/2020"&lt;/span&gt;

&lt;span class="c1"&gt;// new Date().toLocaleDateString('pt-Br',{ timeStyle: 'full' } )&lt;/span&gt;
&lt;span class="c1"&gt;// "20:55:24 Horário Padrão de Brasília"&lt;/span&gt;
&lt;span class="c1"&gt;// new Date().toLocaleDateString('pt-Br',{ timeStyle: 'long' } )&lt;/span&gt;
&lt;span class="c1"&gt;// "20:55:29 BRT"&lt;/span&gt;
&lt;span class="c1"&gt;// new Date().toLocaleDateString('pt-Br',{ timeStyle: 'medium' } )&lt;/span&gt;
&lt;span class="c1"&gt;// "20:55:33"&lt;/span&gt;
&lt;span class="c1"&gt;// new Date().toLocaleDateString('pt-Br',{ timeStyle: 'short' } )&lt;/span&gt;
&lt;span class="c1"&gt;// "20:55"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora os casos mais especificos, porém podem dar uma configuração maior a &lt;em&gt;String&lt;/em&gt; são:&lt;br&gt;
&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;let&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;timeZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;America/Sao_Paulo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Lista de Timezones no fim do artigo&lt;/span&gt;
    &lt;span class="na"&gt;hour12&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="c1"&gt;// Alterna entre a mostragem dos horários em 24 horas, ou então AM/PM&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O Parametro de hourCycle é usada para "Ajustar" a forma que é contado o relógio em determinado lugar, por exemplo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;O &lt;code&gt;h23&lt;/code&gt; significa que o dia, vai até as 23h59m depois muda para 00h00m, já o &lt;code&gt;h24&lt;/code&gt; significa que o dia, vai até as 24h59 depois muda para 01h00m&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Segue abaixo uma tabela simples para ajudar vocês&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ciclo de horas&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;h12&lt;/td&gt;
&lt;td&gt;O Sistema usado de horas é 1-12, correspondido pelo 'h' no padrão; Um relógio de 12 horas, com a meia noite iniciando as 12:00 am&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;h23&lt;/td&gt;
&lt;td&gt;O Sistema usado de horas é 0-23, correspondido pelo 'H' no padrão; Um relógio de 24 horas, com a meia noite iniciando as 00:00 am&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;h24&lt;/td&gt;
&lt;td&gt;O Sistema usado de horas é 1-24, correspondido pelo 'k' no padrão; Um relógio de 24 horas, com a meia noite iniciando as 24:00 am&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;h11&lt;/td&gt;
&lt;td&gt;O Sistema usado de horas é 0-11, correspondido pelo 'K' no padrão; Um relógio de 12 horas, com a meia noite iniciando as 00:00 am&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;hourCycle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h23&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;&lt;sup&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Locale/hourCycle"&gt;Informações mais detalhadas sobre o hourCycle&lt;/a&gt;&lt;br&gt;
&lt;/sup&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Confesso que não entendi muito bem o funcionamento do parametro formatMatcher, porém vou deixar ele registrado aqui, quem conseguir me explicar o conceito dele, e compartilhar com o pessoal, eu agradeço&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;formatMatcher&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="s1"&gt;basic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;best-fit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// best-fit é o formato default.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Considerações Finais.
&lt;/h2&gt;

&lt;p&gt;Pessoal, esse é o meu primeiro texto um pouco mais técnico, tentando detalhar o funcionamento de alguma coisa.&lt;br&gt;
A ideia é que com o tempo eu consiga explicar de forma melhor, e claro aprender junto com vocês;&lt;/p&gt;

&lt;p&gt;Espero que de alguma forma esse artigo venha a ajudar outras pessoas, que assim como eu, estão em busca de conhecimento direto.&lt;/p&gt;

&lt;p&gt;Até a próxima,&lt;/p&gt;

&lt;p&gt;Vou deixar aqui abaixo, alguns links que usei como referencia, pra quem quiser buscar mais informações sobre algum dos assuntos que falei&lt;/p&gt;

&lt;h3&gt;
  
  
  Referencias
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.science.co.il/language/Locale-codes.php"&gt;Lista de Código de Localidade&lt;/a&gt;  &lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"&gt;Lista de Timezones&lt;/a&gt; &lt;br&gt;
&lt;a href="https://caniuse.com/#feat=date-tolocaledatestring"&gt;I Can Use&lt;/a&gt; &lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/3552461/how-to-format-a-javascript-date/33131823"&gt;Stack Overflow - How to Format a Javascript Date&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tips</category>
      <category>date</category>
      <category>terça</category>
    </item>
  </channel>
</rss>
