问题
index.ts:
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req, res }: any) => ({ req, res })
});
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
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;
}
}
}
};
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
.
回答1:
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!]!
}
`
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!).
Resolvers
Your resolver map is a plain JavaScript object, so splitting it it up is trivial.
const resolversA = {
Query: {
users: () => {...},
}
}
const resolversB = {
Query: {
books: () => {...},
}
}
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,
}
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
export default gql`
type User {
id: ID!
username: String!
books: [Book!]!
}
extend type Query {
users: [User!]!
}
`
bookTypeDefs.ts
export default gql`
type Book {
id: ID!
title: String!
author: User!
}
extend type Query {
books: [Book!]!
}
`
userResolvers.ts
export default {
Query: {
users: () => {...},
},
User: {
books: () => {...},
},
}
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)
})
来源:https://stackoverflow.com/questions/60747549/how-to-split-type-definitions-and-resolvers-into-separate-files-in-apollo-server