如何忽略未知的枚举值?

时间:2019-04-26 22:30:39

标签: graphql apollo-server

我想知道什么是在GraphQL / Apollo服务器中忽略/丢弃未知枚举值的最佳方法。

比方说,我的GraphQL模式定义了枚举数组“枚举服务{超市,TicketSales}”,现在可以正常使用,但是后来我正在使用的其他服务上添加了一些新值(例如Playground),而我的客户却没有不支持它,我只想忽略它并返回支持的值而不会出现错误。

在GraphQL中执行此操作的最佳方法是什么。我的第一个想法是制作一条指令,该指令将从架构中读取受支持的值,而忽略其他所有内容,但是在谷歌搜索之后,我找不到如何执行此操作的任何示例。你能指出我要去哪里吗?

2 个答案:

答案 0 :(得分:1)

如果您的解析器函数将接受任意字符串,则可以使用自定义标量类型,也可以仅使用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 }
  }
}

答案 1 :(得分:0)

玩转之后,我发现可以用来解决原始问题的东西,所以我会在这里张贴,以防其他人想知道同一件事。

所以我最初的问题很简短,就是我从另一个服务接收到几种不同的“可用服务”类型的字符串数组,并且我正考虑将它们映射到枚举以获得更好的打字稿支持等。但是问题是,如果我从另一个服务获取一些未知值,我的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%是否可以使用指令处理此类情况,但至少这是一种可能的解决方案。