home / skills / htlin222 / dotfiles / graphql

graphql skill

/claude.symlink/skills/graphql

npx playbooks add skill htlin222/dotfiles --skill graphql

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.9 KB
---
name: graphql
description: Design GraphQL schemas, resolvers, and federation. Use for GraphQL API design or performance issues.
---

# GraphQL Development

Design efficient GraphQL APIs.

## When to Use

- Creating GraphQL schemas
- Resolver implementation
- N+1 query problems
- Federation/stitching
- Performance optimization

## Schema Design

```graphql
type Query {
  user(id: ID!): User
  users(filter: UserFilter, limit: Int = 10): UserConnection!
}

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

type User {
  id: ID!
  email: String!
  name: String!
  posts(first: Int, after: String): PostConnection!
  createdAt: DateTime!
}

input CreateUserInput {
  email: String!
  name: String!
}

type CreateUserPayload {
  user: User
  errors: [Error!]
}

type UserConnection {
  edges: [UserEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

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

type PageInfo {
  hasNextPage: Boolean!
  endCursor: String
}
```

## Resolvers

```javascript
const resolvers = {
  Query: {
    user: (_, { id }, { dataSources }) => dataSources.users.getById(id),

    users: async (_, { filter, limit }, { dataSources }) => {
      const users = await dataSources.users.find(filter, limit);
      return connectionFromArray(users);
    },
  },

  User: {
    // Field resolver with DataLoader for N+1
    posts: (user, args, { loaders }) => loaders.postsByUser.load(user.id),
  },

  Mutation: {
    createUser: async (_, { input }, { dataSources }) => {
      try {
        const user = await dataSources.users.create(input);
        return { user, errors: null };
      } catch (e) {
        return { user: null, errors: [{ message: e.message }] };
      }
    },
  },
};
```

## DataLoader (N+1 Solution)

```javascript
const DataLoader = require("dataloader");

const createLoaders = (dataSources) => ({
  userById: new DataLoader(async (ids) => {
    const users = await dataSources.users.getByIds(ids);
    const userMap = new Map(users.map((u) => [u.id, u]));
    return ids.map((id) => userMap.get(id) || null);
  }),

  postsByUser: new DataLoader(async (userIds) => {
    const posts = await dataSources.posts.findByUserIds(userIds);
    const grouped = groupBy(posts, "userId");
    return userIds.map((id) => grouped[id] || []);
  }),
});
```

## Performance Tips

- Use DataLoader for batching
- Implement query complexity limits
- Add depth limiting
- Cache with Redis/CDN
- Use persisted queries

## Best Practices

- Nullable by default, explicit `!` for required
- Use input types for mutations
- Return payload types with errors
- Implement cursor pagination
- Version via schema evolution

## Examples

**Input:** "Fix N+1 queries"
**Action:** Implement DataLoader, batch database queries

**Input:** "Design user management API"
**Action:** Create schema with types, queries, mutations, pagination