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 🚀
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 😉
El resto de dependencias las instalaremos con el gestor de paquetes de node.
Empezamos... 💻
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:
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.
ℹ️ Dejo los enlaces a la documentación oficial de las librerías instaladas
ExpressJS
express-validator
dotenv
Una vez todo instalado, hay que crear en la raíz del proyecto el archivo del que arrancará el servidor, index.js
Para poder arrancar el proyecto es necesario que se edite el archivo package.json y añadir las siguientes líneas:
"scripts": {
"start": "node .",
"dev": "nodemon .",
"test": "echo \"Error: no test specified\" && exit 1"
},
Esto hará que el servidor arranque con Node o con nodemon.
📖 Breve explicación 📖
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... ☕
Una vez actualizado el package.json, ejecutamos:
npm run dev
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:
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
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:
Ya estamos conectados a nuestra base de datos!!
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í:
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
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:
const MascotaSchema = mongoose.Schema({...},{
timestamps: true
})
Dejo aquí el enlace a la documentación de MongoDB 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
Después ya van las rutas. Vamos a empezar con la ruta de creación de una mascota, en este caso usamos POST.
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.
ℹ️ 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í:
en este caso solo hay 2 parámetros.
❗No hay que olvidar importar este archivo en el index.js de esta forma:
// Importamos las rutas
app.use('/api/mascotas', require('./routes/mascota'))
❗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
RESPUESTA POST
GET + RESPUESTA
Llegado a este punto el código ya funciona!!
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:
He añadido una pequeña funcionalidad dentro de cada función
// 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.
❗ 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
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!!
🔗 Recursos
GitHub (https://github.com/JessicaMeleroDev/SIMPLE-CRUD-API-NODEJS)
Cualquier duda no dudes en dejarla en los comentarios 😄
Top comments (5)
Hola Jessica, disculpa que te moleste pero segui este tutorial como aprendizaje para mi primera API con node y express, hice un intento de delete(lo hice con un put para no perder la data cambiando un field que le llame active) y update, si puedes hecharle un ojo y dejarme saber que tal lo hice aqui mi repo:
github.com/wizsebastian/node-crud-...
Hola WizSebastian, en un principio todo parece correcto :)
Yo aconsejo crear siempre un .gitignore para no subir los archivos node_modules, package-lock.json y .env al repositorio. Los dos primeros se generan al hacer 'npm install', y el archivo .env son las variables de entorno que suelen describirse en el README.md para inicializar el proyecto.
No obstante puedes verlo en mi repositorio. Cualquier duda me comentas.
Gracias ^^
Mil Gracias Jess
Hola! me gusto mucho tu post y bien explicado. tengo una duda en cuanto a la validación con express-validator. Se podría crear la validación en un archivo aparte y llamarlo desde la ruta ? Asi como un middleware ?
Hola! Sí, se puede hacer sin ningún problema