Всем привет! Меня зовут Денис Ребенок, я технический писатель в команде Deckhouse. В этом материале я хочу рассказать про документирование GraphQL API. Если документация на GraphQL API оформлена правильно, разработчики быстро находят ответы, грамотно подобранные примеры сразу работают, а структура понятна с первого взгляда.

В этой статье разберём:
что такое GraphQL API и каковы его отличия от REST-like API;
что такое GraphQL schema и как с ней работать;
как сделать документацию на GraphQL API красивой и удобной для восприятия;
как создавать статические справочники для GraphQL API;
что ещё можно и нужно документировать при документировании GraphQL API.
В конце статьи вы найдёте ссылку на репозиторий на GitHub, который можно скачать, развернуть у себя и использовать, чтобы потренироваться в документировании GraphQL API.
Что такое GraphQL и чем он отличается от REST
GraphQL API — это специальный язык запросов и система их обработки, которая позволяет получать из API только те данные, которые действительно нужны.
Чтобы легче понять, что такое GraphQL API, я сравню его с REST-like API — де-факто корпоративным стандартом, который используют многие и с которым знакомо большинство технических писателей.
Объём возвращаемых данных
В REST сервер обычно возвращает весь объект целиком, даже если клиенту нужны только отдельные поля. Например, при запросе информации о пользователе возвращаются все параметры: name, email, birthDate, address, friends, registrationDate и многое другое, даже если клиенту это не требуется.
Иногда в REST пытаются решить это разными способами. Например, через фильтрацию (добавление в запрос параметров вроде ?fields=name,email), которую нужно реализовать для каждого метода, либо через явные и неявные маски. Но это всё не является частью стандарта и реализуется в каждом API по-своему. Часто — в зависимости от используемого для реализации API языка программирования — это бывает сложно, дорого и не всегда оправдано.
В GraphQL в запросе можно указать, какие поля требуются клиенту, и получить только их. Это позволяет снизить нагрузку на сеть, а также упрощает обработку полученных данных на стороне клиента.

Количество эндпоинтов (endpoints) и нейминг
Это следующее различие между GraphQL API и REST-like API.

В REST-like API существует множество разных эндпоинтов — свой под каждый запрос (операцию). Здесь для запросов используются разные HTTP-методы, такие как GET, POST, PUT, DELETE. И каждый запрос направляется на соответствующий эндпоинт.
В GraphQL API все запросы отправляются на один эндпоинт с использованием HTTP-метода POST, то есть используется одна конечная точка для всех операций. Но вопрос в том, как API-сервер понимает, что именно нужно клиенту: что-то получить, добавить или изменить какой-то объект. Здесь очень важно правильное именование запросов и операций.
Названия сделаны так, чтобы сразу было понятно, что выполняет тот или иной запрос: например, getAuthors означает «получить автора», createAuthors — «создать автора». Отправляются эти названия в теле запроса, там же указывается и тип оперции (query, mutation и пр.). Пример:
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-token-here" \
-d '{"query": "query { getAuthors { id name email } }"}' \
http://<host:port>/graphql/admin
Грамотный нейминг — обязательное условие при проектировании GraphQL API. И на документации, соответственно, это тоже отражается: понятные названия операций способствуют удобному восприятию документации и помогают быстро найти нужную информацию.
Получение всех связанных данных одним запросом
Ещё одно отличие GraphQL API от REST-like API — это возможность получить все связанные данные одним запросом, перечислив их в теле запроса. То есть, например, в GraphQL API мы можем отправить запрос, который нам вернёт информацию о пользователе и всех сущностях, связанных с ним. Допустим, его посты в соцсети, подписки, связи с другими пользователями и так далее.
В REST-like API, чтобы получить эту информацию, нужно выполнить несколько запросов. А это повышает нагрузку на сеть, требует каких-то лишних телодвижений на стороне клиента, чтобы объединить и обработать результаты нескольких запросов.

