<?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"><channel><title><![CDATA[Untitled Publication]]></title><description><![CDATA[Untitled Publication]]></description><link>https://journal.tiagocfrausino.com.br</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 03:32:02 GMT</lastBuildDate><atom:link href="https://journal.tiagocfrausino.com.br/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Componentes Smart × Dumb]]></title><description><![CDATA[Recentemente estive estudando arquitetura de projetos e me deparei com o conceito de componentes Smart e Dumb. Esse conceito ajuda manter uma arquitetura limpa, delegando funções para diferentes componentes e os separando por componentes funcionais e...]]></description><link>https://journal.tiagocfrausino.com.br/smart-dumb-components</link><guid isPermaLink="true">https://journal.tiagocfrausino.com.br/smart-dumb-components</guid><category><![CDATA[shorts]]></category><category><![CDATA[architecture]]></category><category><![CDATA[smart]]></category><category><![CDATA[components]]></category><category><![CDATA[dumb]]></category><dc:creator><![CDATA[Tiago Civatti Frausino]]></dc:creator><pubDate>Fri, 26 May 2023 22:52:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/3BfDXcn9sqM/upload/a744debbfafe291bf7266060d18f22ab.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recentemente estive estudando arquitetura de projetos e me deparei com o conceito de componentes <em>Smart</em> e <em>Dumb</em>. Esse conceito ajuda manter uma arquitetura limpa, delegando funções para diferentes componentes e os separando por <strong>componentes funcionais</strong> e <strong>componentes de apresentação</strong>.</p>
<p><strong>Componentes funcionais (Smart)</strong><br />São responsáveis por alguma logíca de negócio na aplicação, seja manipulação de dados, envio de requisições, ou outra. Também são responsáveis por passar as informações necessárias para os devidos <em>dumb components</em>.</p>
<p><strong>Componentes de apresentação (Dumb)</strong><br />São responsáveis apenas e exclusivamente pelo visual da aplicação. Eles apenas enxergam eles mesmos e não precisam saber nada do resto da aplicação. Podem também exigir parâmetros para uso próprio, como um componente de detalhe de usuário exigir o parâmetro <code>user</code> com informações sobre o usuário em questão.<br />Podem emitir eventos para enviar informações para fora.</p>
]]></content:encoded></item><item><title><![CDATA[[CSS] Footer no final da página]]></title><description><![CDATA[Ao adicionar um footer em uma página, geralmente ele age como esperado e é posicionado no final da tela. Mas se sua página for menor que a tela do usuário, o footer vai ficar no meio do caminho. Muito feio.
Para ajeitar isso, é necessário ajustar o t...]]></description><link>https://journal.tiagocfrausino.com.br/css-footer-no-final-da-pagina</link><guid isPermaLink="true">https://journal.tiagocfrausino.com.br/css-footer-no-final-da-pagina</guid><category><![CDATA[CSS]]></category><category><![CDATA[layout]]></category><dc:creator><![CDATA[Tiago Civatti Frausino]]></dc:creator><pubDate>Fri, 26 May 2023 22:27:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1685140125751/9a0869f2-a6bf-4146-9dd7-a898ca486abe.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ao adicionar um footer em uma página, geralmente ele age como esperado e é posicionado no final da tela. Mas se sua página for menor que a tela do usuário, o footer vai ficar no meio do caminho. Muito feio.</p>
<p>Para ajeitar isso, é necessário ajustar o tamanho do html e body para o máximo da tela e colocar uma margem dinânica no footer.</p>
<pre><code class="lang-scss"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>; <span class="hljs-comment">// Fallback</span>
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100</span>dvh; <span class="hljs-comment">// Compatibilidade com mobile</span>
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
}

