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

Однако на самом деле GraphQL - это просто спецификация, описывающая API. Многие функции, которые можно ожидать от API, такие как логика авторизации / аутентификации, двунаправленная связь или ограничение скорости, еще предстоит реализовать. Недавно запущенный Slash GraphQL - это полностью управляемый бэкэнд GraphQL, который берет на себя всю тяжелую работу по настройке GraphQL API, позволяя вам сосредоточиться на создании своего приложения.

В этой статье мы будем создавать книжный магазин электронной коммерции, основанный на Slash GraphQL. Чтобы продемонстрировать гибкость сервиса, мы также будем извлекать данные из другого источника - Goodreads API - и интегрировать их в наши ответы.

Мы будем создавать наше приложение с использованием Node.js, поэтому на вашем компьютере должна быть установлена ​​как минимум версия 12. Создайте каталог с именем slashql_bookstore и перейдите в него из командной строки.

Создание бэкэнда GraphQL

Настройка Slash GraphQL

Настроить учетную запись на Slash GraphQL просто - вы можете мгновенно войти в свою учетную запись GitHub. Платформа предлагает бесплатную пробную версию, которая будет работать для этой статьи (затем будет установлена ​​фиксированная плата в размере 9,99 долларов США в месяц за данные объемом до 5 ГБ).

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

1. Щелкните «Запустить новый сервер».

2. Назовите бэкэнд «Книжный магазин».

3. Щелкните «Запустить».

Вот и все! Теперь у вас есть сервер, созданный для вас в регионе AWS.

Определение схемы GraphQL

Каждый сервер GraphQL имеет строго типизированную схему, которая определяет объекты и поля, доступные потребителям.

Щелкните «Схема» и вставьте следующие строки:

type Book {
  id: Int!
  isbn: Int!
  title: String! @search(by: [fulltext])
  author: Author!
}
type Author {
  id: Int!
  firstname: String!
  lastname: String!
}

Здесь мы определили два типа - Книга и Автор, которые будут представлять данные в нашем API. Из множества тонкостей, которые предоставляет Slash GraphQL, его поддержка пользовательских директив - одна из самых удобных. Здесь, например, аннотируя поле title с помощью @search, мы можем предоставить нечеткий текст без каких-либо дополнительных действий.

Нажмите «Развернуть», чтобы отправить эту схему в производство.

Настройка данных

Переходим к вставке данных. Мы можем использовать API Explorer не только для добавления данных, но и для их запроса. Чтобы заполнить наш бэкэнд GraphQL, мы определим список книг и их авторов с помощью мутации, которую Slash GraphQL удобно предоставляет нам, на основе нашей схемы:

mutation AddData {
  addBook(input: [
    {id: 1, title: “The Sound and The Fury”, isbn: 9780394747743, author: {id:1, firstname: “William”, lastname: “Faulkner”}},
    {id: 2, title: “Light in August”, isbn: 9780394711898, author:{id:1, firstname: “William”, lastname: “Faulkner”}},
    {id: 3, title: “Giovanni’s Room”, isbn: 9780141032948, author:{id:2, firstname: “James”, lastname: “Baldwin”}},
    {id: 4, title: “The Fire Next Time”, isbn: 9780140182750, author: {id:2, firstname: “James”, lastname: “Baldwin”}},
    {id: 5, title: “To The Lighthouse”, isbn: 9780140274165, author: {id:3, firstname: “Virginia”, lastname: “Woolf”}},
    {id: 6, title: “Orlando”, isbn: 9780241284643, author: {id:3, firstname: “Virginia”, lastname: “Woolf”}}
    ]) {
  numUids
  }
}

Нажмите гигантскую кнопку «Воспроизвести», чтобы добавить эти данные в серверную часть.

Теперь давайте запустим запрос, чтобы убедиться, что эти данные присутствуют:

query GetBooks {
  queryBook {
    title
    isbn
    author {
      firstname
      lastname
    }
  }
}

Вы должны увидеть ответ, в котором будут показаны все ранее введенные данные.

Сборка сервера

Теперь мы воспользуемся Express, чтобы настроить базовый сервер API, который предоставит пользователям доступ к этому источнику Slash GraphQL. Наш Express-сервер действует как не более чем интерфейс для передачи запросов в Slash GraphQL. Его самые важные строки таковы:

const BACKEND_URL = “https://rampant-arm.us-west-2.aws.cloud.dgraph.io/graphql"
async function fetchGraphQL(operationsDoc, variables) {
  const result = await axios({
    method: ‘POST’,
    url: BACKEND_URL,
    headers: {
      ‘Content-Type’: ‘application/json’,
    },
    data: JSON.stringify({
      query: operationsDoc,
      variables,
    }),
  })
  return result.data
}
const query = `
query {
  queryBook {
    title
    isbn
    author {
      firstname
      lastname
    }
  }
}
`
app.get(‘/’, jsonParser, async (req, res) => {
  let gqlResponseData = await fetchGraphQL(query, {})
  res.render(‘index’, { books: gqlResponseData.data.queryBook })
})

