阿波罗 GraphQL Schema Stitching 冲突

3

我想咨询有关GraphQL Schema拼接的问题。我有两个GraphQL模式:

type Name {
   firstname: String!
   lastname: String!
}

type Address {
   street: String!
   number: Int!
}

type User {
   name: Name!
   address: Address!
}

type Query {
   user(userId: String!): User
}

并且

type User {
   age: String!
}

type Query {
   user(userId: String!): User
}

我现在尝试使用graphql-tools的mergeSchemas函数合并模式:

const schema = mergeSchemas({
   schemas: [schema1, schema2]
});

但是与我想要实现的目标(扩展用户类型)不同:

type Name {
   firstname: String!
   lastname: String!
}

type Address {
   street: String!
   number: Int!
}

type User {
   name: Name!
   address: Address!
   age: String!
}

type Query {
   user(userId: String!): User
}

它的结果是这样的: 类型名称 { 名字: 字符串! 姓氏: 字符串! }
type Address {
   street: String!
   number: Int!
}

type User {
   name: Name!
   address: Address!
}

type Query {
   user(userId: String!): User
}

在最终模式中只显示一个用户类型。 我尝试使用mergeSchemas中的onTypeConflict API来扩展类型,但是没有取得任何结果。
是否有一种方法可以通过扩展冲突的类型来合并模式?

你的目标是什么?你只能有一个用户类型。你想合并它们还是只想要第二个用户类型?在你的情况下,发生的是默认行为,它会获取所有同名类型中遇到的第一个类型。 - Reto Aebersold
理想情况下,我想扩展用户类型。我已相应地编辑了我的问题。 - Nicolai Schmid
问题在于,这些不是本地模式,所以我不能轻松地将'type User'更改为'extend type User'。我使用'makeRemoteExecutableSchema'获取它们。 - Nicolai Schmid
2个回答

3
这里提供了一个可能的解决方案来合并对象类型。也许在onTypeConflict中根据类型名称过滤而不是合并每个类型会更有意义。
import cloneDeep from 'lodash.clonedeep'
import { GraphQLObjectType } from 'graphql/type/definition'
import { mergeSchemas } from 'graphql-tools'

function mergeObjectTypes (leftType, rightType) {
  if (!rightType) {
    return leftType
  }
  if (leftType.constructor.name !== rightType.constructor.name) {
    throw new TypeError(`Cannot merge with different base type. this: ${leftType.constructor.name}, other: ${rightType.constructor.name}.`)
  }
  const mergedType = cloneDeep(leftType)
  mergedType.getFields() // Populate _fields
  for (const [key, value] of Object.entries(rightType.getFields())) {
    mergedType._fields[key] = value
  }
  if (leftType instanceof GraphQLObjectType) {
    mergedType._interfaces = Array.from(new Set(leftType.getInterfaces().concat(rightType.getInterfaces())))
  }
  return mergedType
}

const schema = mergeSchemas({
  schemas: [schema1, schema2],
  onTypeConflict: (leftType, rightType) => {
    if (leftType instanceof GraphQLObjectType) {
      return mergeObjectTypes(leftType, rightType)
    }
    return leftType
  }
})

致谢:由Jared Wolinsky编写的mergeObjectTypes函数。


嗨!感谢你的回答,它确实尝试合并两个GraphQL用户类型,但有一个问题。当我运行代码时,它记录了一个错误,即找不到“Name”类型。我认为这是因为它在处理冲突之前先“导入”其他任何类型。 你有什么解决这个问题的想法吗? - Nicolai Schmid

3

这应该会有所帮助

extend type User {
   age: String!
}

除了我没有本地模式之外,我正在尝试使用graphql-tools拼接远程模式。 - Nicolai Schmid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接