本系列文以製作專案為主軸,紀錄小弟學習React以及GrahQL的過程。主要是記下重點步驟以及我覺得需要記憶的部分,有覺得不明確的地方還請留言多多指教。
資料庫與存取資料庫的介面、Prisma Client已經建立好了,現在要從Apollo Server利用Prisma Client,建立能夠存取資料庫的Resolvers。
首先,目前的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建立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。
目前的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方法想想還是分篇寫好了,今天先到這。