Arguments
Arguments customise a field’s behaviour: limit results, filter, paginate, sort. Define them in the schema with types and defaults; access them as the second resolver argument.
Filter, paginate, default, validate
EXAMPLE
# Schema — typed arguments with defaults
type Query {
posts(
first: Int = 20
after: String # cursor
status: PostStatus
authorId: ID
search: String
): PostConnection!
}
enum PostStatus { DRAFT PUBLISHED ARCHIVED }
type PostConnection {
edges: [PostEdge!]!
pageInfo: PageInfo!
}
type PostEdge {
cursor: String!
node: Post!
}
type PageInfo {
endCursor: String
hasNextPage: Boolean!
}
# Resolver — destructure args
Query: {
posts: async (_, { first, after, status, authorId, search }, { db }) => {
// Validate / clamp
const take = Math.min(first ?? 20, 100);
const where = {
status,
authorId,
title: search ? { contains: search, mode: 'insensitive' } : undefined,
id: after ? { gt: decodeCursor(after) } : undefined,
};
const rows = await db.posts.findMany({
where,
take: take + 1, // fetch one extra to detect next page
orderBy: { id: 'asc' },
});
const hasNextPage = rows.length > take;
const edges = rows.slice(0, take).map(p => ({
cursor: encodeCursor(p.id),
node: p,
}));
return {
edges,
pageInfo: { endCursor: edges.at(-1)?.cursor, hasNextPage },
};
},
},
Why it matters
Always cap pagination args server-side. A client asking for first: 1_000_000 shouldn’t take your DB down — clamp to a sensible max in the resolver.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Discussion
Loading…