NEST JS

Paiboon Toomthongkam
Mintelligence
Published in
4 min readSep 6, 2018

--

Nest JS

Language

หากคุณชอบใน TypeScript แล้วอยากทำกับ Node.js แน่นอนว่า ตอนนี้มีตัวช่วยคุณในการสร้าง Backend แบบโคตร “Cool” ทั้งการออกแบบโครงสร้างที่เข้าใจง่าย การแบ่ง Controller เป็นสัดเป็นส่วน คล้ายๆ กับการสร้าง Component ของ Angular การทำ Model ที่ใช้งานร่วมกับคนอื่นง่ายๆ หากคุณชอบใน Angular แน่นอน ตอนนี้ BackEnd Nest JS เป็นคำตอบของคุณแน่นอนในตอนนี้

Installation

Nest JS รองรับ Node.js 8.9.0 ขึ้นไปนะครับ เช็ค Version แล้ว Update ก่อนนะครับ

$ npm i -g @nestjs/cli
$ nest new project --> ชื่อ project ครับ

เมื่อเราสร้างเสร็จแล้วจะได้ Folder src มาครับซึ่งใน src จะมีไฟล์สำคัญๆอยู่ 3ไฟล์ คือ

Controller

สำหรับ Controller มีหน้าที่จัดการ Request จาก Client และส่งข้อมูลกลับไปให้ Client โดย Client จะเรียกผ่าน Routing ต่างๆ เช่น

Controller photo

เราจะประกาศ Routing โดยใช้ Decorator เพื่อเป็นตัวบอกว่า Controller ตัวไหนควรจะจัดการกับ Request ที่ Client เรียก
เมื่อ Client เรียก /photo ผ่าน Get() Controller photo จะเรียก function findAll และ Return ค่าออกไปให้
มีให้เล่นอีกเยอะครับ ลองเข้าไปศึกษาดูครับ Nest JS Controller

สามารถสร้างด้วย Cli ได้ด้วยนะครับ

$ nest g controller photo

Providers

Providers คือ Class ที่เราประกาศ @Injectable() เช่น Service โดยเรียกผ่านด้วย Constructor ของ Service นั้นๆ ว่าจะให้ทำอะไรต่อไป เช่น

ประกาศ Constructor photoService จาก Photoservice แล้วใน function findAll จะเรียก this.photoService.findAll(); ซึ่งจะไปเรียก function findAll ใน Class PhotoService มาใช้งาน

photo.service

PhotoService เป็น Class ที่เป็น Service โดยเราจะต้องประกาศ @ Injectable () ไว้เพื่อบอก Nest JS ว่าเป็น Class ที่เป็น Service เราจะ InjectRepository ตัว Photo เข้ามาในตัวแปร photoRepository เพื่อให้ photoRepository ใช้งาน Model Photo ได้
จะเห็นว่า function findAll ก็จะ Return ค่ากลับไปให้กับ Controller ที่เรียก

สามารถสร้างด้วย Cli ได้ด้วยนะครับ

$   nest g service photo/photo

Modules

Module จะเป็นตัวรวบ ทุกอย่างเพื่อเก็บไว้ใน Module นั้นๆเพื่อง่ายต่อการเอาไปใช้งาน

photo.module

เราจะมี Providers เป็น PhotoService มี Controller เป็น PhotoController และ Exports PhotoService ออกไปให้ใช้ด้วย เมื่อรวมแล้วก็นำไป Import app.module ดังรูป

app.module

และเมื่อมี Controller อื่นต้องการใช้ PhotoService ที่ไม่ใช่ PhotoController จะ Import PhotoModule ดังรูป

และใน Controller ของตัวนั้นๆ จะ เรียก PhotoService มาใช้งานได้ ดังรูป

Middleware

เป็นตัวกรองเมื่อมีการ Request มาจะต้องเข้า Middleware ก่อนถึงจะ Route ไปตาม Request ที่ต้องการได้

สามารถทำได้ตามนี้ครับ

logger.middleware.ts

import { Injectable, NestMiddleware, MiddlewareFunction } from '@nestjs/common';@Injectable()
export class LoggerMiddleware implements NestMiddleware {
resolve(...args: any[]): MiddlewareFunction {
return (req, res, next) => {
console.log('Request...');
next();
};
}
}

app.module.ts

import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middlewares/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class ApplicationModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('cats');
}
}

Pipes

Pipes จะเป็นตัวช่วยให้เราทำงานง่ายขึ้น เช่นการเช็ค Type ของค่าที่ Client ส่งมา

$ npm i --save class-validator class-transformer

create-cat.dto.ts

import { IsString, IsInt } from 'class-validator';export class CreateCatDto {
@IsString()
readonly name: string;
@IsInt()
readonly age: number;
@IsString()
readonly breed: string;
}

จะเห็นได้ว่าเราสามารถเช็ค Type ของ name ต้องเป็น String หรือ age เป็น Number

validation.pipe.ts

import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import { validate } from 'class-validator';
import { plainToClass } from 'class-transformer';
@Injectable()
export class ValidationPipe implements PipeTransform<any> {
async transform(value, { metatype }: ArgumentMetadata) {
if (!metatype || !this.toValidate(metatype)) {
return value;
}
const object = plainToClass(metatype, value);
const errors = await validate(object);
if (errors.length > 0) {
throw new BadRequestException('Validation failed');
}
return value;
}
private toValidate(metatype): boolean {
const types = [String, Boolean, Number, Array, Object];
return !types.find((type) => metatype === type);
}
}

ValidationPipe เป็นอีก Pipes ที่น่าสนใจครับ เราสามารถเช็คข้อมูลที่ Client ส่งมาทั้งหมดได้ ต้องการให้อยู่ใน Type อะไรบ้าง เช่นตัวอย่างข้างบน จะให้อยู่ใน Type
String, Boolean, Number, Array, Object

การเรียกใช้ก็ง่ายครับลองมาดูกัน

cats.controller.ts

@Post()
@UsePipes(ValidationPipe)
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}

แค่ใส่ @UsePipes(ValidationPipe) ไว้บน Functionที่เราต้องการก็ทำงานแล้วครับ

Guards

Guards ทำหน้าที่ตรวจสอบ Request จาก Client ก่อนที่จะไปถึง Routing นั้นๆ คล้ายๆกับ Middleware แต่จะทำงานหลัง Middleware

roles.guard.ts

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class RolesGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
return true;
}
}

cats.controller.ts

@Controller('cats')
@UseGuards(RolesGuard)
export class CatsController {}

เมื่อเราสร้าง Guard ก็นำไปใช้ง่ายๆ ครับ แค่ใส่@UseGuards(RolesGuard) ไว้บน Controller ของเราก็จะทำงานแล้วครับ

Main.ts

ไฟล์นี้จะเป็น Config เพื่อให้ NestJS Run ที่ Port 3000

Running application

ละตอนนี้ก็ได้เวลา Run แล้ว

$ npm run start

เป็นอันว่าผ่านแล้ว

Test Api ด้วย Postman กันเลย

ออกมาแล้วง่ายๆเลยครับ

สรุป

Nest JS เป็นทางเลือกที่ดีมากครับ ในการทำ BackEnd ด้วย Node.js ที่เป็น TypeScript ง่ายและสะดวกในการทำงานร่วมกับผู่อื่น เหมาะมากๆ กับการใช้คู่กับ FrontEnd ที่เป็น Angular

อ้างอิง
NestJS
Github

--

--