Как игнорировать неизвестные значения перечисления?

Мне интересно, как лучше всего игнорировать/отбрасывать неизвестные значения перечисления на сервере GraphQL/Apollo.

Допустим, моя схема GraphQL определяет массив перечислений «enum Service {Supermarket, TicketSales}», и сейчас он работает нормально, но позже другой сервис, который я использую, добавляет некоторые новые значения (например, Playground), и мой клиент просто не поддерживает это, и я просто хотел бы игнорировать его и возвращать поддерживаемые значения без ошибок.

Как лучше всего это сделать в GraphQL. Моей первой идеей было создать директиву, которая будет считывать поддерживаемые значения из схемы и игнорировать все остальное, но после поиска в Google я не нашел хороших примеров, как это сделать. Можете ли вы указать мне направление, куда идти по этому поводу?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Что такое Apollo Client и зачем он нужен?
Что такое Apollo Client и зачем он нужен?
Apollo Client - это полнофункциональный клиент GraphQL для JavaScript-приложений, который упрощает получение, управление и обновление данных в...
0
0
1 122
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если ваша функция распознавателя будет принимать произвольные строки, вы можете использовать собственный скалярный тип или просто 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 }
  }
}

Спасибо за ваш ответ, есть несколько хороших идей, над которыми мне нужно подумать. В моем случае у нас есть множество различных типов «поддерживаемых служб», которые практически представляют собой массив строк, и причина, по которой я хотел бы сопоставить их с перечислениями, заключается в том, что это прояснит для клиента, какие значения можно ожидать, а не просто случайные строки, и, конечно же, я бы получил для них машинописный текст. Со временем у нас, вероятно, будут представлены некоторые новые службы, которые мы еще не поддерживаем, и, конечно, мой сервер должен каким-то образом отфильтровывать их, пока мы не создадим для них поддержку.

phepsi 28.04.2019 09:40

и данные, с которыми я имею дело, поступают из других служб, поэтому в основном я могу внезапно начать получать некоторые новые значения, о которых я не знал. Поскольку моя схема graphql уже определяет допустимые значения, мне интересно, есть ли простой способ разрешить только их и игнорировать все остальное? Может быть, как-то с пользовательским преобразователем и информационным параметром?

phepsi 28.04.2019 09:50
Ответ принят как подходящий

Поиграв, я нашел кое-что, что я могу использовать, чтобы обойти свою первоначальную проблему, поэтому я опубликую это здесь, если кто-то еще задается вопросом о том же.

Итак, моя первоначальная проблема заключалась в том, что я получаю несколько различных строковых массивов типа «доступных служб» от других служб, и я думал сопоставить их с перечислением для лучшей поддержки машинописного текста и т. д. Но проблема заключалась в том, что если я получу какой-то неизвестный значение из другого сервиса, мой 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%, что директивы подходят для таких случаев, но, по крайней мере, это одно из возможных решений.

Другие вопросы по теме