# Миграция из REST в GraphQL

Изучите лучшие практики и рекомендации по миграции с GitHubREST API на GitHubGraphQL от GraphQL.

## Отличия в логике API

GitHub предоставляет два API: REST API и GraphQL API. Для получения дополнительной информации об GitHubAPI с (AUTOTITLE) см. [Сравнение REST API GitHub и GraphQL API](/ru/enterprise-server@3.22/rest/about-the-rest-api/comparing-githubs-rest-api-and-graphql-api).

Миграция из REST в GraphQL сопровождается существенным изменением в логике API. Различия между стилем REST и спецификацией GraphQL затрудняют— и часто делают нежелательной— замену вызовов REST API на запросы API GraphQL один к одному. Ниже приведены примеры миграции.

Чтобы перенести код из [REST API](/ru/enterprise-server@3.22/rest) в GraphQL API, выполните следующие действия:

* ознакомьтесь со [спецификацией GraphQL](https://spec.graphql.org/June2018/);
* Пересмотрите схему GitHub [GraphQL](/ru/enterprise-server@3.22/graphql/reference)
* Подумайте, как ваш существующий код взаимодействует с API GitHub REST
* Используйте [Global Node IDs](/ru/enterprise-server@3.22/graphql/guides/using-global-node-ids) для ссылок на объекты между версиями API

К значительным преимуществам GraphQL относятся:

* [получение только необходимых данных](#example-getting-the-data-you-need-and-nothing-more);
* [вложенные поля](#example-nesting);
* [Строгая типизация](#example-strong-typing)

Ниже приведены примеры каждого из них.

## Пример: получение только необходимых данных

Один вызов REST API получает список участников вашей организации:

```shell
curl -v http(s)://HOSTNAME/api/v3/orgs/:org/members
```

Полезные данные REST содержат избыточную информацию, и какая-то ее часть окажется ненужной, если вам нужно получить только имена членов и ссылки на аватары. Запрос GraphQL, напротив, возвращает только то, что вы указываете:

```graphql
query {
    organization(login:"github") {
    membersWithRole(first: 100) {
      edges {
        node {
          name
          avatarUrl
        }
      }
    }
  }
}
```

Рассмотрим другой пример: получение списка запросов на включение внесенных изменений и проверка возможности слияния для каждого из них. Вызов REST API получает список запросов на включение внесенных изменений и их [сводные представления](/ru/enterprise-server@3.22/rest#summary-representations):

```shell
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls
```

Чтобы определить, можно ли выполнить слияние для запроса на включение внесенных изменений, требуется получить каждый запрос на включение внесенных изменений по отдельности ради его [подробного представления](/ru/enterprise-server@3.22/rest#detailed-representations) (большой объем полезных данных) и проверить, имеет ли его атрибут `mergeable` значение true или false:

```shell
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number
```

При использовании GraphQL для каждого запроса на включение внесенных изменений можно получить только необходимые атрибуты `number` и `mergeable`:

```graphql
query {
    repository(owner:"octocat", name:"Hello-World") {
    pullRequests(last: 10) {
      edges {
        node {
          number
          mergeable
        }
      }
    }
  }
}
```

## Пример: вложенные поля

Благодаря поддержке запросов с вложенными полями можно заменить несколько вызовов REST на меньшее количество запросов GraphQL. Например, получение запроса на включение внесенных изменений вместе с его фиксациями, комментариев без проверки и проверок с помощью **REST API** требует четырех отдельных вызовов:

```shell
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number/commits
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/issues/:number/comments
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number/reviews
```

С помощью **API GraphQL** эти данные можно получить с помощью одного запроса с вложенными полями:

```graphql
{
  repository(owner: "octocat", name: "Hello-World") {
    pullRequest(number: 1) {
      commits(first: 10) {
        edges {
          node {
            commit {
              oid
              message
            }
          }
        }
      }
      comments(first: 10) {
        edges {
          node {
            body
            author {
              login
            }
          }
        }
      }
      reviews(first: 10) {
        edges {
          node {
            state
          }
        }
      }
    }
  }
}
```

Вы также можете расширить мощность этого запроса, подставив [подставив переменную](/ru/enterprise-server@3.22/graphql/guides/forming-calls-with-graphql#working-with-variables) номер pull request.

## Пример: строгая типизация

Схемы GraphQL строго типизированы, что делает обработку данных безопаснее.

Рассмотрим добавление комментария к проблеме или запросу на включение внесенных изменений с помощью [изменения](/ru/enterprise-server@3.22/graphql/reference) GraphQL, когда для значения [`clientMutationId`](/ru/enterprise-server@3.22/graphql/reference/issues#mutation-addcomment) по ошибке было указано целое число вместо строки:

```graphql
mutation {
  addComment(input:{clientMutationId: 1234, subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
    clientMutationId
    commentEdge {
      node {
        body
        repository {
          id
          name
          nameWithOwner
        }
        issue {
          number
        }
      }
    }
  }
}
```

При выполнении этого запроса возвращаются ошибки с указанием ожидаемых типов для операции:

```json
{
  "data": null,
  "errors": [
    {
      "message": "Argument 'input' on Field 'addComment' has an invalid value. Expected type 'AddCommentInput!'.",
      "locations": [
        {
          "line": 3,
          "column": 3
        }
      ]
    },
    {
      "message": "Argument 'clientMutationId' on InputObject 'AddCommentInput' has an invalid value. Expected type 'String'.",
      "locations": [
        {
          "line": 3,
          "column": 20
        }
      ]
    }
  ]
}
```

Если заключить `1234` в кавычки, значение будет преобразовано из целого числа в строку ожидаемого типа:

```graphql
mutation {
  addComment(input:{clientMutationId: "1234", subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
    clientMutationId
    commentEdge {
      node {
        body
        repository {
          id
          name
          nameWithOwner
        }
        issue {
          number
        }
      }
    }
  }
}
```