✅:Entity가 DB Table과 GraphQLType, DTO를 모두 만들어낼 수 있도록 하는 방법에 대해서
- base type을 바탕으로 다른 버전들을 만들 수 있게 해준다.
- partial type - base class를 가져다가 모든 field가 required가 아닌 class를 만들어준다.
- pick type - input type에서 몇가지 특정 property를 선택해서 새로운 class를 만들어준다.
- omit type - base class에서 class를 만드는데 몇몇 field를 제외하고 만든다.
- intersection Type - 두 input을 합쳐주는 역할을 한다.
- Parent type과 child type이 다른 경우
옵션 1번. entity 파일에 @InputType({ isAbstract: true }) 추가하기
옵션 2번. Mapped type()에 두번 째 인자로 InputType을 전달하기
1. 옵션 1번
dto/create-restaurant.dto.ts
import { ArgsType, Field, InputType, OmitType } from '@nestjs/graphql'; import { Restaurant } from 'src/restaurants/entities/restaurant.entity'; @InputType() export class CreateRestaurantDto extends OmitType( Restaurant, ['id'], InputType, // Restaurant에 있는 ObjectType이므로 결과로 나오는 class도 ObjectType 되기 때문에 InputType을 적어준다. ) { }
2. 옵션 2번
- isAbstract란 어떤것으로 확장한다는 것을 의미,
따라서 스키마에 해당 InputType이 포함되지 않게된다.entities/restaurant.entity.ts
import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { IsBoolean, IsOptional, IsString, Length } from 'class-validator'; import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from 'typeorm'; @InputType({ isAbstract: true }) @ObjectType() @Entity() export class Restaurant { @PrimaryGeneratedColumn() @Field((type) => Number) id: number; @Field((type) => String) @Column() @IsString() @Length(5) name: string; @Field((type) => Boolean, { defaultValue: true }) @Column() @IsBoolean() @IsOptional() isVegan?: boolean; @Field((type) => String, { defaultValue: '강남' }) @Column() @IsString() @Length(5) @IsOptional() // 해당 필드를 보내거나 보내지 않아도 된다는 것을 의미 address: string; }
FiedOptions) defaultValue와 nullable 차이
- defaultValue의 값을 설정하면 DB에 특정 필드의 값의 기본 값을 넣을 수 있게된다.
- nullable은 nullable인지 아닌지만을 나타내므로 nullable을 true를 하고 데이터를 넣지 않으면 dto에 내용이 안들간다.
- update에는 id가 필요한데 하나의 DTO로 전달하는 방식에 대해서
- UpdateRestaurantInputType을 만든다.
- PartialType()을 extends하였으며 내부에 CreateRestaurantDto을 전달한다.- UpdateRestaurantDto를 만든다
- Field에 리턴값으로 생성한 UpdateRestaurantInputType을 넣어준다.
- data: UpdateRestaurantInputType을 넣어준다.
upate-restaurant.dto
import { ArgsType, Field, InputType, PartialType } from '@nestjs/graphql'; import { CreateRestaurantDto } from './create-restaurant.dto'; @InputType() export class UpdateRestaurantInputType extends PartialType( CreateRestaurantDto, ) {} @InputType() export class UpdateRestaurantDto { @Field((type) => Number) id: number; @Field((type) => UpdateRestaurantInputType) data: UpdateRestaurantInputType; }
주의) InputType VS ArgsType
- InputType의 데코레이터를 넣으면 Args() 내부에 무조건 인자를 전달해야하며
- ArgsType의 데로레이터는 Args() 내부에 전달하지 않아도 된다.
- restaurants repository에 update method를 사용하여 업데이트 시켜준다.
- update()에 인자로 업데이트 하고 싶은 entity의 field(Ex>id), 업데이트 하고 싶은 내용을 가진 object를 넣어준다.import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { CreateRestaurantDto } from 'src/dtos/create-restaurant.dto'; import { UpdateRestaurantDto } from 'src/dtos/update-restaurant.dto'; import { In, Repository } from 'typeorm'; import { Restaurant } from './entities/restaurant.entity'; @Injectable() export class RestaurantService { constructor( @InjectRepository(Restaurant) private readonly restaurants: Repository<Restaurant>, ) {} updateRestaurant({ id, data }: UpdateRestaurantDto) { return this.restaurants.update(id, { ...data }); } }
- restaurantService에서 만든 updateRestaurant()에 생성했던 updateRestaurantDto를 넣어준다.
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; import { create } from 'domain'; import { CreateRestaurantDto } from 'src/dtos/create-restaurant.dto'; import { UpdateRestaurantDto } from 'src/dtos/update-restaurant.dto'; import { Restaurant } from './entities/restaurant.entity'; import { RestaurantService } from './restaurants.service'; @Resolver((of) => Restaurant) export class RestaurantsResolver { constructor(private readonly restaurantService: RestaurantService) {} @Mutation((returns) => Boolean) // resolver mutation에 어떤 레스토랑을 수정할 지 알려주기 위해 id를 보내야함 async updateRestaurant( @Args('data') updateRestaurantDto: UpdateRestaurantDto, ): Promise<boolean> { try { await this.restaurantService.updateRestaurant(updateRestaurantDto); return true; } catch (error) { return false; } } }
graphql, db, validation을 위해 3번씩 테스트하는 것에 익숙해지자
- 니꼴라스 쌤 우버이츠 강의 중