<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sidney Alex</title>
    <description>The latest articles on DEV Community by Sidney Alex (@s1d3a).</description>
    <link>https://dev.to/s1d3a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F975957%2Fbbd25806-50ea-4450-bdd3-561a6359736d.jpeg</url>
      <title>DEV Community: Sidney Alex</title>
      <link>https://dev.to/s1d3a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/s1d3a"/>
    <language>en</language>
    <item>
      <title>Nuxt 3 Auto-imports: configurando Zod e pasta de Schemas</title>
      <dc:creator>Sidney Alex</dc:creator>
      <pubDate>Thu, 05 Oct 2023 00:41:56 +0000</pubDate>
      <link>https://dev.to/s1d3a/nuxt-3-auto-imports-configurando-zod-e-pasta-de-schemas-g2b</link>
      <guid>https://dev.to/s1d3a/nuxt-3-auto-imports-configurando-zod-e-pasta-de-schemas-g2b</guid>
      <description>&lt;p&gt;Um dos grandes diferenciais do Nuxt 3 é a capacidade de gerenciar automaticamente as &lt;a href="https://nuxt.com/docs/guide/concepts/auto-imports"&gt;importações baseada em seu sistema de diretórios&lt;/a&gt;. Mas nem tudo são flores, e muitas vezes precisamos integrar outras ferramentas que não fazem parte do ecossistema Vue/Nuxt, é o caso do &lt;a href="https://zod.dev/"&gt;Zod&lt;/a&gt;, biblioteca de validação baseada em &lt;code&gt;schemas&lt;/code&gt; e nativamente não possui um &lt;a href="https://nuxt.com/docs/guide/concepts/modules"&gt;módulo&lt;/a&gt; dedicado para o Nuxt.&lt;/p&gt;

&lt;p&gt;Criaremos um módulo interno em uma aplicação Nuxt 3 e configurar a importação automática do Zod e configurar uma pasta chamada &lt;code&gt;schemas&lt;/code&gt; (que não é nativamente suportada pelo Nuxt) para importar automaticamente os arquivos dentro dela.&lt;/p&gt;

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

&lt;p&gt;Iniciaremos um novo projeto inserindo o comando abaixo no nosso terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; npx nuxi@latest init meu-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Instalando dependências
&lt;/h2&gt;

&lt;p&gt;Com a aplicação iniciada, navegamos até a pasta raíz do app e instalar o &lt;code&gt;zod&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; cd meu-app
&amp;gt; npm install zod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após a instalação, é possível utilizar o Zod e definir schemas, mas é necessário realizar a importação dele em cada uso, similar ao arquivo abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NameSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;NameSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Hello World&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que caso eu tome a decisão de isolar o &lt;code&gt;NameSchema&lt;/code&gt; em um arquivo na pasta &lt;code&gt;schemas&lt;/code&gt;, por exemplo, ainda existirá a necessidade de importar o zod nos arquivos, e importar os &lt;code&gt;schemas&lt;/code&gt; da pasta, &lt;a href="https://nuxt.com/docs/guide/concepts/auto-imports#directory-based-auto-imports"&gt;que não é suportada nativamente pelo Nuxt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Resolveremos isso criando um módulo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Escrevendo módulo interno
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nuxt.com/docs/guide/concepts/modules"&gt;Módulos&lt;/a&gt; no ecossistema do Nuxt é considerado uma forma de simplificar integrações e extender/customizar as funcionalidades do framework, e as importações automáticas fazem parte desse comportamento.&lt;/p&gt;

&lt;p&gt;Criaremos um arquivo chamado &lt;code&gt;zod.ts&lt;/code&gt; na pasta &lt;code&gt;modules&lt;/code&gt;, &lt;a href="https://nuxt.com/docs/guide/directory-structure/modules"&gt;sendo a pasta definida pelo Nuxt para criação de módulos e que vão ser carregados quando a aplicação iniciar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Um modulo para adicionar a importação automática do Zod pode ser escrito da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// modules/zod.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addImports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defineNuxtModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nuxt/kit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// definimos o módulo&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineNuxtModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// nome do módulo&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// função que será executada quando o módulo for carregado&lt;/span&gt;
  &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// carregamos o módulo&lt;/span&gt;
    &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Zod internal module loaded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// adicionamos o import&lt;/span&gt;
    &lt;span class="c1"&gt;// equivalente a import {z} from "zod";&lt;/span&gt;
    &lt;span class="nx"&gt;addImports&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Ao executar a aplicação, podemos ver a mensagem que escrevemos no &lt;code&gt;logger&lt;/code&gt; aparecer no terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DVNACNZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4k327f048d50jna9b64b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DVNACNZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4k327f048d50jna9b64b.png" alt='"Zod internal module loaded"' width="417" height="143"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A partir daqui, o {Z} não precisa ser importado em componentes, páginas, composables, server e etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adicionando pasta &lt;code&gt;Schemas&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Agora vamos adicionar o auto-import de uma pasta inteira para não existir a necessidade de importar cada &lt;code&gt;schema&lt;/code&gt; que vamos escrever.&lt;/p&gt;

&lt;p&gt;Modificando o módulo da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// modules/zod.ts&lt;/span&gt;

&lt;span class="c1"&gt;// importamos o addImportsDir&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addImports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addImportsDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defineNuxtModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nuxt/kit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineNuxtModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Zod internal module loaded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;addImports&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Put Zod schemas in 'schemas' folder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Adiciona todos os arquivos da pasta schemas como import&lt;/span&gt;
    &lt;span class="nx"&gt;addImportsDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;schemas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora todos os arquivos que tiverem uma exportação na pasta &lt;code&gt;schemas&lt;/code&gt; vão ter a importação automática configurada.&lt;/p&gt;

