---
description: '[Recomendada para começar] | Área: Backend | Nível recomendado: Iniciante'
---

# CRUD em Memória

{% hint style="info" %}
Esta missão irá aprofundar o conhecimento em lógica de programação backend com a implementação de um CRUD (Create, Read, Update, Delete) diretamente na memória do servidor. Adicionalmente, serão abordadas as melhores práticas de validação de dados e uso adequado dos códigos de status HTTP.
{% endhint %}

## Vídeo

{% embed url="https://youtu.be/EU2kLPmyT1U" %}

**Link direto:** [https://youtu.be/EU2kLPmyT1U](https://youtu.be/EU2kLPmyT1U)

## Tópicos

1. **Configuração do Ambiente de Desenvolvimento:**
   * Configurar o Nodemon para reiniciar o servidor automaticamente a cada alteração.
2. **Estruturação do CRUD:**
   * Revisão dos conceitos de CRUD.
   * Implementação de um array em memória para armazenar dados.
   * Criação de rotas para cada operação do CRUD.
3. **Validação de Dados:**
   * Introdução às técnicas e bibliotecas de validação de dados.
   * Aplicação de validações nas entradas de dados do CRUD.
4. **Status HTTP:**
   * Explicação sobre códigos de status HTTP e suas aplicações.
   * Implementação de códigos de status HTTP apropriados para cada operação do CRUD.

## Material de Apoio

### Repositório no GitHub

{% embed url="https://github.com/SalvatoreAcademy/backend-missao-aprendizado-iniciante-crud-em-memoria" %}

### PDF para Download

{% file src="https://1989749987-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FRonehqhrmNdVr43Njmfs%2Fuploads%2Fv61cnF63Emj3CKMabhOb%2FBackend%20-%20Iniciante%20-%20Missa%CC%83o%20de%20Aprendizado%20-%20CRUD%20em%20Memo%CC%81ria.pdf?alt=media&token=0a6cf495-da88-481f-9148-5bd1f743add8" %}

### Miro

{% embed url="https://miro.com/app/board/uXjVNQ6PZjQ=/?moveToWidget=3458764587647670380&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 função do Nodemon no desenvolvimento de aplicações NodeJS?</summary>

A) Reiniciar o servidor automaticamente a cada alteração no código.

B) Instalar pacotes npm automaticamente.

C) Facilitar a criação de endpoints.

D) Implementar validação de dados.

</details>

<details>

<summary>Resposta correta</summary>

**Qual é a função do Nodemon no desenvolvimento de aplicações NodeJS?**

**Resposta Correta**: A

**Feedback**: O Nodemon reinicia o servidor automaticamente a cada alteração no código, facilitando o desenvolvimento.

</details>

***

<details>

<summary>Complete o código para criar um endpoint que retorne todos os itens da lista.</summary>

{% code lineNumbers="true" %}
```javascript
const express = require("express");
const app = express();

const lista = ['Java', 'Kotlin', 'Android'];

app.get("/personagem", function (req, res) {
  res.send(_________);
});

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 criar um endpoint que retorne todos os itens da lista.**

**Resposta Correta**: `lista.filter(Boolean)`

**Feedback**: O método `filter(Boolean)` remove itens falsy da lista antes de retorná-la.

</details>

***

<details>

<summary>Afirmativa: O código de status HTTP 404 significa "Item não encontrado".</summary>

A) Verdadeiro

B) Falso

</details>

<details>

<summary>Resposta correta</summary>

**Afirmativa: O código de status HTTP 404 significa "Item não encontrado".**

**Resposta Correta**: A

**Feedback**: O código 404 é utilizado para indicar que um item ou recurso não foi encontrado no servidor.

</details>

***

<details>

<summary>Qual comando usamos para instalar o Nodemon como dependência de desenvolvimento?</summary>

A) `npm install nodemon`

B) `npm install --save nodemon`

C) `npm install --save-dev nodemon`

D) `npm install nodemon --saveDev`

</details>

<details>

<summary>Resposta correta</summary>

**Qual comando usamos para instalar o Nodemon como dependência de desenvolvimento?**

**Resposta Correta**: C e D

**Feedback**: Tanto o comando `npm install --save-dev nodemon` quanto `npm install nodemon --save-dev` instalam o Nodemon como uma dependência de desenvolvimento.

</details>

***

<details>

<summary>Complete o código para criar um endpoint que adicione um novo item à lista, verificando se o <code>nome</code> está presente no corpo da requisição e adicionando o item na lista.</summary>

{% code lineNumbers="true" %}
```javascript
const express = require("express");
const app = express();

const lista = ['Java', 'Kotlin', 'Android'];
app.use(express.json());

app.post("/personagem", function (req, res) {
  const body = req.body;
  const novoItem = body._________;

  if (!novoItem) {
    return res.status(400).send('_________');
  }

  if (lista._________(novoItem)) {
    return res.status(409).send('_________');
  }

  lista._________(novoItem);
  res.status(201).send('Item adicionado com sucesso: ' + novoItem);
});

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 criar um endpoint que adicione um novo item à lista.**

**Resposta Correta**:

```javascript
const novoItem = body.nome;

if (!novoItem) {
  return res.status(400).send('Corpo da requisição deve conter a propriedade nome.');
}

if (lista.includes(novoItem)) {
  return res.status(409).send('Esse item já existe na lista.');
}

lista.push(novoItem);
res.status(201).send('Item adicionado com sucesso: ' + novoItem);
```

