Node, Nest, Deno/🦁 Nest - Series

Nest + graphql (3) : Mutation, @ArgsType 과 Validation

DarrenKwonDev 2020. 11. 21. 01:30
 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

 

@Mutation

@Query를 통해서 쿼리를 작성하였듯 @Mutation을 @nestjs/graphql에서 가져와 @Resolver 안에 정의해서 사용할 수 있습니다. 

 

The official Apollo documentation uses an upvotePost() mutation example. This mutation implements a method to increase a post's votes property value. To create an equivalent mutation in Nest, we'll make use of the @Mutation() decorator.

 

@Mutation(returns => Post)
async upvotePost(@Args({ name: 'postId', type: () => Int }) postId: number) {
  return this.postsService.upvoteById({ id: postId });
}

 

 

@ArgsType

다음과 같이 간단한 Mutation을 resolver 안에 정의했다고 가정해봅시다.

import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { Restaurant } from './entities/restaurant.entity'; // @ObjectType임

@Resolver((of) => Restaurant)
export class RestaurantResolver {
  @Mutation(() => Boolean)
  createRestaurant(
    @Args('name') name: string,
    @Args('address') address: string,
    @Args('ownersName') ownersName: string,
    @Args('isVegan') isVegan: boolean,
  ): boolean {
    console.log(name, isVegan, address, ownersName);
    return true;
  }
}

 

 

지금도 작동하긴 하지만 어딘가 아쉽습니다. @Args를 반복해서 넣는 부분 때문이죠 

이런 부분은 @ArgsType을 이용해서 대체할 수 있습니다. @InputType를 이용하는 방식은 직관적이지 않아 생략합니다.

import { ArgsType, Field } from '@nestjs/graphql';

@ArgsType()
export class CreateRestaurantDto {
  @Field(() => String)
  name: string;

  @Field(() => String)
  address: string;

  @Field(() => String)
  ownersName: string;

  @Field(() => Boolean)
  isVegan?: boolean;
}
@Mutation(() => Boolean)
createRestaurant(@Args() createRestaurantDto: CreateRestaurantDto): boolean {
  console.log(createRestaurantDto);
  return true;
}

 

 

추가적으로 @ArgsType에 Validation을 해보겠습니다. 당연히 class니까 class-validation, class-transformer 패키지를 이용할 수 있겠죠

 

import { ArgsType, Field } from '@nestjs/graphql';
import { IsBoolean, IsString, Length } from 'class-validator';

@ArgsType()
export class CreateRestaurantDto {
  @Field(() => String)
  @IsString()
  @Length(5, 10)
  name: string;

  @Field(() => String)
  @IsString()
  address: string;

  @Field(() => String)
  @IsString()
  ownersName: string;

  @Field(() => Boolean)
  @IsBoolean()
  isVegan?: boolean;
}

 

class-validator를 설치했다면 검증할 수 있도록 listen 전에 GlobalPipes를 이용하여 ValidationPipe를 전역으로 사용하도로 설정해줍시다.

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

const PORT = 4000;

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(PORT);
  console.log(`server on : http://localhost:${PORT}`);
}

bootstrap();