Что такое GraphQL

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

С официального сайта:

GraphQL - это язык запросов для API и среда выполнения для выполнения этих запросов с вашими существующими данными. GraphQL предоставляет полное и понятное описание данных в вашем API.

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

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

Начиная.

Я пройду через весь процесс, но вы можете получить весь репозиторий здесь

Создание проекта

Во-первых, нам нужно настроить наш проект.

1 Создайте свой рабочий каталог

В вашем терминале выполните следующую команду: mkdir btc-gql-api && cd btc-gql-api, эта команда создаст новую папку в вашем текущем каталоге и получит доступ к ней.

2 Начните свой проект

В вашем терминале запустите yarn init или npm install и заполните поля, которые будут запрошены. Это создаст в вашем каталоге следующий файл:

package.json

Пакет будет выглядеть примерно так:

{
  "name": "my-new-project",
  "version": "1.0.0",
  "description": "My New Project description.",
  "main": "index.js",
  "repository": {
    "url": "https://example.com/your-username/my-new-project",
    "type": "git"
  },
  "author": "Your Name <[email protected]>",
  "license": "MIT"
}
  • Запустите touch index.js, чтобы создать файл записи в вашем рабочем каталоге. (Если вы находитесь в Windows, создайте файл вручную в редакторе кода).
  • Добавьте команду запуска, в свой package.json добавьте новый раздел:
...
"scripts": {
  "start": "node index.js"
},
...

Ваш пакет должен выглядеть так:

{
  "name": "my-new-project",
  "version": "1.0.0",
  "description": "My New Project description.",
  "main": "index.js","scripts": {
    "start": "node index.js"
  },
  "repository": {
    "url": "https://example.com/your-username/my-new-project",
    "type": "git"
  },
  "author": "Your Name <[email protected]>",
  "license": "MIT"
}

Создайте новую папку с именем graphql в вашем рабочем каталоге, чтобы ваша структура выглядела так:

+ btc-gql-api
|__ graphql
|__ package.json
|__ index.json

Создайте три новых файла с именами types.js, resolvers.js, request.js внутри каталога graphql, ваш проект должен выглядеть так:

+ btc-gql-api
|__+graphql
|____request.js
|____resolvers.js
|____types.js
|__ package.json
|__ index.json

3 Установка зависимостей

Для этого проекта нам понадобятся две зависимости: axios и graphql-yoga, поэтому мы запускаем yarn add axios graphql-yoga.

Вот и все, мы настроили наш проект и можем приступить к написанию кода!

Типы

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

type User {
  name: String!
  email: String!
}

GraphQL поставляется с набором скалярных типов по умолчанию из коробки:

  • Int: 32-битное целое число со знаком.
  • Float: значение с плавающей запятой двойной точности со знаком.
  • String: последовательность символов UTF ‐ 8.
  • Boolean: правда или ложь.
  • ID: Тип скалярного идентификатора представляет собой уникальный идентификатор, часто используемый для выборки объекта или в качестве ключа для кеша. Тип идентификатора сериализуется так же, как String; однако определение его как идентификатора означает, что он не предназначен для чтения человеком.

Также существует способ указать пользовательские скалярные типы. Например, мы могли бы определить тип Date:

scalar Date

Если вы хотите узнать больше о типах в GraphQL, я рекомендую вам ознакомиться с документацией GraphQL.

Создадим наши типы!

Откройте файл ./graphql/types.js в редакторе кода и добавьте следующее:

const typeDefs = `
scalar JSON
type Price {
  price:JSON!
}`;
module.exports = typeDefs;

Что здесь только что произошло? Что ж, как мы узнали раньше, GraphQL использует язык типов для представления объектов в вашем API, для нашего биткойн-API нам сейчас понадобится только один тип в нашей схеме, тип Price

...
type Price {
  price:JSON!
}
...

Как видите, тип Price имеет только одно поле с именем price, а его тип JSON и не может быть нулевым (это то, что ! означает символ). Мы говорили о типе данных по умолчанию, который GraphQL включает по умолчанию, а JSON не входит в их число, поэтому нам нужно его определить:

scalar JSON
type Price {
  price:JSON!
}
...

Запросы

GraphQL предназначен для управления данными, query в основном запрашивает определенные поля для объектов: Запрос:

query {
  getPrices {
    price
  }
}

Результат:

{
  "data": {
    "getPrices": {
      "price": {
        "USD": {
          "15m": 10436.54,
          "last": 10436.54,
          "buy": 10436.54,
          "sell": 10436.54,
          "symbol": "$"
        }
        ...
      }
    }
  }
}

Как видите, ответ имеет ту же структуру, что и запрос.

Типы запросов и мутаций

Есть два других типа типов, которые являются особенными в схеме, Query и Mutation.

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

scalar JSON
type Price {
  price:JSON!
}
type Query {
  getPrices: Price!
  getPrice(currency:String!): Price!
}

