Schema, queries, mutations, subscriptions & resolvers
API# GraphQL is a query language for APIs
# Single endpoint, client specifies data shape
# REST: GET /users/1/posts
# GraphQL:
{
user(id: 1) {
name
posts {
title
}
}
}
# Response: exactly the shape requested
{
"data": {
"user": {
"name": "Alice",
"posts": [{ "title": "Hello" }]
}
}
}# Scalar types
Int Float String Boolean ID
# Object type
type User {
id: ID! # ! = non-null
name: String!
email: String!
age: Int
posts: [Post!]! # non-null list of non-null
}
type Post {
id: ID!
title: String!
author: User!
}
# Input type (for mutations)
input CreateUserInput {
name: String!
email: String!
}
# Enum
enum Role { ADMIN USER GUEST }
# Interface
interface Node { id: ID! }
# Union
union SearchResult = User | Post# Basic query
query {
users {
id
name
}
}
# With arguments
query {
user(id: "1") {
name
email
}
}
# Aliases
query {
alice: user(id: "1") { name }
bob: user(id: "2") { name }
}
# Schema root
type Query {
users: [User!]!
user(id: ID!): User
posts(limit: Int = 10): [Post!]!
}# Mutate data
mutation {
createUser(input: {
name: "Alice"
email: "alice@test.com"
}) {
id
name
}
}
# Schema definition
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, name: String): User!
deleteUser(id: ID!): Boolean!
}# Query with variables
query GetUser($id: ID!) {
user(id: $id) {
name
email
}
}
# Variables (JSON)
{
"id": "1"
}
# Mutation with variables
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
id name
}
}
# Variables
{ "input": { "name": "Alice", "email": "a@b.com" } }# Reusable field sets
fragment UserFields on User {
id
name
email
}
query {
user(id: "1") { ...UserFields }
admin: user(id: "2") { ...UserFields }
}
# Inline fragment (for unions/interfaces)
query {
search(q: "hello") {
... on User { name email }
... on Post { title body }
}
}# Real-time updates via WebSocket
subscription {
messageAdded(channelId: "1") {
id
text
user { name }
}
}
# Schema
type Subscription {
messageAdded(channelId: ID!): Message!
userOnline: User!
}# Built-in directives
query GetUser($withEmail: Boolean!) {
user(id: "1") {
name
email @include(if: $withEmail)
age @skip(if: true)
}
}
# @deprecated
type User {
name: String!
fullName: String @deprecated(reason: "Use name")
}