NestJSでGraphQLを試そうと思ったらつまった件

# NestJSでGraphQLを試そうと思ったらつまった件

GraphQLをためそうと思いとりあえずtodo app作ろうと思ったらつまったので備忘録

## tl;dr

1. @nestjs/graphql,graphql-tools,graphqlをいれて
2. tsconfig.jsonにとりあえず "skipLibCheck": true をいれて
3. apollo-server-expressをいれて
4. 最低でも一つのschemaかく

で動きます。

下に流れとファイルを書いていきます。

### 目次

1. NestJSのアプリケーション作成
2. GraphQLの依存関係をinstallしていきます

### 1. NestJSのアプリケーションを作成

NestJSのcliを利用していくので、[URL](https://docs.nestjs.com/cli/overview#installation)を参考にinstallしておくと便利です。

```terminal
$ nest new nest-graphql
$ cd nest-graphql
$ npm run start
```

[localhost:3000](http://localhost:3000/)に以下のように表示されます。

![localhost_3000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/9e01cc0c-6186-278e-019d-5e3d3324099b.png)


## 2. GraphQLの依存関係をinstallしていきます

[公式ドキュメント](https://docs.nestjs.com/graphql/quick-start)に記載があるように、依存関係を追加していき、app.module.tsを変更していきます。

```terminal
$ npm i --save @nestjs/graphql graphql-tools graphql
```

GraphQL Moduleを追加していきます。

```src/app.module.ts(旧)
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
```

```src/app.module.ts(新)
import { Module } from '@nestjs/common';
//ここから追記
import { GraphQLModule } from '@nestjs/graphql';
//ここまで追記

@Module({
  imports: [
    //ここから追記
    GraphQLModule.forRoot({
      debug: true,
      playground: true,
    }),
　　//ここまで追記
  ],
})
export class AppModule {}
```

記載が完了したところで、serverを起動していきます。(Errorの一つ目がでます)

```terminal
$ npm run start
node_modules/apollo-server-core/dist/ApolloServer.d.ts:5:8 - error TS1259: Module '"/nestjs-graphql/node_modules/@types/ws/index"' can only be default-imported using the 'esModuleInterop' flag

5 import WebSocket from 'ws';
         ~~~~~~~~~

  node_modules/@types/ws/index.d.ts:270:1
    270 export = WebSocket;
        ~~~~~~~~~~~~~~~~~~~
    This module is declared with using 'export =', and can only be used with a default import when using the 'esModuleInterop' flag.

Found 1 error(s).

```

Errorを確認するとtype scriptのdefinitionsがおかしいとあります。
[GitHub issue](https://github.com/nestjs/graphql/issues/854)にもあがっているようにtsconfig.jsonを修正して対応します。


```tsconfig.json(旧)
{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true
  },
  "exclude": ["node_modules", "dist"]
}

```

```tsconfig.json(新)
{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    //ここから追記
    "skipLibCheck": true
　　//ここまで追記
  },
  "exclude": ["node_modules", "dist"]
}

```

表示されたErrorは修正したので、serverを起動します(また、エラーがはかれます。)

```terminal
$ npm run start
 [Nest] 22047   - 2020-05-26 12:15:28 AM   [PackageLoader] The "apollo-server-express" package is missing. Please, make sure to install this library ($ npm install apollo-server-express) to take advantage of GraphQLModule. +10ms
```

apollo-server-expressをinstallしなさいと表示されるので、表示通りapollo-server-expressをinstallします。(こんにちはまた、エラー)

```terminal
$ npm install apollo-server-express
$ npm run start
UnhandledPromiseRejectionWarning: Error: Apollo Server requires either an existing schema, modules or typeDefs
```

schema, modules or typeDefsが必要とのことなので、app.module.tsの追記ととりあえずtodo.graphqlを追加します。

```src/app.module.ts
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';

@Module({
  imports: [
    GraphQLModule.forRoot({
      debug: false,
      playground: true,
      typePaths: ['./**/*.graphql'],
      definitions: {
        path: join(process.cwd(), 'src/graphql.ts'),
        outputAs: 'class',
      },
    }),
  ],
})
export class AppModule {}
```

次に、todo.graphqlを追加します。(これはお好きに変えてください)

```
$ touch src/todo.graphql
```

```src/todo.graphql
type Query {
  getTodos: [Todo]
  todo(id: ID!): Todo
}

type Todo {
  title: String
  id: String
  description: String
}
```

最後にちゃんと動くか確認していきます。

```terminal
$ npm run start
```

を実行して[playground](http://localhost:3000/graphql)が以下のように表示されれば対応終了です。

![Playground - http___localhost_3000_graphql.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/edb679f8-143f-b2f5-6d0b-8aa98401048e.png)

[レポジトリ](https://github.com/Ntakuya/nestjs-graphql/tree/env/graphql)