GraphQL
02 / 04

Schema & Types

Schema & Types

Type System

# Scalar types
String  Int  Float  Boolean  ID

# Custom scalars
scalar DateTime
scalar JSON
scalar Upload

# Object type
type User {
  id: ID!              # ! = non-nullable
  email: String!
  name: String!
  bio: String          # nullable
  age: Int
  role: Role!
  posts: [Post!]!      # non-nullable list of non-nullable Posts
  createdAt: DateTime!
}

# Enum
enum Role {
  USER
  ADMIN
  MODERATOR
}

# Interface
interface Node {
  id: ID!
}

type User implements Node {
  id: ID!
  email: String!
}

# Union
union SearchResult = User | Post | Comment

# Input type (for mutations/arguments)
input CreateUserInput {
  email: String!
  name: String!
  password: String!
  bio: String
}

input PaginationInput {
  page: Int = 1
  limit: Int = 10
}

Query & Mutation Types

# Root types
type Query {
  user(id: ID!): User
  users(pagination: PaginationInput, role: Role): [User!]!
  me: User
  searchUsers(query: String!): [User!]!
}

type Mutation {
  createUser(input: CreateUserInput!): User!
  updateUser(id: ID!, input: UpdateUserInput!): User!
  deleteUser(id: ID!): Boolean!
  login(email: String!, password: String!): AuthPayload!
}

type AuthPayload {
  token: String!
  user: User!
}

type Subscription {
  userCreated: User!
  messageAdded(channelId: ID!): Message!
}

# Field arguments
type Post {
  id: ID!
  title: String!
  comments(limit: Int = 10, after: ID): CommentConnection!
}

# Pagination — Relay-style cursor connection
type UserConnection {
  edges: [UserEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

type UserEdge {
  cursor: String!
  node: User!
}

type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  startCursor: String
  endCursor: String
}

Directives

# Built-in directives
query GetUser($withPosts: Boolean!) {
  user(id: "1") {
    name
    posts @include(if: $withPosts) {
      title
    }
    bio @skip(if: true)
  }
}

# Custom directives (server-side)
directive @auth(requires: Role = USER) on FIELD_DEFINITION
directive @deprecated(reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE
directive @upper on FIELD_DEFINITION

type User {
  email: String! @auth(requires: ADMIN)
  oldField: String @deprecated(reason: "Use newField instead")
}

Schema Stitching / Federation

# Apollo Federation subgraph (service-specific schema)
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key"])

type User @key(fields: "id") {
  id: ID!
  email: String!
  name: String!
}

# Another subgraph can extend User
type User @key(fields: "id") {
  id: ID! @external
  orders: [Order!]!
}

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free