Exercise 2: A Paginated Search Function — Possible Solution ============================================================= import { prisma } from "./lib/prisma"; import { Prisma } from "./generated/prisma/client"; const PAGE_SIZE = 10; export async function searchPosts(term?: string, page = 1) { const where: Prisma.PostWhereInput = { published: true }; const trimmed = term?.trim(); if (trimmed) { where.title = { contains: trimmed }; // add mode: "insensitive" on PostgreSQL } const safePage = Math.max(1, Math.floor(page)); const [posts, total] = await Promise.all([ prisma.post.findMany({ where, orderBy: [{ createdAt: "desc" }, { id: "desc" }], skip: (safePage - 1) * PAGE_SIZE, take: PAGE_SIZE, }), prisma.post.count({ where }), ]); return { posts, totalPages: Math.ceil(total / PAGE_SIZE), page: safePage }; } Why it's safe: - `published: true` is always present, so a missing or empty term only removes the title filter — it can never expose drafts. The title condition is added only when there's a real search term. - The same `where` object is used for both the page and the count, so the page count always matches the results. - Sorting by createdAt, then id, gives a fixed order even when two posts share a timestamp, so pages don't overlap. - The page number is cleaned up, so page 0 or -3 can't produce a negative skip. Prisma.PostWhereInput is the generated type for a Post filter, which lets TypeScript check the object as it's built. WHY THIS WORKS AS AN ANSWER ------------------------------ It handles the undefined-filter trap from the chapter, keeps results and counts consistent, and makes paging stable.