😊

Nest x Fastify x Graphql x Prisma x Railway でAPIを作ろう

2022/12/20に公開

はじめに

修正や追加等はコメントまたはGitHubで編集リクエストをお待ちしております。

Nest のプロジェクト作成

npx nest new [project-name]

Nest に Fastify を導入する

yarn add -D @nestjs/platform-fastify

いらないのでExpressを削除する。

yarn remove @nestjs/platform-express

main.tsを編集する。

main.ts
import { NestFactory } from '@nestjs/core';
+ import {
+     FastifyAdapter,
+     NestFastifyApplication,
+ } from '@nestjs/platform-fastify';
import { AppModule } from './app.module';

async function bootstrap() {
-    const app = await NestFactory.create(AppModule);
+    const app = await NestFactory.create<NestFastifyApplication>(
+        AppModule,
+        new FastifyAdapter(),
+    );
-    await app.listen(3000);
+    await app.listen(process.env.PORT || 3000, '0.0.0.0');
}

bootstrap();

GraphQL の導入

yarn add @nestjs/graphql @nestjs/mercurius graphql mercurius fastify

app.module.tsを編集する。

app.module.ts
import { Module } from '@nestjs/common';
+ import { GraphQLModule } from '@nestjs/graphql';
+ import { MercuriusDriver, MercuriusDriverConfig } from '@nestjs/mercurius';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
-    imports: [],
+    imports: [
+        GraphQLModule.forRoot<MercuriusDriverConfig>({
+            driver: MercuriusDriver,
+            graphiql: process.env.NODE_ENV !== 'production',
+            autoSchemaFile: true,
+            sortSchema: true,
+        }),
+    ],
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule {}

Prisma を導入する

yarn add prisma

Prismaの初期化を行う。

npx prisma init

PostgreSQL を導入する

https://railway.app?referralCode=_1ur3q

RailwayでPostgreSQLを作成する。

Step

  1. New Project をクリックする
  2. 右上の New をクリックする
  3. Database を選択する
  4. PostgreSQL を選択する
  5. Connect をクリックする
  6. Postgres Connection URL をコピーする
  7. .envDATABASE_URL を追加する
.env
DATABASE_URL="postgresql://..."

DB を定義する

schema.prismaを編集する。

簡単な例として、Userテーブルを作成する。

schema.prisma
  // This is your Prisma schema file,
  // learn more about it in the docs: https://pris.ly/d/prisma-schema

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

  datasource db {
    provider = "postgresql"
    url      = env("DATABASE_URL")
  }
+
+ model User {
+   id          String     @default(cuid()) @id
+   email       String     @unique
+   name        String?
+ }

DB をマイグレーションする

npx prisma migrate dev

Prisma Client を導入する

yarn add @prisma/client

prisma.service.tsを作成する。

npx nest g s modules/prisma
prisma.service.ts
- import { Injectable } from '@nestjs/common';
+ import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
+ import { PrismaClient } from '@prisma/client';

@Injectable()
- export class PrismaService {}
+ export class PrismaService extends PrismaClient implements OnModuleInit {
+   async onModuleInit() {
+     await this.$connect();
+   }
+
+   async enableShutdownHooks(app: INestApplication) {
+     this.$on('beforeExit', async () => {
+       await app.close();
+     });
+   }
+ }

GraphQL の型を生成する

yarn add prisa-nestjs-graphql class-transformer

schema.prismaを編集する。

schema.prisma
  // This is your Prisma schema file,
  // learn more about it in the docs: https://pris.ly/d/prisma-schema

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

+ generator nestgraphql {
+  provider = "prisma-nestjs-graphql"
+  output = "../src/@generated/prisma-nestjs-graphql"
+ }

  datasource db {
    provider = "postgresql"
    url      = env("DATABASE_URL")
  }

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

gitignoreを編集する。

.gitignore
...
+ src/@generated

型を生成する。

npx prisma generate

Nest から GraphQL を呼び出せるようにする

Module と Resolver の生成

npx nest g mo components/user
npx nest g r components/user

PrismaService をインポートする

user.module.ts
import { Module } from '@nestjs/common';
+ import { PrismaService } from 'src/prisma/prisma.service';
import { UserService } from './user.service';

@Module({
-   providers: [UserService],
    providers: [UserService, PrismaService],
})
export class UserModule {}
user.resolver.ts
import { Resolver } from '@nestjs/graphql';
+ import { PrismaService } from 'src/prisma/prisma.service';

@Resolver()
export class UserResolver {
+   constructor(private prisma: PrismaService) {}
}

Input と Output の定義

src/interfaces/user/user.model.ts
import { Field, InputType, ID, ObjectType } from '@nestjs/graphql';

@ObjectType()
export class User {
    @Field(() => ID, { nullable: false })
    id!: string;

    @Field(() => String, { nullable: false })
    email!: string;

    @Field(() => String, { nullable: true })
    name!: string | null;
}
src/interfaces/user/user.input.ts
import { Field, InputType } from '@nestjs/graphql';

@InputType()
export class UserInput {
    @Field(() => String, { nullable: false })
    email!: string;

    @Field(() => String, { nullable: true })
    name?: string | null;
}

Query の定義

user.resolver.ts
import { Args, Query, Resolver } from '@nestjs/graphql';
import { User } from 'src/interfaces/user/user.model';
import { PrismaService } from 'src/prisma/prisma.service';

@Resolver()
export class UserResolver {
    constructor(private prisma: PrismaService) {}

    @Query(() => [User])
    async getAllUsers() {
        return await this.prisma.user.findMany();
    }

    @Query(() => User)
    async getUserById(@Args('id') id: string) {
        return await this.prisma.user.findUnique({
            where: {
                id,
            },
        });
    }
}

呼び出してみる

yarn start:dev
curl 'https://...' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'Origin: chrome-extension://flnheeellpciglgpaodhkhmapeljopja' --data-binary '{"query":"{\n  getAllUser {\n    email\n    id\n    name\n  }\n}\n\n","variables":{}}' --compressed

Railway にデプロイする

https://railway.app?referralCode=_1ur3q

データベースの追加は前述したので、ある前提で進めていきます。

Step

  1. PostgreSQL を作成したプロジェクトを選択する
  2. 右上の New をクリックする
  3. Empty Service を選択する
  4. Settings をクリックする
  5. Deploy 項目の Start Commandyarn start:prod を入力する
  6. Source Repo を設定する
  7. DomainsGenerate Domain をクリックする

後はRailwayが自動でデプロイしてくれます。

まとめ

Nest x Fastify x Graphql x Prisma x RailwayでAPIを作ってみました。
Railsと比べて、TypeScriptの型があるので、開発が楽になりました。
また、GraphQLの型を生成してくれるので、開発効率が上がりました。
Railwayは、デプロイが簡単で、値段も安価なので、今後も使っていきたいです。

Next.js で GraphQL を呼び出す

https://zenn.dev/riya_amemiya/articles/6910d97b81e917

Discussion