GraphQL schema: главный источник информации
Процесс создания GraphQL API в идеале начинается с разработки схемы API. Она описывает, какие данные есть в системе, какие операции с ними можно выполнять и как эти данные связаны между собой. Схема помогает сразу увидеть структуру данных и понять, какие объекты доступны в API, какие поля они содержат и как пользователь может к ним обращаться.
Поэтому технический писатель сначала обращается к аналитику, архитектору или разработчику и запрашивает у них готовую GraphQL-схему — с ней он и продолжает дальнейшую работу.
Схема описывает все ключевые элементы API: типы данных (types), используемые в API, запросы (queries), мутации (mutations), подписки (subscriptions), а также аргументы (arguments), директивы (directives) и фрагменты (fragments). Разберём некоторые из них.
Типы данных
В GraphQL API типы описывают структуру и характеристики данных, с которыми можно работать через API. Существует несколько типов:

Объектные типы (object types) описывают объекты, которыми оперирует API (которые могут запрашиваться, создаваться, редактироваться или удаляться).
Каждый объект имеет поля определённого типа (скаляр или объект).
Пример описания объектного типа в схеме:
type User {
id: ID!
name: String!
email: String!
age: Int
posts: [Post!]!
createdAt: String!
}
Скалярные типы (scalar types), или скаляры, — аналоги примитивных типов в языках программирования. К ним относятся, например, String, Int и так далее.
Перечисления (enums) — специальный скалярный тип, который представляет собой ограниченный набор допустимых значений для поля.
Пример описания такого типа из официальной документации:
enum Episode {
NEWHOPE
EMPIRE
JEDI}
Объединения (unions) сочетают в себе несколько объектов разных типов.
Интерфейсы (interfaces) позволяют гибко работать с разными типами данных через один и тот же запрос.
Запросы
Запросы определяют, какие данные можно получить из API. Если сравнивать с тем же REST-like API, это аналог GET-запросов. Примеры нескольких запросов:
type Query {
getBooks: [Book]
getBookById (bookId: ID!): Book
getBookByIsbn (bookIsbn:String!): Book
}
В этом примере описаны три запроса: получение списка книг, получение книги по ID и получение книги по ISBN.
Мутации
Мутации в GraphQL API определяют операции, которые изменяют данные на сервере. Это можно считать особым видом запроса, объединяющим в себе несколько типов запросов, используемых в REST-like API.
Другими словами, мутации выполняют ту же роль, что и методы POST, PUT, PATCH или DELETE в REST API, то есть изменяют данные на сервере: создание, обновление, удаление.
Пример:
type Mutation {
createBook (bookInput:CreateBookInput!): Book!
updateBook(bookId: ID!, bookInput:UpdateBookInput!): Book!
deleteBook(bookId:ID!): Book!
}
В этом примере описаны три мутации: добавление книги в базу, обновление информации о книге и удаление книги из базы. Здесь же наглядно видна важность правильного нейминга: взглянув на имя мутации, можно легко понять, что она выполняет.
Подписки
Подписки позволяют клиентам подписываться на изменения данных на сервере в режиме реального времени:
type Subscription {
bookCreated: Book
}
Под капотом для этого используются WebSockets. Если интересно, подробнее об этом можно прочитать в документации.
Пример GraphQL-схемы
Все перечисленные выше элементы (и не только) описываются в GraphQL-схеме. Вот небольшой пример:
type Author {
id: ID!
name: String!
books: [Book!]!
}
input CreateAuthorInput {
name: String!
}
type Query {
getAuthors: [Author!]!
}
type Mutation {
createAuthor (authorInput:
CreateAuthorInput!): Author!
updateAuthor (authorId: ID!, authorInput:
UpdateAuthorInput!): Author!
}
И уже из этой схемы генерируется документация, отображаемая в графическом интерфейсе GraphiQL Playground.
Документация в GraphiQL Playground
GraphiQL Playground — интерактивный инструмент для тестирования и изучения схемы GraphQL API прямо в браузере. С его помощью можно выполнять запросы и сразу видеть результаты. И от техписа во многом зависит удобство работы с этим интерактивным инструментом.

