<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Danizavtz em códigos]]></title><description><![CDATA[Pensamentos, códigos e ideias.]]></description><link>https://danizavtz.com.br/</link><image><url>https://danizavtz.com.br/favicon.png</url><title>Danizavtz em códigos</title><link>https://danizavtz.com.br/</link></image><generator>Ghost 4.48</generator><lastBuildDate>Thu, 23 Apr 2026 23:29:50 GMT</lastBuildDate><atom:link href="https://danizavtz.com.br/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Moodle criar um novo usuário via web service API]]></title><description><![CDATA[<p>Criar um novo usu&#xE1;rio no moodle com a permiss&#xE3;o <code>core_user_create_user</code>.</p><p>Para isso acesse o <code>Administra&#xE7;&#xE3;o de site</code> -&gt; <code>servidor</code> -&gt; <code>web services</code>-&gt;`Servi&#xE7;os externos`.</p><p>Adicionar uma nova permiss&#xE3;o, cadastre seguindo este template:</p>]]></description><link>https://danizavtz.com.br/moodle-criar-um-novo-usuario-via-web-service-api/</link><guid isPermaLink="false">698be2c927dff060a3f1e79b</guid><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 11 Feb 2026 02:22:13 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1503676260728-1c00da094a0b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDR8fGVkdWNhdGlvbnxlbnwwfHx8fDE3NzA3NzY1NTF8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1503676260728-1c00da094a0b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDR8fGVkdWNhdGlvbnxlbnwwfHx8fDE3NzA3NzY1NTF8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="Moodle criar um novo usu&#xE1;rio via web service API"><p>Criar um novo usu&#xE1;rio no moodle com a permiss&#xE3;o <code>core_user_create_user</code>.</p><p>Para isso acesse o <code>Administra&#xE7;&#xE3;o de site</code> -&gt; <code>servidor</code> -&gt; <code>web services</code>-&gt;`Servi&#xE7;os externos`.</p><p>Adicionar uma nova permiss&#xE3;o, cadastre seguindo este template:</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2026/02/tempImageLGbazc.gif" class="kg-image" alt="Moodle criar um novo usu&#xE1;rio via web service API" loading="lazy" width="1462" height="1130"></figure><p>Depois deste passo basta salvar esta nova persmiss&#xE3;o.</p><p>Criar um token de acesso que possui esta permiss&#xE3;o.</p><p>Para isso navegue para: <code>Servidor</code> -&gt;`Web Services` -&gt; `Gerenciar tokens`</p><p>Criar um token com esta permiss&#xE3;o que foi criada...</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2026/02/tempImageRwUhcl.gif" class="kg-image" alt="Moodle criar um novo usu&#xE1;rio via web service API" loading="lazy" width="1214" height="1236"></figure><p>Pronto, agora basta configurar o postman, para testes e depois integrar &#xE0; sua API.</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2026/02/tempImageDE2z6u.gif" class="kg-image" alt="Moodle criar um novo usu&#xE1;rio via web service API" loading="lazy" width="1258" height="968"></figure><p>Uma coisa a se notar &#xE9; que o moodle possui pol&#xED;tica de senha dessa forma &#xE9; necess&#xE1;rio colocar uma senha que atenda a esta pol&#xED;tica.</p>]]></content:encoded></item><item><title><![CDATA[Como mapear mensagem de erro no FeignClient]]></title><description><![CDATA[<p>Possuo um Feign Client para fazer requisi&#xE7;&#xF5;es em servi&#xE7;os de terceiros.</p><p>Desejo exibir a mensagem de erro corretamente de acordo com os erros apresentados.</p><p>Para isso basta capturar os erros de acordo com a exce&#xE7;&#xE3;o lan&#xE7;ada pelo cliente Feign.</p><p>Possuo</p>]]></description><link>https://danizavtz.com.br/como-3/</link><guid isPermaLink="false">68f9212727dff060a3f1e6c2</guid><category><![CDATA[feign]]></category><category><![CDATA[Java]]></category><category><![CDATA[Exception]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 22 Oct 2025 19:27:32 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1496115965489-21be7e6e59a0?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDR8fGNsaWVudHxlbnwwfHx8fDE3NjExNjExODF8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1496115965489-21be7e6e59a0?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDR8fGNsaWVudHxlbnwwfHx8fDE3NjExNjExODF8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="Como mapear mensagem de erro no FeignClient"><p>Possuo um Feign Client para fazer requisi&#xE7;&#xF5;es em servi&#xE7;os de terceiros.</p><p>Desejo exibir a mensagem de erro corretamente de acordo com os erros apresentados.</p><p>Para isso basta capturar os erros de acordo com a exce&#xE7;&#xE3;o lan&#xE7;ada pelo cliente Feign.</p><p>Possuo o seguinte m&#xE9;todo, que faz a busca de um usu&#xE1;rio em uma api externa:</p><!--kg-card-begin: markdown--><pre><code>public EntityModel&lt;UserDTO&gt; findUserByCpf(@PathVariable(value = &quot;cpf&quot;)String cpf)  {
    UserDTO user = null;
    user = demoClient.getUser(cpf);

    return EntityModel.of(user);
}
</code></pre>
<!--kg-card-end: markdown--><p>O m&#xE9;todo acima est&#xE1; simplificado para um melhor entendimento, desejo complementar a implementa&#xE7;&#xE3;o deste m&#xE9;todo para tratar os erros adequadamente, para poder &quot;setar&quot; a mensagem de erro corretamente de acordo com o erro recebido pelo Feign client.</p><p>Basta adicionar um bloco <code>try ... catch</code> e tratar os erros de acordo com as exce&#xE7;&#xF5;es enviadas pelo Feign Client.</p><!--kg-card-begin: markdown--><pre><code>public EntityModel&lt;UserDTO&gt; findUserByCpf(@PathVariable(value = &quot;cpf&quot;)String cpf)  {
    UserDTO user = null;
    try {
        user = demoClient.getUser(cpf);
    } catch (Exception ex) {
        if (ex instanceof FeignException.BadRequest) {
            String bodyErrorMessage = ((FeignException.BadRequest) ex).contentUTF8();
            DemoClientErrorHandler democlienterror = objectMapperDefaultErrorConfig().readValue(bodyErrorMessage, DemoClientErrorHandler.class);
            }
    }
    //tratar os outros tipos de erros
    return EntityModel.of(user);
}
</code></pre>
<!--kg-card-end: markdown--><p>Basicamente a minha entidade <code>DemoClientErrorHandler</code> &#xE9; um mapeamento em classes Java (POJO) de um &quot;erro&quot; da API externa que estou utilizando.</p><p>Para este exemplo eu usei apenas o BadRequest mas podem ser utilizados quantos forem necess&#xE1;rios, basta seguir o que a documenta&#xE7;&#xE3;o direciona.</p><p>Para implementar este c&#xF3;digo utilizei esta <a href="https://www.baeldung.com/java-feign-client-exception-handling">refer&#xEA;ncia</a>.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Mudar o nome do arquivo a ser salvo no multer]]></title><description><![CDATA[<p>Uma maneira de solucionar o problema &#xE9; renomear o arquivo a partir do ponto que j&#xE1; possui os dados do <code>req.file</code>, ap&#xF3;s ter passado no middleware do multer.</p><p>Toda essa configura&#xE7;&#xE3;o abaixo &#xE9; feita apenas no backend (servidor) [nodejs].</p><p>A solu&#xE7;&#xE3;</p>]]></description><link>https://danizavtz.com.br/mudar-o-nome-do-arquivo-a-ser-salvo-no-multer/</link><guid isPermaLink="false">670ff389dfa2eb0f8251e83b</guid><category><![CDATA[nodejs]]></category><category><![CDATA[multer]]></category><category><![CDATA[express]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 16 Oct 2024 17:28:19 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1635477906625-ef1aea584e17?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDZ8fHJ8ZW58MHx8fHwxNzI5MDk4ODUyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1635477906625-ef1aea584e17?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDZ8fHJ8ZW58MHx8fHwxNzI5MDk4ODUyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Mudar o nome do arquivo a ser salvo no multer"><p>Uma maneira de solucionar o problema &#xE9; renomear o arquivo a partir do ponto que j&#xE1; possui os dados do <code>req.file</code>, ap&#xF3;s ter passado no middleware do multer.</p><p>Toda essa configura&#xE7;&#xE3;o abaixo &#xE9; feita apenas no backend (servidor) [nodejs].</p><p>A solu&#xE7;&#xE3;o, de maneira resumida funciona assim:</p><ol><li>recebe um arquivo (multipart/form-data) no primeiro middleware (ali onde tem o <code>upload.single</code>)</li><li>a partir do segundo middleware j&#xE1; possuo os dados para renomear o arquivo (os dados est&#xE3;o no objeto <code>req.file</code>) s&#xE3;o os padr&#xF5;es do <a href="https://www.npmjs.com/package/multer">multer</a></li><li>uso a lib nativa do nodejs <code>fs</code> para renomear o arquivo, atrav&#xE9;s da fun&#xE7;&#xE3;o <code>fs.renameSync</code></li><li>Renomeia o arquivo atrav&#xE9;s do valor da vari&#xE1;vel <code>req.file.originalname</code>.</li><li>no servidor o arquivo estar&#xE1; no caminho relativo <code>uploads/</code></li></ol><p>Por exemplo: Um arquivo que tenha sido feito o upload vai possuir o nome no padr&#xE3;o do multer (para este passo eu n&#xE3;o configurei o multer para nomear os arquivos. Dessa forma o arquivo que &#xE9; enviado ao meu servidor (ao terminar o primeiro middleware (que &#xE9; o do pr&#xF3;prio multer), vai possuir o nome no seguinte padr&#xE3;o (<code>2a39086031204b49df1b80322e9cd5ff</code>), ap&#xF3;s isso, no segundo middleware (<code>fileNameUploadRename</code>) posso renomear o arquivo.</p><p>Veja um exemplo de implementa&#xE7;&#xE3;o de um middleware que possui esta l&#xF3;gica:</p><pre><code>const fs = require(&apos;fs&apos;);

const multer = require(&apos;multer&apos;);

