Paginate every page
Walk every page of a Relay connection with the paginate() helper.
Most list* functions in @uidu/client return the first page only — they're tuned for the common case of "show the first N." When you need everything (a sitemap, generateStaticParams, an export), use the paginate() helper.
What it does
paginate() repeatedly calls a list query, threading pageInfo.endCursor into the next call's after argument until hasNextPage is false. Returns a flat array of nodes.
Signature
import { paginate, ListEventsDocument } from '@uidu/client';
const all = await paginate(client, ListEventsDocument, {
variables: { first: 100 },
extract: (d) => d.currentWorkspace?.events,
});| Argument | Type | Notes |
|---|---|---|
client | UiduClient | Created with createClient. |
document | TypedDocumentNode | Any List*Document re-exported from @uidu/client. |
variables | Omit<Vars, 'after'> | First-page variables. after is set by paginate itself. |
extract | (data) => RelayConnection | null | Pluck the connection out of the result shape. |
maxPages | number (default 1000) | Safety bound — guards against runaway loops. |
Sitemap with every page
// app/sitemap.ts
import { paginate, ListPagesDocument } from '@uidu/client';
import { client } from '@/lib/uidu';
export default async function sitemap() {
const pages = await paginate(client, ListPagesDocument, {
variables: { projectId: process.env.UIDU_PROJECT_ID!, first: 100 },
extract: (d) => d.currentWorkspace?.project?.pages,
});
return pages.map((p) => ({
url: `https://example.com/${p.slug}`,
lastModified: p.updatedAt,
}));
}generateStaticParams for every event
// app/events/[id]/page.tsx
import { paginate, ListEventsDocument } from '@uidu/client';
import { client } from '@/lib/uidu';
export async function generateStaticParams() {
const events = await paginate(client, ListEventsDocument, {
variables: { first: 100 },
extract: (d) => d.currentWorkspace?.events,
});
return events.map((e) => ({ id: e.id }));
}Other List Documents
The same pattern works with any of the re-exported Documents:
ListBookingsDocument, ListCalendarsDocument, ListCalendarEventsDocument, ListCallsDocument, ListCampaignsDocument, ListEmailCampaignsDocument, ListCoursesDocument, ListDealsDocument, ListDonationCampaignsDocument, ListEmployeesDocument, ListEnrollmentsDocument, ListEventsDocument, ListFormsDocument, ListKbArticlesDocument, ListKbCollectionsDocument, ListLecturesDocument, ListPagesDocument, ListStoriesDocument.
Why a Document, not the list function?
The user-facing listEvents(client, vars) returns a flat array — it throws away pageInfo to keep the common case ergonomic. paginate() needs pageInfo, so it works one level lower against the raw TypedDocumentNode.
Be mindful with very large collections. paginate() is memory-bound — it holds the full result in RAM. For exports of 10k+ records, prefer streaming the data straight to disk or a downstream sink instead.