Paging
Offset and limit, a total you should not count against, and the loop each library writes for you.
A collection answers one shape:
{
"items": [ … ],
"total": 1284
} limit is 1–100 and 30 by default. offset is where to carry on from. total is there wherever the caller pages by offset, because that is exactly when
somebody has to know how far the list goes.
Stop on a short page, not on total #
This is the one thing worth reading on this page. total is a count taken at the
moment of the query, and these lists change while they are being read — somebody adds a title,
a shelf goes private, an import lands. A loop that counts against it either asks for a page
that is not there or stops before the end.
The test is whether the page came back shorter than it asked for. Every library
here does that, and every one of them has a test for it against a server that reports total: 4000 and hands back five rows.
for await (const title of acyka.catalogue.listTitlesAll({ genre: 'Drama' })) {
console.log(title.title);
} // what the paginator does, if you would rather do it yourself
let offset = 0;
const limit = 100;
for (;;) {
const page = await acyka.catalogue.listTitles({ genre: 'Drama', limit, offset });
for (const title of page.items) use(title);
// The test is the page's own length, never `total`.
if (page.items.length < limit) break;
offset += page.items.length;
} The order is stable #
Every ordering the catalogue offers ties, and heavily — thousands of titles share a score and most share a vote count. A tie the database is free to break differently between two queries is a row handed out on page two and again on page three, with another skipped in between. So every ordering ends in the id, which is unique and settles every tie the same way twice.
Which operations page #
These 11, read off the contract — an operation gets a paginator when it takes
both limit and offset, because a loop with only one of the two either
never advances or cannot be sized.
/characters/{id}/titles/titles/people/{id}/characters/people/{id}/titles/titles/{id}/characters/lists/users/{nick}/followers/users/{nick}/following/users/{nick}/lists/following/posts
Everything else answers a whole list, and that is a promise rather than an oversight: a title's staff, a character's voices and the week's calendar are bounded by what they are, so paging them would be a parameter with nothing behind it.