&lt;p&gt;Exemplo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// schemas/nameSchema.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NameSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>nuxt</category>
      <category>zod</category>
      <category>vue</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Decidi reproduzir o novo NLW Setup da Rocketseat... usando Vue.js</title>
      <dc:creator>Sidney Alex</dc:creator>
      <pubDate>Sun, 22 Jan 2023 14:32:05 +0000</pubDate>
      <link>https://dev.to/s1d3a/decidi-reproduzir-o-novo-nlw-setup-da-rocketseat-usando-vuejs-3k08</link>
      <guid>https://dev.to/s1d3a/decidi-reproduzir-o-novo-nlw-setup-da-rocketseat-usando-vuejs-3k08</guid>
      <description>&lt;p&gt;A Rocketseat é uma das comunidades referência no ensino de JavaScript no Brasil. No backend eles variam bastante, mas no frontend eles são 100% focados na dupla React+React Native e os metaframeworks que surgem dessas ferramentas. O NLW é um evento que acontece algumas vezes por ano, onde durante uma semana é feito o desenvolvimento de algumas aplicações, sempre um backend, um frontend e uma aplicação mobile. &lt;br&gt;
O Vue.js sempre foi o meu &lt;code&gt;framework de estimação&lt;/code&gt;, mesmo utilizando React e Angular no trabalho. Então tomei a decisão acompanhar essa edição do evento, mas adicionando uma camada de complexidade: reproduzir as aplicações utilizando Vue e outras ferramentas disponíveis no ecossistema Vue/Nuxt/unJS.&lt;br&gt;
Além do desafio, é uma oportunidade bastante justa de comparar os frameworks ao nível de código, arquitetura e funcionalidades.&lt;/p&gt;
&lt;h2&gt;
  
  
  Backend: Substituindo o Fastify pelo Nitro
&lt;/h2&gt;

&lt;p&gt;O backend construído para o desafio recebe e envia dados no formato JSON, então nada que o Nitro não possa fazer. O &lt;a href="https://nitro.unjs.io/" rel="noopener noreferrer"&gt;Nitro&lt;/a&gt; é o servidor embutido no Nuxt 3 e que assim como outras ferramentas do unJS, pode ser utilizado isoladamente sem nenhuma outra dependência, &lt;a href="https://dev.to/s1d3a/uma-simples-api-rest-com-nitro-prisma-mongodb-5c5"&gt;como explico nesse post.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A instalação de outras bibliotecas como Prisma, Day.js e Zod segue o mesmo padrão encontrado no evento e em suas respectivas documentações. O que muda ao utilizar o Nitro é o sistema de rotas, baseado em arquivos e a construção das rotas, que utiliza eventos no lugar do clássico &lt;code&gt;(request,response)&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zpf97pmfd4qcp2dfcbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zpf97pmfd4qcp2dfcbw.png" alt="Sistema de rotas do nitro" width="657" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As rotas separadas em arquivos ajudam bastante na organização do código e nos obrigam a separar o código específico de cada uma. Abaixo exemplo de uma rota com o Nitro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//   /routes/day/index.get.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dayjs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dayjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../utils/prisma&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineEventHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getDayParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coerce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getDayParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsedDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;startOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;day&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weekDay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parsedDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;day&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;possibleHabits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;habit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;lte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;weekDays&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;some&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;week_day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;weekDay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;parsedDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDate&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;dayHabits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;completedHabits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;dayHabits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dayHabit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dayHabit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;habit_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;possibleHabits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;completedHabits&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;


&lt;p&gt;De forma geral, o backend não é tão diferente. Boa parte da aplicação, principalmente o uso do Prisma, Zod e Day.js é exatamente igual. &lt;br&gt;
Link do repositório completo abaixo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/silvercent011" rel="noopener noreferrer"&gt;
        silvercent011
      &lt;/a&gt; / &lt;a href="https://github.com/silvercent011/nlw-setup-nitro" rel="noopener noreferrer"&gt;
        nlw-setup-nitro
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Tailwind CSS: A configuração que (quase) não mudou.
&lt;/h2&gt;

&lt;p&gt;Por ser um framework do CSS, o Tailwind se torna compatível e visualmente idêntico em todos os frameworks.&lt;/p&gt;

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

&lt;p&gt;O que mudei no &lt;code&gt;tailwind.config.js&lt;/code&gt; se resume a adição dos arquivos com extensão &lt;code&gt;.vue&lt;/code&gt; e a instalação do plugin oficial &lt;code&gt;@tailwindcss/forms&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tailwind.config.js&lt;/span&gt;

&lt;span class="cm"&gt;/** @type {import('tailwindcss').Config} */&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/**/*.{vue,js,ts,jsx,tsx}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#09090A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;gridTemplateRows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;repeat(7, minmax(0,1fr))&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tailwindcss/forms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Frontend: A briga começa aqui!
&lt;/h2&gt;

&lt;p&gt;Não detalharei as diferenças básicas entre os frameworks, existem milhares de artigos na web fazendo isso. Deixarei o link do repositório antes de falarmos sobre Nuxt(esse é o tópico surpresa por aqui).&lt;/p&gt;

