Retseptlar3 min read

CRUD generator (faqat TypeScript)

Loyiha davomida yangi imkoniyatlar qo'shayotganda ilovamizga yangi resurslarni qo'shishimizga to'g'ri keladi. Bu resurslar odatda har safar yangi resurs aniqlaganimizda takrorlanad

Loyiha davomida yangi imkoniyatlar qo'shayotganda ilovamizga yangi resurslarni qo'shishimizga to'g'ri keladi. Bu resurslar odatda har safar yangi resurs aniqlaganimizda takrorlanadigan ko'p amallarni talab qiladi.

Kirish

Keling, User va Product entitetlari uchun CRUD endpointlari taqdim etishimiz kerak bo'lgan real holatni tasavvur qilaylik. Eng yaxshi amaliyotlarga ko'ra, har bir entitet uchun quyidagi bir nechta amallarni bajarishimiz kerak bo'ladi:

  • Kodni tartibli saqlash va aniq chegaralar o'rnatish (bog'liq komponentlarni guruhlash) uchun modul yaratish (nest g mo)
  • CRUD marshrutlarini (yoki GraphQL ilovalari uchun query/mutatsiyalarni) belgilash uchun controller yaratish (nest g co)
  • Biznes mantiqni amalga oshirish va ajratish uchun servis yaratish (nest g s)
  • Resurs ma'lumotlar tuzilmasini ifodalash uchun entitet klass/interfeys yaratish
  • Ma'lumotlar tarmoq orqali qanday yuborilishini belgilash uchun Data Transfer Object larni (yoki GraphQL ilovalari uchun inputlarni) yaratish

Bu juda ko'p qadamlar!

Bu takroriy jarayonni tezlashtirish uchun Nest CLI barcha boilerplate kodni avtomatik generatsiya qiluvchi generator (sxema) taqdim etadi, bu bizni bularni qo'lda bajarishdan qutqaradi va ishlab chiquvchi tajribasini ancha soddalashtiradi.

Note

Sxema HTTP controllerlari, Microservice controllerlari, GraphQL resolverlarga (code first va schema first) hamda WebSocket Gatewaylarga kod generatsiya qilishni qo'llab-quvvatlaydi.

Yangi resurs yaratish

Yangi resurs yaratish uchun loyihangiz ildiz katalogida quyidagi buyruqni bajaring:

Terminal
1$ nest g resource

nest g resource buyrug'i NestJS ning barcha asosiy qismlarini (modul, servis, controller klasslari) emas, balki entitet klassi, DTO klasslari va test (.spec) fayllarini ham generatsiya qiladi.

Quyida generatsiya qilingan controller faylini (REST API uchun) ko'rishingiz mumkin:

TypeScript
1@Controller('users')
2export class UsersController {
3  constructor(private readonly usersService: UsersService) {}
4
5  @Post()
6  create(@Body() createUserDto: CreateUserDto) {
7    return this.usersService.create(createUserDto);
8  }
9
10  @Get()
11  findAll() {
12    return this.usersService.findAll();
13  }
14
15  @Get(':id')
16  findOne(@Param('id') id: string) {
17    return this.usersService.findOne(+id);
18  }
19
20  @Patch(':id')
21  update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
22    return this.usersService.update(+id, updateUserDto);
23  }
24
25  @Delete(':id')
26  remove(@Param('id') id: string) {
27    return this.usersService.remove(+id);
28  }
29}

Shuningdek, u barcha CRUD endpointlar uchun plaseholderlarni (REST API lar uchun marshrutlar, GraphQL uchun query va mutatsiyalar, Microservice va WebSocket Gatewaylar uchun xabar obunalari) avtomatik yaratadi.

Note

Generatsiya qilingan servis klasslari ma'lum bir ORM (yoki ma'lumotlar manbasi) ga bog'lanmagan. Bu generatorni har qanday loyiha ehtiyojlariga yetarlicha moslashuvchan qiladi. Standart holatda barcha metodlar plaseholderlarga ega bo'ladi, shuning uchun ularni loyihangizga xos ma'lumotlar manbalariga moslab to'ldirishingiz mumkin.

Xuddi shunday, GraphQL ilovasi uchun resolverlar yaratmoqchi bo'lsangiz, transport qatlami sifatida GraphQL (code first) (yoki GraphQL (schema first)) ni tanlang.

Bu holda NestJS REST API controlleri o'rniga resolver klassini generatsiya qiladi:

Terminal
1$ nest g resource users
2
3> ? What transport layer do you use? GraphQL (code first)
4> ? Would you like to generate CRUD entry points? Yes
5> CREATE src/users/users.module.ts (224 bytes)
6> CREATE src/users/users.resolver.spec.ts (525 bytes)
7> CREATE src/users/users.resolver.ts (1109 bytes)
8> CREATE src/users/users.service.spec.ts (453 bytes)
9> CREATE src/users/users.service.ts (625 bytes)
10> CREATE src/users/dto/create-user.input.ts (195 bytes)
11> CREATE src/users/dto/update-user.input.ts (281 bytes)
12> CREATE src/users/entities/user.entity.ts (187 bytes)
13> UPDATE src/app.module.ts (312 bytes)
Hint

Test fayllar generatsiya qilinmasligi uchun --no-spec flagini berishingiz mumkin: nest g resource users --no-spec

Quyida ko'rib turganingizdek, nafaqat barcha boilerplate mutatsiya va querylar yaratilgan, balki hammasi bir-biriga bog'langan: UsersService, User entiteti va DTOlardan foydalanilmoqda.

TypeScript
1import { Resolver, Query, Mutation, Args, Int } from '@nestjs/graphql';
2import { UsersService } from './users.service';
3import { User } from './entities/user.entity';
4import { CreateUserInput } from './dto/create-user.input';
5import { UpdateUserInput } from './dto/update-user.input';
6
7@Resolver(() => User)
8export class UsersResolver {
9  constructor(private readonly usersService: UsersService) {}
10
11  @Mutation(() => User)
12  createUser(@Args('createUserInput') createUserInput: CreateUserInput) {
13    return this.usersService.create(createUserInput);
14  }
15
16  @Query(() => [User], { name: 'users' })
17  findAll() {
18    return this.usersService.findAll();
19  }
20
21  @Query(() => User, { name: 'user' })
22  findOne(@Args('id', { type: () => Int }) id: number) {
23    return this.usersService.findOne(id);
24  }
25
26  @Mutation(() => User)
27  updateUser(@Args('updateUserInput') updateUserInput: UpdateUserInput) {
28    return this.usersService.update(updateUserInput.id, updateUserInput);
29  }
30
31  @Mutation(() => User)
32  removeUser(@Args('id', { type: () => Int }) id: number) {
33    return this.usersService.remove(id);
34  }
35}