【GraphQL】Apollo ServerやPrisma・MySQL・TypeScriptを使ってGraphQLのAPIを開発する

GraphQL

1. 概要

TypeScriptをベースにApollo ServerやPrisma・MySQLを使ってGraphQLのAPIを開発する内容となります。

対象としては開発を1年程やってて自分で最初から開発してみたい方になります。そのため細かい用語などの説明はしません。

2. 【GraphQL】Apollo ServerやTypeScriptを使ってGraphQLのAPIを開発する

こちらを参考

3. PrismaやTypeScript、MySQLを使ってデータを操作する

こちらを参考

4. nodeのインストール

こちらを参考

5. プロジェクトを作成

mkdir graphql-apollo-prisma-mysql
cd graphql-apollo-prisma-mysql

6. 必要なライブラリをインストール

npm install @apollo/server graphql ts-node
npm install --save-dev prisma typescript @types/node
npm install @graphql-tools/graphql-file-loader @graphql-tools/load @graphql-tools/schema
npm install @prisma/client

7. TypeScriptでセットアップ

npx tsc --init
npx prisma init
mkdir src
touch src/index.ts
code .

8. 設定ファイルの編集

8-1. tsconfig.json

※差し替え

{
  "compilerOptions": {
    "rootDirs": ["src"],
    "outDir": "dist",
    "lib": ["es2020"],
    "target": "es2020",
    "module": "esnext",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "types": ["node"]
  }
}

8-2. package.json

※追加

{
  "type": "module",
  "scripts": {
    "compile": "tsc",
    "start": "npm run compile && node ./dist/index.js"
  },
  "dependencies": {
    "@apollo/server": "^4.7.5",
    "@graphql-tools/graphql-file-loader": "^8.0.0",
    "@graphql-tools/load": "^8.0.0",
    "@graphql-tools/schema": "^10.0.0",
    "@prisma/client": "^5.0.0",
    "graphql": "^16.7.1",
    "ts-node": "^10.9.1"
  },
  "devDependencies": {
    "@types/node": "^20.4.2",
    "prisma": "^5.0.0",
    "typescript": "^5.1.6"
  }
}

9. Databaseへ接続設定

9-1. 「.env」を修正

DATABASE_URL="mysql://user:password@localhost:3306/mydb"

9-2. 「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"
}

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

10. スキーマを定義

※「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"
}

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

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?
}

11. MySQLを起動

こちらを参考

起動&パーミッション付与

docker-compose up -d
docker-compose exec mysql-server bash
$ mysql -uroot -proot mysql
mysql> GRANT ALL ON *.* TO 'user';
mysql> FLUSH PRIVILEGES;

12. スキーマを作成

npx prisma migrate dev --name init

13. スキーマ定義ファイルを作成

※「src/schema.gql」

type User {
  id: ID!
  email: String!
  name: String
  posts: [Post]
  profile: Profile!
}

type Profile {
  id: ID!
  bio: String
  userId: Int!
}

type Post {
  id: ID!
  title: String!
  content: String
  published: Boolean
  authorId: Int!
}

type Query {
  info: String!
  posts: [Post]
}

14. Resolverを作成

※src/resolvers/query.ts

const posts = (parent, args, contextValue, info) => {
  return contextValue.prisma.post.findMany();
}

export { posts };

15. ソースコード

※src/index.ts

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { loadSchemaSync } from '@graphql-tools/load';
import { addResolversToSchema } from '@graphql-tools/schema';
import { PrismaClient } from '@prisma/client';
import { posts } from './resolvers/query.js';

const schema = loadSchemaSync('src/schema.gql', {
  loaders: [new GraphQLFileLoader()],
});

const prisma = new PrismaClient();

const resolvers = {
  Query: {
    posts
  },
};

const schemaWithResolvers = addResolversToSchema({ schema, resolvers });

const server = new ApolloServer({
  schema: schemaWithResolvers
});

const { url } = await startStandaloneServer(server, {
  context: async ({ req }) => ({
    ...req,
    prisma,
  }),
  listen: { port: 4000 },
});

console.log(`🚀  Server ready at: ${url}`);

16. サンプルデータを登録

こちらを参考

サンプルデータ1

  await prisma.user.create({
    data: {
      name: 'Alice',
      email: 'alice@prisma.io',
      posts: {
        create: { title: 'Hello World' },
      },
      profile: {
        create: { bio: 'I like turtles' },
      },
    },
  })

サンプルデータ2

  await prisma.user.create({
    data: {
      name: 'John',
      email: 'john@prisma.io',
      posts: {
        create: { title: 'Nice guy' },
      },
      profile: {
        create: { bio: 'Reading books' },
      },
    },
  })

サンプルデータ3

  await prisma.user.create({
    data: {
      name: 'Taylor',
      email: 'taylor@prisma.io',
      posts: {
        create: { title: 'Good morning' },
      },
      profile: {
        create: { bio: 'Making songs' },
      },
    },
  })

17. サーバーを起動

npm start
> start
> npm run compile && node ./dist/index.js


> compile
> tsc

🚀  Server ready at: http://localhost:4000/

18. クエリを実行

  • http://localhost:4000

18-1-1. Request

query Query {
  posts {
    title
  }
}

18-1-2. Response

{
  "data": {
    "posts": [
      {
        "title": "Hello World"
      },
      {
        "title": "Nice guy"
      },
      {
        "title": "Good morning"
      }
    ]
  }
}

18-2-1. Request

query Query {
  posts {
    id
    title
    content
    authorId
    published  
  }
}

18-2-2. Response

{
  "data": {
    "posts": [
      {
        "id": "1",
        "title": "Hello World",
        "content": null,
        "authorId": 1,
        "published": false
      },
      {
        "id": "2",
        "title": "Nice guy",
        "content": null,
        "authorId": 2,
        "published": false
      },
      {
        "id": "3",
        "title": "Good morning",
        "content": null,
        "authorId": 3,
        "published": false
      }
    ]
  }
}

19. ディレクトリの構造

.
├── dist
│   ├── index.js
│   └── resolvers
│       └── query.js
├── package-lock.json
├── package.json
├── prisma
│   ├── migrations
│   │   ├── 20230715081438_init
│   │   │   └── migration.sql
│   │   └── migration_lock.toml
│   └── schema.prisma
├── src
│   ├── index.ts
│   ├── resolvers
│   │   └── query.ts
│   └── schema.gql
└── tsconfig.json

7 directories, 11 files

20. 備考

Apollo Serverを使用してGraphQLのAPIを経由しMySQLデータを取得するシンプルな内容でした。

21. 参考

投稿者プロフィール

Sondon
開発好きなシステムエンジニアです。
卓球にハマってます。

関連記事

  1. GraphQL

    【GraphQL】Apollo ServerやPrisma・MySQL…

  2. GraphQL

    【GraphQL】Apollo ServerやTypeScriptを使…

最近の記事

  1. Node.js
  2. AWS
  3. AWS

制作実績一覧

  1. Checkeys