&lt;p&gt;A aplicação web no evento da Rocketseat foi gerada utilizando &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;, sendo incrível já que o Vite é mantido pelo core team do Vue. Significa que os passos para criar o projeto são os mesmos, detalhe para a nova CLI do Vue, baseada no Vite e que está disponível para seleção nas opções do comando &lt;code&gt;yarn create vite&lt;/code&gt; &lt;/p&gt;

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

&lt;p&gt;A estrutura de pastas é a mesma do projeto com React, ambos os frameworks usam arquivos de componentes(SFC) em sua arquitetura.&lt;/p&gt;

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

&lt;p&gt;A composição dos SFCs difere, no JSX os componentes são funções ou classes do JavaScript. No Vue o SFC possui separação entre o template, script e estilo. O único obrigatório é o &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;/src/App.vue
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-screen h-screen flex justify-center items-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full max-w-5xl px-6 flex flex-col gap-16"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Header&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;SummaryTable&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/Header.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SummaryTable&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/SummaryTable.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Entrando no componente &lt;code&gt;SummaryTables&lt;/code&gt;, vemos algumas diferenças entre as duas ferramentas. A primeira delas é a renderização de listas. No JSX precisamos chamar o método &lt;code&gt;map&lt;/code&gt; no objeto ou array que queremos iterar e retornar um novo componente a partir do callback que passamos. No Vue isso é resolvido com o atributo &lt;code&gt;v-for&lt;/code&gt; no elemento que queremos iterar.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
        &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(day, index) in weekDays"&lt;/span&gt;
        &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-zinc-400 text-xl h-10 w-10 font-bold flex items-center justify-center"&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weekDays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;S&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Q&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Q&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;S&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;S&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;No quesito renderização de listas, &lt;strong&gt;ponto para o Vue&lt;/strong&gt;. Mas nem sempre ser mais simples significa ser melhor. No mesmo componente, temos outro exemplo onde o React leva a melhor.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;HabitDay&lt;/span&gt;
        &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"date in summaryDates"&lt;/span&gt;
        &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"date.toString()"&lt;/span&gt;
        &lt;span class="na"&gt;:date=&lt;/span&gt;&lt;span class="s"&gt;"date"&lt;/span&gt;
        &lt;span class="na"&gt;:amount=&lt;/span&gt;&lt;span class="s"&gt;"dayInSummary(date)?.amount"&lt;/span&gt;
        &lt;span class="na"&gt;:defaultCompleted=&lt;/span&gt;&lt;span class="s"&gt;"dayInSummary(date)?.completed"&lt;/span&gt;
      &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;summaryDates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateDatesFromYearBeginning&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dayInSummary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isSame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;day&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;No JSX cada iterável tem o componente gerado de uma função anônima passado no método &lt;code&gt;map&lt;/code&gt;. A função &lt;code&gt;dayInSummary&lt;/code&gt; no projeto com React é declarada e executada na função anônima. A solução mais rápida que encontrei foi declarar a função na tag &lt;code&gt;&amp;lt;scrit&amp;gt;&lt;/code&gt; e chamar nos valores do &lt;code&gt;HabitDay&lt;/code&gt;, com certeza existe uma solução melhor, mas não gastei neurônios aqui. Pela flexibilidade, &lt;strong&gt;ponto do React aqui&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Um ponto levantado durante as aulas é o uso do hook &lt;code&gt;useEffect&lt;/code&gt; para disparar funções quando o componente é montado. Não é proibido, mas o hook não foi feito para resolver esse problema em específico. Enquanto existem RFCs na comunidade React debatendo isso, no Vue podemos utilizar o composable &lt;code&gt;onMounted&lt;/code&gt; para essa finalidade.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt; &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Summary&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;summary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Substituindo o Radix pelo HeadlessUI
&lt;/h2&gt;

&lt;p&gt;O Radix infelizmente não possui versão para Vue, mas sem desespero. Podemos substituir componentes como &lt;code&gt;Dialog&lt;/code&gt; e &lt;code&gt;Popover&lt;/code&gt; tranquilamente com o &lt;a href="https://headlessui.com/" rel="noopener noreferrer"&gt;HeadlessUI&lt;/a&gt;.&lt;br&gt;
O Headless possui versões para React e Vue, é mantido pelo time do Tailwind.&lt;/p&gt;

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

&lt;p&gt;Não é 100%, mas resolve o problema. Componentes como &lt;code&gt;Checkbox&lt;/code&gt; e &lt;code&gt;Progress&lt;/code&gt; podem ser feitos de forma simples utilizando apenas o Vue e Tailwind.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctm1bsavgm026q3k0x8x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctm1bsavgm026q3k0x8x.png" alt="Dialog" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Formulários e Two-Way Data Binding
&lt;/h2&gt;

&lt;p&gt;Aqui o Two-Way Data Binding do Vue ganha destaque simplificando algumas operações. Representado pelo atributo &lt;code&gt;v-model&lt;/code&gt;, o Two-Way Data Binding faz quase que automaticamente algumas operações onde precisamos aplicar alguma regra de negócio. O destaque nessa aplicação é no formulário de recorrência de dias, onde o Vue monta o array com os dias da semana selecionados quase automaticamente.&lt;/p&gt;

&lt;p&gt;Iteramos os dias da semana, e colocamos o &lt;code&gt;index&lt;/code&gt; como valor do checkbox. O &lt;code&gt;v-model&lt;/code&gt; vai e manipular o array armazenado em &lt;code&gt;weekDays&lt;/code&gt; com o que passamos no atributo &lt;code&gt;value&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;/src/components/NewHabitForm.vue
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-col gap-2 mt-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center gap-3"&lt;/span&gt;
      &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(weekDay, index) in availableWeekDays"&lt;/span&gt;
      &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
          &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;
          &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;
          &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;
          &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"weekDays"&lt;/span&gt;
        &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-white leading-tight"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;weekDay&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;availableWeekDays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Domingo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Segunda-Feira&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Terça-Feira&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Quarta-Feira&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Quinta-Feira&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sexta-Feira&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sábado&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weekDays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


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

