如何在Apollo Server中将类型定义和解析器拆分为单独的文件 [英] How to split type definitions and resolvers into separate files in Apollo Server

查看:224
本文介绍了如何在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.tsBookResolver.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