Перейти к содержимому

3. Schema Definition Language

GraphQL Schema

Схема — это сердце GraphQL. Она определяет все типы данных и операции, которые доступны в API. Это контракт между клиентом и сервером.

SDL (Schema Definition Language) — специальный синтаксис для описания схемы GraphQL.

type User {
id: ID!
name: String!
email: String!
age: Int
posts: [Post!]!
}
type Post {
id: ID!
title: String!
body: String!
author: User!
createdAt: String!
}
type Query {
user(id: ID!): User
users: [User!]!
post(id: ID!): Post
posts: [Post!]!
}
ТипОписаниеПример
StringСтрока UTF-8"Привет"
Int32-битное целое42
FloatЧисло с плавающей точкой3.14
BooleanБулево значениеtrue
IDУникальный идентификатор"user-123"

Обязательные поля: восклицательный знак !

Заголовок раздела «Обязательные поля: восклицательный знак !»
type Product {
id: ID! # Обязательное поле — никогда не null
name: String! # Обязательное
price: Float! # Обязательное
description: String # Необязательное — может быть null
discount: Float # Необязательное
}
posts: [Post] # Может быть null, элементы могут быть null
posts: [Post!] # Может быть null, но элементы — нет
posts: [Post]! # Не null, но элементы могут быть null
posts: [Post!]! # Ни массив ни элементы не могут быть null

GraphQL имеет три корневых типа:

type Query {
# Все операции чтения
user(id: ID!): User
product(slug: String!): Product
}
type Mutation {
# Все операции изменения
createUser(input: CreateUserInput!): User!
deletePost(id: ID!): Boolean!
}
type Subscription {
# Real-time операции
messageAdded(chatId: ID!): Message!
userOnline: User!
}

Любое поле может принимать аргументы:

type Query {
# Обязательный аргумент
user(id: ID!): User
# Несколько аргументов
posts(
limit: Int = 10 # С дефолтным значением
offset: Int = 0
orderBy: String
): [Post!]!
# Поиск
searchUsers(query: String!): [User!]!
}

Для мутаций используй input типы — специальные типы только для входных данных:

input CreateUserInput {
name: String!
email: String!
password: String!
age: Int
}
input UpdateUserInput {
name: String
email: String
age: Int
}
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, input: UpdateUserInput!): User!
}

Почему input, а не type? Типы type могут содержать поля, ссылающиеся на другие объектные типы — это создаёт сложности при сериализации входных данных.

enum UserRole {
ADMIN
EDITOR
VIEWER
}
enum PostStatus {
DRAFT
PUBLISHED
ARCHIVED
}
type User {
id: ID!
name: String!
role: UserRole!
}
type Post {
id: ID!
title: String!
status: PostStatus!
}

Использование в запросе:

query {
users {
name
role # Вернёт "ADMIN", "EDITOR" или "VIEWER"
}
}
"""
Пользователь системы.
Может быть администратором, редактором или читателем.
"""
type User {
"Уникальный идентификатор пользователя"
id: ID!
"Полное имя пользователя"
name: String!
"""
Email адрес.
Используется для авторизации.
"""
email: String!
}

Эти комментарии отображаются в GraphiQL и Apollo Studio как документация.

type User {
id: ID!
name: String!
password: String! @deprecated(reason: "Use passwordHash instead")
passwordHash: String!
}
"""Пользователь блога"""
type User {
id: ID!
name: String!
email: String!
role: UserRole!
posts: [Post!]!
comments: [Comment!]!
createdAt: String!
}
enum UserRole {
ADMIN
AUTHOR
READER
}
"""Пост в блоге"""
type Post {
id: ID!
title: String!
slug: String!
body: String!
excerpt: String
status: PostStatus!
author: User!
tags: [String!]!
comments: [Comment!]!
likesCount: Int!
createdAt: String!
updatedAt: String!
}
enum PostStatus {
DRAFT
PUBLISHED
ARCHIVED
}
type Comment {
id: ID!
body: String!
author: User!
post: Post!
createdAt: String!
}
type Query {
me: User
user(id: ID!): User
users(role: UserRole): [User!]!
post(slug: String!): Post
posts(
status: PostStatus
limit: Int = 20
offset: Int = 0
): [Post!]!
searchPosts(query: String!): [Post!]!
}
input CreatePostInput {
title: String!
body: String!
tags: [String!]
status: PostStatus = DRAFT
}
input CreateCommentInput {
postId: ID!
body: String!
}
type Mutation {
createPost(input: CreatePostInput!): Post!
updatePost(id: ID!, input: CreatePostInput!): Post!
deletePost(id: ID!): Boolean!
publishPost(id: ID!): Post!
createComment(input: CreateCommentInput!): Comment!
deleteComment(id: ID!): Boolean!
likePost(postId: ID!): Post!
}
type Subscription {
postPublished: Post!
commentAdded(postId: ID!): Comment!
}
  1. Создай схему для интернет-магазина (Product, Category, Order, User)
  2. Добавь enum OrderStatus со статусами: PENDING, PROCESSING, SHIPPED, DELIVERED, CANCELLED
  3. Создай input типы для создания и обновления продукта
  4. Добавь аргументы пагинации к запросу products
  5. Добавь описание ("""...""") к каждому типу
  • SDL — декларативный язык описания схемы
  • ! — поле обязательное (не null)
  • input типы — только для аргументов мутаций
  • enum — перечисления
  • Документация прямо в схеме через """..."""

Следующий урокТипы GraphQL →