NestJS/GraphQLでObjectやInputの定義を自動化したいあなたへ
はじめに
NestJS/GraphQLで開発を進めていくうちに、ObjectやInputを毎回定義するのが大変で自動化したいなーと思っているときに、ちょうどいいライブラリを見つけたのでその紹介です。
実装(prisma-nestjs-graphql)
インストール
npm install --save-dev prisma-nestjs-graphql
schema.prismaに追記とコード生成
schema.prisma
に以下のコードを追記します。
generator nestgraphql {
provider = "node node_modules/prisma-nestjs-graphql"
output = "../src/@generated/prisma-nestjs-graphql"
}
生成コマンドを叩けば完了です!
npx prisma generate
なかみ
フォルダ構成
現在schema.prisma
にTeacher/Class/Studentを定義しているのですが、それぞれのモデルに対して一つずつフォルダが作成されました。
ファイル構成
Teacherフォルダの中身はこんな感じです。
生成されるファイルが多すぎてかなり文字が小さくなっちゃいました。
よく使うところで行くと、Teacher Object、Get arg、Create input、Update input、Delte inputが完備されています。
他にもCount ArgやUpsert inputなどもありとても便利そうです。
ファイル1例 (TeacherWhereInput)
また、TeacherWhereInput
を除いてみるとAND/OR/NOT検索までついてくる優れものです!
Date型はlte/rteでの検索も可能です。
import { Field } from '@nestjs/graphql';
import { InputType } from '@nestjs/graphql';
import { IntFilter } from '../prisma/int-filter.input';
import { StringFilter } from '../prisma/string-filter.input';
import { DateTimeFilter } from '../prisma/date-time-filter.input';
import { ClassRelationFilter } from '../class/class-relation-filter.input';
@InputType()
export class TeacherWhereInput {
@Field(() => [TeacherWhereInput], {nullable:true})
AND?: Array<TeacherWhereInput>;
@Field(() => [TeacherWhereInput], {nullable:true})
OR?: Array<TeacherWhereInput>;
@Field(() => [TeacherWhereInput], {nullable:true})
NOT?: Array<TeacherWhereInput>;
@Field(() => IntFilter, {nullable:true})
id?: IntFilter;
@Field(() => IntFilter, {nullable:true})
classId?: IntFilter;
@Field(() => StringFilter, {nullable:true})
name?: StringFilter;
@Field(() => DateTimeFilter, {nullable:true})
createdAt?: DateTimeFilter;
@Field(() => DateTimeFilter, {nullable:true})
updatedAt?: DateTimeFilter;
@Field(() => ClassRelationFilter, {nullable:true})
class?: ClassRelationFilter;
}
Extend
パスワードなど外に見せたくないカラムはどうするの?
schema.prisma
で@HideField()
デコレーションをつければ大丈夫です。
スラッシュ3つでprisma-nestjs-graphql
のコマンドとして認識されます。
/// @HideField()
password String
inputにvalidaterを付与したい
schema.prisma
にバリデーション情報を付与します。
fields_Validator_from= "class-validator"
は、Validatorはclass-validator
からインポートされたメソッドだよ。という意味です。
decorateの部分は、数字でグルーピングされていて1
の例でいくと、
CreateOne*Args
クラスのdata
フィールドにclass-validator
のメソッドであるValidateNested
デコレーションを追加するよという意味になります。
(ValidateNested
はネストされているinputに対してもバリデーションを有効にしてくれるデコレーションです。)
generator nestgraphql {
provider = "node node_modules/prisma-nestjs-graphql"
output = "../src/@generated/prisma-nestjs-graphql"
fields_Validator_from = "class-validator"
fields_Validator_input = true
decorate_1_type = "CreateOne*Args"
decorate_1_field = data
decorate_1_name = ValidateNested
decorate_1_from = "class-validator"
decorate_1_arguments = "[]"
decorate_2_type = "CreateMany*Args"
decorate_2_field = data
decorate_2_name = ValidateNested
decorate_2_from = "class-validator"
decorate_2_arguments = "[]"
decorate_3_type = "UpdateOne*Args"
decorate_3_field = data
decorate_3_name = ValidateNested
decorate_3_from = "class-validator"
decorate_3_arguments = "[]"
decorate_4_type = "UpdateMany*Args"
decorate_4_field = data
decorate_4_name = ValidateNested
decorate_4_from = "class-validator"
decorate_4_arguments = "[]"
}
このルール付けの後に、schema.prisma
に定義されているモデルにMaxLengthなどのデコレーションを追加していけば完了です!
model Teacher {
id Int @id @default(autoincrement())
classId Int @unique
/// @Validator.IsNotEmpty()
/// @Validator.MaxLength(255)
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
class Class @relation("teacherToClass", fields: [classId], references: [id])
@@map("teachers")
}
抜粋ですがこのように生成されます。
@InputType()
export class TeacherCreateInput {
@Field(() => String, {nullable:false})
@Validator.IsNotEmpty()
@Validator.MaxLength(255)
name!: string;
@Field(() => Date, {nullable:true})
createdAt?: Date | string;
@Field(() => Date, {nullable:true})
updatedAt?: Date | string;
@Field(() => ClassCreateNestedOneWithoutTeacherInput, {nullable:false})
class!: ClassCreateNestedOneWithoutTeacherInput;
}
@ArgsType()
export class CreateOneTeacherArgs {
@Field(() => TeacherCreateInput, {nullable:false})
@ValidateNested()
data!: TeacherCreateInput;
}
まとめ
実装はほとんどないのに、様々なユースケースに対応できるファイルがたくさん自動生成とても便利そうでした。
ただ、これいつ使うんだ...みたいな機能もあったのでtoo mach感は少しあります...
公式サイト見た感じ他にもいろんな機能ありそうなので使い倒していきたいです。
参考サイト
公式github
Discussion
参考になる記事ありがとうございます!
お尋ねしたいのですがnull許容項目に対してValidationを実行することは可能でしょうか?
例えば以下のようにValidatorを設定してageをnullで渡した場合、@Validator.IsInt()と@Validator.Min(0)に引っかかりエラーとなってしまいました。
nullの場合はバリデーションを行わず、値が入っていた場合のみバリデーションを実行するような書き方をご存知でしたら教えて頂きたいです。
コメントありがとうございます!
その部分は
prisma-nestjs-graphql
というよりも、class-validater
の仕事なのでそちらで調べたほうがいいかもしれません...僕が試してみた感じ、↓のデコレーションをつけたらうまくいきました!
なるほど、class-validaterで制御するものでしたか。
教えて頂きありがとうございます!