Skip to content

Commit

Permalink
feat(empty-results): support empty non-terminal pages
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Data sources must return a final cursor value
for the result set.
  • Loading branch information
djMax committed Apr 1, 2024
1 parent 9b6f095 commit 05227ac
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 11 deletions.
4 changes: 3 additions & 1 deletion __tests__/LetterDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ export class MockLetterSource implements DataSource<LetterResult> {

async getNextResults(cursor: string | undefined) {
const startIndex = this.results.findIndex(result => result.cursor > (cursor ?? ''));
const results = startIndex === -1 ? [] : this.results.slice(startIndex, startIndex + this.pageSize);
return {
total: this.results.length,
hasMore: startIndex + this.pageSize < this.results.length,
results: startIndex === -1 ? [] : this.results.slice(startIndex, startIndex + this.pageSize),
results,
cursor: results[results.length - 1].cursor,
};
}

Expand Down
19 changes: 9 additions & 10 deletions src/asDataGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,17 @@ export function asDataGenerator<T extends ResultWithCursor>(
while (continueFetching) {
const response = await dataSource.getNextResults(currentCursor);
total = response.total;
if (response.results.length === 0) {
continueFetching = false;
} else {
for (const result of response.results) {
if (!filter || filter(result)) {
yield result;
}
currentCursor = result.cursor; // Assuming the cursor for the next fetch is from the last item
continueFetching = response.hasMore;

for (const result of response.results || []) {
if (!filter || filter(result)) {
yield result;
}
// Continue fetching only if we received as many results as we asked for, implying there might be more.
continueFetching = response.hasMore;
currentCursor = result.cursor; // Assuming the cursor for the next fetch is from the last item
}
// There is a nuance here - we COULD return this result-set cursor for the last
// result in the yield above, and that would avoid fetching unused results next time.
currentCursor = response.cursor;
}
},
sortKey: dataSource.sortKey,
Expand Down
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export interface DatasourceResults<T extends ResultWithCursor> {
// If total is available from ALL data sources, a total will
// be returned from the paged set.
total?: number;
// There can be cases where you don't return results, but the cursor
// has advanced anyhow. Once we run out of results, we will use this
// cursor.
cursor: string;
}

/**
Expand Down

0 comments on commit 05227ac

Please sign in to comment.