&lt;p&gt;Se pontuar tudo, o texto ficará maior do que já está. Quem quiser ver a implementação completa, só abrir o repositório abaixo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/silvercent011" rel="noopener noreferrer"&gt;
        silvercent011
      &lt;/a&gt; / &lt;a href="https://github.com/silvercent011/nlw-setup-vue" rel="noopener noreferrer"&gt;
        nlw-setup-vue
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;nlw-setup-vue&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;This template should help get you started developing with Vue 3 in Vite.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Recommended IDE Setup&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/" rel="nofollow noopener noreferrer"&gt;VSCode&lt;/a&gt; + &lt;a href="https://marketplace.visualstudio.com/items?itemName=Vue.volar" rel="nofollow noopener noreferrer"&gt;Volar&lt;/a&gt; (and disable Vetur) + &lt;a href="https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin" rel="nofollow noopener noreferrer"&gt;TypeScript Vue Plugin (Volar)&lt;/a&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Type Support for &lt;code&gt;.vue&lt;/code&gt; Imports in TS&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;TypeScript cannot handle type information for &lt;code&gt;.vue&lt;/code&gt; imports by default, so we replace the &lt;code&gt;tsc&lt;/code&gt; CLI with &lt;code&gt;vue-tsc&lt;/code&gt; for type checking. In editors, we need &lt;a href="https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin" rel="nofollow noopener noreferrer"&gt;TypeScript Vue Plugin (Volar)&lt;/a&gt; to make the TypeScript language service aware of &lt;code&gt;.vue&lt;/code&gt; types.&lt;/p&gt;

&lt;p&gt;If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a &lt;a href="https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669" rel="noopener noreferrer"&gt;Take Over Mode&lt;/a&gt; that is more performant. You can enable it by the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Disable the built-in TypeScript Extension
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;Extensions: Show Built-in Extensions&lt;/code&gt; from VSCode's command palette&lt;/li&gt;
&lt;li&gt;Find &lt;code&gt;TypeScript and JavaScript Language Features&lt;/code&gt;, right click and select &lt;code&gt;Disable (Workspace)&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Reload the VSCode window by running &lt;code&gt;Developer: Reload Window&lt;/code&gt; from the command palette.&lt;/li&gt;

&lt;/ol&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Customize configuration&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;See &lt;a href="https://vitejs.dev/config/" rel="nofollow noopener noreferrer"&gt;Vite&lt;/a&gt;…&lt;/p&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/silvercent011/nlw-setup-vue" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  Nitro + Vue = Nuxt
&lt;/h2&gt;

&lt;p&gt;O Nitro é o servidor que &lt;a href="https://nuxt.com/docs/guide/concepts/server-engine" rel="noopener noreferrer"&gt;vem incluído por padrão no Nuxt 3&lt;/a&gt;. &lt;br&gt;
Então, em um projeto Nuxt, criei a pasta &lt;code&gt;server&lt;/code&gt; e colei a pasta &lt;code&gt;routes&lt;/code&gt; e &lt;code&gt;utils&lt;/code&gt; do projeto backend. Você não leu errado, apenas copiei e colei a pasta. Troquei o nome de &lt;code&gt;routes&lt;/code&gt; para &lt;code&gt;api&lt;/code&gt;. Realizei a configuração do Prisma e pronto! API funcionando dentro do Nuxt.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbxq4h6lwou892chhwwx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbxq4h6lwou892chhwwx.png" alt="Nuxt folders" width="568" height="351"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;p&gt;O Nuxt 3 possui um sistema automático de importações, então as funções do Vue, tudo que estiver em pastas específicas como &lt;code&gt;components&lt;/code&gt; não precisam ser importados, o Nuxt realiza as importações automaticamente.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tailwind e Headless
&lt;/h3&gt;

&lt;p&gt;Fiz a instalação do &lt;a href="https://tailwindcss.nuxt.dev/" rel="noopener noreferrer"&gt;módulo oficial do Tailwind para Nuxt&lt;/a&gt; e do &lt;a href="https://github.com/P4sca1/nuxt-headlessui" rel="noopener noreferrer"&gt;módulo do HeadlessUI&lt;/a&gt; para aproveitar as importações automáticas. Para finalizar copiei o arquivo &lt;code&gt;tailwind.config.js&lt;/code&gt; do nosso frontend.&lt;/p&gt;

&lt;p&gt;Ao executar o comando &lt;code&gt;dev&lt;/code&gt; com o gerenciador de pacotes, o Nuxt inicia o Nitro para backend, Vite para frontend e o módulo do Tailwind habilita uma rota especial que é uma espécie de documentação e exibe modificações que fazemos no arquivo de configurações.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hzf4ump4iki08cbc4ci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hzf4ump4iki08cbc4ci.png" alt="Nuxt Terminal" width="800" height="484"&gt;&lt;/a&gt;&lt;br&gt;
Exemplo da cor de background que está customizada nas configurações do Tailwind.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuwtg5ffjczilhcprvty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuwtg5ffjczilhcprvty.png" alt="Tailwind viewer" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copiando as pastas dentro do &lt;code&gt;src&lt;/code&gt; do frontend, e instalando as bibliotecas restantes, podemos realizar algumas substituições.&lt;/p&gt;
&lt;h3&gt;
  
  
  Substituindo o Axios pelos composables nativos do Nuxt 3