**Feedback**: A mensagem `Corpo da requisição deve conter a propriedade nome.` é enviada quando o nome não está presente no corpo da requisição. A verificação se o item já existe na lista e a adição do novo item são partes essenciais do endpoint.

</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

Crie um endpoint adicional na aplicação ExpressJS que responda com "Número total de itens: X" quando a rota `/personagem/count` for acessada, onde X é o número total de itens na lista.

* Implementar o novo endpoint no arquivo `index.js`.

<details>

<summary>Resposta esperada</summary>

{% code lineNumbers="true" %}
```javascript
app.get("/personagem/count", function (req, res) {
  const totalItens = lista.length;
  res.send(`Número total de itens: ${totalItens}`);
});
```
{% endcode %}

**Feedback**: Certifique-se de que o servidor está ouvindo na porta correta e que a rota `/personagem/count` está devidamente configurada.

</details>

### Revisão de Código

{% hint style="danger" %}
**Analise o código a seguir, encontre e corrija o erro.**
{% endhint %}

{% code lineNumbers="true" %}
```javascript
const express = require("express");
const app = express();

const lista = ['Java', 'Kotlin', 'Android'];

app.get("/personagem/:id", function (req, res) {
  const id = req.params.id;
  const item = lista[id];

  if (!item) {
    return res.status(404).send('Item não encontrado.');
  }

  res.send(item);
});

app.post("/personagem", function (req, res) {
  const body = req.body;
  const novoItem = body.nome;

  if (!novoItem) {
    return res.status(400).send('Corpo da requisição deve conter a propriedade nome.');
  }

  if (lista.includes(novoItem)) {
    return res.status(409).send('Esse item já existe na lista.');
  }

  lista.push(novoItem);
  res.status(201).send('Item adicionado com sucesso: ' + novoItem);
});

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

<details>

<summary>Resposta Correta</summary>

**Erros:**

1. Falta o middleware para processar JSON no Express.
2. Acesso incorreto ao índice da lista (deve ser lista\[id - 1] para seguir a convenção 1-based ID).
3. Verificação inadequada para valores duplicados na lista (deve verificar apenas nomes, não objetos inteiros).

{% code lineNumbers="true" %}
```javascript
const express = require("express");
const app = express();

app.use(express.json());

const lista = ['Java', 'Kotlin', 'Android'];

app.get("/personagem/:id", function (req, res) {
  const id = parseInt(req.params.id);
  const item = lista[id - 1];

  if (!item) {
    return res.status(404).send('Item não encontrado.');
  }

  res.send(item);
});

app.post("/personagem", function (req, res) {
  const body = req.body;
  const novoItem = body.nome;

  if (!novoItem) {
    return res.status(400).send('Corpo da requisição deve conter a propriedade nome.');
  }

  if (lista.includes(novoItem)) {
    return res.status(409).send('Esse item já existe na lista.');
  }

  lista.push(novoItem);
  res.status(201).send('Item adicionado com sucesso: ' + novoItem);
});

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

**Feedback**: Certifique-se de que o middleware `express.json()` está configurado corretamente para processar requisições com JSON, e que a indexação de elementos na lista está correta. Além disso, a verificação para valores duplicados deve ser aprimorada para comparar apenas os nomes dos itens.

</details>

### Projeto Prático

Crie uma nova aplicação ExpressJS que inclua:

1. Um endpoint que responda com todos os itens da lista quando a rota `/personagem` for acessada.
2. Um endpoint que responda com um item específico da lista quando a rota `/personagem/:id` for acessada.
3. Um endpoint que adicione um novo item à lista quando a rota `/personagem` for acessada com uma requisição POST.

#### Tarefas

* **Criação do Projeto**:
  * Inicialize um novo projeto NodeJS.
  * Instale o ExpressJS.
  * Instale e configure o Nodemon.
* **Implementação dos Endpoints**:
  * Crie um novo arquivo `index.js`.
  * Implemente o endpoint que responda com todos os itens da lista na rota `/personagem`.
  * Implemente o endpoint que responda com um item específico na rota `/personagem/:id`.
  * Implemente o endpoint que adicione um novo item à lista com uma requisição POST na rota `/personagem`.

<details>

<summary>Código esperado</summary>

{% code title="index.js" lineNumbers="true" %}
```javascript
const express = require("express");
const app = express();

const lista = ['Java', 'Kotlin', 'Android'];
app.use(express.json());

app.get("/personagem", function (req, res) {
  res.send(lista.filter(Boolean));
});

app.get("/personagem/:id", function (req, res) {
  const id = req.params.id;
  const item = lista[id - 1];

  if (!item) {
    return res.status(404).send('Item não encontrado.');
  }

  res.send(item);
});

app.post("/personagem", function (req, res) {
  const body = req.body;
  const novoItem = body.nome;

  if (!novoItem) {
    return res.status(400).send('Corpo da requisição deve conter a propriedade nome.');
  }

  if (lista.includes(novoItem)) {
    return res.status(409).send('Esse item já existe na lista.');
  }

  lista.push(novoItem);
  res.status(201).send('Item adicionado com sucesso: ' + novoItem);
});

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

**Feedback Detalhado**

* **Verificação dos Endpoints**: Certifique-se de testar cada rota (`/personagem`, `/personagem/:id`, `/personagem` com POST) acessando `http://localhost:3000` e verificando as respostas.
* **Estrutura**: A estrutura básica da aplicação deve seguir a mesma lógica apresentada na missão original.
* **Diferença Sutil**: A inclusão dos novos endpoints oferece um exercício prático de aplicação do conhecimento adquirido, sem introduzir novos conceitos.

</details>