const upload = multer({
    dest: &apos;uploads/&apos;
});
router.post(&apos;/adicionarCurso&apos;, upload.single(&apos;certificado&apos;), (req, res) =&gt; {
    try {
        fs.access(`${req.file.destination}${req.file.originalname}`, fs.constants.COPYFILE_EXCL, (err) =&gt; {
            if (err &amp;&amp; err.errno === -2) {
                fs.renameSync(req.file.path, `${req.file.destination}/${req.file.originalname}`);
                res.status(200).json({ msg: &apos;Opera&#xE7;&#xE3;o realizada com sucesso&apos; });
                return;
            }
            res.status(409).json({ msg: &apos;O arquivo j&#xE1; existe&apos; });
            fs.unlinkSync(req.file.path);
        })
    } catch (err) {
        res.status(500).json({
            err: &quot;Houve um erro ao atualizar o certificado, tente novamente&quot;
        })
    }
});
</code></pre><p>Para mais informa&#xE7;&#xF5;es consulte a documenta&#xE7;&#xE3;o do <a href="https://nodejs.org/api/fs.html">fs</a> e valores das <a href="https://nodejs.org/api/fs.html#fsconstants">constantes do fs</a></p><hr><p>Repare que no exemplo acima eu fa&#xE7;o uso de algumas fun&#xE7;&#xF5;es espec&#xED;ficas da fun&#xE7;&#xE3;o `fs`. Por exemplo uso a constante `COPYFILE_EXCL` que far&#xE1; opera&#xE7;&#xE3;o de c&#xF3;pia falhar se o arquivo de destino j&#xE1; existir. Ou seja, n&#xE3;o desejo sobre-escrever o arquivo. (O que vale &#xE9; o primeiro a ser enviado), ent&#xE3;o eu recomendo que se deseja outro comportamento escolha a constante adequada para a sua situa&#xE7;&#xE3;o.</p><p>Refer&#xEA;ncias:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://nodejs.org/api/fs.html"><div class="kg-bookmark-content"><div class="kg-bookmark-title">File system | Node.js v23.0.0 Documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://nodejs.org/favicon.ico" alt="Mudar o nome do arquivo a ser salvo no multer"><span class="kg-bookmark-author">Node.js v23.0.0 Documentation</span></div></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://nodejs.org/api/fs.html#fsconstants"><div class="kg-bookmark-content"><div class="kg-bookmark-title">File system | Node.js v23.0.0 Documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://nodejs.org/favicon.ico" alt="Mudar o nome do arquivo a ser salvo no multer"><span class="kg-bookmark-author">Node.js v23.0.0 Documentation</span></div></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Erro django runserver]]></title><description><![CDATA[<p>Tenho um problema com o framework Django: inicialmente conseguia subir o servidor normalmente, mas depois de um tempo, quando executo o <code>manage.py</code>, o servidor n&#xE3;o &quot;sobe&quot; e a linha de comando n&#xE3;o informa nenhum erro.</p><p>Ex.:</p><!--kg-card-begin: markdown--><pre><code>C:\Users\eu\untitled\mini_curso_django&</code></pre>]]></description><link>https://danizavtz.com.br/erro-django-runserver/</link><guid isPermaLink="false">670fd7fddfa2eb0f8251e809</guid><category><![CDATA[django]]></category><category><![CDATA[python2]]></category><category><![CDATA[python3]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 16 Oct 2024 16:26:53 GMT</pubDate><content:encoded><![CDATA[<p>Tenho um problema com o framework Django: inicialmente conseguia subir o servidor normalmente, mas depois de um tempo, quando executo o <code>manage.py</code>, o servidor n&#xE3;o &quot;sobe&quot; e a linha de comando n&#xE3;o informa nenhum erro.</p><p>Ex.:</p><!--kg-card-begin: markdown--><pre><code>C:\Users\eu\untitled\mini_curso_django&gt;manage.py runserver 8000
</code></pre>
<!--kg-card-end: markdown--><p>O que pode ser? Como resolvo este erro?</p><p>Voc&#xEA; tem que adicionar o nome <code>python</code> na frente.<br></p><p>O comando completo ficaria assim:</p><pre><code>python manage.py runserver 8000
</code></pre><p>Ou</p><pre><code>python3 manage.py runserver 8000
</code></pre><p>Dependendo da sua vers&#xE3;o instalada do Python.</p><p>Outra dica &#xE9; lembrar de <code>ativar</code> o seu virtualenv, caso esteja utilizando.</p><p>Segue a documenta&#xE7;&#xE3;o relevante.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.djangoproject.com/en/5.1/ref/django-admin/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">django-admin and manage.py | Django documentation</div><div class="kg-bookmark-description">The web framework for perfectionists with deadlines.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://static.djangoproject.com/img/icon-touch.e4872c4da341.png" alt><span class="kg-bookmark-author">Django Project</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://static.djangoproject.com/img/logos/django-logo-negative.1d528e2cb5fb.png" alt></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Como filtrar minha tabela por dados que iniciem por números?]]></title><description><![CDATA[<p>Possuo uma tabela com a seguinte configura&#xE7;&#xE3;o:</p><!--kg-card-begin: html--><table>
<thead>
<tr>
<th>id</th>
<th>nome</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>1.2 Esta&#xE7;&#xE3;o Cursos_Link</td>
</tr>
<tr>
<td>2</td>
<td>Esta&#xE7;&#xE3;o Palestras Banco de dados</td>
</tr>
<tr>
<td>3</td>
<td>1.3 Esta&#xE7;&#xE3;o Cusos_WhatsApp</td>
</tr>
</tbody>
</table><!--kg-card-end: html--><p>Desejo filtrar minha coluna nome que &#xE9; do tipo string, s&</p>]]></description><link>https://danizavtz.com.br/como-filtrar-minha-tabela-por-dados-que-iniciem-por-numeros/</link><guid isPermaLink="false">670fcd5cdfa2eb0f8251e7a7</guid><category><![CDATA[sql]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 16 Oct 2024 14:48:55 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1529078155058-5d716f45d604?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE3fHxkYXRhfGVufDB8fHx8MTcyOTA4OTgzN3ww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1529078155058-5d716f45d604?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE3fHxkYXRhfGVufDB8fHx8MTcyOTA4OTgzN3ww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Como filtrar minha tabela por dados que iniciem por n&#xFA;meros?"><p>Possuo uma tabela com a seguinte configura&#xE7;&#xE3;o:</p><!--kg-card-begin: html--><table>
<thead>
<tr>
<th>id</th>
<th>nome</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>1.2 Esta&#xE7;&#xE3;o Cursos_Link</td>
</tr>
<tr>
<td>2</td>
<td>Esta&#xE7;&#xE3;o Palestras Banco de dados</td>
</tr>
<tr>
<td>3</td>
<td>1.3 Esta&#xE7;&#xE3;o Cusos_WhatsApp</td>
</tr>
</tbody>
</table><!--kg-card-end: html--><p>Desejo filtrar minha coluna nome que &#xE9; do tipo string, s&#xF3; com os dados que comecem com n&#xFA;meros, como proceder?</p><p>Uma maneira de resolver o problema &#xE9; utilizando uma composi&#xE7;&#xE3;o de fun&#xE7;&#xF5;es, utilizando a fun&#xE7;&#xE3;o <code>substring</code> com <code>isnumeric</code>.</p><p>O algoritmo para esta solu&#xE7;&#xE3;o pode ser descrito da seguinte forma:</p><blockquote>Exiba todas as ocorr&#xEA;ncias que possui a coluna nome que a primeira letra que seja um valor num&#xE9;rico.</blockquote><p>Dessa forma em SQL temos:</p><p>A fun&#xE7;&#xE3;o <code>substring</code> vai &quot;recortar&quot; a string nome, e vai retornar o caractere de &#xED;ndice zero da coluna nome. Verificar se este caractere &#xE9; do tipo num&#xE9;rico atrav&#xE9;s da fun&#xE7;&#xE3;o <code>isnumeric</code></p><p>Explicando o funcionamento da fun&#xE7;&#xE3;o <code>isnumeric</code>:</p><blockquote>ISNUMERIC retorna 1 quando a express&#xE3;o de entrada &#xE9; avaliada como um tipo de dados num&#xE9;rico v&#xE1;lido; caso contr&#xE1;rio, retorna 0 (zero).</blockquote><p>Compondo as fun&#xE7;&#xF5;es, temos a seguinte consulta:</p><!--kg-card-begin: markdown--><pre><code>SELECT * FROM cursos WHERE ISNUMERIC(SUBSTRING(nome,1,1)) = 1;
</code></pre>
<!--kg-card-end: markdown--><hr><p>Para resultados mais robustos recomendo utilizar uma fun&#xE7;&#xE3;o <code>trim</code> para remover qualquer espa&#xE7;o em branco inclu&#xED;do acidentalmente na string nome.</p><!--kg-card-begin: markdown--><pre><code>SELECT * FROM cursos WHERE ISNUMERIC(SUBSTRING(TRIM(nome),1,1)) = 1;
</code></pre>
<!--kg-card-end: markdown--><p>Refer&#xEA;ncias:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://learn.microsoft.com/pt-br/sql/t-sql/functions/substring-transact-sql?view=sql-server-ver16"><div class="kg-bookmark-content"><div class="kg-bookmark-title">SUBSTRING (Transact-SQL) - SQL Server</div><div class="kg-bookmark-description">Refer&#xEA;ncia de Transact-SQL para a fun&#xE7;&#xE3;o SUBSTRING. Essa fun&#xE7;&#xE3;o retorna uma parte de uma express&#xE3;o de caractere, bin&#xE1;rio, texto ou imagem especificada.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://learn.microsoft.com/favicon.ico" alt="Como filtrar minha tabela por dados que iniciem por n&#xFA;meros?"><span class="kg-bookmark-author">Microsoft Learn</span><span class="kg-bookmark-publisher">MikeRayMSFT</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="Como filtrar minha tabela por dados que iniciem por n&#xFA;meros?"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://learn.microsoft.com/pt-br/sql/t-sql/functions/isnumeric-transact-sql?view=sql-server-ver16"><div class="kg-bookmark-content"><div class="kg-bookmark-title">ISNUMERIC (Transact-SQL) - SQL Server</div><div class="kg-bookmark-description">ISNUMERIC determina se uma express&#xE3;o &#xE9; um tipo num&#xE9;rico v&#xE1;lido.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://learn.microsoft.com/favicon.ico" alt="Como filtrar minha tabela por dados que iniciem por n&#xFA;meros?"><span class="kg-bookmark-author">Microsoft Learn</span><span class="kg-bookmark-publisher">markingmyname</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="Como filtrar minha tabela por dados que iniciem por n&#xFA;meros?"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://learn.microsoft.com/pt-br/sql/t-sql/functions/trim-transact-sql?view=sql-server-ver16"><div class="kg-bookmark-content"><div class="kg-bookmark-title">TRIM (Transact-SQL) - SQL Server</div><div class="kg-bookmark-description">Remove o caractere de espa&#xE7;o ou outros caracteres especificados do in&#xED;cio e do final de uma cadeia de caracteres.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://learn.microsoft.com/favicon.ico" alt="Como filtrar minha tabela por dados que iniciem por n&#xFA;meros?"><span class="kg-bookmark-author">Microsoft Learn</span><span class="kg-bookmark-publisher">WilliamDAssafMSFT</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="Como filtrar minha tabela por dados que iniciem por n&#xFA;meros?"></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Como criar uma aplicação com https utilizando nodejs+express]]></title><description><![CDATA[<p>Para criar este projeto assumimos que:</p><ul><li>O certificado &#xE9; autoassinado</li><li>&#xC9; uma aplica&#xE7;&#xE3;o que vai funcionar para testar algumas funcionalidades que devem ser servidas via https</li><li>o certificado &#xE9; configurado diretamente na aplica&#xE7;&#xE3;o nodejs-express.</li></ul><p>Vamos ent&#xE3;o ao c&#xF3;digo:</p><p>Criamos um</p>]]></description><link>https://danizavtz.com.br/como-criar-uma-aplicac/</link><guid isPermaLink="false">66b4cebedfa2eb0f8251e705</guid><category><![CDATA[nodejs]]></category><category><![CDATA[express]]></category><category><![CDATA[https]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Thu, 08 Aug 2024 14:29:29 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1558494949-ef010cbdcc31?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHNlY3VyZSUyMHNlcnZlcnxlbnwwfHx8fDE3MjMxMjczMDd8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1558494949-ef010cbdcc31?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHNlY3VyZSUyMHNlcnZlcnxlbnwwfHx8fDE3MjMxMjczMDd8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Como criar uma aplica&#xE7;&#xE3;o com https utilizando nodejs+express"><p>Para criar este projeto assumimos que:</p><ul><li>O certificado &#xE9; autoassinado</li><li>&#xC9; uma aplica&#xE7;&#xE3;o que vai funcionar para testar algumas funcionalidades que devem ser servidas via https</li><li>o certificado &#xE9; configurado diretamente na aplica&#xE7;&#xE3;o nodejs-express.</li></ul><p>Vamos ent&#xE3;o ao c&#xF3;digo:</p><p>Criamos um novo projeto chamado <code>expressapphttps</code> ap&#xF3;s criar o diret&#xF3;rio podemos criar um novo projeto <code>node</code>.</p><p>Supondo que est&#xE1; dentro do diret&#xF3;rio <code>expressapphttps</code> rodar o comando <code>npm init</code></p><p>Ap&#xF3;s responder as perguntas ter&#xE1; um projeto no estado inicial, editar o arquivo:</p><p>***package.json*** neste arquivo editar a se&#xE7;&#xE3;o <code>scripts</code> adicionar duas linhas, as linhas que cont&#xE9;m &quot;start&quot; e &quot;dev&quot;.</p><!--kg-card-begin: markdown--><pre><code>{
  &quot;name&quot;: &quot;expressapphttps&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;express&quot;,
  &quot;main&quot;: &quot;app.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;,
    &quot;start&quot;: &quot;node app.js&quot;,
    &quot;dev&quot;: &quot;node --watch app.js&quot;
  },
  &quot;author&quot;: &quot;danizavtz&quot;,
  &quot;license&quot;: &quot;Apache-2.0&quot;,
  &quot;dependencies&quot;: {
    &quot;express&quot;: &quot;^4.19.2&quot;
  }
}
</code></pre>
<!--kg-card-end: markdown--><p>Ap&#xF3;s editar este arquivo, adicionar um novo arquivo <code>app.js</code>, o conte&#xFA;do desse arquivo deve ser:</p><p>***app.js***</p><!--kg-card-begin: markdown--><pre><code>const express = require(&apos;express&apos;)
const https = require(&apos;https&apos;)
const fs = require(&apos;fs&apos;)
const path = require(&apos;path&apos;)
const app = express();

app.use(&apos;/&apos;, (req, res) =&gt; {
    rres.send(&apos;hello I am SSL Server !&apos;)
});

const options = {
    key: &apos;&apos;,
    cert: &apos;&apos;
}
const port = process.env.PORT || 8080;
const sslServer = https.createServer(options, app);
sslServer.listen(port, () =&gt; {
    console.log(`Secure server is listening on port ${port}`)
});
</code></pre>
<!--kg-card-end: markdown--><p>Primeiramente criamos um certificado v&#xE1;lido. Para isto segui o tutorial desta postagem de <a href="https://dev.to/devland/how-to-generate-and-use-an-ssl-certificate-in-nodejs-2996">blog</a>.</p><p>Os certificados gerados devem ser colocados no diret&#xF3;rio <code>cert</code> .</p><p>Ap&#xF3;s os certificados estarem nos locais devidos, vamos apenas editar para adicionar o caminho relativo para os certificados:</p><!--kg-card-begin: markdown--><pre><code>const express = require(&apos;express&apos;)
const https = require(&apos;https&apos;)
const fs = require(&apos;fs&apos;)
const path = require(&apos;path&apos;)
const app = express();

app.use(&apos;/&apos;, (req, res) =&gt; {
    res.send(&apos;hello I am SSL Server !&apos;)
});

const options = {
    key: fs.readFileSync(path.join(__dirname, &apos;./cert/key.pem&apos;)),
    cert: fs.readFileSync(path.join(__dirname, &apos;./cert/cert.pem&apos;))
}
const port = process.env.PORT || 8080;
const sslServer = https.createServer(options, app);
sslServer.listen(port, () =&gt; {
    console.log(`Secure server is listening on port ${port}`)
});
</code></pre>
<!--kg-card-end: markdown--><p>Pronto, agora ap&#xF3;s iniciar a aplica&#xE7;&#xE3;o ser&#xE1; poss&#xED;vel utilizar est aplica&#xE7;&#xE3;o atrav&#xE9;s do protocolo https.</p>]]></content:encoded></item><item><title><![CDATA[Como criar uma cópia da tabela com a data atual no nome da tabela no Postgres]]></title><description><![CDATA[<p>Uma maneira de resolver o problema &#xE9; utilizar o shell para &quot;montar&quot; a data e criar a tabela com o resultado de um alias para data.</p><p>Segue um exemplo, de como ser&#xE1; o resultado do nome da tabela:</p><pre><code>echo &quot;tbl_xpto_$(printf &apos;%(%d_%m_%Y)</code></pre>]]></description><link>https://danizavtz.com.br/como-criar-uma-copia-da-tabela-com-a-data-atual-no-nome-da-tabela-no-postgres/</link><guid isPermaLink="false">65e9ea38dfa2eb0f8251e638</guid><category><![CDATA[postgres]]></category><category><![CDATA[psql]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Thu, 07 Mar 2024 16:26:04 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1597852074816-d933c7d2b988?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDR8fGRhdGFiYXNlfGVufDB8fHx8MTcwOTgyODg0MXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1597852074816-d933c7d2b988?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDR8fGRhdGFiYXNlfGVufDB8fHx8MTcwOTgyODg0MXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Como criar uma c&#xF3;pia da tabela com a data atual no nome da tabela no Postgres"><p>Uma maneira de resolver o problema &#xE9; utilizar o shell para &quot;montar&quot; a data e criar a tabela com o resultado de um alias para data.</p><p>Segue um exemplo, de como ser&#xE1; o resultado do nome da tabela:</p><pre><code>echo &quot;tbl_xpto_$(printf &apos;%(%d_%m_%Y)T&apos; -1)&quot;
</code></pre><p>A sa&#xED;da para este comando acima &#xE9; o seguinte:</p><!--kg-card-begin: markdown--><pre><code>tbl_xpto_07_03_2024
</code></pre>
<!--kg-card-end: markdown--><p>Verifique que os valores mudam de acordo com a data atual, ent&#xE3;o dependendo do dia que executar o comando, pode receber outro resultado, pois no comando acima, estamos formatando uma sa&#xED;da de data, no formato (<strong>dd_MM_YYYY</strong>)</p><p>Pronto, agora que j&#xE1; sabe como vai ser o nome da tabela, basta utilizar esta mesma l&#xF3;gica para executar este comando utilizando o psql.</p><p>Segue um exemplo:</p><p>Uma maneira de resolver o problema &#xE9; utilizar o shell para &quot;montar&quot; a data e criar a tabela com o resultado de um alias.</p><p>Segue um exemplo, de como ser&#xE1; o resultado do nome da tabela:</p><pre><code>echo &quot;tbl_xpto_$(printf &apos;%(%d_%m_%Y)T&apos; -1)&quot;
</code></pre><!--kg-card-begin: html--><table>
<thead>
<tr>
<th>Formatador</th>
<th>Descri&#xE7;&#xE3;o</th>
</tr>
</thead>
<tbody>
<tr>
<td>%d</td>
<td>dia</td>
</tr>
<tr>
<td>%m</td>
<td>M&#xEA;s</td>
</tr>
<tr>
<td>%Y</td>
<td>(mai&#xFA;sculo) Ano com 4 d&#xED;gitos</td>
</tr>
</tbody>
</table><!--kg-card-end: html--><p>Uma maneira de resolver &#xE9; utilizando uma stored procedure, basta criar uma procedure e depois executar esta <em>stored procedure</em>.</p><pre><code>CREATE OR REPLACE PROCEDURE CRIAR_TABELA_DATA_HOJE() LANGUAGE plpgsql AS
$func$
BEGIN
    execute format(&apos;create table tbl_xpto%s as table tbl_xpto&apos;, to_char(now(), &apos;DD_MM_YYYY&apos;));
END;
$func$;
</code></pre><h2 id="um-caso-de-uso-real">Um caso de uso real</h2><p>Vamos criar uma tabela <code>usuario</code> e inserir 4 usu&#xE1;rios.</p><pre><code>CREATE TABLE IF NOT EXISTS usuario (
    id UUID DEFAULT gen_random_uuid(),
    nome VARCHAR(32)
);

INSERT INTO usuario (nome) VALUES (&apos;a&apos;);
INSERT INTO usuario (nome) VALUES (&apos;b&apos;);
INSERT INTO usuario (nome) VALUES (&apos;c&apos;);
INSERT INTO usuario (nome) VALUES (&apos;d&apos;);
</code></pre><p>Agora queremos criar a nossa <em>stored_procedure</em> que vai criar uma nova tabela usuario07_03_2024. A <em>stored_procedure</em> deve ser da seguinte forma:</p><pre><code>CREATE OR REPLACE PROCEDURE CRIAR_TABELA_DATA_HOJE() LANGUAGE plpgsql AS
$func$
BEGIN
    execute format(&apos;create table usuario%s as table usuario&apos;, to_char(now(), &apos;DD_MM_YYYY&apos;));
END;
$func$;
</code></pre><p>Repare que no comando acima, estamos formatando uma data para o formato de string desejado, e o operador possui o mesmo funcionando do formatador de sa&#xED;da no C. Ent&#xE3;o o resultado ser&#xE1; uma data formatada no padr&#xE3;o (DD_MM_YYYY), separada por underline (_)</p><p>Depois para executar a <em>stored_procedure</em> basta executar:</p><pre><code>CALL CRIAR_TABELA_DATA_HOJE()
</code></pre><p>Ao executar o comando deve existir uma nova tabela em seu esquema do banco de dados.</p><p>Para verificar, basta rodar o comando <code>\dt</code></p><pre><code>               List of relations
 Schema |       Name        | Type  |  Owner   
--------+-------------------+-------+----------
 public | usuario           | table | ***
 public | usuario07_03_2024 | table | ***
(2 rows)

=# select * from usuario08_03_2024 ;
                  id                  | nome 
--------------------------------------+------
 2d668121-39b4-4397-ada0-3760f1adccc3 | a
 51f3ec21-61bc-4b42-b7d2-99368b8dd91e | b
 bbbd5aab-db12-4214-a7cc-84149812e94a | c
 6e441abf-dc2e-48c1-a3af-d9cd3a76172f | d
(4 rows)
</code></pre><hr><h2 id="uma-solu%C3%A7%C3%A3o-utilizando-o-shell">Uma solu&#xE7;&#xE3;o utilizando o shell</h2><p>Uma segunda maneira de resolver o problema &#xE9; utilizar o shell para &quot;montar&quot; a data e criar a tabela com o resultado de um alias.</p><p>Segue um exemplo, de como ser&#xE1; o resultado do nome da tabela:</p><pre><code>echo &quot;tbl_xpto_$(printf &apos;%(%d_%m_%Y)T&apos; -1)&quot;
</code></pre><!--kg-card-begin: html--><table>
<thead>
<tr>
<th>Formatador</th>
<th>Descri&#xE7;&#xE3;o</th>
</tr>
</thead>
<tbody>
<tr>
<td>%d</td>
<td>dia</td>
</tr>
<tr>
<td>%m</td>
<td>M&#xEA;s</td>
</tr>
<tr>
<td>%Y</td>
<td>(mai&#xFA;sculo) Ano com 4 d&#xED;gitos</td>
</tr>
</tbody>
</table><!--kg-card-end: html--><p>A tabela completa dos formatadores pode ser vista na documenta&#xE7;&#xE3;o do comando <a href="https://man7.org/linux/man-pages/man1/date.1.html">date</a></p><p>Pronto, agora que j&#xE1; sabe como vai ser o nome da tabela, basta utilizar esta mesma l&#xF3;gica para executar este comando utilizando o psql.</p><p>Segue um exemplo:</p><pre><code>psql -U &lt;usuario&gt; &lt;nome-db&gt; -c &quot;CREATE TABLE tbl_xpto_$(printf &apos;%(%d_%m_%Y)T&apos; -1) AS TABLE tbl_01&quot;
</code></pre><p>Repare que no comando acima, estamos passando o par&#xE2;metro <code>-c</code> e no argumento deste par&#xE2;metro passamos o comando DDL que cria a c&#xF3;pia da tabela.</p><p>Substitua o valor <code>&lt;nome-db&gt;</code> pelo nome do seu banco de dados. Assim como valor do <code>&lt;usuario&gt;</code> pelo nome do seu usu&#xE1;rio correspondente &#xE0; sua configura&#xE7;&#xE3;o do banco de dados.</p><p>Vale ressaltar tamb&#xE9;m que as regras de forma&#xE7;&#xE3;o de nome das tabelas do postgres n&#xE3;o &#xE9; poss&#xED;vel ter nomes com <code>-</code> (dash), mas se gostaria de utilizar o dash no nome da tabela, pode utilizar a forma de nomes de tabelas literais (onde o nome da tabela deve ser envolvido em aspas duplas). Para saber as regras leia a documenta&#xE7;&#xE3;o da sintaxe das <a href="https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS">palavras chaves</a>.</p><p>Ap&#xF3;s a execu&#xE7;&#xE3;o com sucesso, deve ser solicitado a senha do banco de dados.</p><p>Ao final, se tudo ocorrer com sucesso, deve ser exibido a quantidade de linhas contida na tabela.</p><p>Como refer&#xEA;ncias para esta resposta utilizei esta <a href="https://stackoverflow.com/a/1401495/4598175">publica&#xE7;&#xE3;o</a>.</p><p>Al&#xE9;m da documenta&#xE7;&#xE3;o do <a href="https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-copy-table/">Postgres</a></p>]]></content:encoded></item><item><title><![CDATA[Como instalar e configurar o ESlint em um projeto nodejs]]></title><description><![CDATA[<p>Para este tutorial, estou supondo que j&#xE1; possui um projeto escrito em JavaScript, e deseja adicionar o ESlint afim de fazer an&#xE1;lise est&#xE1;tica do c&#xF3;digo procurar por errors de sintaxe, erros de l&#xF3;gica a n&#xED;vel de c&#xF3;digo</p>]]></description><link>https://danizavtz.com.br/como-instalar-e-configurar-o-eslint-em-um-projeto-nodejs/</link><guid isPermaLink="false">65c3f8b2dfa2eb0f8251e4b0</guid><category><![CDATA[nodejs]]></category><category><![CDATA[lint]]></category><category><![CDATA[eslint]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Thu, 08 Feb 2024 01:25:31 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1461749280684-dccba630e2f6?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDEwfHxjb2RlJTIwZXJyb3J8ZW58MHx8fHwxNzA3MzQyMDc3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1461749280684-dccba630e2f6?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDEwfHxjb2RlJTIwZXJyb3J8ZW58MHx8fHwxNzA3MzQyMDc3fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Como instalar e configurar o ESlint em um projeto nodejs"><p>Para este tutorial, estou supondo que j&#xE1; possui um projeto escrito em JavaScript, e deseja adicionar o ESlint afim de fazer an&#xE1;lise est&#xE1;tica do c&#xF3;digo procurar por errors de sintaxe, erros de l&#xF3;gica a n&#xED;vel de c&#xF3;digo e verifica&#xE7;&#xE3;o de estilo de c&#xF3;digo.</p><p>Ent&#xE3;o caso j&#xE1; possua o seu projeto em JavaScript, pode fazer essa configura&#xE7;&#xE3;o em seu projeto diretamente seguindo as instru&#xE7;&#xF5;es contidas aqui.</p><p>Caso n&#xE3;o possua, um projeto voc&#xEA; pode utilizar este projeto de exemplo que criei, e continuar seguindo as intru&#xE7;&#xF5;es para fazer a sua configura&#xE7;&#xE3;o. Este <a href="https://github.com/danizavtz/eslintconfiguration">projeto </a>&#xE9; uma prova de conceito apenas para praticar a configura&#xE7;&#xE3;o do ESlint em um projeto que n&#xE3;o possui o ESlint configurado. Neste projeto &#xE9; que vamos configurar o ESlint do zero.</p><p>Para utilizar a minha prova de conceito, apenas v&#xE1; ao reposit&#xF3;rio e siga as instru&#xE7;&#xF5;es para instala&#xE7;&#xE3;o.</p><ul><li>Clone o projeto</li><li>Instale as depend&#xEA;ncias</li></ul><p>Pronto, agora voc&#xEA; j&#xE1; possui todos os requisitos para fazer a configura&#xE7;&#xE3;o do ESlint.</p><p>Neste tutorial vamos seguir o que orienta a <a href="https://eslint.org/docs/latest/use/getting-started">documenta&#xE7;&#xE3;o </a>sobre como configurar um projeto, para isso, supondo que est&#xE1; na raiz do projeto que acabou de baixar, basta executar o comando:</p><!--kg-card-begin: markdown--><pre><code>  npm init @eslint/config
</code></pre>
<!--kg-card-end: markdown--><p>Ap&#xF3;s executar este comando, essa ser&#xE1; a sa&#xED;da esperada caso d&#xEA; tudo certo:</p><!--kg-card-begin: markdown--><pre><code>Need to install the following packages:
eslint/create-config@0.4.6
Ok to proceed? (y) y
</code></pre>
<!--kg-card-end: markdown--><p>Respondi que sim, e desta forma houve um passo-a-passo no formato de wizard de shell para fazer a configura&#xE7;&#xE3;o do ESlint em meu projeto.</p><p>Para isso v&#xE1; respondendo perguntas de acordo com o estilo e com o problema que o seu aplicativo visa resolver. </p><p>Primeira pergunta, como gostaria de utilizar o ESlint?</p><!--kg-card-begin: markdown--><pre><code>? How would you like to use ESLint?
</code></pre>
<!--kg-card-end: markdown--><p>Alternativas:</p><ul><li>Para verificar apenas a sintaxe</li><li>Para verificar a sintaxe e encontrar problemas</li><li>Para verificar a sintaxe, encontrar problemas e aplicar estilo de c&#xF3;digo</li></ul><p>Na pr&#xF3;xima pergunta temos, que tipo de m&#xF3;dulos seu projeto usa?</p><!--kg-card-begin: markdown--><pre><code>What type of modules does your project use?
</code></pre>
<!--kg-card-end: markdown--><p>Alternativas:</p><ul><li>JavaScript modules (import/export)</li><li>CommonJS (require/exports)</li><li>Nenhum desses</li></ul><p>Pr&#xF3;xima, Qual framework seu projeto usa?</p><!--kg-card-begin: markdown--><pre><code>Which framework does your project use?
</code></pre>
<!--kg-card-end: markdown--><p>Alternativas:</p><ul><li>React</li><li>Vuejs</li><li>Nenhum</li></ul><p>Neste caso selecionamos nenhum, j&#xE1; que o nosso projeto &#xE9; de backend, e n&#xE3;o vamos ter nenhum tipo de framework relacionado &#xE0; backend.</p><p>A seguinte, seu projeto usa TypeScript?</p><!--kg-card-begin: markdown--><pre><code> Does your project use TypeScript?
</code></pre>
<!--kg-card-end: markdown--><p>Aqui &#xE9; simples, sim ou n&#xE3;o.</p><p>Logo em seguida, tem a pr&#xF3;xima, onde seu projeto roda?</p><!--kg-card-begin: markdown--><pre><code>Where does your code run?
</code></pre>
<!--kg-card-end: markdown--><p>Alternativas:</p><ul><li>Navegador</li><li>Node</li></ul><p>Essa pr&#xF3;xima pode ser a &#xFA;ltima pergunta, como voc&#xEA; gostaria de definir um estilo para o seu projeto?</p><!--kg-card-begin: markdown--><pre><code> How would you like to define a style for your project?
</code></pre>
<!--kg-card-end: markdown--><p>Alternativas, aqui temos uma lista de alternativas, que eu sugiro que d&#xEA; uma pesquisada (se ainda n&#xE3;o conhece algum), minha escolha pessoal &#xE9; o standard (&quot;padr&#xE3;o&quot;), mas veja o que melhor se adequa ao seu projeto. Nas alternativas existem links, ent&#xE3;o voc&#xEA; pode acessar diretamente e descobrir a melhor escolha.</p><p>Alternativas:</p><ul><li>Airbnb: <a href="https://github.com/airbnb/javascript">https://github.com/airbnb/javascript</a></li><li>Standard: <a href="https://github.com/standard/standard">https://github.com/standard/standard</a></li><li>Google: <a href="https://github.com/google/eslint-config-google">https://github.com/google/eslint-config-google</a></li><li>XO: <a href="https://github.com/xojs/eslint-config-xo">https://github.com/xojs/eslint-config-xo</a></li></ul><p>mais uma, em que formato voc&#xEA; deseja que seu arquivo de configura&#xE7;&#xE3;o esteja?</p><!--kg-card-begin: markdown--><pre><code>What format do you want your config file to be in?
</code></pre>
<!--kg-card-end: markdown--><p>Neste caso as alternativas s&#xE3;o auto-explicativas.</p><p>a pr&#xF3;xima, ele fez uma verifica&#xE7;&#xE3;o pelas minhas escolhas, e verificou que &#xE9; necess&#xE1;rio mais algumas deped&#xEA;ncias, e perguntou se eu gostaria de instalar. Gostaria de instal&#xE1;-los agora?</p><!--kg-card-begin: markdown--><pre><code>Checking peerDependencies of eslint-config-standard@latest
Local ESLint installation not found.
The config that you&apos;ve selected requires the following dependencies:
eslint-config-standard@latest eslint@^8.0.1 eslint-plugin-import@^2.25.2 eslint-plugin-n@^15.0.0 || ^16.0.0  eslint-plugin-promise@^6.0.0
</code></pre>
<!--kg-card-end: markdown--><p>Aqui fica a seu crit&#xE9;rio, eu respondi que n&#xE3;o, pois n&#xE3;o quero adicionar muitas depend&#xEA;ncias no projeto, aqui eu prefiro ser conservador e manter o m&#xED;nimo poss&#xED;vel de depend&#xEA;ncias no meu projeto, e ir instalando conforme necessidade. Mas fique &#xE0; vontade para instalar as depend&#xEA;ncias.</p><p>Por &#xFA;ltimo, Qual gerenciador de pacotes voc&#xEA; usa?</p><p>Pronto, agora voc&#xEA; j&#xE1; possui o ESlint instalado, e pode executar o lint em qualquer arquivo.</p><p>Basta rodar o comando:</p><!--kg-card-begin: markdown--><pre><code>npx eslint &lt;seuarquivo&gt;.js
</code></pre>
<!--kg-card-end: markdown--><p>Neste caso o nosso projeto possui apenas um arquivo <code>.js</code> (que &#xE9; o arquivo <code>app.js</code>), dessa forma vou executar o ESlint apenas nele.</p><!--kg-card-begin: markdown--><pre><code>npx eslint app.js
</code></pre>
<!--kg-card-end: markdown--><p>Essa deve ser a sa&#xED;da esperada para o comando acima (supondo que n&#xE3;o fez nenhuma mudan&#xE7;a nos arquivos fonte da aplica&#xE7;&#xE3;o).</p><!--kg-card-begin: markdown--><pre><code>1:35  error  Extra semicolon                                semi
3:22  error  Extra semicolon                                semi
5:1   error  Expected indentation of 2 spaces but found 4   indent
5:50  error  Extra semicolon                                semi
6:3   error  Extra semicolon                                semi
7:38  error  Extra semicolon                                semi
8:17  error  Extra semicolon                                semi
9:63  error  Extra semicolon                                semi
9:64  error  Newline required at end of file but not found  eol-last
</code></pre>
<!--kg-card-end: markdown--><p>Aqui uma exibi&#xE7;&#xE3;o simples, uma linha com cada erro que ocorre no arquivo, agora &#xE9; s&#xF3; corrigir os problemas detectados pelo lint.</p><p>Essas verifica&#xE7;&#xF5;es no c&#xF3;digo seguem as regras que est&#xE3;o no arquivo <code>.eslintrc</code> que foi adicionado ao projeto, ap&#xF3;s a execu&#xE7;&#xE3;o do wizard. &#xC9; nesse arquivo que voc&#xEA; pode personalizar as regras que devem ser verificadas ao rodar o comando <code>npx eslint ...</code></p><p>Voc&#xEA; pode adicionar novas regras no n&#xF3; rules, do arquivo <code>.eslintrc</code> , as regras que voc&#xEA; pode adicionar podem ser procuradas na <a href="https://eslint.org/docs/latest/use/configure/rules">documenta&#xE7;&#xE3;o</a>.</p><p>Para esta aplica&#xE7;&#xE3;o e as configura&#xE7;&#xF5;es atuais, eu ainda desejo adicionar mais algumas regras, segue o conte&#xFA;do do meu arquivo (aqui &#xE9; javascript, ent&#xE3;o adapte a solu&#xE7;&#xE3;o para o seu tipo de arquivo [voc&#xEA; escolheu o formato do arquivo durante o wizard]).</p><!--kg-card-begin: markdown--><pre><code>module.exports = {
  env: {
    browser: true,
    commonjs: true,
    es2021: true
  },
  extends: &apos;standard&apos;,
  overrides: [
    {
      env: {
        node: true
      },
      files: [
        &apos;.eslintrc.{js,cjs}&apos;
      ],
      parserOptions: {
        sourceType: &apos;script&apos;
      }
    }
  ],
  parserOptions: {
    ecmaVersion: &apos;latest&apos;
  },
  rules: {
    &apos;no-console&apos;: 2,
        &apos;no-useless-catch&apos;: &apos;off&apos;,
        &apos;indent&apos;: [
            &apos;error&apos;,
            4
        ],
        &apos;linebreak-style&apos;: [
            &apos;error&apos;,
            ((process.platform === &apos;win32&apos; || process.platform === &apos;win64&apos;) ? &apos;windows&apos; : &apos;unix&apos;)
        ],
        &apos;quotes&apos;: [
            &apos;warn&apos;,
            &apos;single&apos;,
        ],
        &apos;semi&apos;: [
            &apos;error&apos;,
            &apos;always&apos;
        ],
        &apos;eol-last&apos;: [
            &apos;error&apos;,
            &apos;always&apos;
        ]
  }
}
</code></pre>
<!--kg-card-end: markdown--><p>Agora, ap&#xF3;s selecionar suas regras de lint para o seu projeto, voc&#xEA; pode criar um novo comando em seu m&#xF3;dulo, para se encarregar desta tarefa de verificar o lint. A vantagem de ter o script &#xE9; pra facilitar as tarefas de automa&#xE7;&#xE3;o de esteira de CI/CD al&#xE9;m de manter mais organizado a execu&#xE7;&#xE3;o das tarefas atrav&#xE9;s do uso de uma unica ferramenta para centralizar o uso, nesse caso o <code>npm</code>. Ent&#xE3;o edite o seu arquivo para &#xA0;<code>package.json</code>. Fazer essa configura&#xE7;&#xE3;o &#xE9; melhor para um caso de uso de projetos de mundo real. </p><p>Em geral, os meus arquivos de implementa&#xE7;&#xE3;o do server (aplicativo express/node) ficam organizados no <code>server</code> ent&#xE3;o eu crio o meu padr&#xE3;o de verifica&#xE7;&#xE3;o de arquivos em pastas da seguinte forma:</p><p>***package.json***</p><!--kg-card-begin: markdown--><pre><code>{
  &quot;name&quot;: &quot;eslintconfiguration&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;app.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;,
    &quot;start&quot;: &quot;node app.js&quot;,
    &quot;dev&quot;: &quot;node --watch app.js&quot;,
    &quot;lint&quot;: &quot;npx eslint server/**/*.js server/*.js lib/*.js app.js&quot;,
  },
  &quot;repository&quot;: {
    &quot;type&quot;: &quot;git&quot;,
    &quot;url&quot;: &quot;git+ssh://git@github.com/danizavtz/eslintconfiguration.git&quot;
  },
  &quot;keywords&quot;: [
    &quot;nodejs&quot;
  ],
  &quot;author&quot;: &quot;danizavtz&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;bugs&quot;: {
    &quot;url&quot;: &quot;https://github.com/danizavtz/eslintconfiguration/issues&quot;
  },
  &quot;homepage&quot;: &quot;https://github.com/danizavtz/eslintconfiguration#readme&quot;,
  &quot;dependencies&quot;: {
    &quot;express&quot;: &quot;^4.18.2&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;eslint&quot;: &quot;^8.56.0&quot;
  }
}
</code></pre>
<!--kg-card-end: markdown--><p>Em destaque a linha que adicionei na se&#xE7;&#xE3;o scripts do meu arquivo <code>package.json</code>.</p><!--kg-card-begin: markdown--><pre><code>&quot;lint&quot;: &quot;npx eslint server/**/*.js server/*.js lib/*.js app.js&quot;,
</code></pre>
<!--kg-card-end: markdown--><p>Nesse caso todas as vezes que eu executar o comando <code>npm run lint</code> ser&#xE3;o verificados com o ESlint:</p><ul><li>todos arquivos com extens&#xE3;o <code>.js</code> que est&#xE3;o nos subdiret&#xF3;rios que est&#xE3;o na pasta <code>server</code> .</li><li>todos os arquivos com extens&#xE3;o <code>.js</code> que est&#xE3;o no diret&#xF3;rio <code>server</code>.</li><li>todos os arquivos com extens&#xE3;o <code>.js</code> que est&#xE3;o no diret&#xF3;rio <code>lib</code>.</li><li>o arquivo <code>app.js</code></li></ul><p>A vantagem de fazer uma configura&#xE7;&#xE3;o assim &#xE9; que automaticamente, se forem adicionados novos arquivos em qualquer um desses diret&#xF3;rios, eles ser&#xE3;o verificados pelas regras descritas acima. Essa &#xE9; apenas uma ideia de como organizar ent&#xE3;o voc&#xEA; pode adaptar para o seu projeto. </p><p>Agora &#xE9; s&#xF3; corrigir os problemas de lint ;-)</p>]]></content:encoded></item><item><title><![CDATA[Servidor Flask local, expor na rede local]]></title><description><![CDATA[<p>Fiz um projeto no Flask e est&#xE1; no server de teste na porta 5000, algu&#xE9;m como fa&#xE7;o para liberar o app para rede local?</p><p>Uma maneira de resolver o problema, &#xE9; setando a vari&#xE1;vel <code>host</code> da sua aplica&#xE7;&#xE3;o Flask para</p>]]></description><link>https://danizavtz.com.br/servidor-flask-local-expor-na-rede-local/</link><guid isPermaLink="false">65c3932ddfa2eb0f8251e422</guid><category><![CDATA[flask]]></category><category><![CDATA[python3]]></category><category><![CDATA[python2]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 07 Feb 2024 16:43:11 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1461749280684-dccba630e2f6?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDEyfHxmbGFzayUyMHdlYnxlbnwwfHx8fDE3MDczMjU2NTl8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1461749280684-dccba630e2f6?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDEyfHxmbGFzayUyMHdlYnxlbnwwfHx8fDE3MDczMjU2NTl8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Servidor Flask local, expor na rede local"><p>Fiz um projeto no Flask e est&#xE1; no server de teste na porta 5000, algu&#xE9;m como fa&#xE7;o para liberar o app para rede local?</p><p>Uma maneira de resolver o problema, &#xE9; setando a vari&#xE1;vel <code>host</code> da sua aplica&#xE7;&#xE3;o Flask para o valor <code>0.0.0.0</code>.</p><p>Segue um exemplo da configura&#xE7;&#xE3;o que deve ser feita:</p><p><strong>hello.py</strong></p><!--kg-card-begin: markdown--><pre><code>from flask import Flask

app = Flask(__name__)

@app.route(&quot;/&quot;)
def hello_world():
    return &quot;&lt;p&gt;Hello, World!&lt;/p&gt;&quot;

if __name__ == &quot;__main__&quot;:
    app.run(host=&apos;0.0.0.0&apos;)
</code></pre>
<!--kg-card-end: markdown--><p>Depois para executar a aplica&#xE7;&#xE3;o, devemos executar com o seguinte comando:</p><p><code>python hello.py</code></p><p>Repare nas mensagens que s&#xE3;o exibidas no shell</p><!--kg-card-begin: markdown--><pre><code>* Serving Flask app &apos;hello&apos;
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://192.168.157.x:5000
</code></pre>
<!--kg-card-end: markdown--><p>Desta forma ser&#xE1; feito o bind da sua aplica&#xE7;&#xE3;o com todos os endere&#xE7;os ip atuais que est&#xE3;o ligados ao seu host e na porta especificada.</p><p>Sua aplica&#xE7;&#xE3;o agora est&#xE1; acess&#xED;vel via a rede local.</p><p>Repare que neste exemplo coloquei um <code>x</code> no &#xFA;ltimo endere&#xE7;o que est&#xE1; no log. Isso n&#xE3;o &#xE9; um endere&#xE7;o IP v&#xE1;lido. Deixei assim proposital para caso acesse este endere&#xE7;o ocorrer um erro. O endere&#xE7;o que voc&#xEA; deve acessar &#xE9; o que est&#xE1; sendo exibido no log da aplica&#xE7;&#xE3;o, no shell do seu interpretador Python.</p><p>Voc&#xEA; pode acessar esta aplica&#xE7;&#xE3;o completa no <a href="https://github.com/danizavtz/flaskapplocalconfig">github</a>.</p><h2 id="configura%C3%A7%C3%A3o-via-linha-de-comando">Configura&#xE7;&#xE3;o via linha de comando</h2><p>Tamb&#xE9;m &#xE9; poss&#xED;vel configurar o host via linha de comando, neste caso basta utilizar o comando:</p><!--kg-card-begin: markdown--><pre><code>flask --app hello run --host 0.0.0.0
</code></pre>
<!--kg-card-end: markdown--><p>Repare que aqui a ordem dos argumentos &#xE9; importante e o <code>--host</code> deve ser ap&#xF3;s o comando <code>run</code>. Neste caso estou supondo que o script escrito em Python se chamada <code>hello.py</code>.</p><p>Para mais informa&#xE7;&#xF5;es consulte a <a href="https://flask.palletsprojects.com/en/3.0.x/api/#flask.Flask.run">documenta&#xE7;&#xE3;o</a>.</p>]]></content:encoded></item><item><title><![CDATA[Erro no NPM run dev]]></title><description><![CDATA[<p>Estou digitando na linha de comando <code>npm run dev</code> e est&#xE1; retornando esse erro:</p><pre><code class="language-coffeescript">npm ERR! Missing script: &quot;dev&quot;
npm ERR!
npm ERR! To see a list of scripts, run:
npm ERR!   npm run</code></pre><p>Isso ocorre porque n&#xE3;o foi poss&#xED;vel localizar o comando</p>]]></description><link>https://danizavtz.com.br/erro-no-npm-run-dev/</link><guid isPermaLink="false">65b9365ddfa2eb0f8251e2d8</guid><category><![CDATA[nodejs]]></category><category><![CDATA[npm]]></category><category><![CDATA[scripts]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 31 Jan 2024 00:34:53 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1543966888-7c1dc482a810?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG5wbXxlbnwwfHx8fDE3MDY2NjEyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1543966888-7c1dc482a810?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG5wbXxlbnwwfHx8fDE3MDY2NjEyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Erro no NPM run dev"><p>Estou digitando na linha de comando <code>npm run dev</code> e est&#xE1; retornando esse erro:</p><pre><code class="language-coffeescript">npm ERR! Missing script: &quot;dev&quot;
npm ERR!
npm ERR! To see a list of scripts, run:
npm ERR!   npm run</code></pre><p>Isso ocorre porque n&#xE3;o foi poss&#xED;vel localizar o comando dev em seu arquivo <code>package.json</code></p><p>O seu package.json &#xE9; considerado um arquivo <a href="https://pt.stackoverflow.com/q/137147/103217">manifest </a>do seu projeto em javascript (ou nodejs). Se voc&#xEA; j&#xE1; utilizou algum javascript minimamente moderno de alguma maneira voc&#xEA; j&#xE1; interagiu com o npm.</p><p>Quando criamos um package.json ele possui uma se&#xE7;&#xE3;o scripts, que na verdade &#xE9; apenas um n&#xF3; do json em que possui <code>alias</code> para outros comandos. Nesta se&#xE7;&#xE3;o do arquivo &#xE9; que podemos modificar para adicionar o script que est&#xE1; faltando.</p><p>Se voc&#xEA; nunca criou uma aplica&#xE7;&#xE3;o em javascript do zero. Possivelmente n&#xE3;o precisou criar um package.json. A maneira correta de fazer isso &#xE9; via o comando <code>npm init</code></p><p>ao executar este comando, vamos responder algumas perguntas de alguns campos obrigat&#xF3;rios, estas perguntas segue o modelo wizard (que &#xE9; feito no pr&#xF3;prio shell).</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2024/01/npminit.gif.gif" class="kg-image" alt="Erro no NPM run dev" loading="lazy" width="1117" height="578"></figure><p>Ao final da execu&#xE7;&#xE3;o do comando <code>npm init</code> o <code>package.json</code> gerado fica assim:</p><!--kg-card-begin: markdown--><pre><code>{
  &quot;name&quot;: &quot;newproj&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;test&quot;,
  &quot;main&quot;: &quot;app.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;
  },
  &quot;keywords&quot;: [
    &quot;nodejs&quot;
  ],
  &quot;author&quot;: &quot;danizavtz&quot;,
  &quot;license&quot;: &quot;ISC&quot;
}
</code></pre>
<!--kg-card-end: markdown--><p>O conte&#xFA;do do arquivo vai variar, pois depende das perguntas respondidas previamente. Veja que neste arquivo gerado, existe a se&#xE7;&#xE3;o <code>scripts</code> &#xE9; l&#xE1; que devemos adicionar scripts ao projeto, temos &quot;por padr&#xE3;o&quot; um comando <code>test</code> (e esse &#xE9; o &#xFA;nico script em nosso <code>package.json</code> gerado via linha de comando), vamos executar ele para ver o que acontece.</p><!--kg-card-begin: markdown--><blockquote>
<pre><code>npm run test

&gt; newproj@1.0.0 test
&gt; echo &quot;Error: no test specified&quot; &amp;&amp; exit 1

Error: no test specified
</code></pre>
</blockquote>
<!--kg-card-end: markdown--><p>Ele est&#xE1; fazendo explicitamente o que est&#xE1; determinado l&#xE1; no n&#xF3; <code>test</code> da nossa se&#xE7;&#xE3;o scripts. Que &#xE9;, </p><ul><li>executar o comando <a href="https://linuxcommand.org/lc3_man_pages/echoh.html">echo</a></li><li>sair com c&#xF3;digo 1</li></ul><p>O comando echo vai escrever argumentos na linha de comando. O retorno zero <strong>indica ao SO que o programa foi bem sucedido</strong>. Cada outro n&#xFA;mero retornado indica o c&#xF3;digo de uma condi&#xE7;&#xE3;o de erro. Como explicitamente estamos retornando 1 isso ser&#xE1; interpretado como uma condi&#xE7;&#xE3;o de erro.</p><p>Um script npm &#xE9; uma maneira de agrupar tarefas comuns. Podem ser comandos de terminal ou uma sequencia de tarefas que ajudam a automatizar tarefas repetitivas.</p><p>Em geral as tarefas mais comuns de serem executadas s&#xE3;o:</p><ul><li>levantar um servidor e deixar ele no modo listening</li><li>rodar uma especie de live-reloading para ajudar no desenvolvimento</li><li>executar linter</li><li>executar testes</li><li>gerar uma build</li><li>minificar c&#xF3;digo fonte</li><li>ofuscar c&#xF3;digo fonte</li></ul><p>Estes scripts declarados no <code>package.json</code> podem ser usados para auxiliar no momento de deploy e na escrita da pipeline de integra&#xE7;&#xE3;o cont&#xED;nua e entrega cont&#xED;nua do projeto (CI/CD).</p><p>Ent&#xE3;o quando criamos um projeto utilizando nodejs do zero, o &#xFA;nico script que &#xE9; inclu&#xED;do no <code>package.json</code> &#xE9; o script <code>test</code>, que apenas exibe a seguinte mensagem no terminal: <code>Error: no test specified</code>.</p><p>Ent&#xE3;o, se o <code>package.json</code> n&#xE3;o possui o script <code>dev</code> ent&#xE3;o basta criar este script e depois invocar o mesmo.</p><h2 id="como-criar-um-novo-script">Como criar um novo script</h2><p>Afim de criar um novo script no <code>package.json</code> abra o seu editor de texto e apenas adicione a seguinte linha.</p><!--kg-card-begin: markdown--><pre><code>&quot;dev&quot;: &quot;echo dev&quot;
</code></pre>
<!--kg-card-end: markdown--><p>Segue o package.json completo.</p><!--kg-card-begin: markdown--><pre><code>{
  &quot;name&quot;: &quot;newproj&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;test&quot;,
  &quot;main&quot;: &quot;app.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;,
    &quot;dev&quot;: &quot;echo dev&quot;

  },
  &quot;keywords&quot;: [
    &quot;nodejs&quot;
  ],
  &quot;author&quot;: &quot;danizavtz&quot;,
  &quot;license&quot;: &quot;ISC&quot;
}
</code></pre>
<!--kg-card-end: markdown--><p>Agora ao executar o comando <code>npm run dev</code> agora ser&#xE1; exibida a mensagem <code>dev</code> no terminal.</p><!--kg-card-begin: markdown--><blockquote>
<pre><code>&gt; newproj@1.0.0 dev
&gt; echo dev

dev
</code></pre>
</blockquote>
<!--kg-card-end: markdown--><p>Pronto, agora voc&#xEA; j&#xE1; possui um script dev em seu package.json</p><p>Realmente, em alguns frameworks, como angular/react/vuejs, como eles utilizam ferramentas de linha de comando para criar um novo projeto, eles j&#xE1; facilitam a vida do desenvolvedor e criam alguns scripts pensando em experi&#xEA;ncia do desenvolvimento. Ent&#xE3;o &#xE9; comum vermos alguns scripts a mais, em nosso package.json. </p><p>Em angular por exemplo, temos os seguintes scripts:</p><!--kg-card-begin: markdown--><pre><code>{
//...
&quot;scripts&quot;: {
    &quot;ng&quot;: &quot;ng&quot;,
    &quot;start&quot;: &quot;ng serve -c -o&quot;,
    &quot;build&quot;: &quot;ng build&quot;,
    &quot;watch&quot;: &quot;ng build --watch --configuration development&quot;,
    &quot;test&quot;: &quot;ng test&quot;,
    &quot;e2e&quot;: &quot;ng e2e&quot;,
    &quot;staging&quot;: &quot;ng build --configuration=staging&quot;,
    &quot;qa&quot;: &quot;ng build --configuration=qa --base-href=/qa/&quot;,
    &quot;cypress:open&quot;: &quot;cypress open&quot;,
    &quot;cypress:run&quot;: &quot;cypress run&quot;,
    &quot;lint&quot;: &quot;ng lint&quot;
  },
//...
}
</code></pre>
<!--kg-card-end: markdown--><p>Em vuejs:</p><!--kg-card-begin: markdown--><pre><code>{
//...
&quot;scripts&quot;: {
     &quot;serve&quot;: &quot;vue-cli-service serve&quot;,
     &quot;build&quot;: &quot;vue-cli-service build&quot;,
     &quot;test:unit&quot;: &quot;vue-cli-service test:unit&quot;,
     &quot;test:e2e&quot;: &quot;vue-cli-service test:e2e&quot;,
     &quot;lint&quot;: &quot;vue-cli-service lint&quot;
},
//...
}
</code></pre>
<!--kg-card-end: markdown--><p>Ent&#xE3;o fica &#xE0; crit&#xE9;rio do desenvolvedor, criar o script.</p><p>Em meus projetos pessoais de backend, eu crio os scripts, e em geral &#xE9; pra executar os testes, exibir a cobertura dos testes, e executar a aplica&#xE7;&#xE3;o do backend em uma esp&#xE9;cie de live-reload (quando existem mudan&#xE7;as), que nada mais &#xE9; do que executar o backend via o node, passando como argumento o <code>--watch</code>.</p><p>Ent&#xE3;o em meu projeto, personalizo o script de dev, para o seguinte:</p><!--kg-card-begin: markdown--><pre><code>&quot;dev&quot;: &quot;node --watch bin/www&quot;,
</code></pre>
<!--kg-card-end: markdown--><p>Para utilizar o node com o argumento --watch &#xE9; necess&#xE1;rio ter instalado a vers&#xE3;o do nodejs &gt; 18.0.0.</p><p>Um exemplo de um package.json &quot;do mundo real&quot; pode ser visto <a href="https://github.com/danizavtz/tokenAuth/blob/master/package.json">aqui</a>.</p>]]></content:encoded></item><item><title><![CDATA[Como baixar um arquivo através do download do navegador? Utilizando nodejs]]></title><description><![CDATA[<p>Possuo um endpoint que j&#xE1; funciona e retorna JSON. &#xC9; um endpoint que retorna uma lista de itens, e desejo que quando o usu&#xE1;rio chamar o endpoint o navegador execute a a&#xE7;&#xE3;o padr&#xE3;o de fazer o download, e consequentemente salve o arquivo</p>]]></description><link>https://danizavtz.com.br/como-baixar-um-arquivo-atraves-do-download-do-navegador-utilizando-nodejs/</link><guid isPermaLink="false">65b809ecdfa2eb0f8251e1cc</guid><category><![CDATA[nodejs]]></category><category><![CDATA[download]]></category><category><![CDATA[browser]]></category><category><![CDATA[attachment]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Tue, 30 Jan 2024 13:49:17 GMT</pubDate><media:content url="https://danizavtz.com.br/content/images/2024/01/usuarios-download.png" medium="image"/><content:encoded><![CDATA[<img src="https://danizavtz.com.br/content/images/2024/01/usuarios-download.png" alt="Como baixar um arquivo atrav&#xE9;s do download do navegador? Utilizando nodejs"><p>Possuo um endpoint que j&#xE1; funciona e retorna JSON. &#xC9; um endpoint que retorna uma lista de itens, e desejo que quando o usu&#xE1;rio chamar o endpoint o navegador execute a a&#xE7;&#xE3;o padr&#xE3;o de fazer o download, e consequentemente salve o arquivo no diret&#xF3;rio configurado como padr&#xE3;o para baixar.</p><p>Esse &#xE9; o fluxo que desejo implementar, desta forma, vamos mostrar atrav&#xE9;s de um exemplo concreto como programar esta funcionalidade.</p><p>Do ponto de vista de implementa&#xE7;&#xE3;o tudo isso pode ser conseguido atrav&#xE9;s de mudan&#xE7;as no backend.</p><p>Vamos ent&#xE3;o para a estrutura de dados:</p><!--kg-card-begin: markdown--><pre><code>[{
    &quot;id&quot; : &quot;f7379ae8-8f9b-4cd5-8221-51efe19e721b&quot;,
    &quot;apelido&quot; : &quot;jos&#xE9;&quot;,
    &quot;nome&quot; : &quot;Jos&#xE9; Roberto&quot;,
    &quot;nascimento&quot; : &quot;2000-10-01&quot;,
    &quot;stack&quot; : [&quot;C#&quot;, &quot;Node&quot;, &quot;Oracle&quot;]
},
{
    &quot;id&quot; : &quot;5ce4668c-4710-4cfb-ae5f-38988d6d49cb&quot;,
    &quot;apelido&quot; : &quot;ana&quot;,
    &quot;nome&quot; : &quot;Ana Barbosa&quot;,
    &quot;nascimento&quot; : &quot;1985-09-23&quot;,
    &quot;stack&quot; : [&quot;Node&quot;, &quot;Postgres&quot;]
}]
</code></pre>
<!--kg-card-end: markdown--><p>Em nosso servi&#xE7;o, temos um array composto por um<code>usuario</code> que foi definida na <code><a href="https://github.com/zanfranceschi/rinha-de-backend-2023-q3/blob/main/INSTRUCOES.md">rinha de backend</a></code>.</p><p>Temos agora uma abstra&#xE7;&#xE3;o de um usu&#xE1;rio. Dessa forma vamos implementar um endpoint para recuperar estas informa&#xE7;&#xF5;es. Segue a defini&#xE7;&#xE3;o do servi&#xE7;o, que &#xE9; uma aplica&#xE7;&#xE3;o em nodejs que utiliza o express (estou supondo que j&#xE1; possui uma configura&#xE7;&#xE3;o inicial de um projeto express, esta tarefa &#xE9; trivial mas se quer um exemplo que mostra como fazer a configura&#xE7;&#xE3;o inicial, pode ler esta postagem):</p><!--kg-card-begin: markdown--><pre><code>const express = require(&apos;express&apos;)
const app = express()
app.use(express.json())

app.get(&apos;/usuarios&apos;, (req, res) =&gt; {
    const usuarios = [{
        &quot;id&quot; : &quot;f7379ae8-8f9b-4cd5-8221-51efe19e721b&quot;,
        &quot;apelido&quot; : &quot;jos&#xE9;&quot;,
        &quot;nome&quot; : &quot;Jos&#xE9; Roberto&quot;,
        &quot;nascimento&quot; : &quot;2000-10-01&quot;,
        &quot;stack&quot; : [&quot;C#&quot;, &quot;Node&quot;, &quot;Oracle&quot;]
    },
    {
        &quot;id&quot; : &quot;5ce4668c-4710-4cfb-ae5f-38988d6d49cb&quot;,
        &quot;apelido&quot; : &quot;ana&quot;,
        &quot;nome&quot; : &quot;Ana Barbosa&quot;,
        &quot;nascimento&quot; : &quot;1985-09-23&quot;,
        &quot;stack&quot; : [&quot;Node&quot;, &quot;Postgres&quot;]
    }];
    res.status(200).json(usuarios)
})
</code></pre>
<!--kg-card-end: markdown--><p>J&#xE1; temos um servi&#xE7;o com uma rota que retorna todos os usu&#xE1;rios.</p><h2 id="criando-uma-rota-que-retorna-um-arquivo-para-download-json">Criando uma rota que retorna um arquivo para download JSON</h2><p>J&#xE1; temos a rota que retorna os dados que desejamos que &#xE9; a rota <code>/usuarios</code>. Agora &#xE9; s&#xF3; fazer o envio destes mesmos dados no formato json.</p><p>Para isso vamos apenas adicionar o header <code>Content-Type</code> com os valores <code>application/json</code> e adicionar o header <code>&apos;Content-Disposition</code> com o valor <code>&apos;attachment; filename=test.json&apos;</code></p><p>Esse header &#xE9; o que vai realmente fazer a m&#xE1;gica acontecer.</p><p>Dessa forma criarei uma nova rota <code>/usuarios/download</code> que cont&#xE9;m essa implementa&#xE7;&#xE3;o:</p><!--kg-card-begin: markdown--><pre><code>app.get(&apos;/usuarios/download&apos;, (req, res) =&gt; {
        const usuarios = [{
            &quot;id&quot; : &quot;f7379ae8-8f9b-4cd5-8221-51efe19e721b&quot;,
            &quot;apelido&quot; : &quot;jos&#xE9;&quot;,
            &quot;nome&quot; : &quot;Jos&#xE9; Roberto&quot;,
            &quot;nascimento&quot; : &quot;2000-10-01&quot;,
            &quot;stack&quot; : [&quot;C#&quot;, &quot;Node&quot;, &quot;Oracle&quot;]
        },
        {
            &quot;id&quot; : &quot;5ce4668c-4710-4cfb-ae5f-38988d6d49cb&quot;,
            &quot;apelido&quot; : &quot;ana&quot;,
            &quot;nome&quot; : &quot;Ana Barbosa&quot;,
            &quot;nascimento&quot; : &quot;1985-09-23&quot;,
            &quot;stack&quot; : [&quot;Node&quot;, &quot;Postgres&quot;]
        }];
        res.setHeader(&apos;Content-Disposition&apos;, &apos;attachment; filename=test.json&apos;);
        res.status(200).send(usuarios).end()
    })
</code></pre>
<!--kg-card-end: markdown--><p>Repare que aqui o nome do arquivo &#xE9; <code>test.json</code> (voc&#xEA; pode substituir pelo nome que desejar, desde que sigam as restri&#xE7;&#xF5;es definidas na <a href="https://www.rfc-editor.org/rfc/rfc6266">RFC 6266</a>, que versa sobre o campo header Content-Disposition).</p><p>Outra maneira de implementar esta mesma funcionalidade &#xE9; usar a fun&#xE7;&#xE3;o helper implementada pelo express <code>download</code>. Segue um exemplo de como podemos utilizar a fun&#xE7;&#xE3;o download.</p><!--kg-card-begin: markdown--><pre><code>const fs = require(&apos;fs&apos;);
//...
app.get(&apos;/usuarios/download&apos;, (req, res) =&gt; {
    const usuarios = [{
        &quot;id&quot; : &quot;f7379ae8-8f9b-4cd5-8221-51efe19e721b&quot;,
        &quot;apelido&quot; : &quot;jos&#xE9;&quot;,
        &quot;nome&quot; : &quot;Jos&#xE9; Roberto&quot;,
        &quot;nascimento&quot; : &quot;2000-10-01&quot;,
        &quot;stack&quot; : [&quot;C#&quot;, &quot;Node&quot;, &quot;Oracle&quot;]
    },
    {
        &quot;id&quot; : &quot;5ce4668c-4710-4cfb-ae5f-38988d6d49cb&quot;,
        &quot;apelido&quot; : &quot;ana&quot;,
        &quot;nome&quot; : &quot;Ana Barbosa&quot;,
        &quot;nascimento&quot; : &quot;1985-09-23&quot;,
        &quot;stack&quot; : [&quot;Node&quot;, &quot;Postgres&quot;]
    }];
    fs.writeFileSync(&apos;data.json&apos;, usuarios);
    res.download(&apos;data.json&apos;, &apos;test.json&apos;);
});
</code></pre>
<!--kg-card-end: markdown--><p>Veja que nesse exemplo foi necess&#xE1;rio utilizar a fun&#xE7;&#xE3;o <code>fs</code> que manipula arquivos. Dessa forma vamos escrever no sistema de arquivos um arquivo que possui o nome <code>data.json</code> e ap&#xF3;s escrever o conte&#xFA;do da vari&#xE1;vel <code>usuario</code> neste arquivo, fazemos o envio deste arquivo para o cliente, atrav&#xE9;s da chamada da fun&#xE7;&#xE3;o <a href="http://expressjs.com/pt-br/api.html#res.download">download</a>. A defini&#xE7;&#xE3;o do servi&#xE7;o completo pode ser visto <a href="https://github.com/danizavtz/contentasattachmentdownload">aqui</a>.</p><p>Obrigado</p>]]></content:encoded></item><item><title><![CDATA[Insert com caracteres aleatórios PostgreSQL]]></title><description><![CDATA[<p>Sim, &#xE9; poss&#xED;vel, uma implementa&#xE7;&#xE3;o simples, pode ser a utiliza&#xE7;&#xE3;o da fun&#xE7;&#xE3;o <a href="https://www.postgresql.org/docs/8.2/functions-math.html">random</a>, essa fun&#xE7;&#xE3;o vai gerar um n&#xFA;mero aleat&#xF3;rio entre 0 e 1, em composi&#xE7;&#xE3;o com a fun&</p>]]></description><link>https://danizavtz.com.br/insert-com-caracteres-aleatorios-postgresql/</link><guid isPermaLink="false">654bc8eadfa2eb0f8251e1aa</guid><category><![CDATA[postgres]]></category><category><![CDATA[sql]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 08 Nov 2023 17:45:23 GMT</pubDate><content:encoded><![CDATA[<p>Sim, &#xE9; poss&#xED;vel, uma implementa&#xE7;&#xE3;o simples, pode ser a utiliza&#xE7;&#xE3;o da fun&#xE7;&#xE3;o <a href="https://www.postgresql.org/docs/8.2/functions-math.html">random</a>, essa fun&#xE7;&#xE3;o vai gerar um n&#xFA;mero aleat&#xF3;rio entre 0 e 1, em composi&#xE7;&#xE3;o com a fun&#xE7;&#xE3;o <a href="https://www.postgresql.org/docs/8.2/functions-math.html">md5</a>, essa fun&#xE7;&#xE3;o vai gerar um hash md5 de uma string.</p><p>Dessa forma, voc&#xEA; pode executar o seguinte comando:</p><pre><code>SELECT md5(random()::text);
</code></pre><p>Repare que na fun&#xE7;&#xE3;o acima estamos fazendo uma convers&#xE3;o do valor gerado na fun&#xE7;&#xE3;o random() para o tipo <code>text</code> (um tipo equivalente &#xE0; <code>string</code>).</p><hr><h2 id="gerando-uuid">Gerando UUID</h2><p>Se quer gerar valores do tipo UUID ent&#xE3;o a partir da vers&#xE3;o 13 do postgres &#xE9; poss&#xED;vel utilizar a fun&#xE7;&#xE3;o <a href="https://www.postgresql.org/docs/13/functions-uuid.html">gen_random_uuid</a></p><pre><code>SELECT gen_random_uuid()
</code></pre><h2 id="um-exemplo-de-utiliza%C3%A7%C3%A3o">Um exemplo de utiliza&#xE7;&#xE3;o</h2><p>Suponha que temos o seguinte esquema:</p><pre><code>CREATE TABLE IF NOT EXISTS usuario (
    id UUID DEFAULT gen_random_uuid(),
    nome VARCHAR(32),
    sobrenome VARCHAR(32),
    username VARCHAR(32) UNIQUE,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS verificacao (
    usuario_id UUID REFERENCES usuario(id),
    token VARCHAR(32) NOT NULL,
    criadoem TIMESTAMP
);
</code></pre><p>Desejamos que sempre que seja adicionado um novo usu&#xE1;rio na tabela <code>usuario</code>, seja adicionada uma nova linha na tabela <code>verificacao</code>.</p><p>O fluxo acima pode ser implementado utilizando <a href="https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-MODIFYING">Common Table Expressions</a> usando uma express&#xE3;o auxiliar <code>novo_usuario</code> vamos inserir um novo valor na tabela <code>verificacao</code>:</p><pre><code>WITH novo_usuario AS (
    INSERT INTO usuario (nome, sobrenome, username) VALUES (&apos;eu&apos;, &apos;pessoa&apos;, &apos;eu&apos;) RETURNING id
  )
  INSERT INTO verificacao(usuario_id, token, criadoem) VALUES ((SELECT id FROM novo_usuario), md5(random()::text), now());
</code></pre><p>Depois podemos verificar que a inser&#xE7;&#xE3;o foi feita corretamente da seguinte forma:</p><pre><code>select * from usuario u inner join verificacao v ON (u.id = v.usuario_id);
</code></pre><h3 id="uma-implementa%C3%A7%C3%A3o-utilizando-trigger">Uma implementa&#xE7;&#xE3;o utilizando trigger</h3><p>Outra maneira de implementar este mesmo fluxo &#xE9; atrav&#xE9;s de um <a href="https://www.postgresql.org/docs/16/sql-createtrigger.html">gatilho</a> (trigger) que vai reagir a um evento de nova linha na tabela <code>usuario</code>, e pode ser feito da seguinte forma:</p><pre><code>CREATE OR REPLACE FUNCTION adicionar_nova_verificacao()  RETURNS TRIGGER 
  LANGUAGE PLPGSQL
  AS
$$
BEGIN
    INSERT INTO verificacao(usuario_id, token, criadoem) VALUES (NEW.id, md5(random()::text), now());
    RETURN NEW;
END;
$$

CREATE OR REPLACE TRIGGER adicionar_verificacao AFTER INSERT ON usuario 
REFERENCING NEW TABLE AS novo_usuario
FOR EACH ROW
EXECUTE FUNCTION adicionar_nova_verificacao();
</code></pre><p>Depois para verificar o funcionamento da fun&#xE7;&#xE3;o basta inserir uma nova linha na tabela <code>usuario</code>.</p><pre><code>INSERT INTO usuario (nome, sobrenome, username) VALUES (&apos;eu&apos;, &apos;pessoa&apos;, &apos;eu&apos;);
</code></pre><p>Depois para verificar o funcionamento correto, basta executar a seguinte consulta:</p><pre><code>SELECT * FROM usuario u INNER JOIN verificacao v ON (u.id = v.usuario_id);
</code></pre><p>O resultado dessa consulta &#xE9; que deve haver pelo menos uma linha (caso tenha adicionado apenas uma linha na tabela <code>usuario</code>) em que as colunas <code>usuario_id</code> e <code>id</code> s&#xE3;o iguais.</p><p>No nosso caso os valores aleat&#xF3;rios que s&#xE3;o inseridos s&#xE3;o os valores da coluna <code>token</code> da tabela <code>verificacao</code> no qual o s&#xE3;o obtidos atrav&#xE9;s da &#xA0;composi&#xE7;&#xE3;o da fun&#xE7;&#xE3;o <code>md5</code> e a fun&#xE7;&#xE3;o <code>random</code>.</p>]]></content:encoded></item><item><title><![CDATA[Adicionar informação da cobertura ao Sonarqube]]></title><description><![CDATA[<p>Segundo a <a href="https://docs.sonarsource.com/sonarqube/9.8/analyzing-source-code/test-coverage/javascript-typescript-test-coverage/">documenta&#xE7;&#xE3;o</a>:</p><blockquote>SonarQube oferece suporte ao relat&#xF3;rio de informa&#xE7;&#xF5;es de cobertura de teste como parte da an&#xE1;lise do seu projeto JS/TS.</blockquote><blockquote>No entanto, o SonarQube n&#xE3;o gera o pr&#xF3;prio relat&#xF3;rio de cobertura.</blockquote>]]></description><link>https://danizavtz.com.br/adicionar-informacao-da-cobertura-ao-sonar/</link><guid isPermaLink="false">654385d9dfa2eb0f8251e01c</guid><category><![CDATA[sonar]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Thu, 02 Nov 2023 14:27:55 GMT</pubDate><media:content url="https://danizavtz.com.br/content/images/2023/11/sonarqube.png" medium="image"/><content:encoded><![CDATA[<img src="https://danizavtz.com.br/content/images/2023/11/sonarqube.png" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube"><p>Segundo a <a href="https://docs.sonarsource.com/sonarqube/9.8/analyzing-source-code/test-coverage/javascript-typescript-test-coverage/">documenta&#xE7;&#xE3;o</a>:</p><blockquote>SonarQube oferece suporte ao relat&#xF3;rio de informa&#xE7;&#xF5;es de cobertura de teste como parte da an&#xE1;lise do seu projeto JS/TS.</blockquote><blockquote>No entanto, o SonarQube n&#xE3;o gera o pr&#xF3;prio relat&#xF3;rio de cobertura. Em vez disso, voc&#xEA; deve configurar uma ferramenta de terceiros para produzir o relat&#xF3;rio como parte do seu processo de constru&#xE7;&#xE3;o. Em seguida, voc&#xEA; precisa configurar sua an&#xE1;lise para informar ao SonarScanner onde o relat&#xF3;rio est&#xE1; localizado, para que ele possa peg&#xE1;-lo e envi&#xE1;-lo ao SonarQube, onde ser&#xE1; exibido no painel do seu projeto junto com as demais m&#xE9;tricas de an&#xE1;lise.</blockquote><blockquote>Para projetos JS/TS, o SonarQube oferece suporte direto a todas as ferramentas de cobertura que produzem relat&#xF3;rios no formato LCOV. Al&#xE9;m disso, um formato de cobertura gen&#xE9;rico tamb&#xE9;m &#xE9; suportado se voc&#xEA; desejar usar uma ferramenta n&#xE3;o suportada (embora voc&#xEA; mesmo tenha que converter sua sa&#xED;da para o formato gen&#xE9;rico).</blockquote><p>Sabendo disso vamos integrar essa informa&#xE7;&#xE3;o ao sonar afim de ser poss&#xED;vel ler a informa&#xE7;&#xE3;o da cobertura, essa informa&#xE7;&#xE3;o &#xE9; gerada atrav&#xE9;s de outras ferramentas de terceiros que prov&#xEA;m os dados de cobertura no formato <code>lcov</code>, o sonar l&#xEA; essas informa&#xE7;&#xF5;es e disponibiliza como parte da an&#xE1;lise.</p><p>Neste mesmo link, que compartilhei acima, existe um passo a passo para adicionar a informa&#xE7;&#xE3;o da cobertura ao seu projeto. O objetivo desta publica&#xE7;&#xE3;o &#xE9; adicionar a informa&#xE7;&#xE3;o da cobertura ao sonar.</p><p>Requisitos:</p><ul><li>Ter um servidor sonar configurado</li><li>Ter um cliente sonar configurado</li></ul><p>Para isso vamos utilizar o projeto <a href="https://github.com/danizavtz/tokenAuthDatastore">tokenAuthDatastore</a>, que &#xE9; um c&#xF3;digo fonte p&#xFA;blico que pode ser utilizado para testar essa configura&#xE7;&#xE3;o, ap&#xF3;s finalizar a leitura isso voc&#xEA; pode integrar ao seu projeto. Esse projeto tokenAuthDatastore j&#xE1; possui bibliotecas para execu&#xE7;&#xE3;o e gera&#xE7;&#xE3;o de informa&#xE7;&#xE3;o da cobertura. As ferramentas que utilizei neste projeto podem ser vistas nas configura&#xE7;&#xF5;es do <code>package.json</code></p><!--kg-card-begin: markdown--><pre><code>chai, mocha, nyc, sinon, supertest
</code></pre>
<!--kg-card-end: markdown--><p>Vamos ao passo-a-passo:</p><p>clone o projeto:</p><!--kg-card-begin: markdown--><pre><code>  git clone git@github.com:danizavtz/tokenAuthDatastore.git
</code></pre>
<!--kg-card-end: markdown--><p>entre no diret&#xF3;rio do projeto que foi clonado e instale as depend&#xEA;ncias:</p><!--kg-card-begin: markdown--><pre><code>cd tokenAuthDatastore
npm install
</code></pre>
<!--kg-card-end: markdown--><p>Agora basta executar os testes de cobertura neste projeto. Ao executar os testes de cobertura ser&#xE3;o gerados meta-dados de cobertura do seu c&#xF3;digo fonte no diret&#xF3;rio &#xA0;<code>.nyc_output</code> &#xE9; a partir dessas informa&#xE7;&#xF5;es que ser&#xE1; gerado o relat&#xF3;rio de cobertura.</p><p>Sabendo disso, vamos executar a cobertura do c&#xF3;digo:</p><!--kg-card-begin: markdown--><pre><code>npm run coverage
</code></pre>
<!--kg-card-end: markdown--><p>Ap&#xF3;s executar a cobertura, gerar a informa&#xE7;&#xE3;o de cobertura, com o seguinte comando:</p><!--kg-card-begin: markdown--><pre><code>npm run report-coverage
</code></pre>
<!--kg-card-end: markdown--><p>A partir dos meta-dados ser&#xE1; gerado um novo arquivo na raiz do projeto, o arquivo <code>coverage.lcov</code>. </p><p>&#xC9; esse arquivo que vai servir de insumo para gerar a informa&#xE7;&#xE3;o de cobertura exibida no sonar. Agora basta executar a sua automa&#xE7;&#xE3;o do sonar para ler este arquivo.</p><p>Agora vamos configurar este projeto no sonar, vamos fazer a configura&#xE7;&#xE3;o local, para isso siga os passos da interface gr&#xE1;fica do sonar:</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/criarprojeto.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="1206" height="173" srcset="https://danizavtz.com.br/content/images/size/w600/2023/11/criarprojeto.png 600w, https://danizavtz.com.br/content/images/size/w1000/2023/11/criarprojeto.png 1000w, https://danizavtz.com.br/content/images/2023/11/criarprojeto.png 1206w" sizes="(min-width: 720px) 720px"></figure><p>Preencha as informa&#xE7;&#xF5;es do projeto na p&#xE1;gina seguinte:</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/createproject-1.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="712" height="556" srcset="https://danizavtz.com.br/content/images/size/w600/2023/11/createproject-1.png 600w, https://danizavtz.com.br/content/images/2023/11/createproject-1.png 712w"></figure><p>Repare que no campo <code>main branch name</code>o nome da branch &#xE9; o mesmo nome da branch que eu clonei o meu projeto, que neste caso &#xE9; a branch master. (voc&#xEA; pode verificar esta informa&#xE7;&#xE3;o, executando o comando: <code>git &#xA0;branch</code> no diret&#xF3;rio raiz do projeto que deseja configurar).</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/analysismethod.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="433" height="586"></figure><p>Escolha o m&#xE9;todo de an&#xE1;lise e clique em <code>Generate</code>. Para esse exemplo vou utilizar o m&#xE9;todo local, mas existem v&#xE1;rias possibilidades de configura&#xE7;&#xE3;o, os relevantes s&#xE3;o, Jenkins, Gitlab e Github al&#xE9;m de outros.</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/generatetoken.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="727" height="689" srcset="https://danizavtz.com.br/content/images/size/w600/2023/11/generatetoken.png 600w, https://danizavtz.com.br/content/images/2023/11/generatetoken.png 727w" sizes="(min-width: 720px) 720px"></figure><p>Ap&#xF3;s clicar em generate, ser&#xE1; encaminhado para a pr&#xF3;xima tela onde ser&#xE1; exibido o token. Agora basta apenas clicar em <code>continue</code>.</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/analiseconfirm.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="707" height="616" srcset="https://danizavtz.com.br/content/images/size/w600/2023/11/analiseconfirm.png 600w, https://danizavtz.com.br/content/images/2023/11/analiseconfirm.png 707w"></figure><p>Como se trata de um projeto javascript, ent&#xE3;o eu seleciono a op&#xE7;&#xE3;o de acordo.</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/analizeproject.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="588" height="514"></figure><p>Ap&#xF3;s selecionar esta op&#xE7;&#xE3;o ser&#xE1; apresentado o pr&#xF3;ximo menu com as instru&#xE7;&#xF5;es para executar o sonar no projeto. Clique no bot&#xE3;o <code>copiar</code>.</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/runinproject.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="1164" height="496" srcset="https://danizavtz.com.br/content/images/size/w600/2023/11/runinproject.png 600w, https://danizavtz.com.br/content/images/size/w1000/2023/11/runinproject.png 1000w, https://danizavtz.com.br/content/images/2023/11/runinproject.png 1164w" sizes="(min-width: 720px) 720px"></figure><p>O importante nesta tela &#xE9; este comando para executar o sonar. Com este comando v&#xE1; para o diret&#xF3;rio raiz de onde o projeto foi clonado (o mesmo que possui o arquivo <code>coverage.lcov</code>, que geramos em um passo anterior). Este &#xE9; o comando:</p><!--kg-card-begin: markdown--><pre><code>sonar-scanner.bat -D&quot;sonar.projectKey=tokenAuthDatastore&quot; -D&quot;sonar.sources=.&quot; -D&quot;sonar.host.url=http://localhost:9000&quot; -D&quot;sonar.token=sqp_ec913a0f15298a323d67862cfd3a5f3ecc49cdf8&quot;
</code></pre>
<!--kg-card-end: markdown--><p>Ap&#xF3;s executar este comando ser&#xE1; gerado um relat&#xF3;rio do sonar. Ao gerar o relat&#xF3;rio voc&#xEA; ver&#xE1; que a cobertura est&#xE1; zerada.</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/coverageinfo0.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="741" height="605" srcset="https://danizavtz.com.br/content/images/size/w600/2023/11/coverageinfo0.png 600w, https://danizavtz.com.br/content/images/2023/11/coverageinfo0.png 741w" sizes="(min-width: 720px) 720px"></figure><p>Isso acontece pois &#xE9; necess&#xE1;rio passar mais alguns argumentos de linha de comando, para que seja poss&#xED;vel localizar o arquivo <code>*.lcov</code>e utilizar as informa&#xE7;&#xF5;es contidas nele, seguindo a documenta&#xE7;&#xE3;o compartilhada no inicio da publica&#xE7;&#xE3;o temos que passar este par&#xE2;metro com o seguinte argumento:</p><!--kg-card-begin: markdown--><pre><code> sonar.javascript.lcov.reportPaths=coverage.lcov
</code></pre>
<!--kg-card-end: markdown--><p>Lembrando que o valor deste argumento, deve ser o nome do arquivo que possui a informa&#xE7;&#xE3;o da cobertura, em nosso projeto o nome deste arquivo &#xE9; <code>coverage.lcov</code>.</p><p>Ent&#xE3;o agora, basta executar o comando anterior novamente, com esse novo par&#xE2;metro com seu respectivo argumento. Segue o comando completo:</p><!--kg-card-begin: markdown--><pre><code>sonar-scanner.bat -D&quot;sonar.projectKey=tokenAuthDatastore&quot; -D&quot;sonar.sources=.&quot; -D&quot;sonar.host.url=http://localhost:9000&quot; -D&quot;sonar.token=sqp_ec913a0f15298a323d67862cfd3a5f3ecc49cdf8&quot; -D&quot;sonar.javascript.lcov.reportPaths=coverage.lcov&quot;
</code></pre>
<!--kg-card-end: markdown--><p>Pronto, agora as informa&#xE7;&#xF5;es de cobertura j&#xE1; estar&#xE3;o dispon&#xED;veis, segue um exemplo de como deve ficar:</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/coverageinfo1.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="740" height="227" srcset="https://danizavtz.com.br/content/images/size/w600/2023/11/coverageinfo1.png 600w, https://danizavtz.com.br/content/images/2023/11/coverageinfo1.png 740w" sizes="(min-width: 720px) 720px"></figure><p>Agora s&#xF3; mais um ajuste, vemos que em nosso projeto, ser&#xE1; executado o sonar em todas as pasta, mas na verdade eu n&#xE3;o gostaria de analisar c&#xF3;digos presentes nos diret&#xF3;rios <code>node_modules</code>, assim como tamb&#xE9;m no diret&#xF3;rio <code>tests</code>. &#xA0;Isso vai manter o foco da an&#xE1;lise em meu c&#xF3;digo fonte desenvolvido.</p><p>Vamos ent&#xE3;o reduzir o escopo da an&#xE1;lise, que pode ser conseguido atrav&#xE9;s da exclus&#xE3;o de certos diret&#xF3;rios de serem analisados.</p><p>Vamos usar o par&#xE2;metro: <code>sonar.exclusions</code> .</p><p>O comando final fica assim:</p><!--kg-card-begin: markdown--><pre><code>sonar-scanner.bat -D&quot;sonar.projectKey=tokenAuthDatastore&quot; -D&quot;sonar.sources=.&quot; -D&quot;sonar.host.url=http://localhost:9000&quot; -D&quot;sonar.token=sqp_ec913a0f15298a323d67862cfd3a5f3ecc49cdf8&quot; -D&quot;sonar.javascript.lcov.reportPaths=coverage.lcov&quot; -D&quot;sonar.exclusions=test/**,node_modules/**&quot;
</code></pre>
<!--kg-card-end: markdown--><p>Repare que no final eu utilizei a seguinte sintaxe: test/**. Isso est&#xE1; explicado na <a href="https://docs.sonarsource.com/sonarqube/latest/project-administration/analysis-scope/">documenta&#xE7;&#xE3;o</a>, e &#xE9; um padr&#xE3;o para ignorar subdiret&#xF3;rios e arquivos contidos nestes diret&#xF3;rios.</p><p>Agora ao executar o mesmo comando (adicionando as exclus&#xF5;es), temos a seguinte sa&#xED;da:</p><figure class="kg-card kg-image-card"><img src="https://danizavtz.com.br/content/images/2023/11/coverageinfo2.png" class="kg-image" alt="Adicionar informa&#xE7;&#xE3;o da cobertura ao Sonarqube" loading="lazy" width="1144" height="209" srcset="https://danizavtz.com.br/content/images/size/w600/2023/11/coverageinfo2.png 600w, https://danizavtz.com.br/content/images/size/w1000/2023/11/coverageinfo2.png 1000w, https://danizavtz.com.br/content/images/2023/11/coverageinfo2.png 1144w" sizes="(min-width: 720px) 720px"></figure><p>E isso encerra o nosso tutorial, vemos que o valor da cobertura est&#xE1; de acordo com o mesmo que &#xE9; exibido no github. Por outra ferramenta a codecov. &#x1F64C;</p><p>Tamb&#xE9;m &#xE9; poss&#xED;vel fazer estas mesmas configura&#xE7;&#xF5;es via interface gr&#xE1;fica sem a necessidade de utilizar a linha de comando, &#xA0;basta seguir as instru&#xE7;&#xF5;es presentes na documenta&#xE7;&#xE3;o, que j&#xE1; foi referenciada.</p><p>Agora que j&#xE1; configurou o sonar acrescentando a informa&#xE7;&#xE3;o de cobertura em um projeto, ser&#xE1; poss&#xED;vel utilizar as mesmas ideias presentes aqui para outros projetos.</p>]]></content:encoded></item><item><title><![CDATA[Adicionar repositório remoto GitHub]]></title><description><![CDATA[<p>Vai ser um processo relativamente simples, as etapas seguidas ser&#xE3;o as seguintes:</p><ol><li>iniciar o git</li><li>adicionar um endere&#xE7;o URL para um reposit&#xF3;rio remoto</li></ol><p>Os passos a seguir, assumem que est&#xE1; no diret&#xF3;rio raiz do projeto. Este passo &#xE9; necess&#xE1;rio</p>]]></description><link>https://danizavtz.com.br/adicionar-repositorio-remoto-github/</link><guid isPermaLink="false">65391b09dfa2eb0f8251e00c</guid><category><![CDATA[github]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 25 Oct 2023 13:42:24 GMT</pubDate><content:encoded><![CDATA[<p>Vai ser um processo relativamente simples, as etapas seguidas ser&#xE3;o as seguintes:</p><ol><li>iniciar o git</li><li>adicionar um endere&#xE7;o URL para um reposit&#xF3;rio remoto</li></ol><p>Os passos a seguir, assumem que est&#xE1; no diret&#xF3;rio raiz do projeto. Este passo &#xE9; necess&#xE1;rio para que seja feita a sincronia de maneira correta de acordo com a estrutura de pastas e arquivos que haviam antes.</p><p>ent&#xE3;o estando no diret&#xF3;rio raiz, fa&#xE7;a:</p><pre><code>git init .
</code></pre><p>Isso vai iniciar o git no diret&#xF3;rio atual.</p><p>Ap&#xF3;s iniciar o git, basta configurar o remoto:</p><pre><code>git remote add origin &lt;endere&#xE7;o_url_reposit&#xF3;rio_git&gt;
</code></pre><p>Como descobrir o endere&#xE7;o do reposit&#xF3;rio git? Esse &#xE9; o mesmo endere&#xE7;o utilizado no momento de fazer um clone do projeto. Ent&#xE3;o se estiver utilizando algum sistema de gerenciamento de git voc&#xEA; pode pegar este URL (<code>endere&#xE7;o_url_reposit&#xF3;rio_git</code>) a partir da p&#xE1;gina home do seu projeto. A informa&#xE7;&#xE3;o que deseja est&#xE1; em circulada em azul<br></p><figure class="kg-card kg-image-card"><img src="https://i.stack.imgur.com/9qhUC.png" class="kg-image" alt="inserir a descri&#xE7;&#xE3;o da imagem aqui" loading="lazy"></figure><p><br>Isso vai adicionar um endere&#xE7;o de reposit&#xF3;rio remoto ao seu projeto.</p><p>Para mais informa&#xE7;&#xF5;es consulte a <a href="https://docs.github.com/pt/get-started/getting-started-with-git/managing-remote-repositories">documenta&#xE7;&#xE3;o</a></p>]]></content:encoded></item><item><title><![CDATA[Envio de e-mail com aws ses]]></title><description><![CDATA[<p>Nesta publica&#xE7;&#xE3;o vamos implementar uma integra&#xE7;&#xE3;o com servi&#xE7;o AWS SES e vamos criar uma aplica&#xE7;&#xE3;o completa em que &#xE9; poss&#xED;vel enviar um e-mail.</p><p>Para esta implementa&#xE7;&#xE3;o vamos utilizar as seguintes tecnologias, que utiliza o</p>]]></description><link>https://danizavtz.com.br/envio-de-e-mail-com-aws-ses/</link><guid isPermaLink="false">652ea0c7dfa2eb0f8251decb</guid><category><![CDATA[aws-sdk]]></category><category><![CDATA[aws-ses]]></category><category><![CDATA[javascript]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[simple-email]]></category><category><![CDATA[aws]]></category><dc:creator><![CDATA[Danizavtz]]></dc:creator><pubDate>Wed, 18 Oct 2023 23:29:42 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1523474253046-8cd2748b5fd2?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDV8fGFtYXpvbnxlbnwwfHx8fDE3MjMwNjE0ODN8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1523474253046-8cd2748b5fd2?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDV8fGFtYXpvbnxlbnwwfHx8fDE3MjMwNjE0ODN8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Envio de e-mail com aws ses"><p>Nesta publica&#xE7;&#xE3;o vamos implementar uma integra&#xE7;&#xE3;o com servi&#xE7;o AWS SES e vamos criar uma aplica&#xE7;&#xE3;o completa em que &#xE9; poss&#xED;vel enviar um e-mail.</p><p>Para esta implementa&#xE7;&#xE3;o vamos utilizar as seguintes tecnologias, que utiliza o backend para renderizar o frontend e integrar o servi&#xE7;o da aws. &#xC9; uma aplica&#xE7;&#xE3;o tradicional html renderizada no servidor (server side rendering). No modelo <code>single page application</code>.</p><ul><li>nodejs para backend e frontend (utilizando html puro)</li><li>aws ses</li></ul><p>O aws ses (&#xE9; um servi&#xE7;o pago), essa implementa&#xE7;&#xE3;o &#xE9; uma prova de conceito de implementa&#xE7;&#xE3;o de uma p&#xE1;gina de contato em que &#xE9; enviado um e-mail para mim mesmo. Via o servi&#xE7;o da aws ses.</p><p>Voc&#xEA; pode ver um exemplo do funcionamento da p&#xE1;gina <a href="https://api.danizavtz.com.br">aqui</a>. Esta p&#xE1;gina n&#xE3;o possui integra&#xE7;&#xE3;o com &#xA0;o backend, est&#xE1; dispon&#xED;vel apenas para ser ter uma &#xED;deia do funcionamento e como ficar&#xE1; o projeto depois de pronto (do ponto de vista de apresenta&#xE7;&#xE3;o).</p><h2 id="implementando-o-frontend">Implementando o frontend</h2><p>A implementa&#xE7;&#xE3;o do frontend possui apenas duas rotas uma para a GET vai renderizar o formul&#xE1;rio de contato.</p><!--kg-card-begin: markdown--><pre><code>export default function layout({ contato }) {
  const { email, message, title, errors } = contato;
  return `
    &lt;html lang=&quot;pt-br&quot;&gt;
    &lt;head&gt;
      &lt;title&gt;Sendmail app&lt;/title&gt;
        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, maximum-scale=1&quot;&gt;
        &lt;link href=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot; integrity=&quot;sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN&quot; crossorigin=&quot;anonymous&quot;&gt;
    &lt;/head&gt;

    &lt;body class=&quot;&quot;&gt;
      &lt;nav class=&quot;container-fluid navbar navbar-expand navbar-light bg-light&quot;&gt;
        &lt;ul class=&quot;navbar-nav ms-auto&quot;&gt;
          &lt;li class=&quot;nav-item&quot;&gt;&lt;a class=&quot;nav-link&quot; href=&quot;/&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/nav&gt;
      &lt;main class=&quot;mt-4 container py-4 position-relative&quot;&gt;
      &lt;h2&gt;Contato&lt;/h2&gt;
      &lt;form method=&quot;post&quot; class=&quot;has-validation mt-3&quot; action=&quot;/&quot;&gt;
      &lt;div class=&quot;mb-3&quot;&gt;
          &lt;label for=&quot;servicestatus&quot; class=&quot;form-label&quot;&gt;&lt;/label&gt;
          &lt;input type=&quot;hidden&quot; class=&quot;form-control ${errors.service.length ? &apos;is-invalid&apos;: &apos;&apos;}&quot; id=&quot;servicestatus&quot; name=&quot;servicestatus&quot; value=&quot;&quot;&gt;
          &lt;div class=&quot;invalid-feedback&quot;&gt;
            ${errors.service.length &gt; 0 ? errors.service[0]: &apos;&apos;}
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;mb-3&quot;&gt;
          &lt;label for=&quot;email&quot; class=&quot;form-label&quot;&gt;E-mail&lt;/label&gt;
          &lt;input type=&quot;text&quot; class=&quot;form-control ${errors.email.length ? &apos;is-invalid&apos;: &apos;&apos;}&quot; id=&quot;email&quot; name=&quot;email&quot; value=&quot;${email}&quot;&gt;
          &lt;div class=&quot;invalid-feedback&quot;&gt;
            ${errors.email.length &gt; 0 ? errors.email[0]: &apos;&apos;}
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;mb-3&quot;&gt;
          &lt;label for=&quot;title&quot; class=&quot;form-label&quot;&gt;T&#xED;tulo&lt;/label&gt;
          &lt;input type=&quot;text&quot; class=&quot;form-control ${errors.title.length ? &apos;is-invalid&apos;: &apos;&apos;}&quot; id=&quot;title&quot; name=&quot;title&quot; value=&quot;${title}&quot;&gt;
          &lt;div class=&quot;invalid-feedback&quot;&gt;
            ${errors.title.length &gt; 0 ? errors.title[0]: &apos;&apos;}
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;mb-3&quot;&gt;
          &lt;label for=&quot;message&quot; class=&quot;form-label&quot;&gt;Mensagem&lt;/label&gt;
          &lt;textarea class=&quot;form-control ${errors.message.length ? &apos;is-invalid&apos;: &apos;&apos;}&quot; id=&quot;message&quot; name=&quot;message&quot;&gt;${message}&lt;/textarea&gt;
          &lt;div class=&quot;invalid-feedback&quot;&gt;
            ${errors.message.length &gt; 0 ? errors.message[0]: &apos;&apos;}
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;button id=&quot;btnenviar&quot; type=&quot;submit&quot; class=&quot;btn btn-primary&quot;&gt;

        Enviar &lt;/button&gt;
      &lt;/form&gt;
      &lt;/main&gt;
    &lt;/body&gt;
    &lt;/html&gt;
  `;
}
</code></pre>
<!--kg-card-end: markdown--><p>Outra a mesma rota para o POST que vai fazer a valida&#xE7;&#xE3;o dos dados do formul&#xE1;rio e caso esteja tudo certo far&#xE1; o envio do e-mail. Caso seja feito o envio com sucesso, ent&#xE3;o sera exibida uma tela de sucesso ao enviar.</p><!--kg-card-begin: markdown--><pre><code>export default function sucesso() {
    return `
      &lt;html lang=&quot;pt-br&quot;&gt;
      &lt;head&gt;
        &lt;title&gt;Sendmail app&lt;/title&gt;
          &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, maximum-scale=1&quot;&gt;
          &lt;link href=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot; integrity=&quot;sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN&quot; crossorigin=&quot;anonymous&quot;&gt;
      &lt;/head&gt;

      &lt;body class=&quot;&quot;&gt;
        &lt;nav class=&quot;container-fluid navbar navbar-expand navbar-light bg-light&quot;&gt;
          &lt;ul class=&quot;navbar-nav ms-auto&quot;&gt;
            &lt;li class=&quot;nav-item&quot;&gt;&lt;a class=&quot;nav-link&quot; href=&quot;/&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/nav&gt;
        &lt;main class=&quot;mt-4 container py-4 position-relative&quot;&gt;
        &lt;div class=&quot;row justify-content-md-center&quot;&gt;
        &lt;div class=&quot;col col-md-auto text-center&quot;&gt;
          &lt;div id=&quot;sucesso&quot; class=&quot;d-flex justify-content-center h1&quot;&gt; Mensagem enviada com sucesso
          &lt;/div&gt;
          &lt;br&gt;
          &lt;a href=&quot;/&quot; class=&quot;btn btn-primary justify-content-center&quot; role=&quot;button&quot;&gt;Voltar&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;
        &lt;/main&gt;
      &lt;/body&gt;
      &lt;/html&gt;
    `;
  }
</code></pre>
<!--kg-card-end: markdown--><p>Agora para integrar os servi&#xE7;os vamos implementar a funcionalidade de envio de e-mai, como dito, o envio ser&#xE1; feito via o servi&#xE7;o AWS &#xA0;<code>simple email service</code></p><p>Para isso vamos apenas adicionar a biblioteca do aws sdk, e criar uma inst&#xE2;ncia do servico SES, ele vai ficar respons&#xE1;vel pelo envio do e-mail.</p><p>Vamos instalar o sdk da aws, para isso utilize o npm install</p><!--kg-card-begin: markdown--><pre><code>npm install @aws-sdk/client-sesv2
</code></pre>
<!--kg-card-end: markdown--><p>Ap&#xF3;s fazer essa instala&#xE7;&#xE3;o, edite o arquivo <code>server/index.js</code>, adicionar o import e fazer as configura&#xE7;&#xF5;es b&#xE1;sicas para o envio de um e-mail, nesta tarefa fomos guiados pela documenta&#xE7;&#xE3;o da AWS do <a href="https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/sesv2/">servi&#xE7;o sesv2</a>.</p><p>O resultado final fica assim, aqui vou mostrar apenas a implementa&#xE7;&#xE3;o do m&#xE9;todo <code>sendMail</code>:</p><!--kg-card-begin: markdown--><pre><code>async sendMail(req, res) {
    const contato = new Contato(req.body)
    if (contato.email.trim() === &apos;&apos;) {
      contato.errors.email.push(&apos;E-mail n&#xE3;o pode ser vazio&apos;)
    }
    if (contato.title.trim() === &apos;&apos;) {
      contato.errors.title.push(&apos;T&#xED;tulo n&#xE3;o pode ser vazio&apos;)
    }
    if (contato.message.trim() === &apos;&apos;) {
      contato.errors.message.push(&apos;Mensagem n&#xE3;o pode ser vazio&apos;)
    }
    if (contato.errors &amp;&amp; (contato.errors.email.length &gt; 0 || contato.errors.message.length &gt; 0 || contato.errors.title.length &gt; 0)) {
      return res.send(layout({ contato: contato }))
    } //at&#xE9; aqui faz valida&#xE7;&#xE3;o dos campos obrigat&#xF3;rios, renderiza o form com as mensagens de erro e os dados do formul&#xE1;rio

    const input = { // SendEmailRequest
      FromEmailAddress: &quot;contato@danizavtz.com.br&quot;,
      ReplyToAddresses: [
        &quot;daniellucena@yahoo.com.br&quot;,
      ],
      Destination: { // Destination
          ToAddresses: [ // EmailAddressList
            &quot;daniellucena@yahoo.com.br&quot;,
          ]
      },
      Content: { // EmailContent
        Simple: { // Message
          Subject: { // Content
            Data: req.body.title, // required
            Charset: &quot;UTF-8&quot;,
          },
          Body: { // Body
            Text: {
              Data: `Mensagem de: ${req.body.email}, \nMensagem: ${req.body.message}`, // required
              Charset: &quot;UTF-8&quot;,
            }
          }
        }
      }
    };
    const command = new SendEmailCommand(input);
    try {
        await client.send(command);
        res.send(sucesso())
    } catch (err) {
        console.log(err); //esta linha n&#xE3;o &#xE9; necess&#xE1;ria, &#xE9; utilizada apenas para debug
        contato.errors.service.push(&apos;Houve um erro durante o envio&apos;)
        return res.send(layout({ contato: contato }))
    }
  }
</code></pre>
<!--kg-card-end: markdown--><p>Repare que temos um input do tipo &quot;hidden&quot;, ele serve para incluir a mensagem de erro no caso de haver um erro no envio, (quando esse erro vem do servi&#xE7;o aws-ses).</p><p>Veja a <a href="https://github.com/danizavtz/mailsenderaws">vers&#xE3;o completa</a> deste projeto.</p><p></p><p></p><p></p>]]></content:encoded></item></channel></rss>