&lt;/h3&gt;

&lt;p&gt;O Nuxt 3 possui &lt;code&gt;composables&lt;/code&gt;(hooks para quem vem do React) nativos que realizam requisições otimizadas. As rotas que declaramos na pasta &lt;code&gt;server/api&lt;/code&gt; são tipadas automaticamente.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxghmz3wcyebc06qm67r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxghmz3wcyebc06qm67r.png" alt="rotas tipadas" width="800" height="165"&gt;&lt;/a&gt;&lt;br&gt;
A resposta da api também é tipada pelo Nuxt, que suporta Top-level await, então matamos o estado vazio inicial e o composable &lt;code&gt;onMouted&lt;/code&gt; de todos os componentes, substituindo apenas por um await na tag &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuun0e0gdemytsgnoe0i4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuun0e0gdemytsgnoe0i4.png" alt="resposta tipada" width="685" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A implementação completa no repositório abaixo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/silvercent011" rel="noopener noreferrer"&gt;
        silvercent011
      &lt;/a&gt; / &lt;a href="https://github.com/silvercent011/nlw-setup-nuxt" rel="noopener noreferrer"&gt;
        nlw-setup-nuxt
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Nuxt 3 Minimal Starter&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;Look at the &lt;a href="https://nuxt.com/docs/getting-started/introduction" rel="nofollow noopener noreferrer"&gt;Nuxt 3 documentation&lt;/a&gt; to learn more.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Make sure to install the dependencies:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; yarn&lt;/span&gt;
yarn install

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; npm&lt;/span&gt;
npm install

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; pnpm&lt;/span&gt;
pnpm install&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Development Server&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Start the development server on &lt;a href="http://localhost:3000" rel="nofollow noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run dev&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Production&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Build the application for production:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run build&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Locally preview production build:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run preview&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Check out the &lt;a href="https://nuxt.com/docs/getting-started/deployment" rel="nofollow noopener noreferrer"&gt;deployment documentation&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/silvercent011/nlw-setup-nuxt" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


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

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Inicializando o mongoose no Nitro (a forma fácil, rápida e talvez a única...)</title>
      <dc:creator>Sidney Alex</dc:creator>
      <pubDate>Sun, 27 Nov 2022 01:55:09 +0000</pubDate>
      <link>https://dev.to/s1d3a/inicializando-o-mongoose-no-nitro-a-forma-facil-rapida-e-talvez-a-unica-3pke</link>
      <guid>https://dev.to/s1d3a/inicializando-o-mongoose-no-nitro-a-forma-facil-rapida-e-talvez-a-unica-3pke</guid>
      <description>&lt;p&gt;Oi! Nem eu esperava gostar tanto de escrever por aqui. No post passado expliquei como criar uma REST API simples utilizando o Nitro e o Prisma combinado ao MongoDB.&lt;/p&gt;

&lt;p&gt;Acontece que o Prisma não é o ODM mais famoso do MongoDB no universo JavaScript/Node. A biblioteca mais utilizada (e acredito que vai ser assim por muito tempo) é o &lt;a href="https://mongoosejs.com/" rel="noopener noreferrer"&gt;mongoose&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vamos começar com a estrutura padrão do Nitro.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53n7dnloy37306mray1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53n7dnloy37306mray1i.png" alt="browsercode" width="424" height="321"&gt;&lt;/a&gt;&lt;br&gt;
Se você não sabe como chegamos aqui, dá uma olhadinha no &lt;a href="https://dev.to/s1d3a/uma-simples-api-rest-com-nitro-prisma-mongodb-5c5"&gt;post anterior&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Instalando o mongoose
&lt;/h2&gt;

&lt;p&gt;Dentro do projeto, execute o comando a seguir para instalar o mongoose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i mongoose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Instanciando o mongoose
&lt;/h2&gt;

&lt;p&gt;Diferente do Prisma, o mongoose não cria as conexões automaticamente. Precisamos criar uma instancia do mongoose no inicio da nossa aplicação, mas como fazer isso se o Nitro inicia automaticamente e todos os arquivos que criamos são rotas?&lt;/p&gt;

&lt;p&gt;Para isso, o Nitro possui um sistema de plugins customizados. &lt;a href="https://nitro.unjs.io/guide/advanced/plugins" rel="noopener noreferrer"&gt;Segundo a documentação&lt;/a&gt;, cada plugin que escrevemos é executado de forma síncrona na primeira inicialização do servidor, que é o lugar mais adequado para inicializar o mongoose no Nitro.&lt;/p&gt;

&lt;p&gt;Vamos criar uma pasta chamada &lt;code&gt;plugins&lt;/code&gt; na raiz do nosso projeto, dentro dela criaremos um arquivo chamado &lt;code&gt;mongooseConnect.ts&lt;/code&gt;. O nome pode ser qualquer um de sua escolha.&lt;/p&gt;

&lt;p&gt;Dentro do arquivo escreveremos o seguinte conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//plugins/mongooseConnect.ts&lt;/span&gt;

