NestJSでGraphQLのモジュール開発

# はじめに
自分なりに、どう作っていくかってのを記述したメモです。
追加開発とかなら４以降を手順通りするか、コピペすれば流用していけるはず。
※共通化部分をどうしていくかは課題。

# 環境

```
"@nestjs/common": "^8.0.0",
"@nestjs/core": "^8.0.0",
"@nestjs/graphql": "^9.0.4",

"@nestjs/cli": "^8.0.0",
```

# 全体の流れ

1. プロジェクト作成
2. GraphQLのライブラリ導入
3. 初期起動確認
4. GraphQL用のモジュール作成
    1. モジュール
    2. リゾルバー
    3. サービス
    4. モデル（スキーマのtype）
5. ロジックの実装
6. 起動確認
7. Queryの実行

# プロジェクト作成

```bash
nest new nest-graphql-new
cd nest-graphql-new

```
※package管理はyarnを利用

# ライブラリ導入

```bash
yarn add @nestjs/graphql graphql apollo-server-express
```

# 初期起動確認

```bash
yarn start

# ストップ
Ctrl + c
```

# モジュール作成
[https://docs.nestjs.com/cli/usages#nest-generate](https://docs.nestjs.com/cli/usages#nest-generate)

```bash
nest g module recipes
nest g resolver recipes --no-spec
nest g service recipes --no-spec
nest g class recipes/models/recipe --no-spec
```

# ロジック実装

### app.modules.ts
- コメント化のみ
- RecipesModuleは自動で入る

```bash
import { Module } from '@nestjs/common';
// import { AppController } from './app.controller';
// import { AppService } from './app.service';
import { RecipesModule } from './recipes/recipes.module';

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

※app.controllerとserviceは除外した。（Rest的にも使う時はあっても良い）

## recipes/recipes.modules.ts
- GraphQLModuleの定義追加

```bash
import { Module } from '@nestjs/common';
import { RecipesResolver } from './recipes.resolver';
import { RecipesService } from './recipes.service';
import { GraphQLModule } from '@nestjs/graphql';

@Module({
  providers: [RecipesResolver, RecipesService],
  imports: [
    GraphQLModule.forRoot({
      installSubscriptionHandlers: true,
      autoSchemaFile: 'schema/recipe.gql',
      // debug: true,
      // playground: true,
    }),
  ],
})
export class RecipesModule {}
```

## recipes/models/recipe
- モデル定義、データ型のようなもの

```
import { Field,ID, ObjectType} from '@nestjs/graphql';

@ObjectType()
export class Recipe {
  @Field(type =>ID)
  id: string;

  @Field()
  name: string;

}
```

## recpes/recipes.service.ts
- データ取得のロジック実装。
- ここで外部API使ってデータ取得したりしなかったり。

```
import { Injectable } from '@nestjs/common';
import { Recipe } from './models/recipe';

@Injectable()
export class RecipesService {
  async findOneById(id: string): Promise<Recipe> {
    const recipe = new Recipe();
    recipe.id = '1234';
    recipe.name = 'name';

    return recipe;
  }
}
```

※サービス実装（疎通用でテストデータ設定）

## recpes/recipes.resolver.ts
- クライアントのからの呼び出し定義的な。

```
import { Resolver, Args, Query } from '@nestjs/graphql';
import { RecipesService } from './recipes.service';
import { Recipe } from './models/recipe';

@Resolver(of => Recipe)
export class RecipesResolver {
  constructor(private readonly recipesService: RecipesService) {
  }
  @Query(returns => Recipe)
  async recipe(@Args('id') id: string): Promise<Recipe> {
    return await this.recipesService.findOneById(id);
  }
}
```

起動確認

```bash
yarn start
yarn run v1.22.11
$ nest start
[Nest] 29754  - 09/24/2021, 11:31:53 AM     LOG [NestFactory] Starting Nest application...
[Nest] 29754  - 09/24/2021, 11:31:53 AM     LOG [InstanceLoader] AppModule dependencies initialized +17ms
[Nest] 29754  - 09/24/2021, 11:31:53 AM     LOG [InstanceLoader] RecipesModule dependencies initialized +1ms
[Nest] 29754  - 09/24/2021, 11:31:53 AM     LOG [InstanceLoader] GraphQLSchemaBuilderModule dependencies initialized +0ms
[Nest] 29754  - 09/24/2021, 11:31:53 AM     LOG [InstanceLoader] GraphQLModule dependencies initialized +0ms
[Nest] 29754  - 09/24/2021, 11:31:53 AM     LOG [NestApplication] Nest application successfully started +44ms
```

■play ground起動
http://localhost:3000/graphql

Queryの実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247263/9915ff87-4d87-3334-14e5-ece3c4b95e89.png)


# まとめ

基礎の進め方としては、こんな感じで開発していけそう。

GraphQLModule.forRootこの定義が、AppModuleに定義するべきかどうかってのがあるが、上記のようにすると、モジュール単位で分離していけそう。

モデル内で他モジュールのモデル利用とか考えると、モデルは外に出した方が良いのかも。

この辺りは、実装進めてみて考える。ひとまず叩き台としてのメモです。

# 参考

[Documentation | NestJS - A progressive Node.js framework](https://docs.nestjs.com/graphql/quick-start)

[nest/sample/23-graphql-code-first at master · nestjs/nest](https://github.com/nestjs/nest/tree/master/sample/23-graphql-code-first)