1. NodeJS al limite con NestJS
Arturo Silvelo
Arturo Silvelo NodeJS al limite con NestJS
2. NestJS
NestJS es un nuevo framework para NodeJS que utiliza las
ventajas de Typescript para poder construir aplicaciones grandes,
escalables y mantenibles.
Arturo Silvelo NodeJS al limite con NestJS
4. Modules I
Los m´odulos son la estructura principal de la aplicaci´on.
Mediante ellos encapsularemos otras estructuras como los
componentes y los controladores.
Arturo Silvelo NodeJS al limite con NestJS
5. Modules II
Para crear nuestra aplicaci´on deberemos crear un modulo ra´ız.
1 import { Module } from ’@nestjs/common ’ ;
2
3 @Module({})
4 export c l a s s AppModule { }
Y creamos nuestro fichero principal que iniciara el servidor.
1 import { NestFactory } from ’@nestjs/core ’ ;
2 import { AppModule } from ’./app.module ’ ;
3
4 async f u n c t i o n b o o t s t r a p () {
5 const app = await NestFactory . c r e a t e ( AppModule ) ;
6 await app . l i s t e n (3000) ;
7 }
8
9 b o o t s t r a p () ;
Arturo Silvelo NodeJS al limite con NestJS
6. Controller I
Los controladores son los encargados de manejar las peticiones
HTTP.
Para crear un controlador:
1 Creamos una nueva clase
2 A˜nadir el decorador @Controller()
@Controller admite un par´ametro, que ser´a el endpoint.
Arturo Silvelo NodeJS al limite con NestJS
7. Controller II
A cada m´etodo de la clase se le puede a˜nadir un decorador para
definir a que verbo responder.
1 import { C o n t r o l l e r , Get } from "@nestjs/common" ;
2
3 @ C o n t r o l l e r ( ’users ’)
4 export c l a s s U s e r s C o n t r o l l e r {
5
6 @Get ()
7 r e t r i e v e A l l () {
8 return [{ name : ’Arturo ’ } , { name : ’Pepe ’ }]
9 }
10 }
Por ´ultimo, para que nuestra aplicaci´on sepa de la existencia del
controlador tendremos que a˜nadirlo al m´odulo.
1 c o n t r o l l e r s : [ U s e r s C o n t r o l l e r ]
2 })
Arturo Silvelo NodeJS al limite con NestJS
8. Components I
Los componentes juegan el rol de servicio, y pueden ser inyectados
en otros componentes o en los controladores.
La manera de crear un componente es la misma que de un
controlador a diferencia del decorador, que en este caso ser´a
@Component.
Arturo Silvelo NodeJS al limite con NestJS
9. Components II
1 import { Component } from "@nestjs/common" ;
2
3 @Component ()
4 export c l a s s U s e r s S e r v i c e {
5 p r i v a t e u s e r s = [{ name : ’Arturo ’ } , { name : ’Pepe ’ } ] ;
6
7 r e t r e i v e A l l () {
8 return t h i s . u s e r s ;
9 }
10 }
Modificaremos nuestro controlador para inyectar el servicio.
1 c o n s t r u c t o r ( p r i v a t e u s e r s S e r v i c e : U s e r s S e r v i c e ) { }
2
3 @Get ()
4 r e t r i e v e A l l () {
5 return t h i s . u s e r s S e r v i c e . r e t r e i v e A l l ()
6 }
Y por ´ultimo a˜nadiremos el componente creado al modulo.
1 @Module({
2 c o n t r o l l e r s : [ U s e r s C o n t r o l l e r ] ,
3 components : [ U s e r s S e r v i c e ]
4 })
Arturo Silvelo NodeJS al limite con NestJS
10. Middlewares I
Act´ua antes de que la petici´on llegue al controlador.
NestJS cuenta con el decorador @Middleware y la interfaz
NestMiddleware para implementar la l´ogica del middleware.
Arturo Silvelo NodeJS al limite con NestJS
11. Middlewares II
1 import { Middleware , NestMiddleware , ExpressMiddleware } from ’@nestjs/common ’ ;
2 import { Request } from ’express ’ ;
3
4 @Middleware ()
5 export c l a s s LoggerMiddleware implements NestMiddleware {
6 r e s o l v e () : ExpressMiddleware {
7 return ( req : Request , res , next ) => {
8 c o n s o l e . log ( ‘ [ ${req . method }] ${req . o r i g i n a l U r l } ‘) ;
9 next () ;
10 };
11 }
12 }
Si nuestro middleware es sencillo y no necesita DI podemos
implementar de una forma m´as sencilla.
1 }
2
3 export const loggerMiddleware = ( req , res , next ) => {
4 c o n s o l e . log ( ‘ [ ${req . method }] ${req . o r i g i n a l U r l } ‘) ;
5 next () ;
6 };
Arturo Silvelo NodeJS al limite con NestJS
12. Middlewares III
Y como siempre necesitaremos indicarle a nuestro m´odulo que
vamos a usar un middleware.
1 export c l a s s UsersModule implements NestModule {
2 c o n f i g u r e ( consumer : MiddlewaresConsumer ) : void {
3 consumer
4 //*
5 . apply ( LoggerMiddleware )
6 . forRoutes ( U s e r s C o n t r o l l e r ) ;
7 /*/
8
9 .apply( loggerMiddleware )
10 .forRoutes ({ path: ’/users ’, method: RequestMethod .GET });
11 //*/
12 }
13 }
Arturo Silvelo NodeJS al limite con NestJS
13. Exception Filters I
Una de las mejores caracter´ısticas de NestJS es la incorporaci´on
de una capa de control de excepciones.
La gesti´on de excepciones nos permite crear nuestras excepciones
personalizadas, extendiendo la clase HttpException.
1 import { HttpException , HttpStatus } from "@nestjs/common" ;
2
3 export c l a s s RemoveUserException extends HttpException {
4 c o n s t r u c t o r ( i d : s t r i n g ) {
5 super ( ‘ The u s e r ${ i d } doesn ’t exist ‘, HttpStatus.NOT_FOUND);
6 }
7 }
Arturo Silvelo NodeJS al limite con NestJS
14. Exception Filters II
O bien podemos capturar nuestras todas las excepciones o aquellas
de una clase en concreto y controlarlas.
1 @Catch ()
2 export c l a s s H t t p E x c e p t i o n F i l t e r implements E x c e p t i o n F i l t e r {
3 catch ( e x c e p t i o n : HttpException , response ) {
4 const s t a t u s = e x c e p t i o n . g e t S t a t u s () ;
5 l e t e r r o r = e x c e p t i o n . getResponse () ;
6 l e t message ;
7 i f ( typeof e r r o r === ’object ’ && ( e r r o r as Object ) . hasOwnProperty ( ’
message ’) ) {
8 message = e r r o r [ ’message ’ ] ;
9 } e l s e {
10 message = ‘ I t ’s a message from the exception filter ‘;
11 }
12
13 response
14 .status(status)
15 .json ({
16 statusCode: status ,
17 message ,
18 });
19 }
20 }
Arturo Silvelo NodeJS al limite con NestJS
15. Exception Filters III
Las excepciones podemos hacer que solo afecten a un controlador
o a toda la aplicaci´on.
1 async f u n c t i o n b o o t s t r a p () {
2 const app = await NestFactory . c r e a t e ( AppModule ) ;
3 app . u s e G l o b a l F i l t e r s (new H t t p E x c e p t i o n F i l t e r () ) ;
4 await app . l i s t e n (3000) ;
5 }
Arturo Silvelo NodeJS al limite con NestJS
16. Pipes I
Los pipes nos permiten transformar los datos de entrada en la
salida deseada.
Para generar un nuevo pipe
1 Crear una clase que implemente PipeTransform
2 Decorar con @Pipe()
3 Inyectarla en el par´ametro que queramos transformar.
Arturo Silvelo NodeJS al limite con NestJS
17. Pipes II
1 import { PipeTransform , Pipe , ArgumentMetadata , BadRequestException } from ’
@nestjs/common ’ ;
2 import { v a l i d a t e } from ’class -validator ’ ;
3 import { p l a i n T o C l a s s } from ’class -transformer ’ ;
4
5 @Pipe ()
6 export c l a s s V a l i d a t i o n P i p e implements PipeTransform<any> {
7 async transform ( value , metadata : ArgumentMetadata ) {
8 const { metatype } = metadata ;
9 i f ( ! metatype | | ! t h i s . t o V a l i d a t e ( metatype ) ) {
10 return v a l u e ;
11 }
12 const o b j e c t = p l a i n T o C l a s s ( metatype , v a l u e ) ;
13 const e r r o r s = await v a l i d a t e ( o b j e c t ) ;
14 i f ( e r r o r s . l e n g t h > 0) {
15 throw new BadRequestException ( ’Validation failed ’) ;
16 }
17 return v a l u e ;
18 }
19
20 p r i v a t e t o V a l i d a t e ( metatype ) : boolean {
21 const types = [ String , Boolean , Number , Array , Object ] ;
22 return ! types . f i n d (( type ) => metatype === type ) ;
23 }
24 }
Arturo Silvelo NodeJS al limite con NestJS
18. Pipes III
1 @Post ()
2 c r e a t e U s e r (@Body(new V a l i d a t i o n P i p e () ) newUser : CreateUserDto ) {
3 return t h i s . u s e r s S e r v i c e . c r e a t e U s e r ( newUser ) ;
4 }
Arturo Silvelo NodeJS al limite con NestJS
19. Guardas
Los Guards tienen una ´unica responsabilidad, decidir si una ruta es
accesible o no.
Son muy ´utiles para el manejo de roles en nuestra aplicaci´on.
1 Con el decorador @Guard()
2 Implentar la interfaz CanActivate.
3 Injectarlo con @UseGuards(Guard)
https://docs.nestjs.com/guards
Arturo Silvelo NodeJS al limite con NestJS
20. Swagger I
Swagger es una herramienta extremadamente ´util para describir,
producir, consumir y visualizar API.
NestJS proporciona un modulo para generar nuestra
documentaci´on de una manera f´acil y sobre el c´odigo, lo que nos
permite que nuestra documentaci´on este siempre actualizada con
el c´odigo.
Arturo Silvelo NodeJS al limite con NestJS
21. Swagger II
1 async f u n c t i o n b o o t s t r a p () {
2 const app = await NestFactory . c r e a t e ( AppModule ) ;
3 app . u s e G l o b a l F i l t e r s (new H t t p E x c e p t i o n F i l t e r () ) ;
4 const o p t i o n s = new DocumentBuilder ()
5 . s e t T i t l e ( ’Contacts Example ’)
6 . s e t D e s c r i p t i o n ( ’The contacts API description ’)
7 . s e t V e r s i o n ( ’1.0 ’)
8 . b u i l d () ;
9 const document = SwaggerModule . createDocument ( app , o p t i o n s ) ;
10 SwaggerModule . setup ( ’/api’ , app , document ) ;
11
12 await app . l i s t e n (3000) ;
13 }
14
15 b o o t s t r a p () ;
Arturo Silvelo NodeJS al limite con NestJS
22. Swagger III
1 @ApiResponse ({ s t a t u s : 204 , d e s c r i p t i o n : ’The record has been successfully
deleted.’ })
2 @ApiResponse ({ s t a t u s : 404 , d e s c r i p t i o n : ’Not Found ’ })
3 @Delete ( ’:id’)
4 removeById (@Param( ’id’) i d : s t r i n g ) {
5 l e t removeStatus = t h i s . u s e r s S e r v i c e . removeById(+ i d ) ;
6 i f ( removeStatus ) throw new RemoveUserException ( i d ) ;
7 }
Arturo Silvelo NodeJS al limite con NestJS
23. Mongo I
Para guardar nuestros datos en Mongo, NestJs no proporciona un
m´odulo para configurar de manera sencilla.
Arturo Silvelo NodeJS al limite con NestJS
24. Mongo II
Necesitamos definir un schema de nuestros datos para configurar
nuestro Mongo.
1 import ∗ as mongoose from ’mongoose ’ ;
2
3 export const UserSchema = new mongoose . Schema({
4 name : String ,
5 number : String ,
6 }) ;
Despu´es importamos el modulo de mongo en nuestro module de
usuarios y definimos nuestra colecci´on.
1 @Module({
2 imports : [ MongooseModule . f o r F e a t u r e ([{ name : ’User ’ , schema : UserSchema }])
] ,
3 c o n t r o l l e r s : [ U s e r s C o n t r o l l e r ] ,
4 components : [ U s e r s S e r v i c e ]
5 })
Arturo Silvelo NodeJS al limite con NestJS
25. Mongo III
Inyectamos el modelo en nuestro servicio para conectarnos a la
base de datos.
1 @Component ()
2 export c l a s s U s e r s S e r v i c e {
3 c o n s t r u c t o r ( @InjectModel ( UserSchema ) p r i v a t e r e a d o n l y userModel : Model<IUser
>) { }
4
5 async r e t r e i v e A l l () : Promise<I U s e r []> {
6 return await t h i s . userModel . f i n d () ;
7 }
8
9 async r e t r i e v e B y I d ( u s e r I d : s t r i n g ) : Promise<IUser> {
10 return await t h i s . userModel . f i n d B y I d ( u s e r I d ) ;
11 }
12
13 async c r e a t e U s e r ( newUser : CreateUserDto ) {
14 return await t h i s . userModel . c r e a t e ( newUser ) ;
15 }
16
17 async removeById ( u s e r I d : s t r i n g ) {
18 await t h i s . userModel . findByIdAndRemove ( u s e r I d ) ;
19 }
20
21
22 }
Arturo Silvelo NodeJS al limite con NestJS
26. Mongo IV
En nuestro modulo principal importamos el modulo de mongo para
realizar la conexi´on con la base de datos. NestJS nos proporciona
un modulo para trabajar con mongoDB
1 @Module({
2 imports : [ UsersModule , MongooseModule . forRoot ( ’mongodb :// localhost/nest ’) ] ,
3 })
4 export c l a s s AppModule { }
Arturo Silvelo NodeJS al limite con NestJS