Construindo aplicação do zero com node.js: Parte 4
Tags: node, javascript, webdev, programming
Published: 2022-11-14 14:42:06

Depois de desenvolver toda a regra principal da aplicação, vamos começar a implementar de fato as nossas dependências.

## Mão na massa
Primeiramente vamos alterar o arquivo **.env**, que foi criado lá parte 2, deixe o arquivo com as seguintes informações:
```env
APP_PORT=8001

DB_DIALECT=postgres
DB_HOST=db_two_factor
DB_DATABASE=two_factor
DB_USER=root
DB_PASSWORD=root

JWT_SECRET=My@jwt#Secret%

EMAIL_HOST=smtp.gmail.com
EMAIL_USER=email_de_exemplo@gmail.com
EMAIL_PASS=sua_senha
EMAIL_PORT=465
```
Essas são todas as credenciais necessárias nesse projeto. Recomendo parar e subir os containers novamente, depois, acesse o terminal do serviço *node* para que possamos instalar nossas bibliotecas.

Outro detalhe é que os dados acima são somente de exemplo, se você tem uma conta do google, assim como eu, altere somente os campos **EMAIL_USER** e **EMAIL_PASS**, agora caso queiram utilizar algo diferente, é necessário alterar o **EMAIL_HOST** e talvez o **EMAIL_POST**.

## Dependências
A primeira dependência que vamos instalar, é uma biblioteca que fará o carregamento das informações contidas no arquivo *.env*, no terminal, execute o comando abaixo para fazer a instalação:
```bash
npm i dotenv
```

Após isso, crie um arquivo chamado **load-env.js** dentro de  **src/infra/env**. Nesse arquivo vamos implementar a lógica para que ele consiga ler as informações do nosso arquivo *.env*. Adicione o código abaixo no arquivo:
```js
import { config } from 'dotenv';

const loadEnv = async () => {
    let env = '';

    if (process.env.NODE_ENV) {
        env = `.${process.env.NODE_ENV}`;
    }

    const configPath = `.env${env}`;

    const result = config({
        path: configPath
    });

    if (result.error) {
        throw result.error
    }
}

export default loadEnv;
```

Agora, na raiz da nossa aplicação, crie um arquivo chamado **index.js** com o seguinte conteúdo:
```js
import loadEnv from './src/infra/env/load-env.js';

async function run() {
    await loadEnv();
}

run();
```

Esse arquivo será o ponto de partida da nossa aplicação. Por enquanto deixemos ele assim, voltaremos a modificá-lo no futuro.

Em seguida, vamos instalar uma biblioteca para manipular senhas, ela será útil por exemplo para criptografar senhas e fazer comparações de hashs:
```bash
npm i bcrypt
```

Agora crie um arquivo chamado **password-hash.js**, dentro de **src/infra/hash**, com o conteúdo abaixo:
```js
import IPasswordHash from './../../domain/ipassword-hash.js';
import Bcrypt from 'bcrypt';
import { promisify } from 'util';
const compareAsync = promisify(Bcrypt.compare);

export default class PasswordHash extends IPasswordHash {
    constructor() {
        super();
    }

    compare(password, hash) {
        return compareAsync(password, hash);
    }
}
```
Basicamente implementamos nosso comparativo de senha, detalhe para o uso da função interna do *node* chamada **promisify**, que converte funções **callback** para **promise**, facilitando o use de qualquer recurso.

Agora vamos instalar duas bibliotecas muito úteis, a primeira vai servir para gerar um token jwt, e o segundo nos servirá para gerar uuids:
```bash
npm i jsonwebtoken short-uuid
```

Após a instalação, vamos começar por configurar a nossa geração de token *jwt*. Dentro de **src/infra/jwt**, crie o arquivo **jwt.js**, com o seguinte conteúdo:
```js
import IToken from './../../domain/itoken.js';
import JWT from 'jsonwebtoken';

export default class Jwt extends IToken {
    constructor() {
        super();
    }

    generateWebToken(user) {
        const token = JWT.sign({
            id: user.id,
            email: user.email,
        }, process.env.JWT_SECRET);

        return token;
    }
}
```
Aqui não tenho muito o que falar a não ser recomendar pesquisarem um pouco sobre essa biblioteca para terem noção do quão poderosa ela é.

Agora vamos configurar nosso gerador de *uuids*, dentro de **src/infra/token**, crie o arquivo **token-service.js**, e insira o conteúdo abaixo:
```js
import Short from 'short-uuid';
import IGenerateToken from '../../domain/igenerate-token.js';

export default class TokenService extends IGenerateToken {
    constructor() {
        super();
    }

    getToken() {
        return Short.uuid();
    }

    getEmailToken() {
        return Short.generate();
    }
}
```

