Claude
Skills
Sign in
โ† Back

graphql

Included with Lifetime
$97 forever

GraphQL query language and runtime for APIs enabling clients to request exactly the data they need with strongly-typed schemas and single endpoint architecture.

Backend & APIs

What this skill does


# GraphQL Skill

## Summary
GraphQL is a query language and runtime for APIs that enables clients to request exactly the data they need. It provides a strongly-typed schema, single endpoint architecture, and eliminates over-fetching/under-fetching problems common in REST APIs.

## When to Use
- Building flexible APIs for multiple client types (web, mobile, IoT)
- Complex data requirements with nested relationships
- Mobile-first applications needing bandwidth efficiency
- Reducing API versioning complexity
- Real-time data with subscriptions
- Microservices aggregation and federation
- Developer experience with strong typing and introspection

## Quick Start

### 1. Define Schema (SDL)
```graphql
# schema.graphql
type User {
  id: ID!
  name: String!
  email: String!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
  publishedAt: DateTime
}

type Query {
  user(id: ID!): User
  users: [User!]!
  post(id: ID!): Post
}

type Mutation {
  createPost(title: String!, content: String!, authorId: ID!): Post!
  updatePost(id: ID!, title: String, content: String): Post!
  deletePost(id: ID!): Boolean!
}
```

### 2. Write Resolvers (TypeScript + Apollo Server)
```typescript
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { readFileSync } from 'fs';

// Load schema
const typeDefs = readFileSync('./schema.graphql', 'utf-8');

// Mock data
const users = [
  { id: '1', name: 'Alice', email: '[email protected]' },
  { id: '2', name: 'Bob', email: '[email protected]' },
];

const posts = [
  { id: '1', title: 'GraphQL Intro', content: 'Learning GraphQL...', authorId: '1' },
  { id: '2', title: 'Apollo Server', content: 'Building APIs...', authorId: '1' },
];

// Resolvers
const resolvers = {
  Query: {
    user: (_, { id }) => users.find(u => u.id === id),
    users: () => users,
    post: (_, { id }) => posts.find(p => p.id === id),
  },

  Mutation: {
    createPost: (_, { title, content, authorId }) => {
      const post = {
        id: String(posts.length + 1),
        title,
        content,
        authorId,
      };
      posts.push(post);
      return post;
    },

    updatePost: (_, { id, title, content }) => {
      const post = posts.find(p => p.id === id);
      if (!post) throw new Error('Post not found');
      if (title) post.title = title;
      if (content) post.content = content;
      return post;
    },

    deletePost: (_, { id }) => {
      const index = posts.findIndex(p => p.id === id);
      if (index === -1) return false;
      posts.splice(index, 1);
      return true;
    },
  },

  User: {
    posts: (user) => posts.filter(p => p.authorId === user.id),
  },

  Post: {
    author: (post) => users.find(u => u.id === post.authorId),
  },
};

// Create server
const server = new ApolloServer({ typeDefs, resolvers });

startStandaloneServer(server, {
  listen: { port: 4000 },
}).then(({ url }) => {
  console.log(`๐Ÿš€ Server ready at ${url}`);
});
```

### 3. Query Data (Client)
```typescript
// Using Apollo Client
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';

const client = new ApolloClient({
  uri: 'http://localhost:4000',
  cache: new InMemoryCache(),
});

// Query
const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
      posts {
        id
        title
        publishedAt
      }
    }
  }
`;

const { data } = await client.query({
  query: GET_USER,
  variables: { id: '1' },
});

// Mutation
const CREATE_POST = gql`
  mutation CreatePost($title: String!, $content: String!, $authorId: ID!) {
    createPost(title: $title, content: $content, authorId: $authorId) {
      id
      title
      content
    }
  }
`;