&lt;span class="c1"&gt;// Importação do mongoose&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Definição do plugin&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNitroPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nitroApp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// inicializando a conexão com o mongodb&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SUA URI DE CONEXÃO COM O MONGODB&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MongoDB conectado&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Conexão com o MongoDB falhou&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Para que o plugin funcione, precisamos registra-lo no arquivo de configuração do Nitro, o &lt;code&gt;nitro.config.ts&lt;/code&gt;. Faremos o registro da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//nitro.config.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineNitroConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nitropack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNitroConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// registrando o plugin&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./plugins/mongooseConnect.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Com essa configuração, você deve conseguir utilizar 100% do mongoose no seu projeto com Nitro. Até logo 👋👋👋👋👋&lt;/p&gt;

</description>
      <category>ai</category>
      <category>learning</category>
      <category>automation</category>
    </item>
    <item>
      <title>Uma simples API REST utilizando Nitro ⚗ + Prisma 🔺 + MongoDB 🍃</title>
      <dc:creator>Sidney Alex</dc:creator>
      <pubDate>Sun, 20 Nov 2022 18:40:43 +0000</pubDate>
      <link>https://dev.to/s1d3a/uma-simples-api-rest-com-nitro-prisma-mongodb-5c5</link>
      <guid>https://dev.to/s1d3a/uma-simples-api-rest-com-nitro-prisma-mongodb-5c5</guid>
      <description>&lt;p&gt;Ao pesquisar sobre construir APIs ou webservices utilizando JavaScript/Node.js é comum encontrar diversos tutoriais utilizando frameworks (além de guias, utilizando os módulos nativos do Node) como &lt;a href="http://expressjs.com/pt-br/" rel="noopener noreferrer"&gt;Express&lt;/a&gt; ou &lt;a href="https://nestjs.com/" rel="noopener noreferrer"&gt;NestJS&lt;/a&gt;, ferramentas sólidas e bastante utilizadas na comunidade. É de se esperar, considerando o tamanho que o ecossistema JavaScript, que não ficaríamos limitados a apenas duas ferramentas, certo?&lt;/p&gt;

&lt;p&gt;Recentemente, o desenvolvimento do &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt 3&lt;/a&gt; tem chamado bastante a minha atenção, não só por ser o framework fullstack do Vue (quem me conhece pessoalmente, sabe que defendo o Vue com unhas e dentes), mas principalmente pela forma que o time escolheu para desenvolver as bases do framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  UnJS
&lt;/h2&gt;

&lt;p&gt;O time do Nuxt criou organização, o &lt;a href="https://unjs.io/" rel="noopener noreferrer"&gt;UnJS&lt;/a&gt;, responsável por criar e manter diversos pacotes que são "universais" e agnósticos de qualquer framework e/ou ambiente. Juntos, muitos desses pacotes formam a base do Nuxt 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  H3 e Nitro
&lt;/h2&gt;

&lt;p&gt;Sendo um framework fullstack, o Nuxt oferece a possibilidade de criar um servidor http dentro do projeto, o &lt;a href="https://github.com/unjs/h3" rel="noopener noreferrer"&gt;H3&lt;/a&gt; é responsável por isso. Quando utilizado isoladamente, o H3 é muito similar ao express, mas no lugar dos callbacks é utilizado um sistema próprio de eventos. &lt;/p&gt;

&lt;p&gt;O &lt;a href="https://nitro.unjs.io/" rel="noopener noreferrer"&gt;Nitro&lt;/a&gt;, que vamos utilizar nesse tutorial, combina o servidor http do H3 com algumas outras bibliotecas do UnJS que nos dão algumas features interessantes, como &lt;em&gt;autoimports&lt;/em&gt; das bibliotecas instaladas e um sistema de rotas baseado em arquivos &lt;em&gt;(como encontramos em frameworks como Next.js ou no próprio Nuxt)&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;O Nitro é o servidor http que é gerado automaticamente na pasta &lt;code&gt;server&lt;/code&gt; de um projeto Nuxt 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que vamos construir hoje?
&lt;/h2&gt;

&lt;p&gt;Criaremos do zero uma API REST de uma biblioteca, gerenciando o CRUD de Livros, Autores e Gêneros.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utilizaremos o Nitro como servidor HTTP.&lt;/li&gt;
&lt;li&gt;Nosso ORM será o &lt;a href="https://www.prisma.io/" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;O banco de dados será uma instância no &lt;a href="https://www.mongodb.com" rel="noopener noreferrer"&gt;MongoDB&lt;/a&gt; criada no &lt;a href="https://www.mongodb.com/atlas/database" rel="noopener noreferrer"&gt;Atlas&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Como o Prisma suporta diversos bancos de dados relacionais, sinta-se a vontade para utilizar outras opções se preferir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando um projeto Node e instalando o Nitropack
&lt;/h2&gt;

&lt;p&gt;Vamos criar uma pasta, e iniciar um projeto Node.js dentro dela.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir books-nitro-api
cd books-nitro-api
npm init -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ainda com o terminal aberto, vamos instalar o nitropack como dependência de desenvolvimento utilizando o comando abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --dev nitropack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abrindo a pasta no nosso editor de código, podemos inserir os scripts do nitro no nosso &lt;code&gt;package.json&lt;/code&gt;. O resultado deve ser parecido com o código abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"books-nitro-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nitro dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nitro build"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nitropack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.0.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;O TypeScript é gerenciado de forma automática pelo Nitro.&lt;br&gt;
Vamos criar o arquivo &lt;code&gt;tsconfig.json&lt;/code&gt; na raiz do nosso projeto, e adicionar o seguinte conteúdo como indicado na &lt;a href="https://nitro.unjs.io/guide/introduction/typescript" rel="noopener noreferrer"&gt;documentação&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./.nitro/types/tsconfig.json"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As pastas &lt;code&gt;.nitro&lt;/code&gt; e &lt;code&gt;.output&lt;/code&gt; são geradas automaticamente assim que rodamos o projeto.&lt;/p&gt;

