我想知道在GraphQL / Apollo服务器中忽略/丢弃未知枚举值的最佳方法是什么。
假设我的GraphQL架构定义了枚举数组“enum Service {Supermarket,TicketSales}”,它现在运行正常,但后来我正在使用的其他服务是添加一些新值(例如Playground),而我的客户端只是不支持它我只想忽略它并返回支持的值而不会出错。
在GraphQL中执行此操作的最佳方法是什么。我的第一个想法是制定指令,从架构中读取支持的值并忽略其他所有内容,但在谷歌搜索后我没有找到任何好的例子如何做到这一点。你能指点一下这个方向吗?
如果您的解析器函数将接受任意字符串,那么您可以使用自定义标量类型,或只使用String
。
"""
The type of a service. `Supermarket` means..., and
`TicketSales` means...; any other value is ignored.
"""
scalar Service
GraphQL通常将责任放在客户端上以符合服务器的期望,而不是让服务器尝试支持任何请求。有几个地方你可以合理地期望这样的枚举值出现:
enum Service { Supermarket, TicketSales }
type Query {
inAReturnValue: Service!
asAQueryParam(service: Service!): Node
}
type Mutation {
asAMutationInput(service: Service!): Node
}
特别是,如果服务器只是不明白,那么告诉服务器“使这个对象的类型成为游乐场”可能没有意义。相反,如果服务器知道“游乐场”,它可以在客户可能不期望的情况下返回它。在这里有一个枚举使它明确了服务器所知道的内容。服务器说了它支持的内容,客户有责任进行合作。
请注意,客户端可以查明服务器是否支持操场,如果它是枚举值,这可能有助于它通知其行为。
query GetServiceTypes {
__type(name: "Service") {
enumValues { name }
}
}
在玩完之后,我发现了一些我可以用来解决原始问题的东西,所以我会在这里发布,以防其他人想知道同样的事情。
所以我原来的问题很简单,我正在从另一个服务接收几种不同的“可用服务”类型的字符串数组,我正在考虑将它们映射到枚举以获得更好的打字稿支持等。但问题是,如果我得到一些未知的来自另一个服务的值,我的graphql将失败。
所以我最初的想法是用指令解决它,我毕竟工作了:
# In schema
directive @mapUnknownTo(value: String) on ENUM
enum SomeAttribute @mapUnknownTo(value: "__UNKNOWN__") {
SomeAttribute1
AnotherAttribute
SomethingElse
__UNKNOWN__
}
指令实现是:
import { SchemaDirectiveVisitor } from 'graphql-tools';
import { GraphQLEnumType } from 'graphql';
export class MapUnknownToDirective extends SchemaDirectiveVisitor {
visitEnum(type: GraphQLEnumType) {
const { value = '__UNKNOWN__' } = this.args;
const valueMap = type.getValues().reduce((map, v) => map.set(v.value, v.name), new Map<string, string>());
type.serialize = (v: string): string => valueMap.get(v) || value;
}
}
因此,这会将模式中未定义的所有值映射到某个自定义值,这不是我最初想要的,但至少它没有给出错误,所以没关系。
我仍然不能100%确定指令是否可以用于此类案例,但至少它是一种可能的解决方案。