fix(pages): clamp public listing page values#337
Conversation
Greptile SummaryThis PR introduces a shared
Confidence Score: 3/5Not safe to merge as-is: the pagination logic is correct, but the tool that wrote this PR corrupted every non-ASCII character it touched across all seven listing pages, replacing them with multi-character mojibake sequences that will render visibly broken in browsers. The encoding corruption affects visible user-facing content (approximate price hints, em-dashes in headings, arrows in links, lightning-bolt icons) on every public marketplace page. The pagination helper itself is sound and the tests are thorough, but the character corruption must be fixed before merging. All seven page files (affiliates, directory, for-hire, gigs, mcp, prompts, skills) need their non-ASCII characters restored to their original Unicode code points; src/lib/pagination.ts should have its DEFAULT_MAX_PAGE cap reconsidered. Important Files Changed
Reviews (1): Last reviewed commit: "fix(pages): clamp public listing pages" | Re-trigger Greptile |
| return `≈ $${(offer.price_sats * offer.commission_rate).toFixed(2)} USD`; | ||
| } | ||
| if (offer.commission_type === "flat" && offer.commission_flat_sats > 0 && btcUsd) { | ||
| return `≈ $${((offer.commission_flat_sats / 1e8) * btcUsd).toFixed(2)} USD`; | ||
| return `≈ $${((offer.commission_flat_sats / 1e8) * btcUsd).toFixed(2)} USD`; |
There was a problem hiding this comment.
Unicode characters corrupted across all seven pages
Every non-ASCII decorative character in the PR's changed files has been replaced with a mojibake equivalent: ≈ → ≈, — → â€", → → â†', ✕ → ✕, ⚡ → âš¡. These are the raw UTF-8 byte sequences of the originals re-encoded as Latin-1 then stored back as UTF-8 — a classic double-encoding error. A browser serving the UTF-8 page will render these literally (e.g. showing "â€" 50 âš¡" instead of "— 50 ⚡"), breaking visible content for all affected listing pages. The same corruption appears in src/app/directory/page.tsx, src/app/for-hire/[[...tags]]/page.tsx, src/app/gigs/[[...tags]]/page.tsx, src/app/mcp/page.tsx, src/app/prompts/page.tsx, and src/app/skills/page.tsx — the pattern is present throughout the PR.
| const DEFAULT_MAX_PAGE = 100_000; | ||
|
|
||
| export function parsePageParam( | ||
| value: string | null | undefined, | ||
| maxPage = DEFAULT_MAX_PAGE | ||
| ) { | ||
| const parsed = parseInt(value || "1", 10); | ||
| return Number.isFinite(parsed) | ||
| ? Math.min(Math.max(parsed, 1), maxPage) | ||
| : 1; | ||
| } |
There was a problem hiding this comment.
Max page cap of 100,000 permits database offsets up to ~2 million rows
DEFAULT_MAX_PAGE = 100_000 with a typical limit of 20 allows offset = (100_000 - 1) * 20 = 1_999_980. PostgreSQL evaluates large offsets by scanning and discarding all preceding rows, so a request near the cap could cause significant query latency even against an otherwise small table. A tighter ceiling (e.g. 10,000) would still be far beyond any realistic catalog depth while avoiding full-table scans on malicious or accidental edge requests.
|
Addressed the Greptile note in 1352479: restored the touched page files with proper Unicode characters and switched the public page cap from 100,000 to 1,000 pages to avoid very deep offsets. The pagination helper/tests were updated to match the tighter cap. |
Summary
parsePageParamhelper for public listing pagespagequery values before computing pagination offsetsFixes #336.
Verification