const { data: postData } = await client.mutate({
  mutation: CREATE_POST,
  variables: {
    title: 'New Post',
    content: 'Hello GraphQL!',
    authorId: '1',
  },
});
```

---

## Core Concepts

### GraphQL Fundamentals
- **Schema-First Design**: Define API contract with Schema Definition Language (SDL)
- **Type Safety**: Strongly-typed schema enforced at runtime and build-time
- **Single Endpoint**: All queries and mutations go through one URL (e.g., `/graphql`)
- **Client-Specified Queries**: Clients request exactly what they need
- **Hierarchical Data**: Queries mirror the shape of returned data
- **Introspection**: Schema is self-documenting and queryable

### Operations
```graphql
# Query - Read data (GET-like)
query GetUser {
  user(id: "1") {
    name
  }
}

# Mutation - Modify data (POST/PUT/DELETE-like)
mutation CreateUser {
  createUser(name: "Alice", email: "[email protected]") {
    id
    name
  }
}

# Subscription - Real-time updates (WebSocket)
subscription OnPostCreated {
  postCreated {
    id
    title
    author {
      name
    }
  }
}
```

### Fields and Arguments
```graphql
type Query {
  # Field with arguments
  user(id: ID!): User
  users(limit: Int = 10, offset: Int = 0): [User!]!

  # Search with multiple arguments
  searchPosts(
    query: String!
    category: String
    limit: Int = 20
  ): [Post!]!
}
```

---

## Schema Definition Language (SDL)

### Basic Type Definition
```graphql
type User {
  id: ID!              # Non-null ID scalar
  name: String!        # Non-null String
  email: String!
  age: Int             # Nullable Int
  isActive: Boolean!
  posts: [Post!]!      # Non-null list of non-null Posts
  profile: Profile     # Nullable object type
}

type Profile {
  bio: String
  avatarUrl: String
  website: String
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
  tags: [String!]      # Non-null list, nullable elements
  publishedAt: DateTime
}
```

### Input Types (for mutations)
```graphql
input CreateUserInput {
  name: String!
  email: String!
  age: Int
}

input UpdateUserInput {
  name: String
  email: String
  age: Int
}

type Mutation {
  createUser(input: CreateUserInput!): User!
  updateUser(id: ID!, input: UpdateUserInput!): User!
}
```

### Interfaces
```graphql
interface Node {
  id: ID!
  createdAt: DateTime!
  updatedAt: DateTime!
}

type User implements Node {
  id: ID!
  createdAt: DateTime!
  updatedAt: DateTime!
  name: String!
  email: String!
}

type Post implements Node {
  id: ID!
  createdAt: DateTime!
  updatedAt: DateTime!
  title: String!
  content: String!
}

type Query {
  node(id: ID!): Node  # Can return User or Post
}
```

### Unions
```graphql
union SearchResult = User | Post | Comment

type Query {
  search(query: String!): [SearchResult!]!
}

# Client query with fragments
query Search {
  search(query: "graphql") {
    ... on User {
      name
      email
    }
    ... on Post {
      title
      content
    }
    ... on Comment {
      text
      author { name }
    }
  }
}
```

### Enums
```graphql
enum Role {
  ADMIN
  MODERATOR
  USER
  GUEST
}

enum PostStatus {
  DRAFT
  PUBLISHED
  ARCHIVED
}

type User {
  id: ID!
  name: String!
  role: Role!
}

type Post {
  id: ID!
  title: String!
  status: PostStatus!
}
```

---

## Type System

### Scalar Types
```graphql
# Built-in scalars
scalar Int       # Signed 32-bit integer
scalar Float     # Signed double-precision floating-point
scalar String    # UTF-8 character sequence
scalar Boolean   # true or false
scalar ID        # Unique identifier (serialized as String)

# Custom scalars
scalar DateTime  # ISO 8601 timestamp
scalar Email     # Email address
scalar URL       # Valid URL
scalar JSON      # Arbitrary JSON
scalar Upload    # File upload
```

### Custom Scalar Implementation
```typescript
// DateTime scalar (TypeScript)
import { GraphQLScalarType, Kind } from 'graphql';

const DateTimeScalar = new GraphQLScalarType({
  name: 'DateTime',
  description: 'ISO 8601 DateTime',

  // Serialize to client (output)
  serialize(value: Date) {
    return value.toISOString();
  },

  // Parse from client (input)
  parseValue(value: string) {
    return new Date(value);
  },

  // Parse from que

Related in Backend & APIs