/** * The offset-pagination protocol behind `NTable`'s page controls. * * The kit already owns the consuming half — `useDynamicPageSize` measures how * many rows fit, `buildPageItems` renders the bar. This is the fetching half: * how one page is requested, and how "is there another one" is answered when * the endpoint does not say. * * Pure, framework-agnostic, and usable on the server. Nothing here knows about * react-query. */ /** A page response from an endpoint that reports a result total. */ interface ApiPage { rows: T[]; /** Rows matching the query on the server, or `null` if the endpoint is silent. */ total: number | null; } interface OffsetPagination { limit: number; offset: number; } interface OffsetPage { rows: T[]; hasNextPage: boolean; nextOffset: number; /** How many rows match in total, or `null` if the endpoint does not say. */ total: number | null; } /** * Fetches one window. * * The bare-array return is not a legacy concession to delete later: plenty of * endpoints have no cheap way to count, and `COUNT(*)` over a filtered join is * exactly the query worth avoiding. Both shapes are first-class. */ type OffsetPageFetcher = (pagination: OffsetPagination) => Promise | T[]>; declare const DEFAULT_PAGE_SIZE = 25; /** * The largest `limit` a server will honour. Requests are clamped to it, and it * is the ceiling the probe row cannot exceed — see `fetchOffsetPage`. */ declare const DEFAULT_MAX_PAGE_SIZE = 100; interface OffsetPageOptions { /** Defaults to `DEFAULT_MAX_PAGE_SIZE`. Match your server's clamp. */ maxLimit?: number; } declare function createOffsetPagination(pageIndex?: number, pageSize?: number, { maxLimit }?: OffsetPageOptions): OffsetPagination; declare function getPageIndex({ limit, offset }: OffsetPagination): number; /** * Fetches one page and answers whether another follows. * * Two strategies, chosen by what the endpoint returns: * * - **With a total**, continuation is arithmetic — no extra rows, no extra * request. * - **Without one**, the request carries a *probe row*: it asks for `limit + 1` * and reports a next page when that extra row comes back. The probe is * discarded before returning, so callers always receive at most `limit` rows. * * Whether an endpoint reports a total is only knowable from its response, so * the probe row rides along on the first request either way. The one case the * probe cannot cover is a request already at `maxLimit`, where there is no room * to ask for one more; continuation then costs a second single-row lookahead. * That is the case a result total exists to avoid, and why the endpoints * backing numbered pages should report one. */ declare function fetchOffsetPage(fetchPage: OffsetPageFetcher, pagination: OffsetPagination, { maxLimit }?: OffsetPageOptions): Promise>; type QueryValue = string | number | boolean | null | undefined; /** * Drops empty entries from a query object, so an untouched filter contributes * no parameter at all rather than `?status=`. * * `false` and `0` are kept — both are meaningful filter values, and dropping * them is the bug this exists to prevent. */ declare function cleanQuery(query: Record): Record; export { type ApiPage, DEFAULT_MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, type OffsetPage, type OffsetPageFetcher, type OffsetPageOptions, type OffsetPagination, type QueryValue, cleanQuery, createOffsetPagination, fetchOffsetPage, getPageIndex };