Next.js✖️NestJS✖️GraphQLのフルスタックアプリのための環境構築(バックエンド構築編)

# 今回はNestJsを用いたバックエンド

今回構築する技術は

- NestJS
- Next.js
- GraphQL
- prisma
- mysql(docker)

### 1. Nestプロジェクト作成

#### 1. NestJS プロジェクトのセットアップ

```
npm install -g @nestjs/cli
```

```
nest new backend
cd backend
```

#### 2. Prismaのセットアップ

```
npm install prisma --save-dev
npm install @prisma/client
```

今回は、mysqlを利用してDBを構築するためこちらにしています
各自環境に合わせてください

```
npx prisma init
```

```schema.prisma
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id    String  @id @default(cuid())
  email String  @unique
  name  String
}
```

#### 3. Dockerでmysqlの構築

https://qiita.com/Itsuki54/items/d2020be8e85727289c2d

詳しくはこちらの記事をご覧ください

```
touch docker-compose.yml
mkdir -p docker/mysql/sql
touch ./docker/mysql/sql/1_init.sql
touch .env
```

```docker-compose.yaml
version: '3'
services:
  db:
    image: mysql:8.0
    ports:
      - '3311:3306'
    environment:
      MYSQL_ROOT_PASSWORD: 'root'
      MYSQL_USER: 'docker'
      MYSQL_PASSWORD: 'docker'
      MYSQL_DATABASE: 'test_db'
      TZ: 'Asia/Tokyo'
    volumes:
      - db-store:/var/lib/mysql
      - ./docker/mysql/sql:/docker-entrypoint-initdb.d

volumes:
  db-store:
```
:::note warn
ポートに注意
:::

```docker/mysql/sql/1_init.sql
GRANT CREATE, ALTER, DROP, REFERENCES ON *.* to 'docker' @'%';
```

```.env
MYSQL_ROOT_PASSWORD = your_root_password
MYSQL_DATABASE = mydatabase

DATABASE_URL = mysql://docker:docker@localhost:3307/test_db
```

起動すればDBコンテナが立ち上がります
```
docker compose up -d
```

```
npx prisma migrate dev --name init
```
これでprismaのセットアップも完了です！

#### 4. GraphQLのセットアップ

```
npm install @nestjs/graphql @nestjs/apollo apollo-server-express graphql-tools graphql
```

```src/prisma.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    await this.$connect();
  }
}
```

##### 機能追加

serviceの追加
```
nest g service users
```
これでserviceとテストのテンプレが作成されました
以下のように修正します
```src/users/users.service.ts
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma.service';
import { User, Prisma } from '@prisma/client';

@Injectable()
export class UsersService {
  constructor(private prisma: PrismaService) {}

  async user(id: string): Promise<User | null> {
    return this.prisma.user.findUnique({
      where: { id },
    });
  }

  async users(): Promise<User[]> {
    return this.prisma.user.findMany();
  }

  async createUser(data: Prisma.UserCreateInput): Promise<User> {
    return this.prisma.user.create({
      data,
    });
  }
}
```

controllerの追加
```
nest g controller users
```
自動追加を修正
```src/users/users.controller.ts
import { Controller, Get, Param, Post, Body } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from '@prisma/client';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get(':id')
  async findUserById(@Param('id') id: string): Promise<User> {
    return this.usersService.user(id);
  }

  @Get()
  async users(): Promise<User[]> {
    return this.usersService.users();
  }

  @Post()
  async createUser(
    @Body() userData: { name: string; email: string },
  ): Promise<User> {
    return this.usersService.createUser(userData);
  }
}
```

moduleの作成

```
nest g module users
```
修正
```src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { PrismaService } from '../prisma.service';

@Module({
  controllers: [UsersController,],
  providers: [UsersService, PrismaService]
})
export class UserModule {}
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { PrismaService } from '../prisma.service';

@Module({
  controllers: [UsersController,],
  providers: [UsersService, PrismaService]
})
export class UserModule {}
```

```src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UsersService } from './users/users.service';
import { UsersController } from './users/users.controller';
import { UsersModule } from './users/users.module';

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

### これでバックエンドは完成しました！