Абревіатура API означає Application Programming Interface (програмний інтерфейс програми). Це, як випливає з назви, інтерфейс, за допомогою якого розробники та користувачі взаємодіють з даними.
У цій статті ви познайомитеся з основами розробки API із застосуванням стандарту GraphQL.
Що таке GraphQL
GraphQL - мова запитів з відкритим вихідним кодом, розроблена компанією Facebook. Вона створювалася як ефективніша альтернатива REST для розробки і використання програмних інтерфейсів застосунків.
GraphQL має безліч переваг, наприклад:
- Ви отримуєте інформацію саме в тому обсязі, в якому запитуєте. На відміну від REST, відповідь на запит не буде містити непотрібних даних.
- Вам буде необхідна всього одна кінцева точка, ніяких додаткових версій для єдиного API.
- GraphQL - сильно типізована мова, що дозволяє попередньо оцінити коректність запиту в рамках системи типів цього синтаксису, до виконання. Це дозволяє розробляти потужніші API.
З чого почати
Для того, щоб зрозуміти, як застосовувати стандарт на практиці, ми будемо використовувати сервер в базовій конфігурації - Graphpack .
Для початку потрібно створити новий каталог для проєкту. В даному випадку ім'я каталогу буде graphql-server
, проте назва не принципова.
Відкрийте термінал і введіть:
mkdir graphql-server
На вашому комп'ютері повинен бути встановлений npm
або yarn
.
Перейдіть в створений вами каталог, якщо ви ще цього не зробили і введіть команду в залежності від використовуваного менеджера:
npm init -y
або
yarn init
npm
створить файл package.json
, в якому будуть зберігатися всі створені вами залежності і команди.
Тепер необхідно встановити одну залежність, яку ми будемо використовувати в рамках цієї статті.
Graphpack дозволяє створити сервер GraphQL з базовою конфігурацією. Ця функція дозволить продовжити роботу, не витрачаючи часу на налаштування.
Використовуючи термінал, в кореневому каталозі проєкту встановіть Graphpack за допомогою наступної команди:
npm install --save-dev graphpack
Або, якщо ви використовуєте yarn
:
yarn add --dev graphpack
Після установки Graphpack перейдіть до файлу package.json
та додайте наступний код:
"scripts": { "dev": "graphpack", "build": "graphpack build" }
Створіть на сервері каталог src
. В даному прикладі це буде єдиний каталог на сервері, в якому необхідно буде створити три файли.
В каталозі src
створіть файл schema.graphql
. У цей файл додайте код:
type Query { hello: String }
У цьому файлі буде знаходитися вся схема GraphQL.
Створіть другий файл в тому ж каталозі, назвіть його resolvers.js
. Додайте туди наступний код:
import { users } from "./db"; const resolvers = { Query: { hello: () => "Hello World!" } }; export default resolvers;
У цьому файлі будуть розміщені інструкції щодо виконання операцій GraphQL.
Створіть третій файл, db.js
, що містить код:
export let users = [ { id: 1, name: "John Doe", email: "john@gmail.com", age: 22 }, { id: 2, name: "Jane Doe", email: "jane@gmail.com", age: 23 } ];
Для навчання роботі з GraphQL немає потреби використовувати справжні дані. Цей файл потрібен для симуляції звернень до бази даних.
Після виконання операцій каталог src
повинен виглядати наступним чином:
src |--db.js |--resolvers.js |--schema.graphql
Тепер необхідно виконати команду npm run dev
для npm
або yarn dev
для yarn
. Термінал має вивести інформацію про успішний запуск сервера:
Тепер можна перейти до localhost:4000
. Система готова до роботи над API на основі GraphQL. Для розробки використовується IDE GraphQL Playground .
Схема
Для створення схем в GraphQL використовується власна мова Schema Definition Language (SDL). SDL володіє інтуїтивно зрозумілим синтаксисом і універсальна для будь-якої технології, що використовується.
Типи
Типи - одна з основних особливостей GraphQL. Це кастомні об'єкти, які визначають, як буде виглядати API. Наприклад, при розробці програмного інтерфейсу для програми, що взаємодіє з соцмережами, в API варто оголосити типи Posts
, Users
, Likes
, Groups
.
У типах є поля, які повертають певні різновиди даних. Наприклад, при створенні типу User, в нього варто включити поля name
, email
і age
. Поля типів можуть бути будь-якими і завжди повертають дані в форматі Int
, Float
, String
, Boolean
, ID
, List of Object Types
, або Custom Objects Types
.
Щоб створити перший тип, відкрийте файл schema.graphql
і замініть раніше прописаний там тип Query наступним кодом:
type User { id: ID! name: String! email: String! age: Int }
Кожен запис типу User
повинен мати ідентифікаційний номер, тому поле id
містить дані відповідного типу. Поля name
та email
містять String
(змінну типу рядка символів), а age
- цілочислову змінну.
Знак оклику в кінці визначення поля означає, що це поле не може бути порожнім. Єдине поле без знаку оклику - age
.
GraphQL оперує трьома основними концепціями:
- queries - запити, з їх допомогою отримують дані з сервера.
- mutations - зміни, модифікація даних на сервері і їх оновлення.
- subscriptions - підписки, методи підтримки постійного зв'язку з сервером.
Запити
Відкрийте файл schema.graphql
і додайте тип Query:
type Query { users: [User!]! }
Запит users
буде повертати масив з однієї і більше записів типу User. Оскільки у визначенні використані знаки оклику, відповідь на запит не може бути порожньою.
Для отримання конкретного запису User
необхідно створити відповідний запит. В даному випадку це буде запит user
у типі Query
. Додайте в код наступний рядок:
user(id: ID!): User!
Тепер код повинен виглядати так:
type Query { users: [User!]! user(id: ID!): User! }
Як бачите, в запитах GraphQL можна передавати аргументи. В даному випадку для отримання конкретного запису в запиті як аргумент використовується його поле id
.
Місцезнаходження даних, які будуть оброблятися у відповідності із запитом, визначається у файлі resolvers.js
. Відкрийте цей файл і імпортуйте навчальну базу даних db.js
:
import { users } from "./db"; const resolvers = { Query: { hello: () => "Hello World!" } }; export default resolvers;
Потім замініть функцію hello
на user
і users
:
import { users } from "./db"; const resolvers = { Query: { user: (parent, { id }, context, info) => { return users.find(user => user.id === id); }, users: (parent, args, context, info) => { return users; } } }; export default resolvers;
У кожному резолвері запиту є чотири аргументи. У запиті user
як аргумент передається вміст поля id
запису бази даних. Сервер повертає вміст відповідного запису. Запит users
не містить аргументів і завжди повертає весь масив цілком.
Для тестування отриманого коду перейдіть до localhost:4000
.
Наступний код повинен повернути список всіх записів db.js
:
query { users { id name email age } }
Отримати перший запис з бази можна за допомогою цього коду:
query { user(id: 1) { id name email age } }
Зміни (Mutations)
У GraphQL зміни - спосіб модифікувати дані на сервері і отримати оброблену інформацію. Цей процес можна розглядати як аналогічний концепції CUD (Create, Update, Delete) в стандарті REST.
Для створення зміни відкрийте файл schema.graphql
і додайте новий тип mutation
:
type Mutation { createUser(id: ID!, name: String!, email: String!, age: Int): User! updateUser(id: ID!, name: String, email: String, age: Int): User! deleteUser(id: ID!): User! }
В даному випадку вказано три різних зміни:
createUser
: Необхідно передати значення полівid
,name
,email
таage
. Функція повертає запис типуUser
.updateUser
: Необхідно передати значення поляid
, нове значення поляname
,email
абоage
. Функція повертає запис типуUser
.deleteUser
: Необхідно передати значення поляid
. Функція повертає запис типуUser
.
Тепер відкрийте файл resolvers.js
і нижче об'єкта Query
створіть новий об'єкт mutation
:
Mutation: { createUser: (parent, { id, name, email, age }, context, info) => { const newUser = { id, name, email, age }; users.push(newUser); return newUser; }, updateUser: (parent, { id, name, email, age }, context, info) => { let newUser = users.find(user => user.id === id); newUser.name = name; newUser.email = email; newUser.age = age; return newUser; }, deleteUser: (parent, { id }, context, info) => { const userIndex = users.findIndex(user => user.id === id); if (userIndex === -1) throw new Error("User not found."); const deletedUsers = users.splice(userIndex, 1); return deletedUsers[0]; } }
Повний код файлу resolvers.js
повинен виглядати так:
import { users } from "./db"; const resolvers = { Query: { user: (parent, { id }, context, info) => { return users.find(user => user.id === id); }, users: (parent, args, context, info) => { return users; } }, Mutation: { createUser: (parent, { id, name, email, age }, context, info) => { const newUser = { id, name, email, age }; users.push(newUser); return newUser; }, updateUser: (parent, { id, name, email, age }, context, info) => { let newUser = users.find(user => user.id === id); newUser.name = name; newUser.email = email; newUser.age = age; return newUser; }, deleteUser: (parent, { id }, context, info) => { const userIndex = users.findIndex(user => user.id === id); if (userIndex === -1) throw new Error("User not found."); const deletedUsers = users.splice(userIndex, 1); return deletedUsers[0]; } } }; export default resolvers;
Зробіть запит до localhost:4000
:
mutation { createUser(id: 3, name: "Username", email: "name@example.com", age: 21) { id name email age } }
Він повинен повернути новий запис типу User
. Спробуйте також інші функції зміни.
Підписки
Як згадувалося раніше, за допомогою підписок підтримується постійний зв'язок між клієнтами і сервером. Базова підписка виглядає наступним чином:
subscription { users { id name email age } }
Незважаючи на те що цей код виглядає схожим на запит, працює він трохи інакше. При оновленні даних сервер виконує певний в підписці запит GraphQL і розсилає оновлені дані клієнтам. Більш детальну інформацію про роботу з підписками можна почитати в цьому матеріалі.
висновок
Стандарт GarphQL набирає популярність. В рамках опитування State of JavaScript , проведеного серед JS-розробників, більше половини респондентів вказали, що чули про цю технологію і хотіли б з нею ознайомитися, а п'ята частина вже її використовує і не має наміру відмовлятися. Якщо вірити цьому тренду, GraphQL очікує активний розвиток. Сподіваємося, що даний матеріал дав вам загальне уявлення про GraphQL і зацікавив надалі його вивченні.
Джерело: A Beginner's Guide to GraphQL
Ще немає коментарів