本文来源:https://github.com/ardatan/graphql-tools

    When using graphql-tools, you describe the schema as a GraphQL type language string:

    1. const typeDefs = /* GraphQL */ `
    2. type Author {
    3. id: ID! # the ! means that every author object _must_ have an id
    4. firstName: String
    5. lastName: String
    6. """
    7. the list of Posts by this author
    8. """
    9. posts: [Post]
    10. }
    11. type Post {
    12. id: ID!
    13. title: String
    14. author: Author
    15. votes: Int
    16. }
    17. # the schema allows the following query:
    18. type Query {
    19. posts: [Post]
    20. }
    21. # this schema allows the following mutation:
    22. type Mutation {
    23. upvotePost(postId: ID!): Post
    24. }
    25. # we need to tell the server which types represent the root query
    26. # and root mutation types. We call them RootQuery and RootMutation by convention.
    27. schema {
    28. query: Query
    29. mutation: Mutation
    30. }
    31. `
    32. export default typeDefs

    Then you define resolvers as a nested object that maps type and field names to resolver functions:

    1. const resolvers = {
    2. Query: {
    3. posts() {
    4. return posts
    5. }
    6. },
    7. Mutation: {
    8. upvotePost(_, { postId }) {
    9. const post = find(posts, { id: postId })
    10. if (!post) {
    11. throw new Error(`Couldn't find post with id ${postId}`)
    12. }
    13. post.votes += 1
    14. return post
    15. }
    16. },
    17. Author: {
    18. posts(author) {
    19. return filter(posts, { authorId: author.id })
    20. }
    21. },
    22. Post: {
    23. author(post) {
    24. return find(authors, { id: post.authorId })
    25. }
    26. }
    27. }
    28. export default resolvers

    At the end, the schema and resolvers are combined using makeExecutableSchema:

    1. import { makeExecutableSchema } from '@graphql-tools/schema'
    2. const executableSchema = makeExecutableSchema({
    3. typeDefs,
    4. resolvers
    5. })