Источник: Nuances of Programming
GraphQL — это открытый язык запросов и управления данными для API.
Нам больше не нужно играть в догадки, как в случае с REST, поскольку этот язык строго типизирован. Перед выполнением запроса инструменты обеспечивают его синтаксическую верность и соответствие системе типов GraphQL.
Так как TypeScript — это типизированный язык, он идеально сочетается с GraphQL. Используя их вместе, можно обеспечить согласование типов в бэкенде и фронтенде.
Зачем нам вручную определять интерфейсы TS? При написании кода вручную велика вероятность появления ошибок, поэтому и был разработан graphql-codegen .
Генератор кода GraphQL — это инструмент командной строки, способный генерировать типизацию TypeScript на основе схемы GraphQL. При разработке GraphQL-бэкенда возникает много случаев, когда мы пишем то, что уже описано в схеме, только в ином формате. Например, сигнатуры механизмов интерпретации, модели MongoDB, службы Angular и т.д.
graphql-code-generator.com
Если коротко, то это инструмент командной строки, который выполнит за нас всю трудоемкую работу. В этой статье мы познакомимся с ним поглубже и посмотрим, как его можно использовать для создания запроса с помощью Typescript, React и Apollo.
Настройка генератора кода GraphQL
Начнем с установки библиотеки GraphQL:
yarn add graphqlnpm install — save graphql
Далее нужно добавить cli :
yarn add -D @graphql -codegen/clinpm install --save-dev @graphql -codegen/cli
Генератор кода считывает всю конфигурацию из файла codegen.yml . Можно сгенерировать ее автоматически, воспользовавшись мастером установки. Запустим его:
yarn graphql-codegen initnpx graphql-codegen init
Для нашего примера выберем Typescript и Apollo.
После настройки останется только выполнить типичную команду установки:
npm install / yarn install
Чтобы не усложнять, мы будем потреблять демонстрационную конечную точку GraphQL. Можно найти много таких точек здесь .
После настройки codegen.yml будет выглядеть так:
Параметр schema сообщает инструменту о местонахождении конечной точки GraphQL, в качестве которой мы будем использовать Star Wars.
В этом сценарии мы применяем схему URL, но для ее определения также можно задействовать локальный файл .qql :
schema: 'src/**/*.graphql'
Или указать файл с несколькими шаблонами:
Параметр documents сообщает инструменту командной строки, откуда извлекать gql fragments/mutations/queries .
Имейте в виду, что генератор кода является голым инструментом, настройка которого производится с помощью плагинов. Обратите внимание на раздел plugins в codegen.yml . Так настраивается ядро.
В этой статье мы сосредоточимся на React с Apollo и Typescript, но его также можно использовать и с любыми другими вендорами или средами. Можно даже выводить код в других языках программирования, например в Java, .Net и Kotlin.
Для автоматической генерации всех типов нужно выполнить:
yarn generate
Обратите внимание, что сейчас мы получим сбой, так как еще не создали файл qql для парсинга.
Error : Unable to find any GraphQL type definitions for the following pointers: 'src/**/*.gql'
Создание запроса GraphQL
В этом примере им будет разбитый на страницы запрос для перечисления всех планет из Звездных войн.
Обратиться к конечной точке Star Wars можно здесь .
Вот как там будет выглядеть наш запрос:
Создадим на основе этого запроса файл planets.qql :
Обратите внимание, как мы объявляем запрос с приставкой query . Мы используем $ для объявления переменной $after и указываем для нее тип String . Он не является обязательным и не делает ее однозначно String , так как на начальной странице это значение будет пусто.
Теперь можно сгенерировать первый запрос:
npm generate / yarn generate
На этот раз вместо сбоя нас ожидал успех, так как теперь есть запрос для генерации в src/queries/planets.gql . Можете проверить сгенерированный файл src/generated/graphql.tsx и начать использовать его в проекте.
Подстройка генератора
Мы уже сгенерировали запрос с базовой конфигурацией. Теперь посмотрим, как можно улучшить генерируемый код более углубленной настройкой.
В этом инструменте командной строки есть набор предустановленных настроек, с которыми можно ознакомиться здесь . Вот некоторые из них:
config:
withHooks: true withComponent: false withHOC: false
Поскольку подход Component и HOC устарел, вам будет рекомендована версия hook . Если вы привыкли следовать рекомендациям, то все будет в порядке.
Есть несколько достойных внимания вариантов конфигурации. Вот три наиболее, на мой взгляд, актуальных:
1. Функциональное программирование
Сгенерированный код будет придерживаться стиля функционального программирования:
config:
constEnums: true immutableTypes: true
Это защитит вас от возможной мутации объектов результата запроса и необходимости использовать стиль кода, не допускающий изменения. В TypeScript очень удобно предотвращать мутации с помощью модификатора readonly .
2. Приставка
В некоторых командах принято добавлять приставки, например, к перечислениям и интерфейсам. В инструменте командной строки для этого есть ряд опций:
config:
typesPrefix: I
typesSuffix: I
enumPrefix: false
3. Стиль кода
Некоторые группы разработчиков не любят необязательные поля или используют их особым образом. Этот инструмент позволяет настроить поведение полей optional :
config:
avoidOptionals:
field: true inputValue: true object : true defaultValue: true
В документации по этой части есть и много другой полезной информации.
После настройки конфигурации итоговый файл codegen.yml будет выглядеть так:
Настройка клиента Apollo
Для получения возможности использовать и выполнять сгенерированный запрос, нужно настроить Apollo Client.
yarn add @apollo /client graphqlnpm install @apollo /client graphql
@apollo/client : этот пакет содержит практически все необходимое для настройки Apollo Client. Он включает внутренний кэш памяти, управление локальным состоянием, обработку ошибок и уровень представления на основе React.
graphql : этот пакет предоставляет логику для парсинга запросов GraphQL.
apollographql.com
Обратите внимание, что в codegen.yml мы используем typescript-react-apollo , который уже генерирует запросы Apollo.
Далее настроим Apollo Client и Provider:
Вот теперь можно применять сгенерированный запрос.
Использование сгенерированного GraphQL-запроса
При использовании интеграции Apollo генератор будет предоставлять автоматические или ручные запросы:
// активируется автоматически при рендеринге компонентов const { data, loading} = useAllPlanetsQuery();
// активируется вручную через вызов метода "getPlanets" const [getPlanets, { loading, data }] = useAllPlanetsLazyQuery();
В зависимости от ситуации вы будете применять тот или иной вариант — тип данных у них будет одинаков. Давайте взглянем на возвращаемый тип для PlanetQuery .
А теперь посмотрим все это в действии:
Так как все генерируется автоматически, можно не бояться потери синхронизации между бэкендом и фронтендом.
Чтобы извлечь из сгенерированного файла обобщенные типы, выполните следующее:
import type { Planet } from ‘../generated/graphql’;
А этой инструкцией можно получить тип конкретного запроса и извлечь пользовательские типы:
import type { AllPlanetsQuery } from '../generated/graphql' ;
Заключение
Мы рассмотрели генерацию простого GraphQL-запроса, но этот инструмент способен и на многое другое. Он предлагает такие возможности, как Fragments , Mutations и многие другие плагины.
Graphql Code Generator выполняет всю тяжелую работу за нас. Его очень легко настроить и адаптировать под ваши потребности. Этот инструмент уменьшает количество ручной работы, в ходе которой нередко возникают ошибки.
Удачным решением будет выполнять yarn generate в непрерывной интеграции. Это гарантирует стабильность и целостность в процессе разработки.
Читайте также:
Перевод статьи Jose Granja : Mixing Typescript and GraphQL Code Generator