Essa biblioteca vai nos fornecer dois recursos: o primeiro é a geração de um uuid completo, algo como *fd5c084c-ff7c-4651-9a52-37096242d81c*, além disso, ela também permite a geração de identificadores menores, então o método **generate()** retornaria algo parecido com isso *mhvXdrZT4jP5T8vBxuvm75*.

Agora vamos instalar a biblioteca que vai fazer o envio de e-mail:
```bash
npm i nodemailer
```

Após a instalação, vamos configurar nosso serviço de e-mail, dentro do diretório **src/infra/email**, crie um arquivo chamado **body-email-html.js**, ele vai conter o conteúdo html que será enviado para o cliente:
```js
const bodyEmailHtml = (token) => {
    return `<!DOCTYPE html>
        <html>
        <head>
        <style>
            .container {
                margin: 10% 20%;
                border-radius: 10px;
                background-color: white;
            }
              
            .title {
                padding: 1% 0% 0%;
                text-align: center
            }
               
            p {
                color:blue;
                text-align: center;
                font-family: Arial, sans-serif;
                font-size: 30px;
                padding-bottom: 5%;
            }
        </style>
        </head>
        <body>
            <div class="container">
                <div class="title">
                    <h3>Use the token below to finish login.</h3>
                </div>
                <hr/>
                <p>${token}</p>
            </div>
        </body>
        </html>`;
};

export default bodyEmailHtml;
```

Ainda dentro do mesmo diretório, crie um arquivo chamado **email.js**, nele vamos realmente implementar a funcionalidade de envio:
```js
import IEmail from './../../domain/iemail.js';
import nodemailer from "nodemailer";
import bodyEmailHtml from './body-email-html.js';

export default class Email extends IEmail {
    constructor() {
        super();
    }

    async send(user) {
        const transporter = nodemailer.createTransport({
            host: process.env.EMAIL_HOST,
            port: process.env.EMAIL_PORT,
            auth: {
                user: process.env.EMAIL_USER,
                pass: process.env.EMAIL_PASS,
            },
        });

        await transporter.sendMail({
            from: process.env.EMAIL_USER,
            to: user.email,
            subject: "Hello, see you token",
            html: bodyEmailHtml(user.emailToken)
        });
    }
}
```

Como podem ver, não tem nada de complexo, basicamente informamos a configuração de conexão, e após isso enviamos o e-mail para o remetente correto. Outra recomendação é olhar mais detalhadamente essa biblioteca para ter uma noção dos inúmeros outros recursos que ela oferece.

Bem pessoal, a partir de agora faremos algumas instalações bem úteis, porém só vamos configurá-las no próximo artigo. Vamos começar pelo **hapi**, que fará todo o intermédio entre as requisições web e a nossa aplicação:
 ```bash
npm i @hapi/boom @hapi/hapi @hapi/inert @hapi/vision hapi-swagger joi
```
**Muitos devem conhecer o express ou outra lib que faça a mesma coisa, caso queira utilizar algo diferente do hapi, fiquem a vontade.**


Em seguida, vamos instalar um orm, que vai servir para intermediar nossa comunicação e manipulação do banco, eu optei pelo **sequelize**, mas fique a vontade se quiser utilizar outro:
```bash
npm i pg pg-hstore sequelize
```

E por último, mas não menos importante, vamos instalar uma lib, que é bem útil enquanto você desenvolve.
```bash
npm i --save-dev nodemon
```
O **nodemon** é bem útil enquanto desenvolvemos, pois não precisaremos reiniciar o servidor a cada alteração. Para vocês que estão seguindo esses artigos, não será tão útil, devido eu ter feito de uma forma mais organizada, mas para mim que fazia o projeto e não segui exatamente a ordem dos artigos, ajudou bastante.

Outro ponto é que essa biblioteca, assim como a de teste, vai ser instalada somente para ambiente de desenvolvimento.

## Resumo
Neste artigo, vimos a instalação e uso de algumas dependências, recomendo novamente que pesquisem um pouco mais sobre cada biblioteca instalada, seus recursos, etc.

Se você for um dev mais experiente, e conheça ou queira utilizar outras bibliotecas, deixei claro que você pode fazer isso tranquilamente. Repare que essas mudanças não afetam a nossa lógica principal, esse é um benefício de adotar uma arquitetura que tenha como foco a camada de regras de negócio. Até o próximo artigo.