🙆
NestJsの環境構築をしてPlaygroundを起動するまで
Nest CLIでプロジェクト作成
npm i -g @nestjs/cl
nest n nestjs_sample
パッケージマネージャーは今回はnpmを選択する。
サンプルの削除
- サンプルファイルの削除
rm ./src/app.controller.ts ./src/app.controller.spec.ts ./src/app.service.ts
- controllers,providersから削除したファイルの設定を削除
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: `.env.${process.env.NODE_ENV}`,
}),
],
controllers: [],
providers: [],
})
export class AppModule { }
GraphQLの設定
- GraphQL関連のライブラリのインストール
npm i graphql @nestjs/graphql @nestjs/apollo class-validator
- Apollo Serverの設定+スキーマファイルを自動生成するように設定
app.module.ts
import { ApolloDriverConfig, ApolloDriver } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';
@Module({
imports: [
+ GraphQLModule.forRoot<ApolloDriverConfig>({
+ driver: ApolloDriver,
+ autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
+ sortSchema: true,
+ }),
],
controllers: [],
providers: [],
})
export class AppModule { }
スキーマのmoduleを作成する
今回はschema配下に各moduleを追加していく方針にする。そのため、まずschema.module.tsを作成する。
- schema.module.tsを作成する。
nest g module schema
schema.module.tsが作成されると、自動でapp.module.tsに設定を追加してくれる。
app.module.ts
import { ApolloDriverConfig, ApolloDriver } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';
import { SchemaModule } from './schema/schema.module';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
sortSchema: true,
}),
+ SchemaModule,
],
controllers: [],
providers: [],
})
export class AppModule {}
DTOを作成する
以下の構成でDTOを作成する。
src
└── schema
└── users
└── dto
├── args
│ ├── user.args.ts
│ └── users.args.ts
├── input
│ ├── createUser.input.ts
│ └── deleteUser.input.ts
└── models
└── user.model.ts
- model:返却値
- args:Queryの場合の引数
- input:Mutationsの場合の引数
model
mkdir -p ./src/schema/users/dto/models/
touch ./src/schema/users/dto/models/user.model.ts
user.model.ts
import { Field, Int, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class User {
@Field(() => Int)
id: number;
@Field({ nullable: true })
firstName?: string;
@Field({ nullable: true })
lastName?: string;
}
args
mkdir -p ./src/schema/users/dto/args/
touch ./src/schema/users/dto/args/user.args.ts
touch ./src/schema/users/dto/args/users.args.ts
user.args.ts
import { ArgsType, Field } from '@nestjs/graphql';
import { IsNumber } from 'class-validator';
@ArgsType()
export class UserArgs {
@Field({ nullable: true, description: 'ID' })
@IsNumber()
id: number;
}
users.args.ts
import { ArgsType, Field } from '@nestjs/graphql';
import { IsNotEmpty, MaxLength } from 'class-validator';
@ArgsType()
export class UsersArgs {
@Field({ nullable: true, description: '名' })
@IsNotEmpty()
@MaxLength(30)
firstName?: string;
@Field({ nullable: true, description: '姓' })
@IsNotEmpty()
@MaxLength(10)
lastName?: string;
}
input
mkdir -p ./src/schema/users/dto/input/
touch ./src/schema/users/dto/input/createUser.input.ts
touch ./src/schema/users/dto/input/deleteUser.input.ts
createUser.input.ts
import { Field, InputType } from '@nestjs/graphql';
import { IsNotEmpty, MaxLength } from 'class-validator';
@InputType()
export class CreateUserInput {
@Field({ nullable: false, description: '名' })
@IsNotEmpty()
@MaxLength(30)
firstName?: string;
@Field({ nullable: false, description: '姓' })
@IsNotEmpty()
@MaxLength(10)
lastName?: string;
}
deleteUser.input.ts
import { Field, InputType } from '@nestjs/graphql';
import { IsNumber } from 'class-validator';
@InputType()
export class DeleteUserInput {
@Field({ nullable: false, description: 'ID' })
@IsNumber()
id: number;
}
サンプルのmodule,service,resolverを作成する
nest g module schema/users
nest g service schema/users
nest g resolver schema/users
コマンドを実行すると以下のようにファイルが作成される。
src
└── schema
└── users
├── users.module.ts
├── users.resolver.spec.ts
├── users.resolver.ts
├── users.service.spec.ts
└── users.service.ts
~spec.tsはテストクラスなので今回はノータッチ。
また、schema.module.tsに自動でapp.module.tsに設定を追加してくれる。
schema.module.tsが作成されると、自動でschema.module.tsに設定を追加してくれる。
schema.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';
@Module({
+ imports: [UsersModule]
})
export class SchemaModule {}
resolver
users.resolver.ts
import {
Args,
Mutation,
Query,
Resolver,
} from '@nestjs/graphql';
import { UserArgs } from './dto/args/user.args';
import { UsersArgs } from './dto/args/users.args';
import { CreateUserInput } from './dto/input/createUser.input';
import { DeleteUserInput } from './dto/input/deleteUser.input';
import { User } from './dto/models/user.model';
import { UsersService } from './users.service';
@Resolver()
export class UsersResolver {
constructor(private usersService: UsersService) {}
@Query(() => User, { description: 'ユーザーを取得します。' })
async user(@Args() userArgs: UserArgs) {
const { id } = userArgs;
return this.usersService.findOneById(id);
}
@Query(() => [User], { description: 'ユーザー一覧を取得します。' })
async users(@Args() usersArgs: UsersArgs) {
return this.usersService.findAll(usersArgs);
}
@Mutation(() => User, { description: 'ユーザーを登録します。' })
async createUser(@Args("input") createUserInput: CreateUserInput) {
return this.usersService.create(createUserInput);
}
@Mutation(() => Boolean, { description: 'ユーザーを削除します。' })
async deleteUser(@Args("input") deleteUserInput: DeleteUserInput) {
const { id } = deleteUserInput;
return this.usersService.delete(id);
}
}
service
サンプルなので返却値は固定。
users.service.ts
import { Injectable } from '@nestjs/common';
import { UsersArgs } from './dto/args/users.args';
import { CreateUserInput } from './dto/input/createUser.input';
import { User } from './dto/models/user.model';
const user: User = {
id: 1,
firstName: "太郎",
lastName: "山田"
}
@Injectable()
export class UsersService {
async create(input: CreateUserInput): Promise<User> {
return {
id: 1,
firstName: input.firstName,
lastName: input.lastName
};
}
async findOneById(id: number): Promise<User> {
return user;
}
async findAll(userArgs: UsersArgs): Promise<User[]> {
return [user] as User[];
}
async delete(id: number): Promise<boolean> {
return true;
}
}
GraphQL Playgroundを起動する
package.jsonのscriptsを確認すると、build
やlint
などのスクリプトが並んでいる。
package.json
{
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
}
このうち、start~
が起動のスクリプトなのでそちらを使用する。今回はstart:dev
を使用する。
npm start start:dev
上記のコマンドを実行するとGraphQL Playgroundが立ち上がるので以下のURLにアクセスする。
左ペインでクエリを実行すると、右ペインに実行結果が表示される。
また、schemaファイルの自動生成の設定がされているので、起動時にschema.gqlが作成される。
query,mutationを実行する
今回はuser,users,createUser,deleteUserの4つがあるので、以下のように実行すると、それぞれ実行結果が得られる。
user
query {
user(id:1) {
id
firstName
lastName
}
}
users
query {
users {
id
firstName
lastName
}
}
createUser
mutation {
createUser(input: {
firstName: "太郎",
lastName: "山田"
}) {
firstName
lastName
}
}
deleteUser
mutation {
deleteUser(input: {
id: 1
})
}
Discussion