Skip to content

Cheatsheet NestJS ​

Halaman ini merangkum command, decorator, dan pola kode yang paling sering muncul di materi. Gunakan sebagai referensi cepat ketika Anda sedang praktik.

Command Utama ​

KebutuhanCommand
Membuat proyek NestJSnest new nestjs-task-management
Membuat modulenest g module tasks
Membuat controller tanpa specnest g controller tasks --no-spec
Membuat service tanpa specnest g service tasks --no-spec
Menjalankan dev serveryarn start:dev
Menjalankan testyarn test
Menjalankan test watch modeyarn test --watch
Menjalankan PostgreSQL via Dockerdocker run --name postgres-nest -p 5432:5432 -e POSTGRES_PASSWORD=postgres -d postgres

Decorator NestJS yang Sering Muncul ​

DecoratorDipakai diFungsi
@Module()Class moduleMengelompokkan controller, provider, import, dan export
@Controller('tasks')Class controllerMenentukan route dasar controller
@Injectable()Service/providerMenjadikan class bisa di-inject oleh NestJS
@Get()Method controllerHandler untuk HTTP GET
@Post()Method controllerHandler untuk HTTP POST
@Patch()Method controllerHandler untuk partial update
@Delete()Method controllerHandler untuk delete
@Body()Parameter handlerMengambil request body
@Param()Parameter handlerMengambil path parameter
@Query()Parameter handlerMengambil query string
@UseGuards()Controller atau handlerMelindungi route dengan guard

Decorator Validasi ​

DecoratorFungsi
@IsNotEmpty()Nilai wajib ada dan tidak kosong
@IsEnum(TaskStatus)Nilai harus termasuk enum tertentu
@IsString()Nilai harus string
@IsOptional()Field boleh tidak dikirim, tetapi tetap divalidasi jika ada
@MinLength()Panjang minimal string
@MaxLength()Panjang maksimal string
@Matches()Validasi string menggunakan regular expression

Pola Layering ​

text
Client Request
  -> Controller: menerima HTTP request dan mengambil param/body/query
  -> DTO/Pipe: memvalidasi bentuk input
  -> Service: menjalankan business logic
  -> Repository: berinteraksi dengan database
  -> Entity: representasi table database
  -> Response: dikembalikan oleh NestJS sebagai JSON

Pola Response Error ​

KondisiExceptionStatus
Input tidak validBadRequestException atau ValidationPipe400
Data tidak ditemukanNotFoundException404
Credential salahUnauthorizedException401
Username sudah dipakaiConflictException409
Error tidak terdugaInternalServerErrorException500

Formula Praktis ​

typescript
constructor(private readonly tasksService: TasksService) {}

Gunakan constructor injection untuk dependency. Jangan membuat instance service manual dengan new, karena itu melewati dependency injection container NestJS.

typescript
@Post()
createTask(@Body() createTaskDto: CreateTaskDto) {
  return this.tasksService.createTask(createTaskDto)
}

Controller cukup menerima request dan menyerahkan pekerjaan ke service. Detail validasi, persistence, dan business rules sebaiknya tidak menumpuk di controller.

Decorator Authentication dan Authorization ​

Decorator / ClassDipakai diFungsi
@UseGuards(AuthGuard())Controller / handlerMelindungi route agar hanya bisa diakses dengan JWT valid
@GetUser()Parameter handlerDecorator custom untuk mengambil user dari request (dari JWT)
@InjectRepository()Constructor serviceInject TypeORM repository ke dalam service
@CreateDateColumn()Entity propertyOtomatis mengisi tanggal saat baris dibuat
@OneToMany()Entity propertyRelasi satu entitas memiliki banyak entitas lain
@ManyToOne()Entity propertyRelasi banyak entitas dimiliki satu entitas lain
@Exclude()Entity propertyMenyembunyikan field dari serialisasi JSON (class-transformer)

Logging — Referensi Cepat ​

typescript
// Instansiasi logger (dalam class)
private logger = new Logger('NamaClass')

// Level-level log
this.logger.log('Pesan info umum')
this.logger.verbose('Detail aktivitas rutin')
this.logger.debug('Info debug untuk developer')
this.logger.warn('Peringatan non-fatal')
this.logger.error('Error fatal', error.stack)  // selalu sertakan stack trace

// Pola try/catch yang benar di repository
try {
  return await query.getMany()
} catch (error) {
  this.logger.error('Gagal mengambil data', error.stack)
  throw new InternalServerErrorException()
}

Configuration — Referensi Cepat ​

typescript
// Mendaftarkan ConfigModule (app.module.ts)
ConfigModule.forRoot({
  envFilePath: `.env.stage.${process.env.STAGE}`,
  validationSchema: configValidationSchema,  // opsional tapi direkomendasikan
})

// Membaca nilai konfigurasi (dalam constructor)
constructor(private configService: ConfigService) {}
const dbHost = this.configService.get<string>('DB_HOST')

// Inisialisasi modul yang bergantung pada ConfigService
TypeOrmModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: async (config: ConfigService) => ({
    type: 'postgres',
    host: config.get('DB_HOST'),
    // ...
  }),
})

TypeORM — Relasi dan Query Builder ​

typescript
// Relasi one-to-many / many-to-one
@OneToMany((_type) => Task, (task) => task.user, { eager: false })
tasks: Task[]

@ManyToOne((_type) => User, (user) => user.tasks, { eager: true })
user: User

// Query builder dengan filter dan pembatasan user
const query = this.createQueryBuilder('task')
query.where({ user })                               // filter per user
query.andWhere('task.status = :status', { status }) // filter tambahan
query.andWhere(                                     // selalu bungkus OR
  '(task.title LIKE :search OR task.description LIKE :search)',
  { search: `%${search}%` },
)
return query.getMany()

Unit Testing — Referensi Cepat ​

typescript
// Struktur dasar test file
describe('TasksService', () => {
  let service: TasksService
  let repository

  const mockRepo = () => ({ findOne: jest.fn(), save: jest.fn(), delete: jest.fn() })

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [
        TasksService,
        { provide: TasksRepository, useFactory: mockRepo },
      ],
    }).compile()

    service = module.get<TasksService>(TasksService)
    repository = module.get<TasksRepository>(TasksRepository)
  })

  it('should return a task when found', async () => {
    repository.findOne.mockResolvedValue(mockTask)
    const result = await service.getTaskById('id', mockUser)
    expect(result).toEqual(mockTask)
  })

  it('should throw NotFoundException when not found', async () => {
    repository.findOne.mockResolvedValue(null)
    await expect(service.getTaskById('id', mockUser)).rejects.toThrow(NotFoundException)
  })
})

File .env yang Wajib Ada ​

bash
# .env.stage.dev
STAGE=dev
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_DATABASE=task-management
JWT_SECRET=supersecretkey

# .gitignore (pastikan ada baris ini)
.env.stage.prod