Наша библиотека для написания схем в JavaScript hits 1.0
Разработчики пользовательского интерфейса любят GraphQL, потому что он позволяет им получать данные быстро и эффективно, без необходимости выполнять несколько вызовов API или пытаться разобраться в устаревшей документации. При таком большом количестве преимуществ на клиенте может показаться, что реализация сервера для получения всех этих функций может быть очень сложной. И полтора года назад, когда GraphQL только был открыт, все выглядело именно так! Примеров было немного, а синтаксис для определения типов и полей на первый взгляд выглядел довольно сложным.
Еще в январе 2016 года мы с Йонасом Хелфером искали способы упростить работу с GraphQL, и одна вещь привлекла наше внимание - язык определения схемы:
type Person { name: String age: Int picture: Url }
Он появлялся повсюду в спецификации, но использовался просто как красивое сокращение. На самом деле вы не могли использовать его для создания сервера GraphQL. Но… что, если бы вы могли? К счастью, пока мы думали об этом, GraphQL.js быстро улучшал свою экспериментальную поддержку языка схемы в парсере. Еще не было достаточно функций для создания полноценного сервера с модульными частями, интерфейсами и многим другим, но наша миссия заключалась в том, чтобы максимально упростить разработку серверов GraphQL. Итак, Йонас построил прототип первой библиотеки GraphQL Apollo, graphql-tools, которая позволяет вам создавать GraphQL API, используя только язык схемы.
graphql-tools 1.0 🎉
Сегодня, через полтора года после начала проекта, мы с Джонасом рады объявить о выпуске 1.0 graphql-tools
, с особой благодарностью давнему участнику проекта Hagai Cohen! graphql-tools
готов к производству и был протестирован десятками компаний в своих производственных приложениях.
Вот что можно делать с graphql-tools
:
- Создайте схему с помощью языка определения схем GraphQL, используя при этом все функции GraphQL.js, включая преобразователи, интерфейсы и объединения.
- Импортируйте настраиваемые скалярные типы из npm, а также создайте свои собственные
- Полностью смоделируйте свой API на основе определения схемы и настройте эти макеты.
- Обработка некоторых распространенных ошибок, возникающих при разработке сервера.
В конце вы получаете обычный объект схемы GraphQL.js, точно так же, как и напрямую с эталонной реализацией. Вы можете использовать это с вашим любимым промежуточным программным обеспечением сервера GraphQL, таким как graphql-server-express или express-graphql. Если вы считаете, что чего-то не хватает, сообщите о проблеме или отправьте PR - мы хотим, чтобы graphql-tools
был очень легким и непредвзятым, но мы всегда ищем возможные улучшения!
Создание простого сервера GraphQL
Если вы новичок в GraphQL, graphql-tools
- отличный способ создать свой первый сервер. В этом посте мы рассмотрим некоторые из самых простых способов использования, в том числе:
- Схема приветственного мира (и введение в Launchpad, инструмент для изучения серверов GraphQL).
- Простая схема только для чтения с авторами и сообщениями.
- Та же схема с добавленной мутацией.
Давайте перейдем к этому, и, надеюсь, к концу поста вы увидите, что создание прототипа простой схемы GraphQL может быть очень простым делом! В будущих публикациях мы рассмотрим некоторые более сложные темы, такие как имитация и доступ к базам данных и API.
Привет, мир с инструментами graphql
Вот как написать схему GraphQL hello world с graphql-tools
:
import { makeExecutableSchema } from 'graphql-tools'; // Construct a schema using the GraphQL schema language const typeDefs = ` type Query { hello: String } `; // Provide resolver functions for your schema fields const resolvers = { Query: { hello: (root, args, context) => { return 'Hello world!'; }, }, }; // Get a GraphQL.js Schema object export const schema = makeExecutableSchema({ typeDefs, resolvers, });
Щелкните здесь, чтобы увидеть живую демонстрацию и отредактировать код в своем браузере!
В этом сообщении в блоге мы собираемся включать в каждый фрагмент кода ссылку на живой пример на Launchpad, новой демонстрационной платформе сервера GraphQL. Войдите в систему и нажмите Fork, чтобы отредактировать код, или Download, чтобы получить приложение Node.js, которое вы можете запускать локально!
Каждая схема GraphQL состоит из двух частей:
- Схема, определяющая поля и типы в API; это похоже на определение маршрута в REST API.
- Резольверы, которые представляют собой функции, вызываемые во время выполнения поля, аналогичные методам контроллера в REST.
А теперь давайте сделаем это немного поинтереснее…
Вложенные типы и запросы
Одно из самых больших преимуществ GraphQL API заключается в том, что это не просто плоский список конечных точек - это фактически граф типов, которые могут ссылаться друг на друга. Давайте создадим простой API с двумя типами, которые ссылаются друг на друга. Посмотрите полный пример на Launchpad, и мы выделим важные части ниже:
type Author { id: Int! firstName: String lastName: String posts: [Post] } type Post { id: Int! title: String author: Author } type Query { posts: [Post] author(id: Int!): Author }
Вы можете видеть, что у нас здесь отношения как «один-ко-многим», так и «один-к-одному»: у авторов есть несколько сообщений, но у каждого сообщения ровно один автор.
Язык схемы довольно интуитивно понятен - ключевое слово type
определяет «тип объекта», который может иметь несколько полей, и вы можете использовать [ ]
, чтобы указать список, и !
, чтобы указать ненулевое поле (все элементы в этой схеме должны иметь id
). Тип Query
является особенным, поскольку он определяет набор полей, доступных на первом уровне запроса.
Давайте посмотрим на резолверы здесь:
const resolvers = { Query: { posts: () => posts, author: (_, args) => find(authors, { id: args.id }), }, Author: { posts: (author) => filter(posts, { authorId: author.id }), }, Post: { author: (post) => find(authors, { id: post.authorId }), }, };
Эти преобразователи представляют собой простые функции, и в этом примере они считывают данные из массивов authors
и posts
прямо в коде, поскольку мы пока не хотим углубляться в выборку данных. Давайте посмотрим на эти фальшивые данные:
const authors = [ { id: 1, firstName: 'Tom', lastName: 'Coleman' }, { id: 2, firstName: 'Sashko', lastName: 'Stubailo' }, { id: 3, firstName: 'Mikhail', lastName: 'Novikov' }, ]; const posts = [ { id: 1, authorId: 1, title: 'Introduction to GraphQL' }, { id: 2, authorId: 2, title: 'GraphQL Rocks' }, { id: 3, authorId: 2, title: 'Advanced GraphQL' }, { id: 4, authorId: 3, title: 'Launchpad is Cool' }, ];
Обратите внимание, что нам не нужно указывать преобразователи для каждого поля, GraphQL.js имеет концепцию преобразователей по умолчанию, что означает, что он будет подбирать поля firstName
, lastName
и title
на объектах за нас. Давайте проверим работу, выполнив запрос ниже в GraphiQL на Launchpad:
{ posts { title author { firstName } } }
У нас есть отличные результаты! Мы также можем получить с другой точки зрения, начиная с автора:
{ author(id: 2) { firstName posts { title } } }
Отлично, теперь мы начинаем понимать некоторые возможности взаимосвязей между типами в GraphQL.
Добавление мутации
Пока мы работали только с данными, доступными только для чтения. Что, если мы хотим обновить и данные? В GraphQL для этого есть концепция, называемая «мутации». Подобно тому, как запросы используются для получения данных, мутации используются для обновления чего-либо, а затем получения новых результатов.
Во-первых, давайте добавим в нашу схему новый тип:
type Mutation { addPost(authorId: Int!, title: String!): Post }
Теперь все, что нам нужно сделать, это добавить преобразователь для этого поля:
const resolvers = { // ... existing resolvers Mutation: { addPost: (_, args) => { const post = { id: posts.length, authorId: args.authorId, title: args.title, }; posts.push(post); return post; } } };
После того, как вы закончите, он должен выглядеть вот так. Теперь мы можем запустить мутацию в Graph i QL:
mutation AddPost { addPost(authorId: 1, title: "Added via launchpad") { id title author { firstName } } }
Обратите внимание, что при мутации GraphQL мы можем извлекать столько данных, сколько захотим. Затем, когда мы запросим все сообщения, мы получим новое сообщение, которое мы только что добавили в список! Даже не вспотел, и мы уже можем увидеть часть работы, которую GraphQL делает за нас, извлекая связанные данные после мутации. Чтобы убедиться, что вы следовали инструкциям, просмотрите полный пример.
Примечание. Поскольку мы просто сохраняем данные в массиве в памяти, при перезапуске нашего демонстрационного контейнера мы потеряем данные. Это нормально для демонстрации, но вы можете проверить один из примеров о том, как читать и писать в базу данных.
Теперь, когда у вас есть базовая установка с несколькими типами, вы можете разветвить проект и продолжить работу внутри Launchpad или нажать «Загрузить», чтобы отредактировать код локально.
Если вы так же взволнованы развитием технологии GraphQL и предоставлением возможностей разработчикам, как и мы, присоединяйтесь к нам! Мы активно нанимаем сотрудников с открытым исходным кодом, backend и другие роли для работы над технологией API следующего поколения.