Типы перечислений GraphQL разрешают свои значения автоматически?

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

Учитывая следующую схему GraphQL:

type Job {
  description: String!
  status: Status!
}

enum Status {
  PENDING_REVIEW
  PENDING_APPROVAL
  APPROVED
}

и запрос, который выглядит так:

query job {
  description
  status
}

Если бы моя база данных вернула следующее:

{ "description": "Some irrelevant job description", "status": 1 }

Я ожидаю, что GraphQL вернется:

{ "description": "Some irrelevant job description", "status": "PENDING_APPROVAL" }

Я что-то неправильно настроил, или это ожидаемое поведение, которое потребует от меня написания преобразователя для status?

const getQuestionStatus = ({ status }) => ['PENDING_REVIEW', 'PENDING_APPROVAL', 'APPROVED'][status];
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Что такое Apollo Client и зачем он нужен?
Что такое Apollo Client и зачем он нужен?
Apollo Client - это полнофункциональный клиент GraphQL для JavaScript-приложений, который упрощает получение, управление и обновление данных в...
6
0
13 519
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Я думаю, вам нужно реализовать резольвер для него.

Однако, если вы используете Apollo Server, у него есть функция Внутренние ценности, где вы можете использовать 1 в качестве внутреннего значения в распознавателе, Apollo Server автоматически сопоставит его с PENDING_APPROVAL при возврате ответа.

Это зависит от языка, на котором вы реализуете GraphQL. Типы перечислений в GraphQL — это типы перечислений просто и ничего более. Это означает, например, что ваш тип перечисления APPROVED ничего не оценивает. Это дает разработчику больше возможностей делать с ними то, что они хотят. Если вы хотите, чтобы перечисление отображалось в целые числа, вам понадобится преобразователь, как вы описали.

Из Статья о GraphQL по схемам и типам:

Note that GraphQL service implementations in various languages will have their own language-specific way to deal with enums. In languages that support enums as a first-class citizen, the implementation might take advantage of that; in a language like JavaScript with no enum support, these values might be internally mapped to a set of integers.

Ответ принят как подходящий

В GraphQL.js каждое значение перечисления в типе перечисления может иметь связанное с ним значение. Установка этого значения не является обязательной; по умолчанию это строковое представление имени значения. То есть для перечисления типа:

enum ExampleEnum {
  FOO
  BAR
}

по умолчанию значение FOO будет "FOO". Если вы используете graphql-tools для построения своей схемы (или используете apollo-server, который использует graphql-tools под капотом), мы можем передать значения для типа Enum прямо в наши преобразователи:

const resolvers = {
  Query: {
    example: () => 11, // field with ExampleEnum type
  },
  ExampleEnum: {
    FOO: 11,
    BAR: 23,
  },
}

Как только мы это сделали, мы можем вернуть определенное значение в наш преобразователь, и оно будет сериализовано в соответствующее значение Enum. Примечание: то же самое относится и к перечислениям, которые используются в качестве аргументов — если FOO передается в качестве аргумента, распознаватель фактически получит значение 11.

Отсутствие каких-либо значений эквивалентно выполнению:

ExampleEnum: {
  FOO: 'FOO',
  BAR: 'BAR',
}

Также стоит отметить, что предоставление значений не влияет на то, как значения перечисления отображаются в ответе. Когда результат выполнения сериализуется в JSON, значения перечисления всегда отображаются в виде строковых значений, которые соответствуют именам значений перечисления (например, "FOO" и "BAR" в нашем примере).

А как насчет ванильного GraphQL.js?

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

const ExampleEnumType = new GraphQLEnumType({
  name: 'ExampleEnum',
  values: {
    FOO: {
      value: 11,
    },
    BAR: {
      value: 23,
    },
  },
})

Как насчет значений перечисления по умолчанию? Мои тесты показали, что распознаватель получает либо перечисление в виде строки, либо undefined.

Dan Dascalescu 04.06.2020 01:53

Да, вам нужно написать преобразователь из значений перечисления во все, что вам нужно, например. числа согласно документы apollo-server для внутренних значений. Вот как это сделать в TypeScript:

export enum Status {
  DRAFT,
  PENDING,
  APPROVED
}

const typeDefs = gql`
  enum Status {
    DRAFT
    PENDING
    APPROVED
  }

  type Query {
    echo(status: Status!): Int!
  }
`;

const resolvers = {
  Status: {
    DRAFT: Status.DRAFT,
    PENDING: Status.PENDING,
    APPROVED: Status.APPROVED
  },

  Query: {
    echo(_, { status }): String {
      console.info(status);
      return status;
    }
  }
};

Вот Песочница кода, показывающая автоматический анализ и возврат перечисления.

Однако обратите внимание, что для значений перечисления по умолчанию, которые являются параметрами запроса, поведение сомнительно — преобразователь может получить значение перечисления в виде строки или undefined.

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