graphql
SKILL.md
GraphQL Development
Design efficient GraphQL APIs.
When to Use
- Creating GraphQL schemas
- Resolver implementation
- N+1 query problems
- Federation/stitching
- Performance optimization
Schema Design
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
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)
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
Weekly Installs
4
Repository
htlin222/dotfilesInstalled on
claude-code3
windsurf2
antigravity2
gemini-cli2
trae1
opencode1