模式拼接通过添加前缀解决冲突
Schema Stitching resolve conflict by adding prefix
所以我有这两个模式
架构 1
type Permission {
relation: Relation
}
enum Relation {
ONE
TWO
THREE
}
架构 2
type Permission {
relation: Relation
}
enum Relation {
FOUR
FIVE
SIX
}
预期结果类似于:(但我愿意接受不同的想法)
合并后我想提出的查询是:
{
permissions{
relation
}
}
得到类似
的结果
"permissions": [
{
"relation": "ONE"
},
{
"relation": "SIX"
}
]
或
"permissions": [
{
"relation": "schema1ONE"
},
{
"relation": "schema2SIX"
}
]
以及像这样的突变:
mutation{
createPermission(
relation: ONE
){
relation
}
}
mutation{
createPermission(
relation: SIX
){
relation
}
}
或
mutation{
createPermission(
relation: schema1ONE
){
relation
}
}
mutation{
createPermission(
relation: schema2SIX
){
relation
}
}
我正在尝试在 graphql-tools 上使用 transformSchema
函数,但无法完全正确地计算出来:
const Schema1 = await getRemoteSchema('schema1_url', 'schema1');
const Schema2 = await getRemoteSchema('schema2_url', 'schema2');
const schemas = [Schema1, Schema2]
const schema = mergeSchemas({
schemas: schemas,
resolvers: {}
});
getRemoteSchema 定义
export const getRemoteSchema = async (uri: string, schemaName: string): Promise<GraphQLSchema> => {
const httpLink = new HttpLink({ uri, fetch });
const schema = await introspectSchema(httpLink);
const executableSchema = makeRemoteExecutableSchema({
schema,
httpLink,
});
// transform schema by renaming root fields and types
const renamedSchema = transformSchema(
executableSchema,
[
new RenameTypes(name => {
if (name == 'Relation') {
return schemaName + name
} else {
return name
}
}),
// new RenameRootFields((operation, name) => `${schemaName}_${name}`)
]
);
return renamedSchema;
}
我犯了这个错误https://glitch.com/edit/#!/schema-stitching-conflict
这样更容易看出问题。
目前我没有看到使用 graphql-tools 实现所需行为的简便方法,因为在 mergeSchemas()
的实现中,选项 onTypeConflict
是 first deprecated and later removed,尽管它仍然存在于 public 界面上。使用该选项,我们能够简单地传递一个回调,该回调知道冲突的类型及其相应的 AST。
transformSchema()
但是,当您尝试使用它时,只会重命名枚举类型名称而不是枚举值。您很可能需要实施自己的转换,而不是使用预定义的转换来实现您的目标。不过,我还是建议您看看 the implementation of ConvertEnumValues
。这可能会让您更好地了解在实现您自己的 Transform
.
时如何根据您的需要遍历和操作 AST
例如,我会考虑一个实现,它会跟踪它所看到的所有 GraphQlEnumTypes
并在遇到名称冲突时深度合并它们。您可以使用模块范围内的变量或使用 Transform
中的实例属性来跟踪。如果你做后者,不要忘记提前实例化它并通过引用将它传递给后续的 tranformSchema()
调用。
您需要 RenameTypes
和 RenameRootFields
转换,
RenameTypes
转换类型名称
来自:Permission
和 Relation
(冲突类型),
至:schema1_Permission
、schema2_Permission
和:schema1_Relation
、schema1_Relation
RenameRootFields
转换这些类型的查询名称
来自:permission(id: ID!): Permission
至:schema1_permission(id: ID!): schema1_Permission
和 schema2_permission(id: ID!): schema2_Permission
和:permissions: [Permission]
至:schema1_permissions: [schema1_Permission]
和 schema2_permissions: [schema2_Permission]
转换类似于:
const {
makeExecutableSchema,
addMockFunctionsToSchema,
transformSchema,
RenameTypes,
RenameRootFields
} = require('graphql-tools');
const schema1 = makeExecutableSchema({
typeDefs: `
type Permission {
id: ID!
text: String
relation: Relation
}
type Query {
permissions: [Permission]
permission(id: ID!): Permission
}
enum Relation {
ONE
TWO
THREE
}
`
});
addMockFunctionsToSchema({ schema: schema1 });
const renamedSchema1 = transformSchema(
schema1,
[
new RenameTypes(name => {
if (name == 'Relation' || name == 'Permission') {
return 'schema1_' + name
} else {
return name
}
}, { renameBuiltins: false, renameScalars: true }),
new RenameRootFields((_op, name) => {
return name.includes('ermission') ? `schema1_${name}` : name
})
]
);
参考资料:
https://www.apollographql.com/docs/graphql-tools/schema-transforms/
https://www.apollographql.com/docs/graphql-tools/schema-stitching/
所以我有这两个模式
架构 1
type Permission {
relation: Relation
}
enum Relation {
ONE
TWO
THREE
}
架构 2
type Permission {
relation: Relation
}
enum Relation {
FOUR
FIVE
SIX
}
预期结果类似于:(但我愿意接受不同的想法) 合并后我想提出的查询是:
{
permissions{
relation
}
}
得到类似
的结果"permissions": [
{
"relation": "ONE"
},
{
"relation": "SIX"
}
]
或
"permissions": [
{
"relation": "schema1ONE"
},
{
"relation": "schema2SIX"
}
]
以及像这样的突变:
mutation{
createPermission(
relation: ONE
){
relation
}
}
mutation{
createPermission(
relation: SIX
){
relation
}
}
或
mutation{
createPermission(
relation: schema1ONE
){
relation
}
}
mutation{
createPermission(
relation: schema2SIX
){
relation
}
}
我正在尝试在 graphql-tools 上使用 transformSchema
函数,但无法完全正确地计算出来:
const Schema1 = await getRemoteSchema('schema1_url', 'schema1');
const Schema2 = await getRemoteSchema('schema2_url', 'schema2');
const schemas = [Schema1, Schema2]
const schema = mergeSchemas({
schemas: schemas,
resolvers: {}
});
getRemoteSchema 定义
export const getRemoteSchema = async (uri: string, schemaName: string): Promise<GraphQLSchema> => {
const httpLink = new HttpLink({ uri, fetch });
const schema = await introspectSchema(httpLink);
const executableSchema = makeRemoteExecutableSchema({
schema,
httpLink,
});
// transform schema by renaming root fields and types
const renamedSchema = transformSchema(
executableSchema,
[
new RenameTypes(name => {
if (name == 'Relation') {
return schemaName + name
} else {
return name
}
}),
// new RenameRootFields((operation, name) => `${schemaName}_${name}`)
]
);
return renamedSchema;
}
我犯了这个错误https://glitch.com/edit/#!/schema-stitching-conflict 这样更容易看出问题。
目前我没有看到使用 graphql-tools 实现所需行为的简便方法,因为在 mergeSchemas()
的实现中,选项 onTypeConflict
是 first deprecated and later removed,尽管它仍然存在于 public 界面上。使用该选项,我们能够简单地传递一个回调,该回调知道冲突的类型及其相应的 AST。
transformSchema()
但是,当您尝试使用它时,只会重命名枚举类型名称而不是枚举值。您很可能需要实施自己的转换,而不是使用预定义的转换来实现您的目标。不过,我还是建议您看看 the implementation of ConvertEnumValues
。这可能会让您更好地了解在实现您自己的 Transform
.
例如,我会考虑一个实现,它会跟踪它所看到的所有 GraphQlEnumTypes
并在遇到名称冲突时深度合并它们。您可以使用模块范围内的变量或使用 Transform
中的实例属性来跟踪。如果你做后者,不要忘记提前实例化它并通过引用将它传递给后续的 tranformSchema()
调用。
您需要 RenameTypes
和 RenameRootFields
转换,
RenameTypes
转换类型名称
来自:Permission
和 Relation
(冲突类型),
至:schema1_Permission
、schema2_Permission
和:schema1_Relation
、schema1_Relation
RenameRootFields
转换这些类型的查询名称
来自:permission(id: ID!): Permission
至:schema1_permission(id: ID!): schema1_Permission
和 schema2_permission(id: ID!): schema2_Permission
和:permissions: [Permission]
至:schema1_permissions: [schema1_Permission]
和 schema2_permissions: [schema2_Permission]
转换类似于:
const {
makeExecutableSchema,
addMockFunctionsToSchema,
transformSchema,
RenameTypes,
RenameRootFields
} = require('graphql-tools');
const schema1 = makeExecutableSchema({
typeDefs: `
type Permission {
id: ID!
text: String
relation: Relation
}
type Query {
permissions: [Permission]
permission(id: ID!): Permission
}
enum Relation {
ONE
TWO
THREE
}
`
});
addMockFunctionsToSchema({ schema: schema1 });
const renamedSchema1 = transformSchema(
schema1,
[
new RenameTypes(name => {
if (name == 'Relation' || name == 'Permission') {
return 'schema1_' + name
} else {
return name
}
}, { renameBuiltins: false, renameScalars: true }),
new RenameRootFields((_op, name) => {
return name.includes('ermission') ? `schema1_${name}` : name
})
]
);
参考资料: https://www.apollographql.com/docs/graphql-tools/schema-transforms/ https://www.apollographql.com/docs/graphql-tools/schema-stitching/