Здесь мы определили вспомогательную функцию fetchGraphQL, которая устанавливает необходимые заголовки и данные для отправки в Slash GraphQL. Имейте в виду, что вам нужно будет изменить BACKEND_URL, чтобы он соответствовал URL-адресу, который вам дает Slash GraphQL. Затем мы пишем запрос GraphQL, который определяет данные, которые нам нужны. Наконец, мы настраиваем маршрут для получения этих данных, а затем отображаем их в нашем представлении:

<div class=”container”>
  {{#each books}}
  <div class=”row”>
    <div class=”col-md-4">
      <h2>{{title}}</h2>
      <h4>{{author.firstname}} {{author.lastname}}</h4>
      <p><strong>ISBN:</strong> {{isbn}}</p>
    </div>
  </div>
  <hr>
  {{/each}}
</div>

Наше мнение поддерживается популярной библиотекой шаблонов handlebars. Мы можем передать наши данные JSON во фрагмент HTML и перебирать ключи и значения, что значительно упрощает отображение информации. Здесь мы используем цикл #each для просмотра каждой книги, возвращаемой GraphQL API, а затем вставляем данные в теги HTML. Вы заметите, что у нас есть заполнители, которые соответствуют именам ключей JSON; они заменяются реальными данными при просмотре страницы.

После того, как вы установили все зависимости с помощью npm, запустите сервер с node server.js. Затем перейдите на localhost: 3000 в своем браузере:

Вы должны получить тот же ответ, что и API Explorer Slash GraphQL.

Расширить сервер

В качестве последнего шага мы хотим предоставить некоторые данные рецензентов об этих книгах. Но мы не хотим создавать здесь фиктивные данные; вместо этого мы будем использовать Goodreads API. Прежде чем продолжить, убедитесь, что вы создали там учетную запись и получили ключ API.

Одна из многих вещей, которыми выделяется Slash GraphQL, - это способность объединять разрозненные источники данных в один интерфейс GraphQL. Возможно, вы захотите выполнять вызовы к другим конечным точкам API, находящимся под вашим контролем. Для поддержки этого Slash GraphQL предоставляет директиву @custom, которая позволяет вам реализовать собственное поведение для полей и преобразователей GraphQL.

Во-первых, давайте добавим нашу рейтинговую информацию к существующей схеме:

type Rating @remote {
  ratings_count: Int!
  average_rating: Float!
}

Наш тип рейтинга определяет имена полей, которые мы ожидаем от API book.show_by_isbn. Нам не нужно определять все поля, предоставляемые их REST API, только те, которые нам интересны. Slash GraphQL знает, как преобразовать этот ответ в GraphQL.

Что касается полей, нам нужно будет указать URL-адрес, по которому мы хотим вызвать, вместе с методом HTTP:

type Book {
  # …
  rating: Rating @custom(http: {
  url: “https://goodreads-api-munger.glitch.me?isbn=$isbn",
  method: GET
  })
  # …
}

Вы можете заметить здесь, что мы на самом деле призываем к проекту с ошибками. API Goodreads не возвращает данные JSON в удобном и удобном формате. Мы будем обращаться к промежуточному серверу, который переведет данные в более читаемый формат. Детали этого сервера не так уж и важны (но вы можете проверить это, если хотите). важно отметить, что этот URL может заменять что угодно, что может быть очень полезно, если вы взаимодействуете с данными, которые принадлежат вам.

Еще одна удивительная вещь - Slash GraphQL заменит вам данные. Видите ту часть URL-адреса, в которой написано: $ isbn? В зависимости от объекта, возвращаемого нашим запросом, Slash GraphQL подставит реальное значение поля для этой переменной. Это делает ваши URL-запросы гибкими и простыми в управлении.

Это все, что нам нужно сделать, чтобы ввести некоторые пользовательские данные. Теперь наш запрос GraphQL может просто добавить это поле рейтинга, чтобы ввести эти внешние данные. Давайте заменим запрос в нашем server.js на этот:

const query = `
query {
  queryBook {
    title
    isbn
    rating {
      ratings_count
      average_rating
    }
    author {
      firstname
      lastname
    }
  }
}
`

И давайте обновим представление, чтобы отобразить эту информацию:

<div class=”container”>
  {{#each books}}
    <div class=”row”>
      <div class=”col-md-4">
      <h2>{{title}}</h2>
      <h4>{{author.firstname}} {{author.lastname}}</h4>
      <p><strong>ISBN:</strong> {{isbn}}</p>
      <p>Rating: {{rating.average_rating}} (out of {{rating.ratings_count}} votes)</p>
    </div>
  </div>
  <hr>
  {{/each}}
</div>

Если вы перезапустите сервер и вернетесь к localhost: 3000, вы также должны увидеть заполненные рейтинги:

Заключение

Slash GraphQL позволяет невероятно легко настроить GraphQL API производственного уровня, но мы коснулись лишь поверхности. Помимо возможности комбинировать разрозненные местоположения данных, он также поддерживает авторизацию, подписку и даже шифрование.

Вы можете получить полный исходный код этого руководства на GitHub. Если вы еще этого не сделали, не забудьте зарегистрироваться в Slash GraphQL - не стесняйтесь делиться своими творениями с остальной частью сообщества Dgraph.