Это означает, что наша служба GraphQL имеет тип запроса с полями getPrices и getPrice, и оба они равны нашему типу Price, и мы видим, что поле getPrice имеет аргумент (currency:String!). Каждое поле типа объекта GraphQL может иметь ноль или более аргументов.

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

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

7 Помощник по запросу

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

Откройте файл, который мы создали ранее: ./graphql/request.js и добавьте следующее:

const axios = require("axios");
module.exports = {
  getPrices: async () => {
    const url = "https://blockchain.info/ticker";
    try {
      return await axios.get(url);
    } catch (error) {
      console.error(error);
    }
  }
};

Мы собираемся использовать axios для выполнения GET запроса, но вы легко можете использовать любой другой инструмент для этого.

8 резольверов

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

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

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

Откройте файл ./graphql/resolvers.js и добавьте следующее:

const requests = require("./requests");
const resolvers = {
  Query: {
    // Get all available prices
    async getPrices(parent, args, ctx, info) {
      const prices = await requests.getPrices();
      return { price: prices.data };
    },
    // Get the price of a given currency symbol
    async getPrice(parent, args, ctx, info) {
      const prices = await requests.getPrices();
      return { price: { [args["currency"]]: prices.data[args["currency"]] } };
    }
  }
};
module.exports = resolvers;

Давайте разберемся, сначала мы импортируем наш помощник по запросу:

const request = require("./request");

Нам не нужно объявлять или преобразовывать объект:

const resolvers = {
  Query: {
    // Get all available prices
    async getPrices(parent, args, ctx, info) {
      const prices = await requests.getPrices();
      return { price: prices.data };
    },
    // Get the price of a given currency symbol
    async getPrice(parent, args, ctx, info) {
      const prices = await requests.getPrices();
      return { price: { [args["currency"]]: prices.data[args["currency"]] } };
    }
  }
};

У нашего объекта преобразователя есть корень с именем Query, и внутри этого объекта мы собираемся объявить все преобразователи, которые есть в нашей схеме GraphQL, обратите внимание, что мы назвали эти преобразователи так же, как и в файле types.js.

Каждый преобразователь - это просто функция, реализующая наш помощник по запросу, наша функция преобразователя получает четыре аргумента:

  • parent: Предыдущий объект, который для поля корневого типа запроса часто не используется.
  • args: аргументы, предоставленные полю в запросе GraphQL.
  • ctx: значение, которое предоставляется каждому преобразователю и содержит важную контекстную информацию, такую ​​как текущий зарегистрированный пользователь или доступ к базе данных.
  • info: значение, которое содержит информацию о поле, относящуюся к текущему запросу, а также сведения о схеме.

9 Сервер

Теперь, когда у нас есть types, resolvers и помощники, нам просто нужно настроить server, чтобы завершить наш очень маленький биткойн-API.

Откройте файл index.js, который мы создали ранее, и добавьте следующее:

const { GraphQLServer } = require("graphql-yoga");
const typeDefs = require("./graphql/types.js");
const resolvers = require("./graphql/resolvers.js");
const server = new GraphQLServer({
  typeDefs,
  resolvers,
  context: {
    //if we pass anything here can be available in all resolvers
  }
});
server.start(() => console.log("Server is running on localhost:4000☄"));

Как видите, мы импортировали библиотеку GraphQLServer и наши typeDefs и преобразователи, затем мы создаем новый экземпляр GraphQLServer и передаем конфигурацию:

...
const server = new GraphQLServer({
  typeDefs,
  resolvers,
  context: {
    //if we pass anything here can be available in all resolvers
  }
});
...

Наконец-то запускаем сервер !:

server.start(() => console.log("Server is running on localhost:4000☄"));

Вот и все! Теперь нам просто нужно запустить npm start в нашем терминале, и если с нашим кодом все в порядке, мы должны увидеть следующее сообщение:

Server is running on localhost:4000☄

Откройте браузер и попали в http://localhost:4000, если все работает, вы должны увидеть интерфейс игровой площадки.

Проверьте запросы: Все доступные валюты:

query{
  getPrices{
    price
  }
}

Запросить конкретную валюту:

query($currency:String!){
  getPrice(currency:$currency){
    price
  }
}
# Variables:
{
  "currency": "USD"
}

Вы должны увидеть такой ответ:

Вот и все, мы создали очень простой биткойн API с GraphQL и изучили основы, чтобы начать работу с GraphQL. Если вы хотите узнать больше об этой технологии, перейдите на GraphQL.org.

В следующих сообщениях мы узнаем, как использовать мутации для создания адресов биткойнов и отправки транзакций в сеть с помощью тестовой сети, а затем мы собираемся создать веб-клиент с использованием клиента Apollo и React для взаимодействия с нашим GraphQL API.

Если у вас есть вопросы, не сомневайтесь, задавайте их в комментариях или подписывайтесь на меня в твиттере в LuisAcerv, я буду рад помочь!

Удачного кодирования!

Ресурсы:

Https://graphql.org/learn