iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 26
0
Modern Web

React + GraphQL 全端練習筆記系列 第 26

仿Trello - Apollo Server 串接 Prisma

本系列文以製作專案為主軸,紀錄小弟學習React以及GrahQL的過程。主要是記下重點步驟以及我覺得需要記憶的部分,有覺得不明確的地方還請留言多多指教。

資料庫與存取資料庫的介面、Prisma Client已經建立好了,現在要從Apollo Server利用Prisma Client,建立能夠存取資料庫的Resolvers。

建立獨立schema檔案

首先,目前的Apollo Server只有index這個檔案,不管是GraphQL的型別定義還是resolvers都寫在這,但是接下來會逐步擴大Schema,如果一直放在index中會不好管理。

所以要將schema做成獨立檔案後在將schema導回index給Apollo server用。

首先建立src資料夾,然後建立schema.js。
在schema.js中定義type跟resolvers:

// server/src/schema.js
const { gql } = require("apollo-server");

const typeDefs = gql`
  type List {
    id: ID
    title: String
    order: Int
    todos: [Todo]
  }

  type Todo {
    id: ID
    name: String
    order: Int
    listId: Int
    list: List
  }

  type Query {
    lists: [List]
  }

  type Mutation {
    addTodo(name: String, listId: Int): Todo!
  }
`;

const resolvers = {
   Query: {
    lists: (parent, args, context) => {
      //串接Prisma Client
    },
  },
};

這邊定義的typedefs跟介紹Apollo Server時不同,List跟Todo要改成匹配Prisma Schema。

Query跟Mutation部分則是砍掉重鍊,先以Query list作串接Prisma的範例。

graphql-tools

接著要利用 graphql-tools建立Apollo server可使用的schema物件,graphql-tools是一系列幫助建立GraphQL schema的工具,最低限度只要提供以graphql語法寫成的字串就能生成schema。

先安裝:

npm install graphql-tools

然後在schema.js中使用:

//schema.js
const { makeExecutableSchema } = require("graphql-tools");
const { gql } = require("apollo-server");

const typeDefs = `...`

const resolvers = { ... }

//建立schema
const schema = makeExecutableSchema({
  resolvers,
  typeDefs,
});

//導出schema
module.exports = {
  schema,
};

利用 graphql-tools 的 makeExecutableSchema()將 typeDefs跟 resolvers編譯成schema後導出。

接著到index.js導入剛剛建好的schema。

// server/index.js
const { ApolloServer, gql } = require("apollo-server");
const { schema } = require("./src/schema.js"); //導入schema

const server = new ApolloServer({schema});

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}.`);
});

原本index中的假資料、typedefs跟resolvers都可以刪掉了,改成用schema.js生成的schema建立Apollo server。

利用context串接 prisma client

目前的shcema中resolvers還沒有任何作用,要能夠在resolvers中使用prisma client來存取資料庫才行。

而在Apollo server中連接資料庫的功能,會利用context:

                      //這個
lists: (parent, args, context) => {
  //串接Prisma Client
},

context是所有resolver在執行時都能夠存取到的物件、或產生物件的function,所以把資料庫端口放在context中,就能讓所有resolvers都利用到。

首先建立 context檔案:

// src/context.js
const { PrismaClient } = require("@prisma/client");

const prisma = new PrismaClient();

//回傳帶有prisma鍵值的物件作為context
function createContext() {
  return { prisma };
}

module.exports = {
  createContext,
};

在index中引入並提供給Apollo server使用:

const { ApolloServer, gql } = require("apollo-server");
const { schema } = require("./src/schema");
const { createContext } = require("./src/context");
                                        //加入context
const server = new ApolloServer({ schema, context: createContext });

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}.`);
});

這樣當Server收到請求時,所有resolver都能從context中存取到prisma client,現在可以到schema裡開始用prisma client的方法編寫resolver:

const resolvers = {
  Query: {
    lists: (parent, args, context) => {
             //從context中取得prisma client方法
      return context.prisma.list.findMany({ include: { todos: true } });
    },
  },
}

關於Prisma Client 的 CRUD方法想想還是分篇寫好了,今天先到這。

References:


上一篇
仿Trello - Prisma Migrate 與添加Seeder
下一篇
仿Trello - Prisma client CRUD
系列文
React + GraphQL 全端練習筆記30

尚未有邦友留言

立即登入留言