Graphql:完全改变模式中的字段类型
Graphql: completely change field type in schema
我需要完全改变字段类型。
情况:我有一个结合了多种服务的网关。它通过自省获取它们的模式,通过向类型添加名称空间(使用 apollo graphql-tools)来转换它们,并通过构建具有 ServiceNameQuery
类型和设置 ServiceNameQuery
的新模式将它们放入嵌套查询(例如 Query: { ServiceName: { serviceQuery } }
)中=15=] 解析器。之后我需要创建跨服务链接。
我有 ServiceA
,其类型为 属性 related
,其中包含来自 TargetType
和 ServiceB
的 ID。我需要将 属性 related
的类型从 ID
更改为 TargetType
并添加一个解析器,它将从 ServiceB
.
获取数据
这是一个真实的例子:
为此,我 运行 visitSchema
(从 graphql-tools
转换)合并模式,找到我需要的字段,从模式中获取 TargetType
并更改字段键入并设置这样的解析器:
const targetType = schema.getType('TargetType');
field.type = targetType;
field.astNode.type = targetType.astNode;
field.resolve = (parent, args, ctx, info) => {
console.log(parent);
return null;
};
当我 运行 console.log 在将结果模式传递给 graphql 服务器之前对结果模式进行类型 - 我看到它的类型和 astNode 确实发生了变化并且它们是正确的。
当我运行反省时——我发现那个类型的字段是正确的。
但是当我 运行 像 query { ServiceA { serviceQuery { id related { id } } } }
这样的查询时,我在请求解析阶段遇到错误:
Error: Field "related" must not have a selection since type "ID" has no subfields.
GraphQL request (5:19)
4: id
5: related {
^
6: id
at asErrorInstance (/.../node_modules/graphql/execution/execute.js:555:43)
at process._tickCallback (internal/process/next_tick.js:68:7)
它的事件不会尝试调用 serviceQuery
解析器。
当我更改类型定义时,它从哪里获取该字段的 ID 类型?我还需要在哪里更改它的类型?
UPD
即使我像这样创建新类型:
schema = return visitSchema(schema, {
[VisitSchemaKind.OBJECT_TYPE](type: GraphQLObjectType) {
if (type.getFields().relatedNews) {
// console.log(type.getFields());
return new GraphQLObjectType({
name: type.name,
fields: {
...fromPairs(Object.values(type.getFields()).map(({name, type, args, resolve, description}) => [name, {type, args: {}, resolve, description}])),
relatedNews: {
type: schema.getType('NewsArticle'),
resolve(obj) {
console.log('foo');
}
}
}
});
}
return type;
},
});
我一直收到此错误并且未触发解析器。如果我以相同的方式添加一个具有不同名称的新字段 - 那行得通。但是如果名字相同——错误
好的,我知道了。拼接模式跟踪底层拼接模式。在顶级架构中更改类型不会影响它,因此会导致内部类型冲突。所以在合并之前应该改变类型
我需要完全改变字段类型。
情况:我有一个结合了多种服务的网关。它通过自省获取它们的模式,通过向类型添加名称空间(使用 apollo graphql-tools)来转换它们,并通过构建具有 ServiceNameQuery
类型和设置 ServiceNameQuery
的新模式将它们放入嵌套查询(例如 Query: { ServiceName: { serviceQuery } }
)中=15=] 解析器。之后我需要创建跨服务链接。
我有 ServiceA
,其类型为 属性 related
,其中包含来自 TargetType
和 ServiceB
的 ID。我需要将 属性 related
的类型从 ID
更改为 TargetType
并添加一个解析器,它将从 ServiceB
.
这是一个真实的例子:
为此,我 运行 visitSchema
(从 graphql-tools
转换)合并模式,找到我需要的字段,从模式中获取 TargetType
并更改字段键入并设置这样的解析器:
const targetType = schema.getType('TargetType');
field.type = targetType;
field.astNode.type = targetType.astNode;
field.resolve = (parent, args, ctx, info) => {
console.log(parent);
return null;
};
当我 运行 console.log 在将结果模式传递给 graphql 服务器之前对结果模式进行类型 - 我看到它的类型和 astNode 确实发生了变化并且它们是正确的。
当我运行反省时——我发现那个类型的字段是正确的。
但是当我 运行 像 query { ServiceA { serviceQuery { id related { id } } } }
这样的查询时,我在请求解析阶段遇到错误:
Error: Field "related" must not have a selection since type "ID" has no subfields.
GraphQL request (5:19)
4: id
5: related {
^
6: id
at asErrorInstance (/.../node_modules/graphql/execution/execute.js:555:43)
at process._tickCallback (internal/process/next_tick.js:68:7)
它的事件不会尝试调用 serviceQuery
解析器。
当我更改类型定义时,它从哪里获取该字段的 ID 类型?我还需要在哪里更改它的类型?
UPD 即使我像这样创建新类型:
schema = return visitSchema(schema, {
[VisitSchemaKind.OBJECT_TYPE](type: GraphQLObjectType) {
if (type.getFields().relatedNews) {
// console.log(type.getFields());
return new GraphQLObjectType({
name: type.name,
fields: {
...fromPairs(Object.values(type.getFields()).map(({name, type, args, resolve, description}) => [name, {type, args: {}, resolve, description}])),
relatedNews: {
type: schema.getType('NewsArticle'),
resolve(obj) {
console.log('foo');
}
}
}
});
}
return type;
},
});
我一直收到此错误并且未触发解析器。如果我以相同的方式添加一个具有不同名称的新字段 - 那行得通。但是如果名字相同——错误
好的,我知道了。拼接模式跟踪底层拼接模式。在顶级架构中更改类型不会影响它,因此会导致内部类型冲突。所以在合并之前应该改变类型