如何在Apollo Server中将类型定义和解析器拆分为单独的文件 [英] How to split type definitions and resolvers into separate files in Apollo Server
问题描述
index.ts:
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req, res }: any) => ({ req, res })
});
UserSchema.ts
UserSchema.ts
export const typeDefs = gql`
scalar TimeStamp
type Query {
getUser(id: Int!): User
}
type Mutation {
addUser(
name: String!
email: String
age: Int
register_at: TimeStamp!
): Boolean!
}
type User {
id: Int!
name: String!
email: String!
age: Int!
register_at: TimeStamp!
}
`;
UserResolver.ts
UserResolver.ts
export const resolvers = {
TimeStamp: timeStamp,
Query: {
getUser: async (_: any, args: any) => {
const { id } = args;
return await User.findOne({ where: { id: id } });
}
},
Mutation: {
addUser: async (_: any, args: any) => {
const { name, email, age, register_at } = args;
try {
const user = User.create({
name,
email,
age,
register_at
});
await user.save();
return true;
} catch (error) {
return false;
}
}
}
};
如果我有其他类型定义和解析器(例如BookSchema.ts
和BookResolver.ts
),我想知道如何初始化Apollo Server实例.
I would like to know how I would initialize my Apollo Server instance if I had additional type definitions and resolvers, for example BookSchema.ts
and BookResolver.ts
.
推荐答案
类型定义
ApolloServer
构造函数可以接受一个数组,而不仅仅是一个DocumentNode
对象.因此,您可以执行以下操作:
Type Definitions
The ApolloServer
constructor can accept an array instead of just the one DocumentNode
object. So you can do something like:
const server = new ApolloServer({
typeDefs: [userTypeDefs, bookTypeDefs],
resolvers,
})
请注意,如果您还想拆分单个类型的字段定义,则需要使用类型扩展语法.例如:
Note that if you want to split up an individual type's field definitions as well, you'll need to use type extension syntax. For example:
const typeDefsA = gql`
type Query {
users: [User!]!
}
`
const typeDefsB = gql`
extend type Query {
books: [Book!]!
}
`
const typeDefsC = gql`
extend type Query {
posts: [Post!]!
}
`
以上内容将合并为一个Query
类型.您可以根据需要添加任意数量的扩展名,但是要扩展必须的类型必须存在(即,不能只有三个extend type Query
定义).记住这一点,我通常会创建一组基本"类型定义,例如:
The above will be combined into a single Query
type. You can have as many extensions as you want, but the type you're extending must exist (i.e., you can't have just three extend type Query
definitions). Keeping this in mind, I usually create a "base" set of type definitions like:
type Query
type Mutation
然后我所有其他类型定义都可以扩展这些类型.请注意,由于这些基本"类型没有任何字段,因此我们根本不使用大括号(一组空的大括号将导致语法错误!).
Then all my other type definitions can extend these types. Notice that because these "base" types don't have any fields, we don't use curly brackets at all (an empty set of curly brackets will result in a syntax error!).
您的解析器映射是一个普通的JavaScript对象,因此将其拆分很简单.
Your resolver map is a plain JavaScript object, so splitting it it up is trivial.
const resolversA = {
Query: {
users: () => {...},
}
}
const resolversB = {
Query: {
books: () => {...},
}
}
但是,如果尝试使用Object.assign
或传播语法来组合这些解析器映射,则会受到伤害,因为每个对象都将覆盖所有公共属性(例如Query
).因此,请勿执行以下操作:
However, if you attempt to combine these resolver maps using Object.assign
or spread syntax, you'll be hurting because any common properties (like Query
) will be overridden by each object. So do not do this:
const resolvers = {
...resolversA,
...resolversB,
}
相反,您想深度合并对象,以便所有子属性(及其属性,等等)也被合并.我建议使用lodash
,但是可以使用许多实用程序.
Instead, you want to deep merge the objects, so that any child properties (and their properties, and so on) are merged as well. I recommend using lodash
but there's any number of utilities you can use.
const resolvers = _.merge({}, resolversA, resolversB)
将它们放在一起
您的代码可能看起来像这样:
Putting it all together
Your code might look something like this:
userTypeDefs.ts
userTypeDefs.ts
export default gql`
type User {
id: ID!
username: String!
books: [Book!]!
}
extend type Query {
users: [User!]!
}
`
bookTypeDefs.ts
bookTypeDefs.ts
export default gql`
type Book {
id: ID!
title: String!
author: User!
}
extend type Query {
books: [Book!]!
}
`
userResolvers.ts
userResolvers.ts
export default {
Query: {
users: () => {...},
},
User: {
books: () => {...},
},
}
bookResolvers.ts
bookResolvers.ts
export default {
Query: {
books: () => {...},
},
Book: {
author: () => {...},
},
}
index.ts
import userTypeDefs from '...'
import userResolvers from '...'
import bookTypeDefs from '...'
import bookResolvers from '...'
// Note: This is also a good place to put any types that are common to each "module"
const baseTypeDefs = gql`
type Query
`
const apollo = new ApolloServer({
typeDefs: [baseTypeDefs, userTypeDefs, bookTypeDefs],
resolvers: _.merge({}, userResolvers, bookResolvers)
})
这篇关于如何在Apollo Server中将类型定义和解析器拆分为单独的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!