Важно
Ранее мы говорили о GraphQL как о технологии и API, а теперь речь заходит о GraphiQL (перед QL добавлено «i») Playground — инструменте, в котором можно всё посмотреть и попробовать.
Комментарии для удобной работы с GraphiQL Playground
Чтобы документация отображалась в интерфейсе GraphiQL, в схему нужно добавить комментарии — и этим занимается технический писатель. В схеме GraphQL поддерживаются два типа комментариев:
Комментарии с решёткой (#). Они не отображаются в интерфейсе GraphQL API и могут использоваться для служебных целей, например для заметок разработчиков.
# Комментарий, которого не будет видно
Комментарии в тройных кавычках (""" … """). Это именно те комментарии, с которыми работает техпис. Они отображаются в GraphiQL Playground и поддерживают разметку CommonMark. Последнее значит, что в комментариях можно использовать жирный и курсивный текст, заголовки, ссылки, даже таблицы. Всё это красиво отрисуется в GraphQL Playground. Подробнее о разметке CommonMark читайте на официальном сайте.
"""Комментарий, который виден в документации"""
type Author {
id: ID!
name: String!
books: [Book!]!
}
Вот как комментарии в тройных кавычках выглядят в схеме — и именно из них генерируется документация:

А вот такой результат получается в самом GraphiQL Playground:

Согласитесь, это выглядит гораздо приятнее, чем просто обычный текст: добавлена структура, сразу понятно, куда смотреть.
Примеры кода для GraphiQL Playground
Подробных текстов, комментариев с заголовками, списками и таблицами зачастую бывает недостаточно для пользователей GraphQL API.
Поэтому рекомендую добавлять в документацию блоки кода — причём брать их из реальных примеров. Идите к разработчикам, спрашивайте, какие кейсы они реализуют с помощью конкретных фрагментов кода, и включайте эти фрагменты в GraphQL-схему.
Пример описания мутации в схеме GraphQL API с блоком кода:

Блоки кода значительно улучшают восприятие документации: она становится нагляднее и удобнее для чтения. Вот как приведённый выше комментарий с примером кода отрисуется в GraphiQL Playground:

Разработчик может скопировать такой блок, вставить его, например, в GraphiQL Playground и сразу попробовать, как всё работает.
Это позволяет сэкономить время на разборе того, как вообще строится тот или иной запрос.
Перед добавлением в схему блоков кода рекомендую их прогонять через GraphQL Formatter. Он находит любые ошибки и делает так, чтобы код красиво рендерился в интерфейсе GraphiQL Playground.
В коде можно сделать подсветку синтаксиса, чтобы в GraphiQL Playground это выглядело ещё понятнее и нагляднее:

С подсветкой гораздо быстрее найти нужную информацию и проще понять, что за запрос перед вами: какие данные он запрашивает и как вообще устроен.
Это вполне по силам техническому писателю. Интерфейс GraphiQL Playground генерируется на основе шаблона страницы — в нашем случае это шаблон на React. Его можно доработать, добавив подсветку кода.
Как именно реализовать подсветку — решать вам, исходя из потребностей и навыков. Например, можно написать собственный JavaScript-код, добавить нужные CSS- и HTML-правила прямо в шаблон — и всё будет корректно отображаться.
А можно воспользоваться готовым решением. Я, например, использовал библиотеку Prism. В ней можно указать языки, подсветку которых нужно поддерживать, после чего будут сгенерированы готовые фрагменты кода. Их достаточно скопировать, вставить в ваш шаблон генерации GraphiQL Playground — и документация начнёт отображаться с красивой и читаемой подсветкой синтаксиса.
Ещё можно добавить возможность копировать эти фрагменты одним нажатием кнопки. Представьте: пользователь кликает по кнопке, код сразу попадает в буфер обмена, он вставляет его в GraphiQL Playground — и всё работает.

Это тоже вполне по силам техническому писателю. Как и в случае с подсветкой, есть несколько вариантов реализации:
самостоятельно написать нужные скрипты и стили и внедрить их в шаблон, из которого генерируется документация;
воспользоваться готовым решением;
обратиться к своим коллегам — фронтендерам или разработчикам, чётко объяснив, чего вы хотите добиться.
Когда вы внедрите такую функцию, я гарантирую: вы получите положительный фидбэк от тех, кто будет работать с вашей документацией.
Мы рассмотрели одну форму документирования GraphQL API — документацию, встроенную в GraphiQL Playground. Но иногда бывают ситуации, когда доступ к Playground пользователям не предоставляется: например, по требованиям безопасности или по другим причинам. Да и GraphiQL Playground может вообще не генерироваться при сборке API. В таких случаях нам на помощь приходит следующая форма документирования — статические сайты-справочники.
Статические сайты-справочники
Ещё один способ документирования GraphQL API — это создание статических сайтов-справочников. Наверняка многие сталкивались с подобными сайтами при работе с REST API, gRPC или другими видами API. Это отдельные веб-страницы, на которых отображается вся информация об API: описание методов и типов данных, примеры запросов и другая полезная документация.
Найти инструмент для генерации такого статического сайта можно на сайте официальной экосистемы GraphQL — там собрано множество инструментов для разработчиков, аналитиков и других участников процесса, включая технических писателей.
Один из таких инструментов — SpectaQL. Он генерирует статические сайты на основе данных, полученных с помощью запроса интроспекции (Introspection queries) — ещё одна важная тема, которую техпису стоит изучить перед началом документирования GraphQL API.
Вот так может выглядеть статический сайт с документацией по GraphQL API, сгенерированный с помощью SpectaQL:

Интроспекция в GraphQL
Интроспекция — это специальный GraphQL-запрос, который позволяет сразу получить всю информацию, содержащуюся в схеме: все типы данных, все query-запросы, мутации, подписки и так далее.
Если в схеме есть комментарии, оформленные в тройных кавычках (как мы обсуждали ранее), они также попадают в результат интроспекции. Именно эти данные SpectaQL использует для генерации статического сайта.
Сам запрос интроспекции может выглядеть довольно объёмно (на скриншоте лишь его малая часть):

На самом деле этот запрос не так страшен, как кажется: если уделить ему немного внимания, всё становится понятным и легко воспринимается.
А ещё его можно сделать и более узконаправленным — запрашивать не всю схему целиком, а только определённые её части. Например, получить только информацию о типах данных и на её основе сгенерировать документацию:

Как именно превращать эти данные в документацию — решать вам: можно использовать SpectaQL или любой другой подходящий инструмент.
Как генерировать документацию с помощью SpectaQL
Можно выделить два основных сценария генерации сайта-справочника с помощью SpectaQL.
Первый вариант — полная автоматизация.
Вы скачиваете себе репозиторий с этим генератором, указываете настройки в определённых местах и запускаете генератор. Он самостоятельно делает запрос интроспекции, получает ответ, обрабатывает его и генерирует сайт. То есть всё автоматизировано.
Второй вариант — ручной подход.
Техпис, аналитик или другой участник процесса создания документации делает запрос интроспекции вручную, обрабатывает его результаты, копирует нужную часть и передаёт всё в генератор SpectaQL. Далее запускается генератор, который создает сайт.
Кастомизация сайта-справочника, созданного с помощью SpectaQL
Независимо от того, используется полная автоматизация или сборка вручную, технический писатель может кастомизировать внешний вид статического сайта. Так как SpectaQL — это Open Source-инструмент и вы работаете с его репозиторием напрямую, можно изменять его под свои нужды. Там есть всё необходимое — папки со стилями, скриптами, шаблонами. Вы это всё изменяете под себя и получаете статический сайт-справочник именно таким, каким хотите его видеть.
Что ещё документировать и как
Мы рассмотрели две основные формы документирования GraphQL API:
документацию, встроенную в схему и отображаемую в GraphiQL Playground;
документацию в виде статического сайта-справочника.
Однако мой опыт показывает, что этого может быть недостаточно.
Я рекомендую дополнить документацию следующими элементами (можно разместить их, например, в отдельном разделе портала документации):
1. Краткий обзор технологии. Объясните, что такое GraphQL, зачем он нужен и в чём его преимущества. Это особенно полезно для тех, кто с этой технологией раньше не сталкивался, — им будет проще «вкатиться».
2. Описание запросов, мутаций и подписок — с акцентом на принципы их построения. Не ограничивайтесь абстрактными примерами. Лучше подойти к разработчикам, спросить: «Как вы решали такую-то задачу? Как использовали такие-то возможности?» Полученные реальные кейсы включите в документацию — это сделает её гораздо более практичной.
3. Сравнения и аналогии с REST API или другими API, с которыми ваша команда работала ранее. На примере знакомых концепций новая технология усваивается значительно легче — пользователи быстрее понимают, как к ней подступиться.
4. Раздел с некоторыми концепциями API. Поговорим о них подробнее.
Концепции в GraphQL API, которые стоит описать в документации
GraphQL вводит некоторые новые концепции, касающиеся организации данных и взаимодействия с ними. И я рекомендую рассмотреть некоторые из них в документации. Это особенности и «фишки» технологии, которые позволяют использовать API гораздо эффективнее. Внимания заслуживают следующие моменты, которые стоит включить в документацию: псевдонимы, фрагменты, переменные и директивы.
Псевдонимы(aliases) позволяют переименовывать поля в ответе на запрос.

Это полезно, например, когда одним запросом запрашивается несколько одинаковых объектов и нужно чётко различать, какое поле к какому объекту относится. С помощью псевдонимов структура ответа становится более понятной и удобной для обработки.
Фрагменты (fragments) — это способ вынести повторяющийся набор полей в отдельную конструкцию и многократно её использовать.

Представьте: вы запрашиваете много однотипных объектов, и для каждого пришлось бы перечислять один и тот же список полей ответа. Без фрагментов запрос стал бы громоздким и трудночитаемым. С фрагментами же он остаётся компактным и аккуратным.
Переменные (variables) позволяют выделять динамические значения в запросе и передавать их в запрос в виде отдельного словаря.

Это полезная штука, например, для фронтендеров при работе с выпадающими списками, формами или другими интерактивными элементами. С помощью переменных мы можем управлять ответом, который получаем. И фронтендеры это очень активно используют.
Директивы (directives) дают возможность динамически менять структуру запроса «на лету».

Например, с помощью директивы можно указать, что определённое поле должно возвращаться только при выполнении какого-то условия. Это позволяет адаптировать запрос и его ответ без необходимости писать несколько разных версий.
Если вы включите описание упомянутых выше «штук» в документацию — с пояснениями и примерами, — разработчики точно оценят вашу работу. Они будут довольны.
Где «пощупать» GraphQL API и набить руку в документировании
Перед тем как приступить к документированию GraphQL API, естественно, захочется «пощупать» эту технологию на реальных примерах. И это вполне возможно — потренироваться можно в нескольких местах:
Официальный сайт GraphQL. На его страницах есть интерактивная документация: прямо в неё встроены редактируемые примеры запросов. Вы можете редактировать их и сразу видеть, как меняется результат. Это отличный способ «набить руку».
Реальный GraphQL API от GitHub. Платформа уже давно использует GraphQL, вы можете войти под своим аккаунтом и выполнять запросы к своим репозиториям, проектам и профилю. Главное — действовать осторожно, чтобы случайно ничего не сломать или не удалить.
Специальный тренировочный API — Rick and Morty API. Там вы не только потренируетесь строить запросы, но и заодно узнаете интересные факты о персонажах мультсериала. Однако учтите: в этом API работают только query-запросы, то есть получать данные можно, а мутации недоступны.
Конечно, пробовать запросы — это полезно, но, перед тем как документировать реальный API, наверняка захочется потренироваться именно на процессе документирования.
Для этого подойдёт репозиторий, о котором я упоминал в начале. Вы можете скачать его и развернуть GraphQL API локально. Следуйте подробной инструкции в репозитории: там описано, где и что писать, как оформлять схему, как добавлять комментарии и генерировать документацию. В репозитории даже есть готовый пример.
В этом локальном API работают и query-запросы, и мутации, а главное — всё это развернуто у вас на машине локально. Вы будете полным хозяином ситуации: сможете экспериментировать сколько угодно, ничего не боясь сломать.
Скачивайте, тренируйтесь, прокачивайте навыки — и создавайте действительно крутую документацию для пользователей GraphQL API.
P. S.
Читайте также в нашем блоге: