Создание API-интерфейсов GraphQL с помощью Node

Опубликовано: 2022-12-20

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

GraphQL — это язык запросов, созданный Facebook, который в 2015 году превратился в проект с открытым исходным кодом. Он предлагает интуитивно понятный и гибкий синтаксис для описания и доступа к данным в API.

В этом руководстве рассказывается, как создать проект GraphQL Node.js. Мы будем использовать GraphQL для создания приложения Todo в веб-фреймворке Express.js для Node.

Что такое GraphQL?

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

GraphQL — это среда выполнения на стороне сервера для выполнения запросов с использованием системы типов, которую вы определили для своих данных. Кроме того, GraphQL не привязан к какой-либо конкретной базе данных или механизму хранения. Вместо этого он поддерживается вашим существующим кодом и хранилищем данных. Подробное сравнение этих технологий можно найти в руководстве GraphQL vs. RESTful API.

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

Терминология GraphQL

Система типов GraphQL используется для описания того, какие данные можно запрашивать и какими данными можно манипулировать. Это ядро ​​GraphQL. Давайте обсудим различные способы описания и обработки данных в GraphQ.

Типы

Типы объектов GraphQL — это модели данных, содержащие строго типизированные поля. Между вашими моделями и типами GraphQL должно быть сопоставление 1-к-1. Ниже приведен пример типа GraphQL:

 type User { id: ID! # The "!" means required firstname: String lastname: String email: String username: String todos: [Todo] # Todo is another GraphQL type }

Запросы

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

Ниже мы определяем и сопоставляем запросы с соответствующим RESTful API:

 type RootQuery { user(id: ID): User # Corresponds to GET /api/users/:id users: [User] # Corresponds to GET /api/users todo(id: ID!): Todo # Corresponds to GET /api/todos/:id todos: [Todo] # Corresponds to GET /api/todos }

Мутации

Если запросы GraphQL — это запросы GET , мутации — это запросы POST , PUT , PATCH и DELETE , которые манипулируют API GraphQL.

Мы поместим все мутации в одну RootMutation , чтобы продемонстрировать:

 type RootMutation { createUser(input: UserInput!): User # Corresponds to POST /api/users updateUser(id: ID!, input: UserInput!): User # Corresponds to PATCH /api/users removeUser(id: ID!): User # Corresponds to DELETE /api/users createTodo(input: TodoInput!): Todo updateTodo(id: ID!, input: TodoInput!): Todo removeTodo(id: ID!): Todo }

Вы заметили использование типов -input для мутаций, таких как UserInput , TodoInput . Всегда рекомендуется всегда определять типы ввода для создания и обновления ваших ресурсов.

Вы можете определить типы ввода , как показано ниже:

 input UserInput { firstname: String! lastname: String email: String! username: String! }

Резольверы

Резолверы сообщают GraphQL, что делать, когда запрашивается каждый запрос или мутация. Это базовая функция, которая выполняет тяжелую работу по обращению к уровню базы данных для выполнения операций CRUD (создание, чтение, обновление, удаление), обращению к внутренней конечной точке RESTful API или вызову микрослужбы для выполнения запроса клиента.

Вы можете создать новый файл resolvers.js и добавить следующий код:

 import sequelize from '../models'; export default function resolvers () { const models = sequelize.models; return { // Resolvers for Queries RootQuery: { user (root, { id }, context) { return models.User.findById(id, context); }, users (root, args, context) { return models.User.findAll({}, context); } }, User: { todos (user) { return user.getTodos(); } }, } // Resolvers for Mutations RootMutation: { createUser (root, { input }, context) { return models.User.create(input, context); }, updateUser (root, { id, input }, context) { return models.User.update(input, { ...context, where: { id } }); }, removeUser (root, { id }, context) { return models.User.destroy(input, { ...context, where: { id } }); }, // ... Resolvers for Todos go here } }; }

Схема

Схема GraphQL — это то, что GraphQL открывает миру. Таким образом, типы, запросы и мутации будут включены в схему, чтобы быть доступными для всего мира.

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

 schema { query: RootQuery mutation: RootMutation }

В приведенном выше сценарии мы включили RootQuery и RootMutation , созданные нами ранее, чтобы показать их миру.

Как GraphQL работает с Nodejs и Expressjs

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

GraphQL Apollo предоставляет реализацию для Node.js и Express.js и упрощает начало работы с GraphQL.

В следующем разделе вы узнаете, как создать и разработать свое первое приложение GraphQL в бэкэнд-фреймворке Nodes.js и Express.js с использованием GraphQL Apollo.

Настройка GraphQL с помощью Express.js

Создать сервер GraphQL API с помощью Express.js очень просто. В этом разделе мы рассмотрим, как создать сервер GraphQL.

Инициализировать проект с помощью Express

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

Создайте папку для своего проекта и установите Express.js с помощью этой команды:

 cd <project-name> && npm init -y npm install express

Приведенная выше команда создает новый файл package.json и устанавливает библиотеку Express.js в ваш проект.

Далее мы структурируем наш проект, как показано на изображении ниже. Он будет содержать различные модули для функций проекта, таких как пользователи, задачи и т. д.

Список файлов в graphql-todo.
Файлы для graphql-todo .

Инициализировать GraphQL

Начнем с установки зависимостей GraphQL Express.js. Выполните следующую команду для установки:

 npm install apollo-server-express graphql @graphql-tools/schema --save

Создание схем и типов

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

 const { gql } = require('apollo-server-express'); const users = require('./users'); const todos = require('./todos'); const { GraphQLScalarType } = require('graphql'); const { makeExecutableSchema } = require('@graphql-tools/schema'); const typeDefs = gql` scalar Time type Query { getVersion: String! } type Mutation { version: String! } `; const timeScalar = new GraphQLScalarType({ name: 'Time', description: 'Time custom scalar type', serialize: (value) => value, }); const resolvers = { Time: timeScalar, Query: { getVersion: () => `v1`, }, }; const schema = makeExecutableSchema({ typeDefs: [typeDefs, users.typeDefs, todos.typeDefs], resolvers: [resolvers, users.resolvers, todos.resolvers], }); module.exports = schema;

Пошаговое руководство по коду

Давайте проработаем фрагмент кода и разберем его:

Шаг 1

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

Интерфейс командной строки, показывающий «константный» код для импорта GraphQL и других расширений.
Импорт GraphQL и расширений.
Шаг 2:

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

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

Боретесь с простоями и проблемами WordPress? Kinsta — это решение для хостинга, предназначенное для экономии вашего времени! Ознакомьтесь с нашими функциями
Интерфейс командной строки, показывающий «константный» код для создания нашего скалярного типа и нашего первого преобразователя.
Создание скалярного типа для времени, а также нашего первого преобразователя.

Приведенный выше фрагмент кода показывает, что мы импортировали разные схемы в функцию makeExecutableEchema. Такой подход помогает нам структурировать приложение по сложности. Далее мы создадим импортированные схемы Todo и User.

Создание схемы Todo

Схема Todo показывает простые операции CRUD, которые могут выполнять пользователи приложения. Ниже представлена ​​схема, реализующая операцию Todo CRUD.

 const { gql } = require('apollo-server-express'); const createTodo = require('./mutations/create-todo'); const updateTodo = require('./mutations/update-todo'); const removeTodo = require('./mutations/delete-todo'); const todo = require('./queries/todo'); const todos = require('./queries/todos'); const typeDefs = gql` type Todo { id: ID! title: String description: String user: User } input CreateTodoInput { title: String! description: String isCompleted: Boolean } input UpdateTodoInput { title: String description: String isCompleted: Boolean } extend type Query { todo(id: ID): Todo! todos: [Todo!] } extend type Mutation { createTodo(input: CreateTodoInput!): Todo updateTodo(id: ID!, input: UpdateTodoInput!): Todo removeTodo(id: ID!): Todo } `; // Provide resolver functions for your schema fields const resolvers = { // Resolvers for Queries Query: { todo, todos, }, // Resolvers for Mutations Mutation: { createTodo, updateTodo, removeTodo, }, }; module.exports = { typeDefs, resolvers };

Пошаговое руководство по коду

Давайте проработаем фрагмент кода и разберем его:

Шаг 1:

Сначала мы создали схему для нашего Todo, используя GraphQL type , input и extend . Ключевое слово extend используется для наследования и добавления новых запросов и мутаций к существующему корневому запросу и мутации, которые мы создали выше.

Интерфейс командной строки, показывающий схему нашего скрипта Todo, включая новые входные данные.
Создание схемы для нашего Todo.
Шаг 2:

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

Интерфейс командной строки, показывающий код для создания преобразователя для нашего Todo.
Создание резольвера.

Имея функцию распознавателя, мы можем создавать отдельные методы для бизнес-логики и манипулирования базой данных, как показано в примере create-todo.js .

Создайте файл create-user.js в папке <code>./mutations</code> и добавьте бизнес-логику для создания нового Todo в вашей базе данных.

 const models = require('../../../models'); module.exports = async (root, { input }, context) => { return models.todos.push({ ...input }); };

Приведенный выше фрагмент кода представляет собой упрощенный способ создания нового Todo в нашей базе данных с помощью Sequelize ORM. Вы можете узнать больше о Sequelize и о том, как его настроить с помощью Node.js.

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

Далее мы настроим сервер с Express.js и запустим только что созданное приложение Todo с GraphQL и Node.js.

Настройка и запуск сервера

Наконец, мы настроим наш сервер, используя библиотеку apollo-server-express , которую мы установили ранее, и настроим ее.

apollo-server-express — это простая оболочка Apollo Server для Express.js. Рекомендуется, поскольку она была разработана для разработки Express.js.

Используя примеры, которые мы рассмотрели выше, давайте настроим сервер Express.js для работы с недавно установленным apollo-server-express .

Создайте файл server.js в корневом каталоге и вставьте следующий код:

 const express = require('express'); const { ApolloServer } = require('apollo-server-express'); const schema = require('./modules'); const app = express(); async function startServer() { const server = new ApolloServer({ schema }); await server.start(); server.applyMiddleware({ app }); } startServer(); app.listen({ port: 3000 }, () => console.log(`Server ready at http://localhost:3000`) );

В приведенном выше коде вы успешно создали свой первый сервер CRUD GraphQL для Todos и пользователей. Вы можете запустить свой сервер разработки и получить доступ к игровой площадке, используя http://localhost:3000/graphql. Если все прошло успешно, вы должны увидеть экран ниже:

Интерфейс разработки, показывающий простой запрос в ответ.
Экран проверки.

Резюме

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

В этом руководстве разъясняется GraphQL и демонстрируется, как разработать свой первый API GraphQL с помощью Express.js.

Дайте нам знать, что вы строите с помощью GraphQL.