Closed5

prisma + Next な app に Apollo Server 3 入れてみる

nbstshnbstsh

Creating Graphql Endpoint

とりあえず query できるところまでやる。

typeDefs

graphql/schema.ts に typeDefs を作成する。

graphql/schema.ts
import { gql } from 'apollo-server-micro';

export const typeDefs = gql`
  type Query {
    info: String
  }
`;

resolver

graphql/resolvers.ts に resolver 作る。

graphql/resolvers.ts
export const resolvers = {
  Query: {
    info: () => 'Hello World!',
  },
};

server

pages/api/graphql.ts に apollo-server setup

Apollo Server 3 は GraphQL playground を内包しておらず、代わりに Apollo Studio に redirect するようになったみたい。その関係で CORS の設定をしてあげる必要があると。req.method が OPTIONS だった場合に処理を終了させているのも Apollo Studio を正しく動作させるため。

pages/api/graphql.ts
import { ApolloServer } from 'apollo-server-micro'
import { typeDefs } from '../../graphql/schema'
import { resolvers } from '../../graphql/resolvers'
import Cors from 'micro-cors'

const cors = Cors()

const apolloServer = new ApolloServer({ typeDefs, resolvers })

const startServer = apolloServer.start()

export default cors(async function handler(req, res) {
  if (req.method === 'OPTIONS') {
    res.end()
    return false
  }
  await startServer

  await apolloServer.createHandler({
    path: '/api/graphql',
  })(req, res)
})

// Body parsing is disabled here since it is handled by GraphQL.
export const config = {
  api: {
    bodyParser: false,
  },
}

これでとりあえず動くところまでOK。
dev server 起動して、localhost:3000/api/graphql を開くと Apollo Studio が表示されるので、"Query Your Server" を押してそのまま進むと info query を実行できる。

nbstshnbstsh

Initialize Prisma Client

prsma client を使いまわせるように init しておく。
Next の開発環境で prisma を使用すると database connection limit を使い果たしてしまう問題が起こるらしいので、こちらの "Best practice for instantiating PrismaClient with Next.js" をもとに lib/prisma に セットアップする。

lib/prisma.ts
// see "Best practice for instantiating PrismaClient with Next.js"
// https://www.prisma.io/docs/support/help-articles/nextjs-prisma-client-dev-practices
import { PrismaClient } from '@prisma/client';

declare global {
  var prisma: PrismaClient | undefined;
}

export const prisma =
  global.prisma ||
  new PrismaClient({
    log: ['query'],
  });

if (process.env.NODE_ENV !== 'production') global.prisma = prisma;

export default prisma;
nbstshnbstsh

Creating a GraphQL context

次は graphql context の setup をしていく。graphql/context.ts を作成。

resolver 内で prisma client にアクセスできるように prisma client instance を含んだ context factory を作成。また、context の型も用意しておく

graphql/context.ts
import { prisma } from '@/lib/prisma';
import { PrismaClient } from '@prisma/client';

export type GraphqlContext = {
  prisma: PrismaClient;
};

export const createContext = async (): Promise<GraphqlContext> => {
  return {
    prisma,
  };
};

次に、作成した context factory を ApolloServer に渡してあげる。

pages/api/graphql.ts
import { ApolloServer } from 'apollo-server-micro';
import { createContext } from 'graphql/context';
import { resolvers } from '../../graphql/resolvers';
import { typeDefs } from '../../graphql/schema';

const apolloServer = new ApolloServer({
  typeDefs,
  resolvers,
  context: createContext,
});

これで resolver で prisma 使えるようになる。

nbstshnbstsh

Query Sample with Prisma

実際に、prisma からデータを取得する Query を作ってみる。

graphql/resolvers.ts
import { GraphqlContext } from './context';

export const resolvers = {
  Query: {
    info: () => 'Hello World!',
    users: async (_parent: unknown, _args: {}, context: GraphqlContext) => {
      return context.prisma.user.findMany();
    },
  },
};

これで prisma を介して user の一覧を取得できる。

ここまでできればとりあえずのセットアップは完了かな。

このスクラップは2021/12/15にクローズされました