# Preparando para integrar com Frontend

{% hint style="info" %}
Preparar aplicações backend para uma integração eficiente e segura com o frontend, implementando práticas essenciais de configuração de CORS, tratamento de erros e validação de dados, além de conhecer boas práticas no design de API focado no frontend.
{% endhint %}

## Vídeo

{% embed url="<https://youtu.be/_FNqVtgfYQ0>" %}

**Link direto:** <https://youtu.be/_FNqVtgfYQ0>

## Tópicos

1. **Introdução ao CORS:**
   * Explicação do que é CORS e por que é necessário em aplicações modernas web.
   * Demonstração prática de como habilitar CORS em uma aplicação Express.js.
2. **Tratamento de Erros:**
   * Boas práticas para o tratamento de erros para garantir que o frontend possa reagir adequadamente.
   * Implementação de tratamento de erros assíncronos usando `express-async-errors`.
   * Tratamento de rotas não encontradas (404) para retornar respostas JSON.
   * Tratamento de erros para ObjectId inválido no MongoDB.
3. **Validação de Dados:**
   * Importância da validação de dados recebidos pelo backend.
   * Introdução às bibliotecas de validação de dados, como Joi.
   * Implementação de validações de payload usando Joi.
4. **Design de API focado no Frontend:**
   * Princípios de design de API que facilitam o consumo pelo frontend.
   * Exemplos de como unificar endpoints e simplificar payloads para reduzir a carga no frontend.
   * Melhores práticas de design de API, incluindo consistência, documentação, paginação e versionamento.

## Material de Apoio

### Repositório no GitHub

{% embed url="<https://github.com/SalvatoreAcademy/backend-missao-aprendizado-iniciante-preparando-para-integrar-com-frontend>" %}

### PDF para Download

{% file src="/files/Gh6lSyoIVKakVyI1owiO" %}

### Miro

{% embed url="<https://miro.com/app/board/uXjVNQ6PZjQ=/?moveToWidget=3458764587647670430&cot=14>" %}

## Exercícios de Fixação

{% hint style="info" %}
Use esses exercícios para reforçar o que acabou de aprender. Se errar, leia a explicação para entender melhor o conceito.
{% endhint %}

<details>

<summary>Qual é a principal função do CORS em uma aplicação web?</summary>

A) Permitir que recursos restritos em uma página web sejam solicitados de um domínio diferente.

B) Proteger a aplicação contra ataques de injeção de SQL.

C) Garantir a segurança das senhas armazenadas no banco de dados.

D) Melhorar a performance da aplicação web.

</details>

<details>

<summary>Resposta correta</summary>

**Qual é a principal função do CORS em uma aplicação web?**

**Resposta Correta**: A

**Feedback**: CORS permite que recursos restritos em uma página web sejam solicitados de um domínio diferente, superando limitações de segurança dos navegadores.

</details>

***

<details>

<summary>Complete o código para configurar o middleware de CORS em uma aplicação Express.js.</summary>

{% code lineNumbers="true" %}

```javascript
const express = require('express');
const cors = require('cors');
const app = express();

app.use(________);

app.listen(3000, function () {
  console.log("Aplicação rodando em http://localhost:3000");
});
```

{% endcode %}

</details>

<details>

<summary>Resposta correta</summary>

**Complete o código para configurar o middleware de CORS em uma aplicação Express.js.**

**Resposta Correta**:

```javascript
app.use(cors());
```

**Feedback**: O middleware `cors()` habilita CORS na aplicação, permitindo que ela responda a requisições de diferentes domínios.

</details>

***

<details>

<summary>Verdadeiro ou Falso: O middleware express-async-errors simplifica o tratamento de erros assíncronos em uma aplicação Express.js.</summary>

A) Verdadeiro

B) Falso

</details>

<details>

<summary>Resposta correta</summary>

**Verdadeiro ou Falso: O middleware express-async-errors simplifica o tratamento de erros assíncronos em uma aplicação Express.js.**

**Resposta Correta**: A

**Feedback**: Verdadeiro. O `express-async-errors` simplifica o tratamento de erros assíncronos, passando automaticamente os erros para o middleware de tratamento de erros padrão do Express.

