既に Apollo Server 3 ベースのバックエンドを稼働中だが、今回新しい環境を作ることになったので、Apollo Server 4 で行うことに!
ライブラリ別相互関係
頭の整理を含め、PostGreSQL や SQLite などの関係データベースを持つバックエンド環境を作る上に必要なライブラリー別の位置付け(?)を考えて見たのが⬇︎です。

- Nexus は GraphQL スキマです。GraphQL Server と Prisma を繋ぎやすくしてくれます。
– GraphQL 用ファイルを自動生成:nexus-typegen.ts
– Prisma 用ファイル自動生成:schema.graphql - Prisma はオブジェクト関係マッピング(Object-relational mapping、ORM) データベース(SQList、PostgreSQLなど)とオブジェクト指向プログラミング言語の間の非互換なデータを変換してくれます。
プロジェクトを作成する
apollo-server-express を使うと、ポート番号や Endpoint の変更ができます。(任意)
Apollo Server 4からは @apollo/server/express4 の expressMiddleware を使用します。
try🐶everything jacetemp$ mkdir backend && cd backend try🐶everything backend$ npm init -y try🐶everything backend$ npm install @apollo/server express graphql cors body-parser try🐶everything backend$ npm install --save-dev typescript ts-node-dev
tsconfig.json を作成する
// tsconfig.json
try🐶everything backend$ cat tsconfig.json
{
"compilerOptions": {
"target": "ES2018",
"module": "commonjs",
"lib": ["esnext"],
"strict": true,
"allowJs": true,
"rootDir": ".",
"outDir": "dist",
"sourceMap": true,
"moduleResolution": "node",
"types": ["node"],
"typeRoots": ["./node_modules/@types", "./src/@types"],
"esModuleInterop": true,
"resolveJsonModule": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
try🐶everything backend$
scripts コマンドを追加する
try🐶everything backend$ cat package.json
{
。。。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "ts-node-dev --transpile-only --no-notify src/index.ts", // <-- 追加
"dev:typecheck": "tsc --noEmit --watch", // <-- 追加
"build": "tsc"
},
Nexus を設定する
try🐶everything backend$ mkdir src && touch src/schema.ts
try🐶everything backend$ cat src/schema.ts
import { makeSchema } from "nexus";
import { join } from "path";
export const schema = makeSchema({
types: [],
outputs: {
// src/generated/* にスキマファイルを保存するように設定(任意)
typegen: join(__dirname, "generated", "nexus-typegen.ts"),
schema: join(__dirname, "generated", "schema.graphql"),
},
});
try🐶everything backend$
try🐶everything backend$ touch src/index.ts
import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
import express from "express";
import http from "http";
import cors from "cors";
import pkg from "body-parser";
import { schema } from "./schema";
const { json } = pkg;
interface MyContext {
token?: String;
}
export async function startApolloServer() {
const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer<MyContext>({
schema,
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});
await server.start();
app.use(
"/graphql",
cors<cors.CorsRequest>(),
json(),
expressMiddleware(server, {
context: async ({ req }) => ({ token: req.headers.token }),
})
);
await new Promise<void>((resolve) =>
httpServer.listen({ port: 4000 }, resolve)
);
console.log(`🚀 Server ready at http://localhost:4000/graphql`);
}
startApolloServer();
try🐶everything backend$
動作を確認する
try🐶everything backend$ yarn dev yarn run v1.22.19 $ ts-node-dev --transpile-only --no-notify src/index.ts [INFO] 09:33:06 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.9.1, typescript ver. 5.2.2) 🚀 Server ready at http://localhost:4000/graphql
http://localhost:4000/graphql に接続します。

(⬆︎) Fields に表示される ok: Boolean! にチェックを入れて、exampleQuery ボタンを押すと、"ok": true と結果が出れば OK です。
Prisma を設定する
PostgreSQL と繋ぎます。
パッケージを設置する
try🐶everything backend$ npm init -y try🐶everything backend$ npm install prisma typescript ts-node @types/node --save-dev
Prismaを初期化する
このコマンドは次の 2 つのことを行います。
schema.prismaというファイルを含むprismaという新しいディレクトリを作成します。
このファイルには、データベース接続変数とスキーマ モデルを含むPrisma スキーマが含まれています。- プロジェクトのルート ディレクトリに
.env ファイルを作成します。このファイルは、環境変数 (データベース接続など) を定義するために使用されます。
try🐶everything backend$ npx prisma init ✔ Your Prisma schema was created at prisma/schema.prisma You can now open it in your favorite editor. Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started 2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlite, sqlserver or mongodb (Preview). 3. Run prisma db pull to turn your database schema into a Prisma schema. 4. Run prisma generate to generate the Prisma Client. You can then start querying your database. ... try🐶everything backend$
データベースを接続する
DB の設定が必要です。まだの方は ⬇︎⬇︎ 記事で設定できます。
データベースに接続するには、Prisma スキーマのデータソース ブロックの URL フィールドをデータベース接続 URL に設定する必要があります。.env ファイル 内の DATABASE_URL を、既存のデータベースを指すように設定します。
// prisma/schema.prisma
...
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// .env
// johndoe:randompassword に実際の所有者とパスワードに書き換えてください。
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
※ 環境変数がコミットされないように、.gitignore ファイルに .env を追加しておく!
データベース スキマ を作成する
Prisma Migrate を使用してデータベースにテーブルを作成します。 次の Prisma データ モデルを prisma/schema.prisma の Prisma スキーマに追加します。
// prisma/schema.prisma
...
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String @db.VarChar(255)
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model Profile {
id Int @id @default(autoincrement())
bio String?
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
profile Profile?
}
データ モデルをデータベース スキーマにマップするには、prisma merge CLI コマンドを使用する必要があります。( $ npx prisma migrate dev --name init )
このコマンドは次の 2 つのことを行います。
– この移行用に新しい SQL 移行ファイルを作成します。
– prisma/migrations/実行時刻_init/migraion.sql
– データベースに対して SQL 移行ファイルを実行します。
try🐶everything backend$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "xxxxxx", schema "public" at "localhost:5432"
Applying migration `20231013063024_init`
The following migration(s) have been created and applied from new schema changes:
migrations/
└─ 20231013063024_init/
└─ migration.sql
Your database is now in sync with your schema.
✔ Generated Prisma Client (v5.4.2) to ./node_modules/@prisma/client in 47ms
try🐶everything backend$
※ prisma-client-js ジェネレーターがスキーマで定義されている場合、@prisma/client がインストールされているかどうかがチェックされ、存在しない場合はインストールされます。
実行結果:Prisma 側
// prisma/migrations/20231013063024_init/migration.sql
-- CreateTable
CREATE TABLE "Post" (
"id" SERIAL NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"title" VARCHAR(255) NOT NULL,
"content" TEXT,
"published" BOOLEAN NOT NULL DEFAULT false,
"authorId" INTEGER NOT NULL,
CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
);
...
実行結果:PostgreSQL 側
pgAdmin4: Servers > PG-01 > Databases > your-project-db > Schemas > public > Tables > Properties

クエリを作成する
Prisma Client を生成したので、データベース内のデータを読み書きするクエリを作成し、いくつかの基本機能を調べます。src/script.ts という名前の新しいファイルを作成し、次のコードをそれに追加します。
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
const allUsers = await prisma.user.findMany(); // <-- 全てのユーザを調べる
console.log(allUsers);
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
$ npx ts-node src/script.ts コマンドを実行しますと、まだ、データがないので、[] が表示されれば OK です。
try🐶everything backend$ npx ts-node src/script.ts [] try🐶everything backend$
他、データの書き込み や 修正 などの続きはこのリンクを貼りながら、割愛いたします。
以上で、基本的な GraphQL 開発環境が完成しました。
参考文献
Nexus Tutorial // <– Prisma 以外のところまではこれがベスト!
Migrating to Apollo Server 4 // <– apollo-server-express
Prisma: Relational Databases // <– PostgreSQL設定まで!
Prisma Quickstart // <– SQLiteに接続し操作する


コメント