graphql - 覆盖 GraphQL 联合/接口类型的“根”对象值
问题描述
我有一个委托给内部 gRPC 服务的 Apollo GraphQL 服务。该服务有一个端点,它返回一条包含 a 的消息,oneof
我将其映射到Union
GraphQL 中的 a 。
这很简单,但在实施解析器时会涉及相当程度的样板。假设我有以下 protobuf 消息定义:
message MyUnionMessage {
oneof value {
UnionType1 type1 = 1;
UnionType1 type2 = 3;
UnionType1 type3 = 4;
}
}
message UnionType1 {<type 1 props>}
message UnionType2 {<type 2 props>}
message UnionType3 {<type 3 props>}
我对应的 GraphQL 架构如下所示:
union MyUnionType = UnionType1 | UnionType2 | UnionType3
type UnionType1 {<type 1 props>}
type UnionType1 {<type 2 props>}
type UnionType1 {<type 3 props>}
在 gRPC 的 javascript 绑定中,一个MyUnionMessage
对象将有两个属性:value
一个是指示所包含值类型的字符串,另一个是为该类型命名的属性。因此,例如,如果我有一个MyUnionMessage
包含 aUnionType2
的对象,则该对象将如下所示:
{
value: 'type2',
type2: {...}
}
这对于实现来说很好,因为我可以对 in 中的值__resolveType
做一个简单的处理,但是我必须为所有具体类型的所有字段编写一个解析器。switch
value
我正在寻找的是能够做到这样的事情:
resolvers = {
MyUnionType: {
__resolveType(obj) {
switch(obj.value) {
case 'type1': return 'UnionType1';
case 'type2': return 'UnionType2';
case 'type3': return 'UnionType3';
default: return null;
},
__resolveValue(obj) {
return obj[obj.value];
},
},
};
基本上,我想在通用联合(或接口)类型级别编写一个“解析器”,在对象传递给具体解析器之前对其进行转换。
这样的事情可能吗?
解决方案
我敢打赌,这种情况通常可以通过在数据到达__resolveType
逻辑之前转换数据来解决。例如,假设您有一个Query
返回列表的字段MyUnionType
。该字段的解析器可能类似于:
function resolve (arr) {
return arr.map(obj => {
return {
...obj[obj.value]
type: obj.value // or whatever field name that won't cause a collision
}
})
}
然后你switch
在type
里面,__resolveType
你很高兴。当然,这意味着如果您有多个返回 a 的字段MyUnionType
,您需要将该逻辑提取到每个解析器都可以使用的实用程序函数中。
我认为没有真正的方法可以用现有的 API 来做你想做的事情。当然,您可以执行以下操作:
const getUnionType(obj) {
switch(obj.value) {
case 'type1': return 'UnionType1';
case 'type2': return 'UnionType2';
case 'type3': return 'UnionType3';
default: {
throw new Error(`Unrecognized type ${obj.value}`)
}
}
}
const resolvers = {
MyUnionType: {
__resolveType(obj) {
const type = getUnionType(obj)
Object.assign(obj, obj[obj.value])
return type
},
},
};
这行得通,但请记住它有点脆弱,因为它假设resolveType
将始终获得与函数相同的根值resolve
,假设将来可能会发生变化。
推荐阅读
- javascript - Javascript - 未捕获的 SyntaxError:意外标记“其他”
- firebase - 如何在 React Native Firebase 的 Firebase 身份验证中避免重新验证
- amazon-web-services - Lambda@Edge URL 使用 NodeJS 重定向到 s3 SignedUrl
- spring - 在spring boot security中的会话超时后,我如何重定向到不同的jsp页面(而不是重定向到登录页面)
- python - 为什么最终字典不能用作 TypedDict 中的文字?
- reactjs - 如何在 Slatejs 中创建 Read_More 和 Read_less 按钮
- python - UnboundLocalError:分配前引用的局部变量“parsed_upd”
- javascript - JQuery Ajax If else
- apache-beam - apache 梁中的动态管道
- javascript - 100 个获取请求中有 1 个失败并导致错误。如何继续该计划?