Creación de una API sencilla con NodeJs en Español
Tags: node, mongodb, api, express
Published: 2021-02-03 19:44:51

En este post vamos a crear una API bastante sencilla para iniciarse en el mundo de Node y Express conectándola a una base de datos no-relacional en local.

#### Pre-requisitos :rocket:
Necesitas tener instalado:
* NodeJS (https://nodejs.org/es/download/)
* MongoDB (https://docs.mongodb.com/manual/administration/install-community/)
* Tu editor de código favorito, Atom, Visual Studio, etc.
* MongoDB Compass (https://www.mongodb.com/try/download/compass)
* Postman o similar (https://www.postman.com/downloads/).

Si no tienes alguno, pincha en el enlace y sigue los pasos :wink:

El resto de dependencias las instalaremos con el gestor de paquetes de node.

## Empezamos... :computer:

Lo primero de todo vamos a empezar definiendo lo que es una API. Una API es un conjunto de protocolos por los cuales el front se comunica con la base de datos y obtiene respuesta de sus peticiones. Existen distintos tipos de métodos de comunicación, pero los más usados son GET, POST, PUT y DELETE.

Sabiendo esto, voy a dividir en 5 apartados todos los pasos a seguir para la creación de esta API.

### Parte I. Inicialización del proyecto.
Lo primero de todo es crear una carpeta en un directorio y ponerle un nombre. Abrimos la terminal en el directorio de la carpeta y escribimos:
```
npm init
```
Tras darle a intro aparecerán una serie de preguntas como las siguientes del cuadro azul:
![npm-init](https://dev-to-uploads.s3.amazonaws.com/i/v7obx1rcjzzss3zwux0a.png)

Puedes ir rellenando cada pregunta o presionar enter con lo que sale por defecto.

Este comando crea un archivo llamado *package.json* el cual contiene información sobre el proyecto como el nombre, descripción, el autor... y además contendrá todas las dependencias que vayamos instalando.

Los siguientes comandos son para la instalación de dependencias que se van a utilizar en el proyecto.
```
npm install express express-validator dotenv mongoose --save
``` 
```
npm install nodemon --save-dev
```
El segundo comando son las dependencias que se usan solo en el entorno de desarrollo.

:information_source: Dejo los enlaces a la documentación oficial de las librerías instaladas
[ExpressJS](https://expressjs.com/es/4x/api.html)
[express-validator] (https://express-validator.github.io/docs/)
[dotenv] (https://www.npmjs.com/package/dotenv)


Una vez todo instalado, hay que crear en la raíz del proyecto el archivo del que arrancará el servidor, *index.js*

![index](https://dev-to-uploads.s3.amazonaws.com/i/59a12pkhft7zxho8io7d.png)
 
Para poder arrancar el proyecto es necesario que se edite el archivo *package.json* y añadir las siguientes líneas:
```javascript
 "scripts": {
    "start": "node .",
    "dev": "nodemon .",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
```
Esto hará que el servidor arranque con Node o con *nodemon*.


:book:  **Breve explicación**  :book:

Voy ha hablar un poco de esta librería, *nodemon*. *Nodemon* nos permite ver a través de la consola todas las peticiones que se van haciendo. Además, si estás codificando y guardas el archivo, *nodemon* automáticamente te recarga el servidor sin que tengas que pararlo y volver a arrancarlo. Esta librería me parece bastante interesante de utilizar a la hora del desarrollo, por eso, como puedes ver está dentro de un apartado llamado "devDependencies" y no en "dependencies".

**Seguimos... :coffee:** 

Una vez actualizado el *package.json*, ejecutamos: 
```
npm run dev
```
Tiene que aparecer algo así:
![server_run](https://dev-to-uploads.s3.amazonaws.com/i/mob4ro3a47pl1qy6u88y.png)
 
Hasta aquí sería la primera parte, la inicialización del proyecto y el arranque del servidor. En el siguiente apartado se crea la conexión a la base de datos y se crean las variables de entorno. 

### Parte II. Conexión a la BD y variables de entorno.
En este apartado vamos a crear un archivo en el que crearemos la conexión a la base de datos. Antes de todo, para poder ver las tablas que se irán creando es necesario tener MongoDB Compass, ya que ahí en donde las podremos ver más fácilmente que por consola.

Creamos en la raíz del proyecto una carpeta llamada *config* y dentro un archivo *db.js* como el siguiente:
![dbjs](https://dev-to-uploads.s3.amazonaws.com/i/mhy9hwkhks0270zpuc1q.png)

También crearemos el archivo *.env* en la raíz del proyecto y añadiremos:
```
PORT=3000
DB_MONGO="url_mongo"
```
 
En el archivo *.env*, la variable **DB_MONGO** suele tener la siguiente estructura: `"mongodb://localhost:27017/api"`
Suele ser localhost si es en local. Después va el nombre de la base de datos.

Una vez creado el archivo *.env*, hay que editar el archivo *index.js* e importar la variable **PORT** y la función *conectarDB*
![index_mod](https://dev-to-uploads.s3.amazonaws.com/i/dawwa9muedqf8im3xviu.png)

Como se puede ver en la imagen, los cuadrados azules representan los cambios que hay que hacer en el archivo.
*El primero, son las importaciones de la función para conectar la base de datos `const conectarDB = require('./config/db.js')` y el archivo de las variables de entorno `require('dotenv').config({path: '.env'})`
*El segundo, `conectarDB()` es la llamada a la función de la conexión a la base de datos. 
*Y el tercero, `const port = process.env.PORT || 4000` se puede ver que hay un 'or'. Esto significa que si el valor de la variable de entorno está en uso, cogerá por defecto el valor '4000'.

Si todo a ido bien, podremos observar en la terminal lo siguiente:
![dbconect](https://dev-to-uploads.s3.amazonaws.com/i/gp7ibbdzc6y14byyq2kt.png)

Ya estamos conectados a nuestra base de datos!!  
![YES](https://media.giphy.com/media/NEvPzZ8bd1V4Y/giphy.gif)

### Parte III. Creación del modelo.
Ya tenemos lo más importante funcionando, ahora hay que crear nuestro modelo de datos. Para ello creamos una carpeta llamada *models* que es donde se ubicarán todos los modelos. Dentro, creamos un archivo con el nombre de nuestro modelo, en mi caso lo he llamado *mascota.js* y queda así:
![modelo](https://dev-to-uploads.s3.amazonaws.com/i/0s9zddbiwk3qob1c689v.png)

En este archivo se pueden ver las propiedades que va a tener nuestro modelo. 
 
Podemos ver 3 tipos de datos: **String, Number y Date**. Estos tipos de datos son los más usados junto con **Boolean** que en este caso no hemos utilizado. También se puede ver en el apartado *sexo* que hay `enum:['Macho', 'Hembra']`. El *enum* hace que solo se permitan los valores que hay entre los [], sino coinciden con esos, salta un error.

El apartado `require: true` hace que si a la hora de hacer una nueva inserción en la base de datos no está ese campo, saltará un error diciendo que es requerido ese campo.

En cuanto al apartado 
```javascript
date: {
  type: Date,
  default: Date.now
}
```
se puede poner así dentro de las propiedades o de esta manera que se crean los *updatedAt* y *createdAt*:
```javascript
const MascotaSchema = mongoose.Schema({...},{
  timestamps: true
})
```
Dejo aquí el enlace a la documentación de [MongoDB](https://mongoosejs.com/docs/schematypes.html) para poder echar un vistazo a todos los tipos de datos y algunos ejemplos de su uso.

### Parte IV. Creación de las rutas.
Ya tenemos nuestro modelo, ahora ha crear las rutas para realizar las peticiones GET, POST, PUT, DELETE.

Primero, creamos una carpeta llamada *routes* y dentro el archivo *mascota.js* en mi caso. Es **importante** que los archivos se nombren en referencia a lo que hacen para así tener una idea más clara de su contenido.

Las primeras lineas son las importaciones
![routeimp](https://dev-to-uploads.s3.amazonaws.com/i/8b5kvkxjzfrlvqdcy7kk.png)

Después ya van las rutas. Vamos a empezar con la ruta de creación de una mascota, en este caso usamos POST.
![postroute](https://dev-to-uploads.s3.amazonaws.com/i/mm46srjo2ybsi5zbp21w.png)
  
Como sale en la imagen, hay 3 parámetros. El parámetro 1 es la ruta misma. En este caso solo tiene '/', pero podemos poner lo que queramos como por ejemplo `router.post('/crear')`
El parámetro 2 utiliza *express-validator* para comprobar que todos los campos se pasan en la llamada y en caso de faltar alguno salta el mensaje que hay en las segundas comillas *'El nombre es necesario'*
`check('nombre','El nombre es necesario').not().isEmpty()`

Y el parámetro 3 es la función que ejecuta la llamada a la base de datos y devuelve la respuesta del servidor. En el siguiente apartado separaremos este parámetro en un controlador y así evitar que nuestro archivo tenga tantas lineas de código y se vea mas limpio.
:information_source: Todo código que se repita se puede separar en un archivo y reutilizarlo.

La llamada GET para recoger todos los datos quedaría así:
![getroute](https://dev-to-uploads.s3.amazonaws.com/i/ebqiquud8wrprtidzsug.png)

en este caso solo hay 2 parámetros.  

:heavy_exclamation_mark:No hay que olvidar importar este archivo en el *index.js* de esta forma: ```javascript
// Importamos las rutas
app.use('/api/mascotas', require('./routes/mascota'))
```
:heavy_exclamation_mark:No olvidar el `module.exports = router;` al final del archivo.
Una vez creadas estas dos llamadas, hay que comprobar que realmente está funcionando, en mi caso Postman.
###### POST 
 ![postmanPost](https://dev-to-uploads.s3.amazonaws.com/i/hnrxwop7p7h7nt1t3yf9.png)
###### RESPUESTA POST
![PostmanPostRes](https://dev-to-uploads.s3.amazonaws.com/i/f328n0aq0j2frx6qcpxw.png)
###### GET + RESPUESTA
![PostmanGet](https://dev-to-uploads.s3.amazonaws.com/i/1bws85sb3tjzu2elj8y8.png)
   
Llegado a este punto el código ya funciona!! 
![ok](https://media.giphy.com/media/V5zZwAejmS58I/giphy.gif)

### Parte V. Creación del controlador.
Este apartado es el mas sencillo de todos. Se trata de separar la función que hay en la llamada y ponerla en otro archivo. Para ello, creamos una carpeta *controllers* y dentro un archivo *mascota.js* como este:

![controller](https://dev-to-uploads.s3.amazonaws.com/i/74riqnxnt8g9taeib7oe.png)

He añadido una pequeña funcionalidad dentro de cada función 
```javascript
// Revisar si hay errores
    const errores = validationResult(req);
    if (!errores.isEmpty()) {
        return res.status(400).json({ errores: errores.array() })
    }
```
 Esto es para que compruebe que no existe ningún error antes de hacer la llamada a la base de datos. En caso afirmativo salta el error.

:heavy_exclamation_mark: No olvidar quitar la función del archivo de rutas y sustituirlo por `router.get('/', mascotaController.recogerMascotas)` e importarlo al principio del archivo `const mascotaController = require('../controllers/mascota')` como muestra la imagen
![routecontroller](https://dev-to-uploads.s3.amazonaws.com/i/0k6zgt8jb3wi5dif96fy.png)
 
 

Como práctica dejo por hacer la llamada de actualizar y de eliminar para que practiques. Más abajo dejo el enlace a mi GitHub para consultar cualquier duda.

Y por fin tenemos nuestra pequeña API!!
![fin](https://media.giphy.com/media/26u4lOMA8JKSnL9Uk/giphy.gif)

### :link: Recursos 
GitHub (https://github.com/JessicaMeleroDev/SIMPLE-CRUD-API-NODEJS)

Cualquier duda no dudes en dejarla en los comentarios :smile: