¿Qué es NestJS?
Está resultando bastante común ver cómo en eventos puramente de Angular, el famoso framework para el desarrollo front, se están colando charlas sobre NestJS. Un framework para el desarrollo en el lado del servidor. Esto es debido a que se inspira en los principios básicos de Angular.
Esta herramienta está creciendo en popularidad a un ritmo vertiginoso entre los desarrolladores de NodeJS, además sus creadores están cuidando mucho la documentación que están elaborando.
¿Qué aporta NestJS?
Nest aporta un gran punto de partida para el desarrollo con NodeJS. En nuestra opinión, el desarrollo con Node puede resultar un poco caótico y si no se tiene una buena metodología y estructura puede que acabemos creando un proyecto difícil de mantener y evolucionar.
NestJS soluciona por completo este problema. Además nos permite integrarlo con todo el ecosistema de librerías que rodea este famoso lenguaje de alta concurrencia… Y todo esto usando Typescript de fondo.
Creando nuestra primera aplicación
En este artículo vamos a construir una pequeña aplicación con la que después podremos ahondar un poco en como estructurar el modelado de datos en NestJS.
En primer lugar, debemos instalar NestJS:
NestJS se apoya en TypeOrm para la comunicación e interacción con la base de datos, así que debemos instalarlo en nuestro proyecto indicando que vamos a usar mysql:
En este punto podemos irnos al fichero de typeorm.config.ts para configurar así la nuestra base de datos y su conexión (usuario, contraseña, etc.):
Importante: debemos crear el esquema manualmente en nuestra base de datos local para que el proyecto la detecte al arrancar.
Una vez configurada la conexión a nuestra base de datos podemos crear los componentes que vamos a necesitar para nuestro CRUD. Para ello, vamos a crear varios componentes que poco a poco veremos cuál es su función.
Modelando una entidad
Vamos a modelar la entidad Task. Esto lo haremos desde el fichero task.entity.ts. Básicamente lo que haremos en este punto es definir nuestra tabla en base de datos. Podemos configurarla como deseemos gracias a los decoradores de TypeORM:
Como vemos en el código hemos creado la tabla Task con tres campos:
- El id que será nuestra clave primaria numérica autogenerada.
- El campo title que será un campo de texto obligatorio.
- Por último un campo descripción también de texto pero en este caso no es obligatorio.
La importancia de los DTO
Un DTO (Data Transfer Object) es un esquema que define cómo debemos recibir los datos para realizar una acción sobre la base de datos (consulta, inserción, modificación, etc.). Nos permite añadir funcionalidad para validar los datos recibidos.
Este es el ejemplo de create-task.dto.ts que define el objeto que debemos recibir para crear un nuevo Task en la base de datos. Estamos indicando que el campo title debe venir de forma obligatoria mientas que el campo descripción es opcional.
Implementando la lógica
Ya podemos implementar la lógica de nuestra aplicación. Para ello, van a entrar en juego tres ficheros:
En primer lugar tenemos task.repository.ts donde tendremos un repositorio con las querys que vamos a realizar sobre nuestro modelo. En este ejemplo hemos creado dos:
El método getTask() realiza una consulta sobre la tabla Task para obtener todos los registros.
Si observamos el método createTask() recibe como parámetro el DTO que hemos creado anteriormente. Como este se encarga de validar los datos recibidos, en este método podemos crear un nuevo Task directamente con el método .save().
Por otro lado, tenemos el fichero task.service.dto como un servicio de Angular este archivo actual como proveedor de funciones para el controlador. En este ejemplo hemos creado las siguientes funciones:
Cabe destacar dos funciones que no llaman a ningún método de TaskRepository para realizar la funcionalidad. Esto es porque estas funciones realizan directamente las acciones en la basé de datos gracias a la funcionalidad de ActiveRecord que nos ofrece TypeOrm.
El método getTaskById() nos permite buscar un solo Task con el método .findOne(). Y el método deleteTask() borra un Task de la base de datos.
Por último, solo falta configurar los endpoints a los que podremos llamar para realizar todas estas acciones sobre la base de datos. Esto debemos hacerlo desde el controlador task.controller.ts.
Como en la imagen, gracias a los decoradores de NestJS podemos definir método y las rutas de cada uno de los endpoints.
Bonus: probando nuestra app con Swagger
Ya podríamos probar las APIS creadas realizando una llamada HTTP a estas. NestJS ofrece integración con muchos servicios, uno de ellos es Swagger que nos permite tanto documentar nuestros endpoints como probarlos de forma sencilla.
Para configurarlo en nuestro proyecto solo tenemos que instalarlo y seguir unos sencillos pasos:
Tras instalarlo, tenemos que configurarlo en el archivo main.ts:
Con esto ya podemos arrancar nuestro proyecto simplemente con el comando npm start esto va a levantar nuestra aplicación en http://localhost:3000 y si accedemos a http://localhost:3000/api vemos la consola de swagger con la que poder probar todos nuestros endpoints:
Aquí podemos ver cómo realizar la llamada al POST de creación:
Y aquí podemos ver cómo llamar al GET que lista todos los Task:
Conclusión
Modelar y crear APIS con NestJS es realmente sencillo además gracias al ecosistema de NodeJS nos permite hacer uso de servicios de forma sencilla como Swagger, JWT, Passport, etc. En próximos artículos profundizaremos en el concepto de modelado y ejecución de queries en la base de datos.
El código de ejemplo que hemos desarrollado está en el siguiente repositorio.