我遇到一种情况,我想在点击该查询的解析器之前有条件地从查询选择中排除某个字段。
用例是我的基础API仅基于用户的语言环境公开某些“字段”,并且如果请求的字段不包含在该语言环境中,则对此API的调用将引发错误。
我尝试了使用指令的方法,
type Person {
id: Int!
name: String!
medicare: String @locale(locales: ["AU"])
}
type query {
person(id: Int!): Person
}
使用SchemaDirectiveVisitor.visitFieldDefinition
,我覆盖field.resolve
的{{1}}字段,以在用户区域设置与指令上定义的任何区域设置都不匹配时返回null。
但是,当具有非medicare
语言环境的客户端执行以下操作
"AU"
从未调用过query {
person(id: 111) {
name
medicareNumber
}
}
}
的字段解析器,查询解析器向基础API发出请求,将选择集中的字段(包括无效的medicare
)附加为查询参数。此时,API调用将返回一个错误对象。
我认为这是有道理的,因为似乎指令解析器位于medicareNumber
上,并且仅在FieldDefinition
解析器返回有效结果时才会调用。
是否有一种方法可以实现这种功能(带有或不带有指令)?
答案 0 :(得分:0)
通常,我会提醒您不要使用这种架构设计。作为客户,如果我在选择集中包含一个字段,则希望在响应中看到该字段-从服务器端从选择集中删除该字段会违反规范,并且可能导致不必要的混乱(尤其是在较大的团队中)或使用公共API)。
如果您正在检查请求的字段以确定要传递给API调用的参数,则强制将某个字段解析为null不会执行任何操作-该字段仍将包含在选择集中。实际上,实际上没有办法创建会影响请求选择集的架构指令。
这里最好的方法是:1)确保模式中任何可能为空的字段都可以为空,以及2)显式过滤选择集到参数逻辑所在的选择集。
编辑:
架构指令不会显示为info
中返回的架构对象的一部分,因此它们不能用作标志。我的建议是维护一个单独的内存映射。例如:
const fieldsByLocale = {
US: {
Person: ['name', 'medicareNumber'],
},
AU: {
Person: ['name'],
},
}
然后,您可以访问相应的列表以使用fieldsByLocale[context.locale][info.returnType]
进行过滤。此过滤逻辑特定于您的数据源(在这种情况下为外部API),因此,这比使用与存储层有关的信息“污染”架构更为干净。如果API发生更改,或者您完全切换到此信息的其他来源(如数据库),则可以更新解析器而无需更改类型定义。实际上,通过这种方式,筛选逻辑可以轻松地存在于域/服务层中,而不是解析程序中。