&lt;p&gt;Finalizando a etapa de configuração, vamos adicionar o arquivo &lt;code&gt;nitro.config.ts&lt;/code&gt; e inserir o conteúdo abaixo que corresponde à função de &lt;a href="https://nitro.unjs.io/guide/introduction/configuration" rel="noopener noreferrer"&gt;configuração&lt;/a&gt; do Nitro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineNitroConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nitropack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNitroConfig&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos criar a nossa primeira rota, como dito anteriormente, o Nitro possui um sistema baseado em arquivos para definir suas rotas. Na raiz vamos criar a pasta &lt;code&gt;router&lt;/code&gt; e criar o arquivo &lt;code&gt;index.ts&lt;/code&gt; que vai corresponder a nossa rota &lt;code&gt;/&lt;/code&gt; do servidor.&lt;/p&gt;

&lt;p&gt;Dentro do arquivo &lt;code&gt;index.ts&lt;/code&gt; vamos definir nosso primeiro evento, assim como sua biblioteca base, o H3, o Nitro é baseado em eventos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/index.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineEventHandler&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;h1&amp;gt;Hello World&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;A estrutura de arquivos deve ficar semelhante à imagem abaixo.&lt;/p&gt;

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

&lt;p&gt;Inicie o servidor de desenvolvimento utilizando o comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O terminal deve exibir as URLs para acessar o servidor, como na imagem abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblbr6koj520uteg4slsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblbr6koj520uteg4slsp.png" alt="code"&gt;&lt;/a&gt;&lt;br&gt;
Observe que as pastas &lt;code&gt;.nitro&lt;/code&gt; e &lt;code&gt;.output&lt;/code&gt; foram geradas automaticamente.&lt;/p&gt;

&lt;p&gt;Ao digitar a URL fornecida no navegador, temos o retorno que escrevemos no arquivo &lt;code&gt;routes/index.ts&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;Não abordaremos em detalhes sobre a criação de um banco de dados com MongoDB neste tutorial.&lt;/p&gt;

&lt;p&gt;Abra uma nova guia, crie uma conta no &lt;a href="https://www.mongodb.com/atlas/database" rel="noopener noreferrer"&gt;MongoDB Atlas&lt;/a&gt; e volte aqui quando já tiver uma &lt;code&gt;string&lt;/code&gt; de conexão com o banco.&lt;/p&gt;

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

&lt;p&gt;Já voltou? Seguindo para a instalação do Prisma!&lt;/p&gt;
&lt;h2&gt;
  
  
  Instalando o Prisma
&lt;/h2&gt;

&lt;p&gt;Vamos utilizar o &lt;a href="https://prisma.io" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt; como nosso &lt;a href="https://pt.wikipedia.org/wiki/Mapeamento_objeto-relacional" rel="noopener noreferrer"&gt;ODM&lt;/a&gt;, uma espécie de tradutor entre o banco de dados e a linguagem de programação.&lt;/p&gt;

&lt;p&gt;Vamos instalar o Prisma como dependência de desenvolvimento, utilizando o comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install prisma --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logo em seguida, vamos instanciar os arquivos do Prisma utilizando o comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx prisma init --datasource-provider mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você vai perceber que houve mudanças nos arquivos do nosso projeto, o comando anterior criou uma pasta chamada &lt;code&gt;prisma&lt;/code&gt; e um arquivo &lt;code&gt;.env&lt;/code&gt; que corresponde à configuração de ambiente da aplicação.&lt;/p&gt;

&lt;p&gt;A estrutura de arquivos deve parecer com a imagem abaixo:&lt;/p&gt;

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

&lt;p&gt;Dentro do arquivo &lt;code&gt;.env&lt;/code&gt; haverá uma propriedade chamada &lt;code&gt;DATABASE_URL&lt;/code&gt;, é aqui que vamos colar a string de conexão com o MongoDB, similar ao snippet abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// .env&lt;/span&gt;
&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongodb+srv://USERNAME:PASSWORD@HOST:PORT/DATABASE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abrindo o arquivo &lt;code&gt;prisma/schema.prisma&lt;/code&gt;, temos algumas informações já inseridas automaticamente pelo Prisma, como o client (que vamos instalar nos próximos passos), o banco de dados, MongoDB no nosso caso, e uma url que importa a nossa variável de ambiente que vai conectar a nossa API ao banco de dados na nuvem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// prisma/schema.prisma&lt;/span&gt;

&lt;span class="nx"&gt;generator&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prisma-client-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;datasource&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongodb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Aqui vamos criar um modelo básico de livro com os campos &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;ìsbn&lt;/code&gt; e &lt;code&gt;description&lt;/code&gt;, além de outros campos relacionados ao banco. Vamos adicionar o seguinte trecho de código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="nx"&gt;Book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;          &lt;span class="nb"&gt;String&lt;/span&gt;    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;id&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectId&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;        &lt;span class="nb"&gt;String&lt;/span&gt;
  &lt;span class="nx"&gt;isbn&lt;/span&gt;        &lt;span class="nb"&gt;String&lt;/span&gt;    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;unique&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
  &lt;span class="nx"&gt;createdAt&lt;/span&gt;   &lt;span class="nx"&gt;DateTime&lt;/span&gt;  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="nx"&gt;updatedAt&lt;/span&gt;   &lt;span class="nx"&gt;DateTime&lt;/span&gt;  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;updatedAt&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;model Book&lt;/code&gt;- aqui informamos ao schema que criaremos uma coleção de documentos, em um banco relacional o Prisma cria uma tabela.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;id          String    @id @default(auto()) @map("_id") @db.ObjectId&lt;/code&gt;- cada documento do MongoDB possui um id único do tipo String, o que significam as notações com @ no final da linha. Essas notações variam de banco para banco dentro do Prisma.&lt;/li&gt;
