| name | graphql |
| description | GraphQL schema design, resolvers, directives, subscriptions, and best practices for API development. |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
| graph | {"domains":["domain:web-development"],"specializations":["specialization:web-development"],"skillAreas":["skill-area:graphql-schema-design","skill-area:api-design"],"roles":["role:backend-engineer","role:fullstack-engineer"],"topics":["topic:graphql-schema-design","topic:api-design"]} |
GraphQL Skill
Expert assistance for designing and implementing GraphQL APIs.
Capabilities
- Design GraphQL schemas with SDL
- Implement resolvers and data loaders
- Create custom directives
- Set up subscriptions for real-time
- Handle authentication and authorization
- Optimize query performance
Usage
Invoke this skill when you need to:
- Design GraphQL API schemas
- Implement resolvers
- Add real-time subscriptions
- Create custom directives
- Optimize N+1 queries
Inputs
| Parameter | Type | Required | Description |
|---|
| typeName | string | Yes | GraphQL type name |
| operations | array | No | queries, mutations, subscriptions |
| directives | array | No | Custom directives |
Schema Design Patterns
Type Definitions
scalar DateTime
scalar JSON
enum Role {
USER
ADMIN
}
enum SortOrder {
ASC
DESC
}
type User {
id: ID!
name: String!
email: String!
role: Role!
posts: [Post!]!
createdAt: DateTime!
updatedAt: DateTime!
}
type Post {
id: ID!
title: String!
content: String!
published: Boolean!
author: User!
Comment
DateTime
Comment
ID
String
User
Post
DateTime
PageInfo
Boolean
Boolean
String
String
UserEdge
User
String
UserConnection
UserEdge
PageInfo
Int
CreateUserInput
String
String
String
Role USER
UpdateUserInput
String
String
Role
UsersFilterInput
String
Role
PaginationInput
Int
String
Int
String
User
user ID User
users
UsersFilterInput
PaginationInput
SortOrder
UserConnection
post ID Post
posts Boolean Post
login String, String AuthPayload
register CreateUserInput AuthPayload
updateUser ID, UpdateUserInput User
deleteUser ID Boolean
createPost String, String Post
updatePost ID, String, String, Boolean Post
deletePost ID Boolean
Post
postUpdated ID Post
commentAdded ID Comment
AuthPayload
String
User
Role USER FIELD_DEFINITION
String FIELD_DEFINITION
Resolvers
import { Resolvers } from '../generated/graphql';
import { Context } from '../context';
import { userResolvers } from './user.resolvers';
import { postResolvers } from './post.resolvers';
import { authResolvers } from './auth.resolvers';
export const resolvers: Resolvers<Context> = {
Query: {
...userResolvers.Query,
...postResolvers.Query,
},
Mutation: {
...authResolvers.Mutation,
...userResolvers.Mutation,
...postResolvers.Mutation,
},
Subscription: {
...postResolvers.Subscription,
},
User: userResolvers.User,
Post: postResolvers.Post,
};
import { GraphQLError } from 'graphql';
import { Context } from '../context';
export const userResolvers = {
Query: {
me: (: , : , { user, prisma }: ) => {
(!user) ();
prisma..({ : { : user. } });
},
: (: , { id }: { : }, { prisma }: ) => {
prisma..({ : { id } });
},
: (
: ,
{ filter, pagination, orderBy }: ,
{ prisma }:
) => {
{ first = , after } = pagination || {};
where = filter?.
? { : { : filter., : } }
: ;
users = prisma..({
where,
: first + ,
: after ? { : after } : ,
: after ? : ,
: { : orderBy || },
});
hasNextPage = users. > first;
edges = users.(, first).( ({
: user,
: user.,
}));
{
edges,
: {
hasNextPage,
: !!after,
: edges[]?.,
: edges[edges. - ]?.,
},
: prisma..({ where }),
};
},
},
: {
: (
: ,
{ id, input }: { : ; : },
{ user, prisma }:
) => {
(!user) ();
(user. !== id && user. !== ) {
();
}
prisma..({
: { id },
: input,
});
},
},
: {
: (: , : , { prisma }: ) => {
prisma..({ : { : parent. } });
},
},
};
DataLoader for N+1
import DataLoader from 'dataloader';
import { PrismaClient, User, Post } from '@prisma/client';
export function createLoaders(prisma: PrismaClient) {
return {
userLoader: new DataLoader<string, User | null>(async (ids) => {
const users = await prisma.user.findMany({
where: { id: { in: ids as string[] } },
});
const userMap = new Map(users.map((u) => [u.id, u]));
return ids.map((id) => userMap.get(id) || null);
}),
postsByAuthorLoader: new DataLoader<string, Post[]>(async (authorIds) => {
posts = prisma..({
: { : { : authorIds [] } },
});
postsByAuthor = <, []>();
posts.( {
authorPosts = postsByAuthor.(post.) || [];
authorPosts.(post);
postsByAuthor.(post., authorPosts);
});
authorIds.( postsByAuthor.(id) || []);
}),
};
}
: {
: loaders..(parent.),
}
Best Practices
- Use input types for mutations
- Implement cursor-based pagination
- Use DataLoader for N+1 prevention
- Add proper error handling
- Document schema with descriptions
Target Processes
- graphql-api-development
- api-design
- backend-development
- real-time-applications