Pengenalan dan Tutorial Node.js Dengan Menggunakan Framework NestJS
Beberapa tahun terakhir, aplikasi web berkembang sangat pesat dengan diperkenalkannya beberapa framework yang cukup populer seperti bootstrap, Angular JS, dan lain sebagainya. Semua framework tersebut memiliki dasar yang sama yaitu framework JavaScript yang sangat populer.
Seiring dengan perkembangannya, terjadi suatu masalah ketika harus mengembangkan aplikasi berbasis server, ada semacam kekosongan di dalamnya, dan di sinilah Node.js muncul untuk mengatasi masalah tersebut.
Node.js merupakan open source lintas platform yang digunakan untuk pengembangan aplikasi web yang berbasis pada server. Aplikasi Node.js ditulis dalam JavaScript dan dapat dijalankan diberbagai sistem operasi. Pada kesempatan kali ini kami akan mengenalkan pengaplikasian Node.js dengan menggunakan Nestjs.
Instalasi
Untuk mencoba tutorial ini bisa melakukan langkah instalasi dibawah ini:
Untuk cara menjalankannya bisa dengan menggunakan perintah berikut:
npm run start:dev
Setelah perintah npm run start:dev dijalankan selanjutnya akan muncul terminal seperti di atas. Hal tersebut menandakan bahwa sistem sudah berjalan. Untuk mengeceknya bisa menggunakan browser dengan mengakses link url berikut klik di sini.
Bekerja dengan controller
NestJS merupakan framework yang menggunakan konsep module untuk memudahkan kita dalam melakukan pengelompokan code program. Untuk membuat controller baru harus didefinisikan pada module terlebih dahulu. Pada awal instalasi akan ada controller default yang dibuat dari template.
import {Controller,Get} from ‘@nestjs/common’;import {AppService} from ‘./app.service’;@Controller()export class AppController {constructor(private readonly appService: AppService) {}@Get()getHello(): string {return this.appService.getHello();}}
Selanjutnya, kita akan mencoba menangkap query dari metode GET dan meresponnya menjadi sebuat JSON response.
import { Controller, Get, Query } from ‘@nestjs/common’;import { AppService } from ‘./app.service’;@Controller()export class AppController {constructor(private readonly appService: AppService) { }@Get()getHello(@Query(‘name’) name: string) {return {name: name}}}
Kode program di atas terdapat query name dan langsung diproses dengan response berupa JSON response.
Link yang digunakan untuk mengakses adalah klik di sini.
Bekerja dengan service
Service pada NestJS ini biasanya saya gunakan untuk tempat logic bisnis yang akan digunakan berulang pada end point yang lain. Sebagai contoh mengambil data user yang aktif saja.
Karena kita belum membahas tentang database maka service di bawah ini akan disimulasikan dengan mengembalikan data dummy.
import { Injectable } from ‘@nestjs/common’;@Injectable()export class AppService {getActiveUser(name: string) {// database query// data logicvar items = [{id: “id_1”,name: “budi”},{id: “id_2”,name: “santi”}]var matchedData = []items.forEach(item => {if (item.name === name) {matchedData.push(item)}})//dummy returnreturn matchedData}}
Untuk penggunaan service pada controller bisa dilakukan dengan cara seperti di bawah ini.
import { Controller, Get, Query } from ‘@nestjs/common’;import { AppService } from ‘./app.service’;@Controller()export class AppController {constructor(private readonly appService: AppService) { }@Get()getHello(@Query(‘name’) name: string) {return {name: name}}@Get(‘/activeUser’)getActiveUser(@Query(‘name’) name: string) {var data = this.appService.getActiveUser(name)return data}}
Response yang didapat setelah dilakukan filter akan menjadi seperti berikut.
Ketika melakukan query mimi, maka tidak akan muncul responsenya. Karena memang tidak ada pada data items dummy.
Bekerja dengan Database
Database yang akan digunakan adalah postgres dengan ORM framework dengan type orm. Sebelum mulai bekerja dengan database kita buat terlebih dahulu databasenya pada postgres.
Nama database yang akan kita gunakan adalah nest_app, di sini kami menggunakan Dbeaver untuk database viewer.
Lalu install type orm dengan menggunakan perintah berikut:
npm install — save @nestjs/typeorm typeorm pg
Setelah type orm terinstall kita akan menambahkan perintah pada package json agar bisa menjalankan migrasi database. Tambahkan script berikut pada package.json.
{“name”: “nest-app”,“version”: “0.0.1”,“description”: “”,“author”: “”,“license”: “MIT”,“scripts”: {“prebuild”: “rimraf dist”,“build”: “nest build”,“format”: “prettier — write \”src/**/*.ts\” \”test/**/*.ts\””,“start”: “nest start”,“start:dev”: “nest start — watch”,“start:debug”: “nest start — debug — watch”,“start:prod”: “node dist/main”,“lint”: “eslint \”{src,apps,libs,test}/**/*.ts\” — fix”,“test”: “jest”,“test:watch”: “jest — watch”,“test:cov”: “jest — coverage”,“test:debug”: “node — inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest — runInBand”,“test:e2e”: “jest — config ./test/jest-e2e.json”,“typeorm”: “node — require ts-node/register ./node_modules/typeorm/cli.js — f src/database.config.ts”},“dependencies”: {“@nestjs/common”: “⁶.10.14”,“@nestjs/core”: “⁶.10.14”,“@nestjs/platform-express”: “⁶.10.14”,“@nestjs/typeorm”: “⁷.1.3”,“mysql”: “².18.1”,“reflect-metadata”: “⁰.1.13”,“rimraf”: “³.0.0”,“rxjs”: “⁶.5.4”,“typeorm”: “⁰.2.25”},“devDependencies”: {“@nestjs/cli”: “⁶.13.2”,“@nestjs/schematics”: “⁶.8.1”,“@nestjs/testing”: “⁶.10.14”,“@types/express”: “⁴.17.2”,“@types/jest”: “25.1.2”,“@types/node”: “¹³.1.6”,“@types/supertest”: “².0.8”,“@typescript-eslint/eslint-plugin”: “².12.0”,“@typescript-eslint/parser”: “².12.0”,“eslint”: “⁶.7.2”,“eslint-config-prettier”: “⁶.7.0”,“eslint-plugin-import”: “².19.1”,“jest”: “²⁴.9.0”,“prettier”: “¹.18.2”,“supertest”: “⁴.0.2”,“ts-jest”: “25.2.0”,“ts-loader”: “⁶.2.1”,“ts-node”: “⁸.6.0”,“tsconfig-paths”: “³.9.0”,“typescript”: “³.7.4”},“jest”: {“moduleFileExtensions”: [“js”,“json”,“ts”],“rootDir”: “src”,“testRegex”: “.spec.ts$”,“transform”: {“^.+\\.(t|j)s$”: “ts-jest”},“coverageDirectory”: “../coverage”,“testEnvironment”: “node”}}
Setelah itu tambahkan database.config.ts
import { ConnectionOptions } from ‘typeorm’;// Check typeORM documentation for more information.const config: ConnectionOptions = {type: ‘postgres’,host: ‘localhost’,port: 5433,username: ‘postgres’,password: ‘******’,database: ‘nest_app’,entities: [__dirname + ‘/model/entity/**/*.entity{.ts,.js}’],// entities: [‘/inventory/src/entity/item.entity.ts’],// We are using migrations, synchronize should be set to false.// synchronize: false,// Run migrations automatically,// you can disable this if you prefer running migration// manually.migrationsRun: false,logging: true,// logger: ‘file’,// allow both start:prod and start:dev to use migrations// __dirname is either dist or src folder, meaning either// the compiled js in prod or the ts in devmigrations: [__dirname + ‘/model/migration/**/*{.ts,.js}’],cli: {migrationsDir: ‘src/model/migration/’,entitiesDir:’src/model/migration/’},};export = config;
Setelah semua ditambahkan, pada directory project akan menjadi seperti berikut:
Kita bisa mengecek apakah type orm sudah bekerja atau belum dengan menggunakan perintah berikut:
npm run typeorm migration:show
Terlihat belum ada migrasi database yang ada pada gambar di atas.
Type ORM dan project sudah bekerja. Sekarang saatnya membuat migrasi untuk create SQL. Pada nestJS mendukung generate dari code program model menjadi SQL create. Untuk langkah selanjutnya kita akan membuat model. Model adalah sebuah class yang merepresentasikan table pada database.
Sekarang kita akan membuat model user dan membuat skeleton directory model entity dan migration agar terbaca oleh type orm.
Skeletonnya adalah sebagai berikut:
Berikut adalah user.entity.ts.
import {PrimaryGeneratedColumn,Column,CreateDateColumn,UpdateDateColumn,Entity,BaseEntity,DeleteDateColumn,OneToMany,} from ‘typeorm’;@Entity()export class User {@PrimaryGeneratedColumn(‘uuid’)id: string;@Column({length: 200,type: ‘varchar’,nullable: true})name: string;@CreateDateColumn({type: ‘timestamp with time zone’,nullable: false})created_at: Date;@UpdateDateColumn({type: ‘timestamp with time zone’,nullable: false})updated_at: Date;@DeleteDateColumn({type: ‘timestamp with time zone’,nullable: false})deleted_at: Date;}
Setelah entity ditulis sekarang kita akan mencoba melakukan generate create SQL database. Dengan menggunakan perintah sebagai berikut:
npm run typeorm migration:generate — -n init_database
Jika, response berhasil akan terlihat seperti sebagai berikut:
Untuk directory project akan otomatis membuat file migration dibawah directory migration.
import {MigrationInterface, QueryRunner} from “typeorm”;export class initDatabase1599549391575 implements MigrationInterface {name = ‘initDatabase1599549391575’public async up(queryRunner: QueryRunner): Promise<void> {await queryRunner.query(`CREATE TABLE “user” (“id” uuid NOT NULL DEFAULT uuid_generate_v4(), “name” character varying(200), “created_at” TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), “updated_at” TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), “deleted_at” TIMESTAMP WITH TIME ZONE, CONSTRAINT “PK_cace4a159ff9f2512dd42373760” PRIMARY KEY (“id”))`);}public async down(queryRunner: QueryRunner): Promise<void> {await queryRunner.query(`DROP TABLE “user”`);}}
Penampakan project directory sekarang akan menjadi seperti ini:
Setelah migrati dibuat, selanjutnya kita akan melakukan eksekusi agar terbenti pysical table pada database. Gunakan perintah berikut:
npm run typeorm migration:run
Hasilnya akan keluar create table sebagai berikut:
Kita bisa melakukan cek migation yang telah dijalankan, dan terlihat seperti ini:
Sekarang kita akan mencoba membuat insert data ke database. Pertama kita akan membuat controller create user. Tetapi, sebelum itu kita akan menambahkan repo.module.ts dan repo.service.ts.
repo.module.ts
import { Global, Module } from “@nestjs/common”;import { TypeOrmModule } from “@nestjs/typeorm”;import { User } from “./entity/user.entity”;import RepoService from “./repo.service”;@Global()@Module({imports: [TypeOrmModule.forFeature([User,])],providers: [RepoService],exports: [RepoService]})export class RepoModule { }repo.service.tsimport { Injectable } from “@nestjs/common”;import { InjectRepository } from “@nestjs/typeorm”;import { Repository } from “typeorm”;import { User } from “./entity/user.entity”;@Injectable()class RepoService {/*** All Models are injected here* You can create a new Injected model here*/public constructor(@InjectRepository(User) public readonly userRepo: Repository<User>){}}export default RepoService;
Setelah ditambahkan service dan module, directory structure akan menjadi seperti berikut:
Lalu kita akan mencoba menambahkan create user pada app.controller.ts dan menambahkan type orm configuration pada app.module.ts. Berikut adalah app.module.ts:
import { Module } from ‘@nestjs/common’;import { AppController } from ‘./app.controller’;import { AppService } from ‘./app.service’;import { RepoModule } from ‘./model/repo.module’;import { TypeOrmModule } from ‘@nestjs/typeorm’;import * as databaseConfig from ‘./database.config’@Module({imports: [RepoModule,TypeOrmModule.forRoot(databaseConfig)],controllers: [AppController],providers: [AppService],})export class AppModule { }Berikut adalah perubahan pada app.controller.tsimport { Controller, Get, Query, Post, Body } from ‘@nestjs/common’;import { AppService } from ‘./app.service’;import { getConnection } from ‘typeorm’;import RepoService from ‘./model/repo.service’;@Controller()export class AppController {constructor(private readonly appService: AppService,private readonly repoService: RepoService) { }@Get()getHello(@Query(‘name’) name: string) {return {name: name}}@Get(‘/activeUser’)getActiveUser(@Query(‘name’) name: string) {var data = this.appService.getActiveUser(name)return data}@Post(‘/user’)async createUser(@Body(‘name’) name: string) {var user = this.repoService.userRepo.create({name: name})await this.repoService.userRepo.save(user)return user}}
Sekarang kita test menggunakan postman:
Dan pada console terminal akan terlihat seperti berikut:
Ini menandakan bahwa insert data dari rest api postman ke database sudah bisa dilakukan.
Sekarang kita akan mencoba mengaktifkan getActive user agar tersambung ke database. Pada app.service.ts akan kita ubah beberapa code agar kita dapat mengakses data pada database.
import { Injectable } from ‘@nestjs/common’;import RepoService from ‘./model/repo.service’;@Injectable()export class AppService {constructor(private readonly repoService: RepoService) {}async getActiveUser(name: string) {// database queryvar matchedData = await this.repoService.userRepo.find({where: {name: name}})return matchedData}}
Pada postman kita coba dengan melakukan cara sebagai berikut:
Hal tersebut menunjukkan bahwa sistem backend sudah siap dijalankan. Semoga tulisan ini bermanfaat dan sila mencoba.
Contributor: Didin