&lt;li&gt;Declaramos os atributos name, isbn e description do tipo String, atenção para a notação &lt;code&gt;@unique&lt;/code&gt; que inserimos no campo isbn, indicando que esse valor não pode se repetir e é único para cada documento.&lt;/li&gt;
&lt;li&gt;Os campos createdAt e updatedAt não são obrigatórios, mas é interessante saber quando o registro foi criado e atualizado pela última vez, as notações são padrão do Prisma.&lt;/li&gt;
&lt;li&gt;Outras informações relevantes podem ser encontradas na &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema" rel="noopener noreferrer"&gt;documentação&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Instalando o Prisma Client
&lt;/h2&gt;

&lt;p&gt;O Prisma Client é a parte do Prisma responsável por gerenciar o banco de dados e gerar a tipagem baseada no schema que criamos no passo anterior. Instale a biblioteca com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @prisma/client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após instalar a biblioteca, é hora de gerar as tipagens específicas que o TypeScript do nosso projeto vai utilizar, a cada modificação do schema devemos rodar o comando&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx prisma generate dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Instanciando cliente do Prisma
&lt;/h2&gt;

&lt;p&gt;Em toda a nossa aplicação, devemos ter apenas um cliente do Prisma gerenciando todas as nossas requisições.&lt;/p&gt;

&lt;p&gt;Crie uma pasta &lt;code&gt;utils&lt;/code&gt; na raiz do nosso projeto e dentro dela um arquivo &lt;code&gt;prisma.ts&lt;/code&gt; com o seguinte conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Criando as rotas da API
&lt;/h2&gt;

&lt;p&gt;Baseado em eventos e com o sistema de rotas baseado em arquivos, o Nitro possui uma organização de arquitetura um pouco diferente de outros frameworks.&lt;/p&gt;

&lt;p&gt;Dentro da pasta &lt;code&gt;routes&lt;/code&gt; crie em seguida as pastas &lt;code&gt;api&lt;/code&gt;, e a seguinte estrutura de arquivos:&lt;/p&gt;

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

&lt;p&gt;Observe que o método da nossa requisição http é declarado no arquivo. &lt;br&gt;
Ambos os arquivos vão responder pela mesma URL na API, &lt;code&gt;http://minhapi/api/books&lt;/code&gt;, mas um com o método &lt;code&gt;GET&lt;/code&gt; e outro com o método &lt;code&gt;POST&lt;/code&gt;.&lt;br&gt;
(Saiba mais sobre os métodos HTTP)[&lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Methods" rel="noopener noreferrer"&gt;https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Methods&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Iniciando pelo código do método &lt;code&gt;GET&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/api/books.get.ts&lt;/span&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineEventHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Na primeira linha importamos o cliente do Prisma que instanciamos no passo anterior.&lt;/li&gt;
&lt;li&gt;Logo em seguida exportamos por padrão em toda rota do Nitro a função do &lt;code&gt;defineEventHandler&lt;/code&gt; do H3, o Nitro vai gerenciar a importação do H3 por padrão, sem precisar declarar explicitamente.&lt;/li&gt;
&lt;li&gt;A função &lt;code&gt;defineEventHandler&lt;/code&gt; recebe por parâmetro uma função anônima que expõe o evento que tanto falamos desde o início do post e que vai ser mais útil quando comentarmos sobre o método POST.&lt;/li&gt;
&lt;li&gt;Como a função anônima que passamos por parâmetro é assíncrona, &lt;a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/Asynchronous/Introducing" rel="noopener noreferrer"&gt;veja mais sobre assincronismo no JS&lt;/a&gt;, definimos uma constante &lt;code&gt;books&lt;/code&gt; e esperamos que o nosso cliente do Prisma retorne todos os livros da API através do método &lt;code&gt;findMany()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Por fim, retornamos o resultado para o cliente que está solicitando os dados a nossa API.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/api/books.post.ts&lt;/span&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineEventHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;readBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newBook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;newBook&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Seguindo a mesma estrutura padrão do anterior, mas observe que na constante &lt;code&gt;payload&lt;/code&gt; eu chamo outro método do H3 e passo o meu evento como parâmetro. Todos os dados da nossa requisição estão guardados dentro do evento. Nesse caso estamos lendo o body que mandamos por requisição com os dados do livro a ser cadastrado.&lt;/li&gt;
&lt;li&gt;Na constante &lt;code&gt;newBook&lt;/code&gt; utilizamos o método &lt;code&gt;create()&lt;/code&gt; do Prisma para inserir um livro no banco de dados, e retornamos ele na linha seguinte.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Então, esse é o tutorial de uma API bem simples utilizando essa stack. Talvez eu volte aqui em outros posts para falar sobre mais detalhes que ficaram de fora desse guia (rotas mais complexas, tratamento de erros, manipulação de eventos, middlewares...), até a próxima 🤓🖖&lt;/p&gt;

</description>
      <category>prisma</category>
      <category>mongodb</category>
      <category>ptbr</category>
      <category>node</category>
    </item>
  </channel>
</rss>