<span class="hljs-selector-class">.footer</span>{
  <span class="hljs-attribute">margin-top</span>: auto;
}
</code></pre>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"header"</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- Barra de navegação --&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page"</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- Conteúdo --&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer"</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- Rodapé --&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>Note que a unidade <code>dvh</code> é usada para responsividade com mobile, que pode mudar seu viewport devido às diversas barras de navegação nativas.<br />Leia mais sobre isso <a target="_blank" href="https://www.w3.org/TR/css-values-4/#viewport-variants:~:text=with%20the%20page.-,dynamic%20viewport,-The%20dynamic%20viewport">aqui</a>.</p>
<p>Essa é uma solução simples, mas que muitas vezes não é intuitiva de implementar.</p>
]]></content:encoded></item><item><title><![CDATA[[Node.js] Manipulação de arquivos]]></title><description><![CDATA[Problema
Subimos vários videos em formato de streaming (HLS) para a AWS, mas eles ficaram nomeados em UTF-8, usando caracteres como ç á ã â. O problema é que esses caracteres especiais não são aceitos como parte de uma URI, então não conseguimos abri...]]></description><link>https://journal.tiagocfrausino.com.br/nodejs-manipulacao-de-arquivos</link><guid isPermaLink="true">https://journal.tiagocfrausino.com.br/nodejs-manipulacao-de-arquivos</guid><category><![CDATA[Node.js]]></category><category><![CDATA[files]]></category><category><![CDATA[File handling]]></category><category><![CDATA[filesystem]]></category><dc:creator><![CDATA[Tiago Civatti Frausino]]></dc:creator><pubDate>Wed, 15 Mar 2023 17:47:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/lRoX0shwjUQ/upload/cc3d6f404188dc5225f1757ee4d76628.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-problema">Problema</h3>
<p>Subimos vários videos em formato de streaming (HLS) para a AWS, mas eles ficaram nomeados em UTF-8, usando caracteres como <code>ç</code> <code>á</code> <code>ã</code> <code>â</code>. O problema é que esses caracteres especiais não são aceitos como parte de uma URI, então não conseguimos abrir os vídeos por browsers que não fazer essa conversão automaticamente (ex. Safari).</p>
<p>Por isso preciso fazer um <em>script</em> que itere sobre um arquivo, leia cada linha, converta em um formato seguro para URI e escreva em um outro arquivo de <em>output.</em></p>
<p>O fluxo é basicamente o seguinte:</p>
<ol>
<li><p>Pegar arquivo m3u8 do video na AWS</p>
<ol>
<li>Fazer um backup</li>
</ol>
</li>
<li><p>Percorrer conteudo e converter caracteres especiais para formato URI friendly</p>
<ol>
<li><p>Ignorar linhas começadas em #</p>
</li>
<li><p>Salvar os nomes para não precisar percorrer denovo</p>
</li>
</ol>
</li>
<li><p>Ler nomes dos sub-arquivos</p>
</li>
<li><p>Repetir passo (1) para cada um até chegar no final (arquivos .ts)</p>
<ol>
<li>Provavelmente usar recursividade</li>
</ol>
</li>
<li><p>Pegar o próximo arquivo na AWS e repetir o processo</p>
</li>
<li><p>Fazer o Upload do arquivo atualizado para a AWS</p>
</li>
</ol>
<h3 id="heading-desenvolvimento">Desenvolvimento</h3>
<p>Será usado Node.js v18 para escrever o <em>script</em>, que é a linguagem que eu tenho mais familiaridade, além do SDK da AWS para fazer a conexão com o bucket S3 onde está os arquivos.</p>
<h3 id="heading-solucao">Solução</h3>
<p>A manipulação de arquivos pelo Node.js foi feita através do módulo FileSystem (fs). O FileSystem também possui uma parte de <code>promises</code> com varias outras funções que funcionam com a arquitetura <code>async await</code> .</p>
<p>Esta foi a função para o processamento de arquivos. Não vou tocar na parte sobre a AWS aqui, pois não é o escopo.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { open } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs/promises'</span>);

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processarHLS</span>(<span class="hljs-params">path, outputPath</span>) </span>{
  <span class="hljs-keyword">let</span> file;
  <span class="hljs-keyword">let</span> out;
  <span class="hljs-keyword">let</span> stream;
  <span class="hljs-keyword">let</span> subpaths = [];
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">/* (1) */</span>
    file = <span class="hljs-keyword">await</span> open(path, <span class="hljs-string">'r+'</span>);
    out = <span class="hljs-keyword">await</span> open(outputPath, <span class="hljs-string">'w+'</span>);
    stream = out.createWriteStream();

    <span class="hljs-comment">/* (2) */</span>
    <span class="hljs-keyword">for</span> <span class="hljs-keyword">await</span> (<span class="hljs-keyword">let</span> line <span class="hljs-keyword">of</span> file.readLines()) {
      <span class="hljs-comment">/* (3) */</span>
      stream.cork();
      <span class="hljs-keyword">if</span> (!line.startsWith(<span class="hljs-string">'#'</span>)) {
        subpaths.push(line);
        line = line
          .split(<span class="hljs-string">''</span>)
          .map(<span class="hljs-function">(<span class="hljs-params">c</span>) =&gt;</span> {
            <span class="hljs-keyword">if</span> (<span class="hljs-regexp">/[A-z0-9%\-_]/</span>.test(c)) <span class="hljs-keyword">return</span> c;
            <span class="hljs-keyword">return</span> <span class="hljs-built_in">encodeURI</span>(c);
          })
          .join(<span class="hljs-string">''</span>);
      }
      stream.write(line + <span class="hljs-string">'\n'</span>);
      <span class="hljs-comment">/* (4) */</span>
      process.nextTick(<span class="hljs-function">() =&gt;</span> {
        stream.uncork();
      });
    }
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  } <span class="hljs-keyword">finally</span> {
    stream?.close();
    out?.close();
    file?.close();
  }
  <span class="hljs-keyword">return</span> subpaths;
}
</code></pre>
<p>O que está acontecendo nesse código? Tem várias partes interessantes como o <code>for await</code> , a escrita e leitura simultânea de dois arquivos e a escrita com buffer através do <code>stream.cork()</code> e <code>stream.uncork()</code> .</p>
<ol>
<li><p>Abertura dos arquivos de <em>input</em> e <em>output</em> em modo de leitura <code>r+</code> e escrita <code>w+</code> . E criação de uma <em>stream</em> de escrita com a ajuda do FileSystem.</p>
</li>
<li><p>Essa estrutura me surpreendeu, mas é simples. <code>for await</code> é usado com iteradores assíncronos, o <code>file.readLines()</code> no caso, que a iteração dentre os elementos não é linear igual em um array, mas cada iteração em sí é assíncrona, como ir no arquivo e ler a próxima linha.</p>
</li>
<li><p>Por padrão a escrita da <em>stream</em> não é bufferizada, cada <code>stream.write()</code> gera um buffer específico para o arquivo. Usando o <code>cork</code> e <code>uncork</code> é possível usar a estrutura de write e flush como em outras linguagens, o que torna o processo mais otimizado, sendo que, a partir da chamada do <code>stream.cork()</code>, cada buffer único do <code>write</code> é armazenado e escrito de uma vez só quando <code>stream.uncork()</code> é chamado. Também pode minimizar a chance de acessos simultâneos no arquivo.</p>
</li>
<li><p>Não entendi bem, mas por recomendação da documentação do FileSystem, o <code>process.nextTick</code> é usado para postergar a execução do <code>stream.cork()</code> para o próximo tick.</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Por que fazer um Journal?]]></title><description><![CDATA[O intuito deste blog é primeiramente para uso pessoal, fazer anotações, e afins. Então prossiga com cautela :)
Resolvi começar a escrever este DEV Journal para melhorar o minha jornada pessoal, depois de um ano trabalhando como desenvolvedor, eu perc...]]></description><link>https://journal.tiagocfrausino.com.br/por-que-fazer-um-journal</link><guid isPermaLink="true">https://journal.tiagocfrausino.com.br/por-que-fazer-um-journal</guid><category><![CDATA[about]]></category><dc:creator><![CDATA[Tiago Civatti Frausino]]></dc:creator><pubDate>Tue, 14 Mar 2023 18:59:44 GMT</pubDate><content:encoded><![CDATA[<p><em>O intuito deste blog é primeiramente para uso pessoal, fazer anotações, e afins. Então prossiga com cautela :)</em></p>
<p>Resolvi começar a escrever este <em>DEV Journal</em> para melhorar o minha jornada pessoal, depois de um ano trabalhando como desenvolvedor, eu percebi o quanto isso seria útil, já que eu acabava me deparando com os mesmos problemas toda hora e não tinha uma solução palpável para recorrer.</p>
<p>Eu percebi que registrar esses processos de desenvolvimento seria saudável, além de ajudar a entender o que estou fazendo na hora, descrever os problemas, o fluxo, as descobertas, e a solução, pode ser muito útil no futuro. Querendo ou não sempre acabamos esquecendo alguns detalhes. Também optei por escrever online em vez de em um caderno, pela possibilidade de compartilhar com colegas de trabalho e amigos.</p>
<p>Fora isso também pretendo registrar algumas dicas ou features interessantes.</p>
<p>Como é um blog pessoal já fica o aviso, tenha um pouco de cautela, não copie direto as soluções, mas sim tente entender o processo, não garanto que tudo que eu colocar aqui esteja 100% correto e não me responsabilizo.</p>
<p>É isso ai.</p>
]]></content:encoded></item></channel></rss>