ワンクリックで
graphql-design
GraphQL schema design, resolver patterns, subscriptions, DataLoader for N+1 prevention, and error handling
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
GraphQL schema design, resolver patterns, subscriptions, DataLoader for N+1 prevention, and error handling
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Route broad or ambiguous AgentKit SEO work to the right module while keeping context scoped. Use when a request spans multiple surfaces, asks for overall digital-presence strategy, involves provider or install architecture, needs agent-context planning, or the correct platform skill is unclear.
Persistent memory system for Claude Code. Two-layer architecture (hot cache + knowledge wiki), safety hooks, /close-day end-of-day synthesis. Zero external dependencies.
Claude-native deep research using DAG-based query planning, parallel subagent execution, and gap-driven iteration. No external API needed.
Web accessibility patterns for WCAG 2.2 compliance including ARIA, keyboard navigation, screen readers, and testing
Authentication and authorization patterns including OAuth2, JWT, RBAC, session management, and PKCE flows
AWS cloud patterns for Lambda, ECS, S3, DynamoDB, and Infrastructure as Code with CDK/Terraform
| name | graphql-design |
| description | GraphQL schema design, resolver patterns, subscriptions, DataLoader for N+1 prevention, and error handling |
type Query {
user(id: ID!): User
users(filter: UserFilter, first: Int = 20, after: String): UserConnection!
}
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
}
type Subscription {
orderStatusChanged(orderId: ID!): Order!
}
type User {
id: ID!
email: String!
name: String!
orders(first: Int = 10, after: String): OrderConnection!
createdAt: DateTime!
}
input CreateUserInput {
email: String!
name: String!
}
type CreateUserPayload {
user: User
errors: [UserError!]!
}
type UserError {
field: String!
message: String!
}
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type UserEdge {
node: User!
cursor: String!
}
type PageInfo {
hasNextPage: Boolean!
endCursor: String
}
Use Relay-style connections for pagination. Return payload types from mutations with both result and errors.
const resolvers: Resolvers = {
Query: {
user: async (_, { id }, ctx) => {
return ctx.dataloaders.user.load(id);
},
users: async (_, { filter, first, after }, ctx) => {
const cursor = after ? decodeCursor(after) : undefined;
const users = await ctx.db.user.findMany({
where: buildFilter(filter),
take: first + 1,
cursor: cursor ? { id: cursor } : undefined,
orderBy: { createdAt: "desc" },
});
const hasNextPage = users.length > first;
const edges = users.slice(0, first).map(user => ({
node: user,
cursor: encodeCursor(user.id),
}));
return {
edges,
pageInfo: {
hasNextPage,
endCursor: edges[edges.length - 1]?.cursor ?? null,
},
};
},
},
Mutation: {
createUser: async (_, { input }, ctx) => {
const existing = await ctx.db.user.findUnique({ where: { email: input.email } });
if (existing) {
return { user: null, errors: [{ field: "email", message: "Already taken" }] };
}
const user = await ctx.db.user.create({ data: input });
return { user, errors: [] };
},
},
User: {
orders: async (parent, { first, after }, ctx) => {
return ctx.dataloaders.userOrders.load({ userId: parent.id, first, after });
},
},
};
import DataLoader from "dataloader";
function createLoaders(db: Database) {
return {
user: new DataLoader<string, User>(async (ids) => {
const users = await db.user.findMany({ where: { id: { in: [...ids] } } });
const userMap = new Map(users.map(u => [u.id, u]));
return ids.map(id => userMap.get(id) ?? new Error(`User ${id} not found`));
}),
userOrders: new DataLoader<{ userId: string }, Order[]>(async (keys) => {
const userIds = keys.map(k => k.userId);
const orders = await db.order.findMany({
where: { userId: { in: userIds } },
orderBy: { createdAt: "desc" },
});
const grouped = new Map<string, Order[]>();
orders.forEach(o => {
const list = grouped.get(o.userId) ?? [];
list.push(o);
grouped.set(o.userId, list);
});
return keys.map(k => grouped.get(k.userId) ?? []);
}),
};
}
Create new DataLoader instances per request to avoid stale cache across users.
const pubsub = new PubSub();
const resolvers = {
Subscription: {
orderStatusChanged: {
subscribe: (_, { orderId }) => {
return pubsub.asyncIterableIterator(`ORDER_STATUS_${orderId}`);
},
},
},
Mutation: {
updateOrderStatus: async (_, { id, status }, ctx) => {
const order = await ctx.db.order.update({ where: { id }, data: { status } });
await pubsub.publish(`ORDER_STATUS_${id}`, { orderStatusChanged: order });
return { order, errors: [] };
},
},
};