Chegamos na terceira aula da Imersão Dev com Google Gemini e vou falar a real para vocês. Estou muito feliz com o que a gente construiu até aqui, porque lá do zero, começamos a criar o nosso servidor e na última aula colocamos uma forma de armazenar os dados da aplicação que estamos fazendo na nuvem. E é legal porque a cada imersão que passa a gente de verdade quer trazer a experiência do mundo real de desenvolvimento para você, que quer fazer transição de carreira, que está estudando, tentando alcançar seus objetivos profissionais. E de verdade, esse conteúdo que
vimos, nem sempre se aprende em duas horas. Nunca se aprende em duas horas. Porque na verdade aqui também estamos abstraindo bastante conteúdo para você conseguir acompanhar a conversa e entender o que nós estamos fazendo. Mas tem muitas camadas para estudar. Se a gente quisesse parar para ficar só falando da forma que a rede se comunica, seria uma imersão inteira. Todas as imersões do ano que vem seriam sobre esse assunto. Com certeza. Então estamos escolhendo uma linguagem simples de trabalhar, com recursos fáceis de configurar, porque o mais importante é se registrar essa ideia. Por exemplo, você
comentou: olha que legal, agora a nossa aplicação trabalha com dados e armazena em algum lugar. Por enquanto esse algum lugar é um array, um objeto que a gente criou e isso está só em memória. No final da última aula a gente começou a acelerar um pouco esse pedal para a gente poder trabalhar com um banco de dados real. Inclusive a gente escolheu o Mongo para trabalhar. Exato, que é um banco muito utilizado em APIs na vida real. Então você vai ver em muitas aplicações, em muitas APIs, em muitos serviços que utilizam exatamente esse mesmo banco
e ele está na nuvem. Os recursos de nuvem existem, entre outras coisas, para dar uma facilitada e para tirar da gente esse trabalho de você ter o seu servidor on-premises, que é o seu servidor próprio de banco de dados. A nuvem gerencia isso para nós e facilita muito esse trabalho. Cuida de autenticação, cuida de segurança, cuida do armazenamento. E isso tudo, essa parte do banco é real. O banco existe e os dados vão estar guardados lá. Não é mais nada em memória. Essa aula será muito legal porque vamos conectar nosso sistema a esse banco. Vamos
colocar alguns códigos novos para ele entender os caminhos que tem que seguir. Mas agora, no final da aula de hoje, a sua aplicação será capaz de gravar dados em um banco que está na nuvem. Mas calma. Antes de sairmos escrevendo código e deixando a nossa aplicação ainda melhor, eu te convido a fazer parte da nossa comunidade no Discord. Lá temos encontros com monitores, pessoas que estão fazendo transição de carreira, pessoas que já programam, já estão atuando no mercado, que ajudam outras pessoas a aprender. É muito legal. Tenho certeza que a experiência de quem entra na
Imersão Dev e faz parte da comunidade do Discord, interage, vê outros projetos, analisa até outros prompts que as pessoas usaram para criar as suas listas, seus arrays ali... É muito diferenciada. Então, faça parte da nossa comunidade no Discord. Assista todas as aulas. Estamos hoje na terceira. Assista todas as aulas pra que você tenha acesso ao seu certificado. Porque eu tenho certeza que, assim como a nossa história na tecnologia, tivemos a oportunidade de contar com professores e professoras tão legais, tão brilhantes, que nos ajudaram e nos formaram para hoje passar o conhecimento que temos. Então, é
uma alegria muito grande. E quando a gente troca, aprendemos com a nossa experiência e com a do outro. Até para criar esse projeto, trocamos as nossas experiências, discutimos abordagens. E tudo o que está acontecendo aqui, como vocês falaram, é reflexo daquilo que a gente vive na vida real, no mercado profissional. Estamos simulando etapas que você vai viver também na sua jornada. E é por isso que eu acho importante que você acompanhe todas as aulas. Porque a gente constrói uma aplicação de pouquinho em pouquinho. Então, lá na última aula, que vamos ter a totalidade do que
a gente pretendia passar, pretendia ensinar, transmitir para vocês nessa imersão. Assista todas as aulas para ir acompanhando e incrementando todos esses pouquinhos que estamos fazendo. É isso aí. Vamos para cima, gente? Você vai lembrar que na última aula, no nosso último encontro, a gente criou uma conta lá no Atlas. Criamos uma conta para usar o MongoDB na cloud. E ele deu para nós algumas informações que nós guardamos. Salvamos o nosso usuário, a nossa senha. Salvamos a nossa string de conexão. Mas, o Atlas ainda pedia para a gente fazer mais um passo, que é instalar no
nosso projeto o pacote que será responsável por cuidar da conexão com o Mongo. Agora, estamos na aula 3. Eu quero saber se você lembra qual é o comando que a gente usa para instalar qualquer pacote no Node. Não só lembro, como vou mostrar aqui na tela. npm install mongodb. Ele fala que isso é um driver. De alguma forma, temos que falar assim, o nosso projeto vai se conectar com o MongoDB. Precisamos dessa dependência. Se você quiser depois pesquisar ou perguntar para o Gemini sobre drivers, porque os drivers são muito importantes em programação. E também, se
você quiser ir na página do NPM e pesquisar todas essas dependências que a gente instalou, você encontra a página delas no site do NPM. Então, NPM MongoDB, NPM Express, você vai encontrar a página que tem todas as documentações dessas dependências e de todas as outras que elas utilizam. Que da hora. Vamos lá, então. Vamos copiar esse código. Isso. Lá no nosso projeto. Vou colocar aqui. npm install Mongodb. E pressionar "Enter". Ele está pensando ali um pouco. Isso é só para adicionar no seu projeto a capacidade de falar com o banco. Ainda vamos configurar essa conexão
com o banco. Vamos precisar dizer onde está o nosso banco. Exato. Se você for no package.json, vai ter lá adicionado esse driver acabamos de instalar junto com o Express. Agora está tudo configurado. Package.json já foi informado. Bom, vamos conectar a nossa aplicação. Pensa assim, o banco de dados. Você pode ter vários bancos dentro do seu espaço de armazenamento. Queremos conectar com um banco específico. E dentro desse banco nós vamos ter, digamos assim, coleções. Que é a forma como a gente se refere. Coleção posts, dependendo da sua aplicação. Coleção usuários, coleção livros. Temos que ter a
nossa coleção posts. Então, lá no site do Mongo, voltamos lá para terminar de fazer essa criação. Dá para fazer pelo código, mas vai ficar mais fácil fazer isso direto pelo site do Mongo. Você pode dar um "done" ali embaixo no botão verde. E no cluster 0, você pode dar um add data ali embaixo. Create a database on Atlas. Vamos criar a nossa database. Temos um cluster, temos esse espaço. Vamos criar agora a primeira database. Podemos colocar imersão, imersão instabytes? Pode ser imersao-instabytes. Beleza. Pode dar um zoom. Qualquer referência com a realidade é mera coincidência, pessoal.
Como eu falei, o Mongo é um banco de objetos. Então, dentro de uma database, temos algumas coleções, dependendo do nosso projeto. Precisamos de pelo menos uma coleção, que é uma coleção de posts. Vamos criar uma coleção chamada "posts". Tudo minúsculo. É como se a nossa database fosse o meu armário e as minhas coleções fossem as minhas gavetas. Dentro das minhas coleções, guardo os objetos que quero utilizar. Exato. Lá embaixo, clica em "Create Database". Ele vai fazer um deploy, vai publicar lá na nuvem do Mongo. Pode levar uns minutinhos para você. Aqui foi rápido. Nós já
temos uma database e no menu da esquerda já tem ali posts. Ele puxa o posts. No canto direito tem insert document. Se você for tudo para direita, vai ter um botão "Insert document". Podemos criar dentro da nossa coleção de posts, dentro da nossa base Instabytes, alguns posts. Quando clicamos em "Insert document", ele já cria um ID pra gente. Olha lá, o identificador. Ele já cria no formato que é específico do Mongo. A gente entra nisso daqui a pouco. E agora podemos ir criando o que quisermos. Então, tem dois pontos? Isso, pode criar aí na esquerda.
Na verdade, você vai clicar à esquerda desses dois pontos. Tem um sinalzinho de dois pontos. Deixa eu dar um super zoom. Esse zoom me ajudou demais. Eu com os meus óculos aqui agradeço. Nossa, eu com o zoom não tava vendo. O que a gente combinou que cada post precisava? Cada post precisa de uma área. Vamos ver? Eu não lembro. Vamos lá. Está lá no nosso server. O ID que já está lá, descrição, imagem e o caminho da imagem. Sim. Podemos dar um nome melhor pra imagem porque vamos lidar com URLs de imagem. Então, pode ser
IMG URL, pode ser imagem URL, o que vocês preferirem. Porque não é uma imagem que estamos guardando. É URL de uma imagem. Nomenclatura é uma coisa muito importante. A vida toda vamos debater, vamos discutir e vamos ficar pensando nos nomes que a gente dá pras coisas. Sem caracteres especiais e sem acento. Na descrição podemos colocar um string qualquer. Descrição, uma imagem. Porque só estamos testando. E agora podemos ir no mais, que apareceu ali do lado da linha 2. Adicionar campo depois de descrição. E agora? Pode ser imagemUrl ou imgUrl. Tudo junto ou a gente faz
assim? Pode ser com camel case. Pode colar o caminho http que estava lá no projeto. E nessas horas sempre surge aquela dúvida. Ah, mas e se eu quiser colocar outro nome? Posso? Meu nome é diferente? Pode! Você pode chamar os campos aí de batatinha, dinossauro e caravela. Não tem problema. O problema é lembrar desse padrão depois. Por isso que a Ju reforçou que nomenclatura é algo tão fundamental. Não podemos olhar o nome e ter pensar o que a pessoa quis dizer. O imgUrl é fácil. Você bate o olho e sabe que é a URL, o
caminho para uma imagem. Descrição, você sabe que é a descrição. Só com cliques criamos aí um primeiro documento no banco. Tem mais um campo que eu acho que é importante colocar. Nós estamos lidando com imagens que vão para o navegador. Existe o texto alternativo da imagem. O texto alternativo serve para que pessoas que usam leitor de tela para navegar pela internet, elas entendam o que tem nessa imagem. Então, a gente coloca uma descrição bem objetiva. É um campo que é sempre recomendado colocar. Ele é muito importante. Então, estamos lidando com imagens. Vamos colocar mais um
campo. Pode clicar no mais. Pensando em acessibilidade também. Escreve só alt. Alt já é padrão. E pode colocar como exemplo: descrição da imagem. Nesse momento, quando a gente preenche, na parte direita, o Mongo já está identificando como string. Se quisesse colocar número, poderíamos usar outros tipos de dados. No caso, são strings mesmo pois estamos trabalhando com texto. E um id, que é o object id, um formato de id do Mongo. Beleza. Pode clicar em "Insert". Ele está inserindo. Então, já temos um banco. Nosso banco já tem um dado. O primeiro registro. Tem uma série de
botões na direita. Acho que você consegue duplicar. Pra gente ter pelo menos uns dois ou três. Tem um desses que serve pra copiar. Clone. Clique em "Clone". Pode trocar os dados ou deixar os mesmos. Pode deixar os mesmos. Ou colocar uma imagem dois, não sei. Vou colocar imagem dois. Só pra gente saber que é o período marcado. Não, vamos colocar. Como chama aquele? Gatinho panqueca. Gato panqueca. Mostra isso aqui. Beleza. Pode deixar o resto. Galera, o mais legal que estamos fazendo aqui é começar a trocar aquele nosso array, que estava em memória, cheio de objetos,
por algo que está no nosso banco de dados. Por isso que estamos criando esse ambiente. Nós populamos esse banco, criamos a coleção, criamos a base, para daqui a pouco poder jogar aquele array fora e trabalhar com esta base de dados. Temos um próximo desafio, que é pegar as informações que estão lá no cloud e trazer para o nosso projeto. Exato. Já temos o banco, já temos a aplicação, já temos o string de conexão. Como a gente junta tudo isso? Primeira coisa que vamos fazer é trazer a string de conexão que a gente copiou para o
nosso projeto. Ela tem informações sensíveis sobre o banco, porque ela é o único ponto de conexão com o banco. Todas as informações que precisa para conectar estão lá. Seu usuário, a senha, o endereço do banco na cloud, etc. Esse tipo de informação não pode ficar pública e ir para o GitHub de jeito nenhum. Existem algumas formas de proteger dados sensíveis. Vamos usar uma das mais básicas, simples e usuais, que é criar variáveis de ambiente. Ok, já estamos no projeto. Como criar uma variável de ambiente e guardar coisas de forma segura? Porque já estamos guardando a
chave de API fora do GitHub. Mas a nossa aplicação não consegue acessar esse txt. Até consegue, mas não de uma forma simples. Abre o terminal, Gui, que nós vamos instalar... Não, não vamos instalar nada, eu viajei na maionese! Podemos só criar um arquivo. Vamos criar um arquivo na raiz do projeto. Esse arquivo tem que chamar ponto, começa com ponto mesmo: ".env". Ele vai virar um ícone de engrenagem. O .env é o arquivo básico, padrão, onde a gente cria esse tipo de variável, que a gente chama de "variável de ambiente". Porque ela existe só dentro do
nosso ambiente. Vamos criar um nome para a nossa variável. Podemos chamá-la de string conexão mesmo. É tudo minúsculo ou maiúsculo? Nesse caso, muito importante, o padrão das variáveis, desse tipo de constante de variável de ambiente, é tudo maiúsculo separado por underline. Então, tudo maiúsculo: STRING_CONEXAO. Colocar um sinal de igual e pegar o valor de tudo que temos aqui. "Ctrl+C". "Ctrl+V". Colou. Se vocês observarem a string de conexão que o Mongo forneceu, Ele já está fornecendo a senha. Às vezes ele pode vir... Pode ser que quando você faça no seu, ele venha com a senha, dizendo
assim: coloque sua senha aqui. É sempre esse esquema, o nome do usuário que você criou, dois pontos, a senha, arroba, o endereço, barra. Aí você pode passar qual que é o cluster, porque você pode ter várias bases de dados dentro do mesmo cluster. Então, vai depois da barra. A estrutura da string de conexão é sempre essa. Então, está tudo preenchido já. E vamos lá no nosso gitignore e adiciona uma linha .env. Minúsculo. Que aqui se trata do arquivo. E esse arquivo não é commitado. Todas as variáveis que a gente coloca nesse arquivo só existem neste
ambiente. Como é que a gente passa essa variável para o Node de forma segura? Porque não podemos colocar isso dentro de um projeto. Sabe o que vamos fazer? Vamos lá no nosso package.json, vamos adicionar uma coisa nova nele. Está vendo a linha 26, scripts? Dentro desse objeto, conseguimos definir alguns comandos que a gente passa para executar tarefas. Então, a gente estava usando até agora Node, Watch, Server.js, a gente estava escrevendo tudo isso na mão. Conseguimos passar isso para dentro de um script. Ou seja, quando executar esse script, ele vai executar o comando que está sendo
passado. Você pode escrever dentro do dev mesmo, que é um dos clássicos, Node, e --watch, que a gente já estava usando. Agora, vamos adicionar o --env -file, tudo junto. Igual a .env. Espaço Server.js. O que estamos fazendo? Estamos passando para dentro do comando para o Node deixar o nosso servidor de pé e ficar recarregando segunda informação, segunda flag, segunda opção que estamos passando. A primeira é essa Watch, segunda opção. Dizendo que tem um arquivo de variáveis de ambiente no meu projeto. E ele se chama env. Então, Node, olha lá. E por último, ele pega tudo
isso e inicia o nosso servidor executando server.js. Poderia escrever esse comando na unha toda vez que fosse mandar rodar para testar, mas, obviamente, é um trabalhão. Por isso a sugestão de usar esse recurso tão legal dos scripts. Agora, sim, podemos abrir o terminal. E subir o nosso servidor. Porém, antes, vamos fazer o seguinte. Vamos lá no server.js? Em qualquer ponto do server.js, vamos adicionar um console para ver se está funcionando. Onde você sugere? Pode ser lá no começo, na linha 2 mesmo. O que você quer fazer? Console.log. E agora vamos realmente acessar esse string de
conexão. Pode tirar as aspas. Vamos passar process.env. Qual é o nome da nossa variável de ambiente? String, tudo maiúsculo. Porque é case sensitive. STRING_CONEXAO. Isso. Vamos subir o servidor para ver se está funcionando? Uma dúvida. A gente alterou aqui no script, usando esse scripts no dev. Eu não subo mais o servidor da forma que estava fazendo. Agora, qual comando que eu uso para subir o servidor? O dev, esse script que estamos usando, ele vai substituir. O node --watch --env-file = env.server.js. Você mesmo falou que não vai precisar rodar tudo isso. Vamos justamente mandar ele rodar
o script dev. Como faz? npm run dev. Lembra que a gente comentou que o NPM funciona com várias coisas. Ele funciona com init para iniciar o projeto, install para instalar um pacote, e agora a gente utilizou ele para rodar esse script. Que legal. E deu certo. Ele conseguiu trazer de uma forma segura exatamente o script que temos ali. O próximo desafio agora é o seguinte. Agora que já temos acesso ao script... O próximo desafio, na verdade, é apagar esse console.log. Se não, o próximo dev que vier já vai ter acesso. Não adianta ter env nem
nada. Isso, mais do que um desafio, é uma necessidade. Agora precisamos de uma forma de dizer para o nosso sistema se conectar com esse banco. Não estou nem chegando no mérito ainda de puxar informações. Primeiro queremos que a conexão seja estabelecida utilizando aquela string de conexão que acabamos de montar. O que vossa excelência sugere? Olha, um caminho muito comum que vossas excelências que estão acompanhando a gente criem um arquivo específico para lidar com essa parte de conectar com o banco. Para quem já conhece orientação a objetos, pode criar uma classe. Para quem não conhece, pode
criar uma função. Não importa muito o como. O que importa é separar essa preocupação. Vamos em outro arquivo colocar essas informações que são referentes à nossa conexão com o banco. Podemos criar um arquivo até numa pasta específica. Como vocês sugerem o nome dessa pasta? Vamos criar uma pasta chamada src. Por que src? É de "source", de código fonte. Por que estamos dando esse nome? Porque é um nome padrão. Dentro do source code, dentro do código fonte, podemos adicionar mais uma pasta para ficar organizada. Então, seleciona o src, clica no ícone de pasta, config.' Config. E
dentro da pasta config, criamos um arquivo que podemos chamar de dbconfig.js ou mongoconfig. O dbconfig acho que fica mais legal. E aí, como que a gente conecta? Uma coisa que é importante saber é que quando usamos drivers, tudo que instalamos que não é do nosso código, temos que entender como utilizar os recursos. No caso do Express, já tínhamos visto a documentação e já descobriu. Para usar o Express, tenho que primeiro chamar a função, depois passar para dentro de app... Quais são os métodos que eu consigo usar? Usar .get, usar .listing. Tudo isso é da documentação
e o Express é que define. Mesma coisa com o driver do Mongo. Para o driver do Mongo funcionar, ele tem algumas funções específicas que temos que executar. Isso é meio o que chamamos de receita de bolo, porque a gente sabe, olha, você vai usar aqui o driver do Mongo chamando essas funções. Aí passa a string de conexão com essa função. Então, o que vamos fazer? Vamos pegar um código, que é a receita de bolo. Esse código já está pronto para não precisarmos digitar muita coisa. Pelo que você falou, Ju, deixa eu ver se eu entendi.
Depois que criamos lá no Atlas, fizemos todas as configurações do que era necessário, para que o meu projeto Mongo se conecte com o banco de dados, é um código que não vai mudar muito. Então, a gente já deixou esse código preparado, vai ficar disponível aqui embaixo, o código que conecta com o código do dbconfig. Nem que ele não vai mudar muito, viu, Gui? Eu vou ser o exagerado e dizer que ele não vai mudar nunca. Inclusive, é comum que em documentações de bancos de dados, já se dê a opção desse tipo de função para várias
linguagens de programação. Você vai lá, copia e cola e ajusta um detalhe. Pode dar um "Ctrl+V". Dei um "Ctrl+V", ele criou um código aqui. Nem são tantas linhas assim, são dezessete linhas de código. Ele tem uma função aqui que conecta ao banco. Lá em cima ele importa MongoClient from Mongodb, que foi o que a gente instalou. Então, MongoClient de onde saiu? Da documentação. Tudo isso a gente utiliza segundo a instrução que a documentação passa. Colocamos dentro de uma função que chamamos em português mesmo, conectar ao banco, e essa função tem um parâmetro, que é nosso
string de conexão. Agora o trabalho, lembra que função a gente declara e depois executa ela, ela não está sendo executada. Aqui ela está só sendo criada. Então, lá no nosso server JS, em algum momento eu vou falar assim: conecta com o banco. E eu passo aquela string de conexão, que eu não lembro, deixa eu dar um "Ctrl+Z" aqui, que eu deletei. É o process.env.STRING_CONEXAO. Beleza. Como eu faço isso, Ju? Se a gente voltar lá no dbconfig, na primeira linha da função, tem export default. "export default" significa que conseguimos pegar essa função que está em um
arquivo e usá-la em outro arquivo. Agora vamos no nosso server.js e importa. Se a gente exportou de um lugar, podemos importar em outro. Então, import, parecido com express, agora import o nome da nossa função, conectarAoBanco. Ele fez automaticamente. Mas um detalhe muito importante, porque às vezes o VSCode se confunde, no front-end não precisa do ".js" no final, mas no Node precisa. Ele autocompletou, mas na linha 2 precisa inserir o ".js". Essa é aquela dica de milhões de quem, trabalha com o negócio no dia a dia. Provavelmente já importamos, não colocamos o .js, tivemos problemas. Aí
você fica procurando. Horas e horas. Procurando o erro... Não, foi ali o Visual Studio Code, que ele foi tentar ajudar. Claro. Eu até entendo. Por isso é importante conhecer a ferramenta, mas também conhecer a linguagem. Achou ruim, faz o código no bloco de notas. Mas, beleza. Então, não podemos esquecer esse ".js" depois. Ele trouxe o nome certinho. O próximo passo é, de fato, conectar passando a string de conexão. A gente já tem a função, que ela foi importada. Vamos testar se ela está funcionando. "Await" é a palavra mágica. await conectarAoBanco. E lembra que ela precisa
receber a string de conexão. Aquele "Ctrl+C" que estava aí. Estava digitando com cuidado pra não dar "Ctrl+C" e perder a string de conexão. Beleza. Vamos no terminal ver o que aconteceu? Olha aí, hein? Conectado ao MongoDB Atlas com sucesso. Está conectado ao banco e não está nem aqui. Está lá na nuvem. O seu sistema está conversando pela internet. Você sabe onde esse banco está? Eu não faço ideia. Sei que está em São Paulo porque configuramos em São Paulo. Mas onde em São Paulo? Eu já não sei. O que importa é que estão fora da nossa
máquina. Está em algum lugar e nesse lugar os nossos dados estão seguros. Estão. Bom, agora o nosso sistema, então. Ele já é capaz de ouvir algumas rotas, mas ainda não fizemos ele buscar o conteúdo no banco. Vou fazer uma provocação aqui. Faça. Na linha 12, que está aqui todos os posts, que era aqueles posts que estávamos usando só o ambiente de desenvolvimento. Daria para eu já puxar esses posts que estão lá na nossa cloud? Daria. Podemos fazer essa adaptação agora. Mas eu só acredito vendo. Vamos fazer o seguinte. Vamos criar uma função. Vamos criar uma
função aí no server mesmo, porque o Gui está doido pra testar. Vamos criar uma function. Vamos chamar essa function de getTodosPosts. Vamos usar "get" porque é o padrão. Quando estamos pegando coisas, usamos a palavra em inglês mesmo. Tem parâmetro? Não, não tem parâmetro, 'porque queremos tudo. Deixa eu te dar uma sugestão, Gui. Pausa o seu servidor, quebra ele, dá um "Ctrl+C", só para que a cada "Ctrl+S" que você está usando, ele não reinicie o servidor e faça uma nova conexão com o banco de dados. Porque imagina que a gente faz um milhão de conexões em
sequência num espaço curto, o servidor vai olhar e falar: ué, estão me atacando ou é isso mesmo? Bem lembrado. A gente espera que tenha muita gente assistindo essa imersão. E na internet parece que essas coisas não importam, mas elas importam. Porque vocês serão muitas pessoas. Ele perguntou se queremos finalizar, confirmei e ele parou. Diferente do que a gente fazia antes, que era só o "Ctrl+C" e ele parava. Tranquilo. Criamos a nossa função na linha 12. Antes de preencher essa função, uma coisa muito importante. Antes da palavra-chave "function", vamos adicionar outra palavra-chave chamada "async". Fica async
function getTodosPosts, já vamos chegar nisso. Aqui dentro, o que vamos fazer? Criar uma const, podemos chamar de db, igual. Vamos fazer o seguinte? Vamos subir um pouco? Deixa eu dar uma olhada. Eu posso acessar aqui, mas fico olhando para a sua tela. Na linha 3, onde estamos só conectando ao banco, agora temos que fazer diferente, porque temos que pegar os dados dessa conexão para conseguir usar os dados dessa conexão. Então, na linha 3, vamos criar uma const. Lá no começo, antes de await, cria uma const. Podemos chamar de conexão mesmo. Conexão. Agora, quando essa função
conectar ao banco, todos os dados relativos a essa conexão vão ficar guardados nessa variável. E lá na linha 3, onde a gente começou a nossa const db, será db igual conexão.db. E aí, qual é o banco de dados? Qual é o nome do banco que a gente criou? Vamos precisar olhar lá no arquivo. Não lembro. Ainda bem que temos o site do Atlas. Porque você pode ir lá e dar uma olhadinha. Vamos lá no site do Atlas. Tira um pouco do zoom. Vamos ver se vai aparecer para a gente. O nome do nosso banco é
imersao-instabytes. Vamos voltar lá. Colocar entre aspas. Isso é uma string. E agora a gente cria uma nova const para guardar a coleção. - Coleção em português? - Coleção em português mesmo. Agora vai chamar db.collection. É um método mesmo. E passa uma nova string. Qual o nome da nossa coleção? Posts. Pode parecer um monte de coisa, mas é simples ler essas linhas. Estou criando o meu objeto db, mas de onde que ele vai vir? Da conexão que eu abri do banco, ponto, o banco de dados que estou acessando. Quer dizer que nesse momento, quando eu passar
pela linha 13, o meu objeto db representa o meu banco chamado imersao-instabytes. Na linha de baixo, que estamos criando outra variável, outro objeto, o que ele está recebendo? O meu banco db.collection. Então eu fui naquele banco e abri uma coleção específica. Fui no meu armário e abri uma gaveta específica. Qual? A gaveta posts. Então, nesse momento, o getTodosPosts, ele está indo e estamos criando objetos para representar o nosso banco e a nossa coleção. Excelente. Agora, temos que retornar o que vamos encontrar dentro de coleção posts. Então, a última linha será um return colecao.find, F-I-N-D. Find
é uma função que não recebe nenhum parâmetro, só abre e fecha parênteses. Depois de fechar parênteses, adiciona mais um ponto e um método toArray, T-O-A-R-R-A-Y, abre e fecha parênteses de novo. Ele vai fazer uma conversão para um array para a gente conseguir retornar. Criamos a função, ela está apagada porque ela não foi executada ainda. Onde que vamos executar? Você está de brincadeira que é no lugar de posts? É claro! Se estamos jogando fora o array, é aí que precisamos da função. O ideal é que esse JSON já pegue o resultado. Então, antes de fazer o
res.status, adicionamos uma linha. Isso. Aí, chama uma const. Olha, eu estou ficando profissional. Pode ser const resultado, que é um comum. Resultado ou posts. Vou chamar de posts. - Posso? - Pode. Posts igual await, chama a função getTodosPosts e executa ela com os parênteses. Está vendo que o VSCode não gostou do await? Porque está faltando um async antes disso. Async e await são um par. Quando usamos a palavra chave await para esperar algo acontecer, temos que avisar antes, aí onde você colocou o cursor. Async com Y. Isso. Async fica no começo da função. Cara, é
muito programador. Await. E aí, vai esperar. Agora, dentro do JSON, colocamos os posts. Os posts que, no caso, não é mais aquela lista. - Posso comentar essas duas linhas? - Pode. Fica a vontade. Não estamos trabalhando com esses IDs ainda. Selecionei todas as linhas, ele comenta com "Ctrl+Barra" essas linhas que não estamos utilizando. Agora, não podemos esquecer de subir o servidor de novo. Ah, é verdade. - Vocês já esqueceram de subir o servidor? - Muitas vezes. Entrar no localhost e falar "não é possível". Deixa eu pôr um console.log, mas nem o console está aparecendo. Mexe
no arquivo hosts da máquina, não sabe o que está acontecendo. Só faltou subir o servidor. - E retorno de função também já... - Nossa, fez a função e esqueceu. É o clássico. - Aconteceu isso? - Muitas vezes. Vamos testar com npm run dev. Agora, subir o nosso servidor. O servidor está de pé, escutando. Vamos ver se conecta ao Mongo. O servidor está escutando e está conectado ao Mongo Atlas. Ou seja, agora temos uma rota /posts que tem que nos servir algo. Como é uma rota GET, podemos testar no navegador. Lembrando que não estamos, nesse caso,
pegando as informações post a post. Queremos pegar de todos. Quando dou "Enter", está de brincadeira! Olha, uma imagem do banco de dados. Para garantir que esses dados, realmente, estão vindo do banco, quem que temos no segundo ID? Pois é, temos o gato panqueca! Ele puxou corretamente os IDs, então conseguimos ver que a imagem 1 é diferente da 2. Os mesmos dados que você criou no Mongo Atlas, agora, você está puxando para a sua aplicação, utilizando Node e Express para poder servir isso. - Que incrível. - Palmas para o profissional. Merece palmas. Merece muitas palmas. E
existem tantos caminhos possíveis para ir agora, porque pode ser que a galera que acompanha a imersão esteja entendendo, está vendo que estamos conseguindo chegar a algum lugar, mas está com aquela dúvida: "o que é aquele arquivo?" "Tinha tanta linha, o que eu faço com ele?" Um caminho possível é adicionar alguns comentários no código ou pedir ajuda para alguém que talvez entenda e possa explicar um pouco. - Gemini. - Dá para mandar para ele. Vou fazer o seguinte, eu selecionei todo o código do server.js da linha 1 até a linha 21, porque, a partir da linha
23, provavelmente vamos refazer alguns passos. Vou voltar no Google Gemini, e colocar todo esse código com "Ctrl+V", e vou falar para ele o seguinte: "Gostaria que você incluísse um comentário antes de cada instrução, dizendo (ou explicando) o que ela faz." Vamos ver. Então, ele está lendo todo o nosso código. Eu posso só copiar na fé e colar no projeto e depois vamos lendo lá? Você pode, se der errado, você está com dois devs para tentar descobrir o que aconteceu. Então, tranquilo. Eu acho que vou ler daqui, que ficou legal. Está bonito o Gemini. Olha só.
Então, o Express são os imports. Ele falou: "conecta o banco de dados utilizando a string de conexão fornecida como variável de ambiente." Check. Foi isso que fizemos. Depois, no app igual a express, permite que o servidor interprete requisições no corpo JSON. Perfeito, está funcionando. Check. Inicie o servidor na porta 3000. - Check? - Sim. - E exibe uma mensagem no console? - Sim, também está certo. Função assíncrona para buscar todos os posts do banco de dados. - Ah, espera aí que agora... - Opa, função assíncrona? Essa aí eu posso pedir mais para o Gemini? -
Se você quiser, pode. - Manda ver. Vamos na fé. Vou colocar todas as linhas, "Ctrl+C" e "Ctrl+V". Ele inseriu vários comentários antes de cada instrução. Entretanto, eu quero saber mais sobre função assíncrona. Vamos voltar no Gemini e vou falar assim... Opa, no Gemini, não em cima no prompt. "Estou estudando JS e gostaria de entender para que servem as instruções assync e await em um código." - Temos que ajudar o Gemini. - Campanha #tecladoParaGui. Deixa falar a real, é que esse computador não é o meu. Ah, complicado. Todo dev dá sua justificativa. Coda das oito da
manhã às dez da noite, esse computador não é meu. Então, estudando JS e gostaria de entender... Pode tentar fazer com que seja uma explicação sucinta. Explique em uma linha. Faça a explicação... Não, explique em uma linha... Explique em uma frase. "Explique em uma frase o que cada função faz." Ou cada instrução faz. Mas como você é um usuário que talvez não saiba disso, não tem problema mandar para o Gemini com alguma palavra que talvez não seja a mais correta pela literatura. - Posso dar um "Enter"? - Pode. Vamos testar. Quero saber para que serve async
e await. Uma função retornará uma promise. Significa que a função pode levar um tempo para ser executada, como uma requisição a uma API. Então, ele já acertou. E não bloqueará a execução do restante do código. Ou seja, alguns processos que fazemos não são síncronos, ou seja, eles não acontecem um seguido do outro. Por exemplo, uma conexão, um banco de dados, pode levar... Por mais que pareça para a gente muito rápido, não é síncrono. Enquanto está acontecendo isso, pode levar algum tempo. Nesse caso, o JavaScript tem que separar esse processamento para acontecer em outro lugar, para
o resto do código não ficar bloqueado. E aí, quando os dados retornam, retornou, esperou acontecer. Tudo voltou. Aí, resume a execução do código. O que ele está falando do await? Ele falou assim: "essa palavra-chave é usada dentro de uma função assíncrona", marcado com async, igual vimos, "para esperar que uma promise seja resolvida antes de continuar a execução." É como uma pausa na função. É exatamente isso. Pausa a função e aguarda o resultado, mas não bloqueia o restante do código. Não pausa o código todo, ou seja, seu sistema continua rodando, ele não fica bloqueado. Tem vários
detalhes, vamos deixar links sobre isso. Tem um artigo bem legal da Alura sobre async e await, que explica mais, porque começamos a entrar na parte de como o processador funciona. Então, o que precisamos saber aqui? Que a async e await, avisamos no começo da função, que dentro dessa função, alguma parte dela, você tem que esperar terminar de acontecer. É como estar com os amigos em casa para jogar videogame, e você liga para a pizzaria, você não vai ficar parado esperando a pizzaria trazer a pizza. É assíncrono. Liguei, "me traz uma pizza". Desliguei e continuei jogando
com a galera. Na hora que a pizza chegar, eu continuo o processamento que estava esperando a pizza. Eu pego as facas, corto, entrego para a galera. Agora, o próximo desafio é o seguinte. Quando desenvolvemos uma aplicação, é muito comum que o código fique uma bagunça. Então, vou deletar esse comentário, que era o get por ID. Não precisamos mais disso agora. Então, temos um monte de código. O código do servidor tem 32 linhas. Com comentários. O que acontece? A medida que esse código for crescendo e novas soluções vão sendo criadas, vamos de 32 para 60, 100,
500... mil linhas de código. Pronto, ninguém dá mais manutenção. E mais do que o número de linhas, que é um problema muito grave, o problema é não separar responsabilidades dentro do nosso código, porque se eu quiser alterar algo que tem a ver com conexão de banco, não faz sentido eu olhar em um arquivo que está falando... Do servidor, da porta, do sei lá onde. Vamos começar a criar uma estrutura de pastas. Vamos fazer isso de forma bem direta, bem simples, sem muita enrolação. Mas que a galera entenda o que estamos fazendo. Queremos organizar o projeto
para que depois fique mais fácil colocar novas funcionalidades nele. Até agora ele já está lindo, agora ele vai ficar incrível. A ideia é sobre a maturidade de desenvolvimento de software. Com certeza. Não se trata de um código que só funciona. Não se trata de um código que funcione e que seja sustentável. Perfeito. A ideia é, de alguma forma, manter a manutenção desse código e manter novas funcionalidades. Remover ou alterar aquilo que já havíamos programado. E já temos um caminho ótimo para começar a fazer isso. O que vocês sugerem? A Ju tinha sugerido criar uma pasta
src, que criamos para criar o config. Vamos continuar usando essa pasta src para poder armazenar diferentes competências. Só vamos criar subpastas para organizar melhor. - Vamos lá. - Como podemos pensar isso? Eu vou abordar um padrão que é muito comum, você vai vê-lo durante toda a sua vida. Vamos pensar na separação. Há três pontos principais nessa aplicação. A rota, por onde chegam as requisições. Temos uma função que recebe essa requisição e faz coisas com ela. E temos a conexão do banco de dados com a aplicação. Vamos usar essas três responsabilidades principais para separar o código.
Dentro do source, vamos começar pela primeira parte, que é a rota, por onde chegam as requisições. - Criando uma pasta? - Isso. Vamos criar uma pasta chamada routes. Routes é mais fácil de falar, porque é o nome padrão. Então, o nome padrão é rotas. Dentro dela, pode ser postRoutes.js. Nossa, a rota ficou postRoutes.js. Agora, tudo que está no server, que é responsabilidade de rota, temos que passar para esse arquivo. E lembra que falamos de import e export. Temos que fazer com que sejam exportadas de um canto e importadas no outro. O legal é que os
comentários do Gemini ajudam a galera a identificar as rotas, porque antes de cada rota, está escrito "rota para fazer isso". Muito bom. - No nosso caso, só temos ela. - Exato. Mas é um exemplo bom para começar a pensar em modularização. Só uma pergunta que tem a ver com isso daí. Quando eu estava estudando, no início da carreira, falavam assim, modularização, padrão de projeto, clean code e tal. E eu ficava estruturando um monte de pasta e arquivo no início em que não tinha nem o projeto feito. - Não faz sentido. - Não, não. Chega num
momento em que já se consegue separar algumas responsabilidades. Só faz sentido fazer a separação desde o início quando você já sabe exatamente e que não é o caso de quem está começando a estudar. Hoje em dia, se eu for cozinhar uma comida que sempre como, já pego direto os ingredientes. Mas se eu for começar uma receita nova, eu vou ler a receita, pôr tudo ali. E mesmo assim, às vezes... Nem me fala, não vamos nem entrar nesse cenário. Beleza, vamos lá. Posso passar essa rota inteira com "Ctrl+X", para o nosso arquivo de postRoutes. Beleza. Mas
o que aconteceu? App do Express não existe nesse arquivo. Então, a aplicação não consegue enxergar um arquivo do outro sem falar explicitamente. - Então, posso importar. - Pode importar Express. Então, import express from "express". Aí o "E" é minúsculo. E aí outra coisa importante. Quando iniciamos o servidor, qual é o melhor caminho, eu acho? Empacotar tudo que é de rota, jogar para fora desse arquivo, para que o server.js possa incorporar isso no servidor. Parece misterioso, mas não é tanto. O que vamos fazer é criar uma função para isso. Vamos no arquivo routes.js, vamos abrir uma
const, const routes igual, vai receber, entre parênteses, app, que será o nosso parâmetro, aí abre o arrow function depois dele. Depois, abre chaves, tudo certinho. O que temos no server que é de rotas? Aquele middleware que é o app.use(express.json()), podemos ir no server.js, tirá-lo de lá e passar para cá. - Qual que é mesmo? - Na linha 9, pode dar um "Ctrl+X". Inclusive, pode levar o comentário dele junto. Opa, verdade. Os dois com "Ctrl+X". Leva para o routes, porque isso faz parte de rotas. Agora, podemos mandar o app.get também aí para dentro, junto com o
comentário dele. "Ctrl+X". - E embaixo do app.use? - "Ctrl+V". Beleza. Perfeito. Agora temos que exportar essa função para poder ser importada em outro lugar. Então, no começo, na const routes, podemos colocar um export default. D-E-F-A-U-L-T. Opa, vamos fazer o seguinte, vamos fazer um pouco diferente. Pega essa linha export default, só o export default. Pode dar um "Ctrl+X" e leva lá para baixo no final do arquivo. E aí, routes. É outra forma da gente exportar. - Ponto e vírgula. - Ponto e vírgula! - Você respirou fundo. - Você já sabia o que estava vindo. Mas viu
que legal que a Ju tinha falado encapsular isso tudo para jogar para fora? Temos esse routes que vai representar tudo o que dá para fazer com rota. Nela, já está avisando que vamos usar o express.json. Nela, temos as rotas e, no final, quando ela montou tudo o que já queria, é que exportamos. Quando formos criar novas rotas, já sabemos onde que vamos. Vamos dentro desse routes que montamos. De alguma forma, eu preciso ir no server e usar isso. Temos que ir lá. Mas, volta nas rotas, no postRoutes. Lembra que falamos de três coisas. Rota, a
lógica de receber requisição, que é diferente da rota, receber requisição e enviar a resposta, e a do banco. Vamos trabalhar agora nessa lógica de requisição e resposta. Também temos um padrão para isso de pasta, de divisão de responsabilidade? Temos. Então, antes de qualquer coisa, vamos abrir um caminho para isso no src, abrindo uma nova pasta e chamando de controller, que é também o nome padrão. - No plural? - Controllers? Pode ser. E aí, dentro de controllers, um arquivo postsController.js É só postsController.js O controller também é uma camada padrão onde, nesse caso, no caso da arquitetura
da API, vamos passar para dentro toda a responsabilidade de lidar com as requisições e as respostas. Ou seja, o que temos no routes que cuida dessa parte? O res.status, getTodosPosts. Tudo a partir de async (req, res), até o final, vamos passar essa responsabilidade para o controlador. Até onde está o parênteses, vou dar um "Ctrl+X". Pode dar "Ctrl+X", vai ficar esquisito porque ficou uma vírgula. Lá no postsController, vou dar um "Ctrl+V". Isso. Beleza. E agora temos que exportar. Primeiro, criamos uma função. Vamos colocar todo esse código em uma função para ficar organizado. Então, lá no topo,
pode chamar de function mesmo. Async function. Pode chamar listarPosts ou listarTodosPosts. Mas você criou com L maiúsculo, não é do padrão JavaScript. - Ah, listarPosts. - Isso, listarPosts. E aí, sim, o que ele recebe? Requisição e resposta. Com "Ctrl+X", passamos isso para cá. - Vamos ver se vai colar direito. - Só ficou um parênteses a mais. E agora não estamos mais criando uma arrow function. Então, tem que apagar a arrow function da linha 1 também. Perfeito. - E esse aqui tira. - Esse aí tira e o outro tira também. Agora, o que temos? Passamos a
responsabilidade de listar os posts para o controlador, que vai receber a requisição, executar a função getTodosPosts, que também sumiu, mas tudo bem, vamos lidar com isso, e enviar a resposta. Então, esse res.status(200) está correto. Precisamos exportar essa função também. Nesse caso, você consegue dar um export nessa função. Antes do export, você pode apagar essa última chave que abriu e fechou. Ela era mais um resquício daquilo que tínhamos quando copiamos a função. Lá no topo, antes do async, você pode colocar um export. E aí também é uma forma de se exportar, export async function listarPosts, etc.
E onde que temos que executar essa função? - Aqui. - Exato. Então, recebemos aqui, mas temos que trazê-la. Se você escrever listarPosts aí... Vamos fazer um teste. Escreve listarPosts, ele localizou... só que faltou .js. - Você está sabido. - Já sofremos com isso. Está quase tudo arrumado. Já separamos a rota, já separamos o controlador, que vai lidar com a requisição e receber a resposta. E agora, devemos separar a parte que conecta a nossa aplicação com o banco. Última separação, última camada no source. Vamos chamar essa camada de models. Lá no source, abre uma pasta models.
E dentro de models, que também é o nome padrão... Ah, eu estava vendo se ele já ia pegar a lógica. - Pode ser model mesmo. - PostModel.js. Isso, porque é o modelo do post. Tudo isso, te convido a pedir para o Gemini te ajudar com os conceitos, que vai te ajudar muito, porque todas essas camadas são camadas padrão nesse tipo de aplicação que estamos criando. Essa estrutura, model, controller, rota, é uma estrutura muito padrão. Você vai ver ela a vida toda, não vai? Não estamos mentindo. E você vai usar para sempre em projetos diferentes. Na
verdade, muito do que estamos trazendo se repetirá em diferentes projetos. Por isso que estamos nos preocupando em trazer esses conceitos para você. Então, essa função getTodosPosts, eu posso retirá-la do servidor e jogar lá no postModel. Aí é uma função que preciso exportar, então export default. - Você já está ninja. - O cara já está sabendo. Já vou até alterar o LinkedIn para Node developer. Aí, isso daqui vou precisar passar no listarPosts. Aí o model tem um detalhe. O model é a camada que faz a conexão da aplicação com o banco. Então aí, lembra da dbConfig?
Lembro, essa conexão. Isso vai ficar lá no model também. Exato, conectarAoBanco fica lá no model. Você está vendo o tamanho que está ficando o server? Não está sobrando nada lá. Quem é javascripteiro gosta assim. Módulo bem pequeno, função bem pequena, arquivo com duas linhas. - Eles gostam. - Padrão do JavaScript. Deixa eu ver o que está faltando, porque eu trouxe o postsModel para cá, o getTodosPosts. Temos a conexão com o banco de dados. Onde exatamente estou usando ele? Lá no controller. Eu vou precisar falar que getTodosPosts vem de model? Isso. Vou ter que falar getTodosPosts.
Ah, agora sim. Falta .js e executar a função. Aqui nós temos uma função, abre e fecha parênteses. Isso. Eu acho que o controller está correto, estamos devolvendo o res.status, a nossa rota também. Perceba que na linha 8 não estamos executando listarPosts. Está certo! Você não executa, não coloca parênteses. Só queremos indexar qualquer função que será chamada quando bater nessa rota. Agora o model é onde fazemos a parte da conexão. Já temos controlador, rota, modelo. Quase tudo do modelo já está pronto. A única coisa que eu acho que está faltando para a gente... - É importar
isso e conectar ao banco. - É verdade. Ele não está no DB. Vamos pegar o que estava no server primeiro. Eu vou tirá-lo daqui e, no postsModel, vou dar um "Enter" na linha 1. Vou chamar assim... - Se eu chamá-lo de novo, dá certo? - Cola ele aí. Conectar... - Ih, não achou. Tentamos. - Temos que trazê-lo na mão mesmo. Ainda bem que está na área de transferência. - Então, from... - Import... É verdade. Não estou no Python. Import conectarAoBanco. Ele perdeu mesmo. Ah, agora achou, mas não preencheu. Ele está dentro da mesma pasta. Então,
temos que usar ../ para sair da pasta, entrar na pasta config/dbConfig.js. Agora, já importamos e o que chama conectarAoBanco está funcionando. Agora, precisamos linkar as rotas no arquivo do servidor. Como que eu falo, por exemplo, que esse app, vamos utilizar todas as rotas que temos no projeto, que no caso são essas aqui. Então, nós criamos essa função nas rotas. No postsRoutes, criamos uma função para empacotar todas as rotas. Ela precisa receber um app, que nesse momento não sabemos qual é, mas importamos o routes aí no começo. Vou colocar routes, vamos ver se ele vai trazer.
Ah, postsRoutes.js. Agora é só executar essa função passando o app para dentro dela. Que é o que ele espera. Que é justamente onde está guardada toda a lógica do Express. Assim que eu subir o servidor, pode executar, Ju? Olha aí, o negócio está ficando cada vez mais complexo. Enquanto você executa, eu vou torcer para dar tudo certo. À medida que estamos avançando, vai... - Recarrega. - Deu bom, puxou do banco. - Quem que temos aqui? - O gato panqueca. De novo, a vantagem agora não é em desempenho do software, nada disso. É que ele está
organizado para quando chegar na aula 4 e começar a acrescentar mais funcionalidades, isso ficar mais fácil para a gente. Fizemos bastante ida e volta com código... importou, exportou. Te daremos o código pronto dessa aula para você conferir e fazer um depara se você precisar. O importante é você saber que separamos a lógica em três responsabilidades principais, que é muito padrão nesse tipo de aplicação. E que importamos e exportou funções de um lado para o outro para que essas partes possam se conectar e as funções serem executadas. Basicamente, foi o que fizemos aqui. Eu não explicaria
melhor do que isso. Estamos chegando ao final da terceira aula da Imersão Dev, onde temos o código já conectando com banco de dados, com modularização e elevamos bastante o nível de engenharia de software. De maturidade da jornada de uma pessoa desenvolvedora. Seu código não vai só funcionar, ele vai funcionar com estilo. É isso que fizemos aqui. Muito obrigado, Ju e André. Olha só, amanhã temos desafios ainda mais incríveis. De alguma forma, vamos manipular as informações que estão no banco de dados, inserindo novos posts, atualizando, editando. Fazendo muita coisa bem legal. Tenho certeza que você vai
gostar muito. Não se esqueça que, para ter acesso ao certificado da imersão, é necessário assistir as cinco aulas. Nós estamos na terceira, falta pouco. Mais duas aulas, você vai ter acesso ao certificado da imersão. E faça parte da comunidade no Discord. Utilize o Gemini como assistente para te auxiliar em algumas dúvidas. Mas por que essa abordagem de código é melhor ou pior? Por que isso faz ou não sentido? O que essa linha de código está fazendo? Tenho certeza que te ajudará em tudo isso de uma forma bem legal. Então, te espero amanhã na quarta aula
da Imersão Dev com o Google Gemini. [♪]