【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. 参考

関連記事

  1. GraphQL

    【GraphQL】Apollo ServerやTypeScriptを使…

  2. GraphQL

    【GraphQL】Apollo ServerやPrisma・MySQL…

最近の記事

  1. AWS
  2. AWS
  3. AWS
  4. AWS
  5. AWS
  6. AWS
  7. AWS
  8. AWS

制作実績一覧

  1. Checkeys