</details>

***

<details>

<summary>Complete o código para validar um ObjectId do MongoDB e retornar um erro apropriado se o ObjectId for inválido.</summary>

{% code lineNumbers="true" %}

```javascript
const { ObjectId } = require('mongodb');

function validateObjectId(req, res, next) {
  const id = req.params.id;

  if (!ObjectId.________(id)) {
    return res.status(400).send({ error: 'ObjectId inválido' });
  }

  next();
}

module.exports = {
  validateObjectId
}
```

{% endcode %}

</details>

<details>

<summary>Resposta correta</summary>

**Complete o código para validar um ObjectId do MongoDB e retornar um erro apropriado se o ObjectId for inválido.**

**Resposta Correta**:

```javascript
if (!ObjectId.isValid(id)) {
  return res.status(400).send({ error: 'ObjectId inválido' });
}
```

**Feedback**: A função `ObjectId.isValid(id)` verifica se o ID fornecido é válido, retornando um erro 400 se não for.

</details>

***

<details>

<summary>Qual é a principal vantagem de utilizar a biblioteca Joi para validação de dados?</summary>

A) Simplificar a validação de esquemas complexos.

B) Melhorar a performance do banco de dados.

C) Garantir a segurança das senhas armazenadas.

D) Facilitar a configuração de variáveis de ambiente.

</details>

<details>

<summary>Resposta correta</summary>

**Qual é a principal vantagem de utilizar a biblioteca Joi para validação de dados?**

**Resposta Correta**: A

**Feedback**: A biblioteca Joi simplifica a validação de esquemas complexos, melhorando a legibilidade do código e fornecendo mensagens de erro detalhadas.

</details>

## Exercícios de Validação

{% hint style="info" %}
Esses exercícios testarão sua compreensão prática. Revise o feedback para melhorar suas habilidades.
{% endhint %}

### Desafio de Código

Implemente a validação de dados e o tratamento de erros usando Joi e middlewares em uma aplicação Express.

#### Arquivo Inicial

{% code title="index.js" lineNumbers="true" %}

```javascript
const express = require('express');
const app = express();
app.use(express.json());

const tarefas = [];

app.post('/tarefas', function (req, res) {
  const novaTarefa = req.body;

  if (!novaTarefa.titulo || !novaTarefa.descricao || !novaTarefa.status) {
    return res.status(400).send('Corpo da requisição deve conter as propriedades titulo, descricao e status.');
  }

  tarefas.push(novaTarefa);
  res.status(201).send(novaTarefa);
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});
```

{% endcode %}

#### Tarefas

* **Validação de Dados com Joi**:
  * Implemente a validação de dados recebidos no endpoint `/tarefas` usando Joi.
* **Tratamento de Erros**:
  * Adicione middlewares para tratamento de erros na aplicação.
* **Configuração de CORS**:
  * Habilite CORS na aplicação.

#### Código Esperado

**Validação de Dados e Tratamento de Erros**

{% code title="index.js" lineNumbers="true" %}

```javascript
const express = require('express');
const cors = require('cors');
const Joi = require('joi');
const app = express();
app.use(express.json());
app.use(cors());

const tarefas = [];

const tarefaSchema = Joi.object({
  titulo: Joi.string().min(3).required(),
  descricao: Joi.string().min(5).required(),
  status: Joi.string().valid('pendente', 'concluída').required()
});

app.post('/tarefas', function (req, res, next) {
  const { error, value } = tarefaSchema.validate(req.body);

  if (error) {
    return res.status(400).send(error.details[0].message);
  }

  tarefas.push(value);
  res.status(201).send(value);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});
```

{% endcode %}

**Feedback**: Certifique-se de validar os dados recebidos com Joi e trate adequadamente os erros usando middlewares. Habilite CORS para permitir requisições de diferentes origens.

### Revisão de Código

{% hint style="danger" %}
**Analise o código a seguir, encontre e corrija o erro relacionado à configuração de CORS e tratamento de erros na integração com frontend.**
{% endhint %}

{% code title="index.js" lineNumbers="true" %}

