😊
Nest x Fastify x Graphql x Prisma x Railway でAPIを作ろう
はじめに
修正や追加等はコメントまたは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 を導入する
RailwayでPostgreSQLを作成する。
Step
-
New Project
をクリックする - 右上の
New
をクリックする -
Database
を選択する -
PostgreSQL
を選択する -
Connect
をクリックする -
Postgres Connection URL
をコピーする -
.env
にDATABASE_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 にデプロイする
データベースの追加は前述したので、ある前提で進めていきます。
Step
-
PostgreSQL
を作成したプロジェクトを選択する - 右上の
New
をクリックする -
Empty Service
を選択する -
Settings
をクリックする -
Deploy
項目のStart Command
にyarn start:prod
を入力する -
Source Repo
を設定する -
Domains
のGenerate Domain
をクリックする
後はRailwayが自動でデプロイしてくれます。
まとめ
Nest x Fastify x Graphql x Prisma x RailwayでAPIを作ってみました。
Railsと比べて、TypeScriptの型があるので、開発が楽になりました。
また、GraphQLの型を生成してくれるので、開発効率が上がりました。
Railwayは、デプロイが簡単で、値段も安価なので、今後も使っていきたいです。
Next.js で GraphQL を呼び出す
Discussion