```javascript
const express = require('express');
const app = express();
app.use(express.json());

const tarefas = [];

app.post('/tarefas', function (req, res) {
  const novaTarefa = req.body;

  if (!novaTarefa.titulo || !novaTarefa.descricao || !novaTarefa.status) {
    return res.status(400).send('Corpo da requisição deve conter as propriedades titulo, descricao e status.');
  }

  tarefas.push(novaTarefa);
  res.status(201).send(novaTarefa);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});
```

{% endcode %}

<details>

<summary>Resposta Correta</summary>

**Erros:**

1. Falta a configuração do CORS para permitir requisições de diferentes origens.
2. O tratamento de erros não está configurado para lidar com erros assíncronos corretamente.

**Código Corrigido:**

{% code title="index.js" lineNumbers="true" %}

```javascript
const express = require('express');
const cors = require('cors');
require('express-async-errors');
const app = express();
app.use(express.json());
app.use(cors());

const tarefas = [];

app.post('/tarefas', function (req, res) {
  const novaTarefa = req.body;

  if (!novaTarefa.titulo || !novaTarefa.descricao || !novaTarefa.status) {
    return res.status(400).send('Corpo da requisição deve conter as propriedades titulo, descricao e status.');
  }

  tarefas.push(novaTarefa);
  res.status(201).send(novaTarefa);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});
```

{% endcode %}

**Feedback**: Certifique-se de habilitar CORS para permitir requisições de diferentes origens e configure o tratamento de erros para lidar com erros assíncronos corretamente.

</details>

### Projeto Prático

Implemente um endpoint para criar tarefas em uma aplicação ExpressJS. As tarefas devem ter as propriedades "título", "descrição" e "status". Utilize CORS, valide os dados usando Joi e implemente o tratamento de erros.

#### Arquivo Inicial

```javascript
const express = require('express');
const cors = require('cors');
const Joi = require('joi');
const app = express();

app.use(express.json());
app.use(cors());

const tarefas = [];

const tarefaSchema = Joi.object({
  titulo: Joi.string().min(3).required(),
  descricao: Joi.string().min(5).required(),
  status: Joi.string().valid('pendente', 'concluída').required()
});

app.post('/tarefas', function (req, res, next) {
  const { error, value } = tarefaSchema.validate(req.body);

  if (error) {
    return res.status(400).send(error.details[0].message);
  }

  tarefas.push(value);
  res.status(201).send(value);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});
```

#### Tarefas

* **Validação de Dados com Joi**:
  * Implemente a validação de dados recebidos no endpoint `/tarefas` usando Joi.
* **Tratamento de Erros**:
  * Adicione middlewares para tratamento de erros na aplicação.
* **Configuração de CORS**:
  * Habilite CORS na aplicação.

<details>

<summary>Código Esperado</summary>

{% code title="index.js" lineNumbers="true" %}

```javascript
const express = require('express');
const cors = require('cors');
const Joi = require('joi');
const app = express();

app.use(express.json());
app.use(cors());

const tarefas = [];

const tarefaSchema = Joi.object({
  titulo: Joi.string().min(3).required(),
  descricao: Joi.string().min(5).required(),
  status: Joi.string().valid('pendente', 'concluída').required()
});

app.post('/tarefas', function (req, res, next) {
  const { error, value } = tarefaSchema.validate(req.body);

  if (error) {
    return res.status(400).send(error.details[0].message);
  }

  tarefas.push(value);
  res.status(201).send(value);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});
```

{% endcode %}

**Feedback Detalhado**

* **Verificação do Endpoint**: Certifique-se de testar a rota `/tarefas` acessando `http://localhost:3000` e verificando as respostas.
* **Validação de Dados**: Garanta que os dados recebidos pelo backend são validados corretamente usando Joi, e que erros de validação são tratados adequadamente.
* **Configuração de CORS**: Verifique se o CORS está configurado corretamente para permitir requisições de diferentes origens.
* **Tratamento de Erros**: Confirme se o tratamento de erros assíncronos está funcionando como esperado e se os erros são corretamente registrados e retornados.

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://salvatore-academy.gitbook.io/dev-fullstack-web/academia/missoes-de-backend/preparando-para-integrar-com-frontend.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
