Skip to content

Commit

Permalink
feat: Better support for Offset Pagination #140
Browse files Browse the repository at this point in the history
  • Loading branch information
lkrzyzanek committed Dec 5, 2023
1 parent a5e6686 commit 773b31f
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ junit.xml

# Node modules
node_modules/
.nx

# Mac OS
.DS_Store
Expand Down
2 changes: 1 addition & 1 deletion examples/in-memory/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const typeDefs = gql`
booksByTitle(first: Int = 10 after: String title: String): BookConnection
booksByAuthor(first: Int = 10 after: String author: String): BookConnection
booksByOffset(first: Int = 10 after: String): BookConnection
booksByOffset(first: Int = 10, after: String, page: Int): BookConnection
booksDynamic(first: Int = 10 after: String): BookConnection
}
Expand Down
2 changes: 1 addition & 1 deletion examples/mongodb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"graphql": "^16.6.0",
"graphql-tag": "2.12.6",
"mongodb": "^5.1.0",
"mongodb-memory-server": "^8.12.1"
"mongodb-memory-server": "^9.1.1"
},
"devDependencies": {
"@graphql-codegen/cli": "^3.2.2",
Expand Down
1 change: 1 addition & 0 deletions examples/mongodb/src/datasources/booksApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const collectionName = "books";
export async function createBooksDataSource(mongoDb: Db) {
const ds = new MongoDbDataSource<BookType, ObjectId, QueryBooksArgs, QueryBooks_DescArgs>({
collectionName,
//@ts-ignore
mongoDb,
filters: (args) => {
const filters = [];
Expand Down
33 changes: 23 additions & 10 deletions packages/core/__tests__/test-offset-ds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,48 @@ describe("offset-totalCount", () => {
});

describe("offset-after", () => {
const array = [{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}];

test("no-offset", async () => {
const ds = new ArrayOffsetDs([{"id": 1}]);
const offset = new OffsetDataSourceWrapper(ds);
return expect(offset.after(undefined, 10, { first: 0 })).resolves.toStrictEqual([{"_index": 0, "id": 1}]);
})
test("offset", async () => {
const ds = new ArrayOffsetDs([{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}]);
test("offset-arg-first", async () => {
const ds = new ArrayOffsetDs(array);
const offset = new OffsetDataSourceWrapper(ds);
return expect(offset.after(2, 1, { first: 0 })).resolves.toStrictEqual([{"_index": 3, "id": 4}]);
})
test("offset-arg-page-1", async () => {
const ds = new ArrayOffsetDs(array);
const offset = new OffsetDataSourceWrapper(ds);
return expect(offset.after(undefined, 2, { page: 1 })).resolves.toStrictEqual([{"_index": 0, "id": 1}, { "_index": 1, "id": 2 }]);
})
test("offset-arg-page-3", async () => {
const ds = new ArrayOffsetDs(array);
const offset = new OffsetDataSourceWrapper(ds);
return expect(offset.after(2, 1, { first: 0 })).resolves.toStrictEqual([
{"_index": 3, "id": 4}
]);
return expect(offset.after(undefined, 3, { page: 2 })).resolves.toStrictEqual([{ "_index": 2, "id": 3 }, {"_index": 3,"id": 4}]);
})

});

describe("offset-before", () => {
const array = [{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}];

test("no-offset", async () => {
const ds = new ArrayOffsetDs([{"id": 1}]);
const offset = new OffsetDataSourceWrapper(ds);
return expect(offset.before(undefined, 10, { last: 0 })).resolves.toStrictEqual([{"_index": 0, "id": 1}]);
})
test("offset", async () => {
const ds = new ArrayOffsetDs([{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}]);
test("offset-arg-last", async () => {
const ds = new ArrayOffsetDs(array);
const offset = new OffsetDataSourceWrapper(ds);
return expect(offset.before(2, 1, { last: 0 })).resolves.toStrictEqual([{"_index": 3, "id": 1}]);
})
test("offset-arg-page-1", async () => {
const ds = new ArrayOffsetDs(array);
const offset = new OffsetDataSourceWrapper(ds);
return expect(offset.before(2, 1, { last: 0 })).resolves.toStrictEqual([
{"_index": 3, "id": 1},
]);
return expect(offset.before(undefined, 3, { page: 2 })).resolves.toStrictEqual([{ "_index": 2, "id": 2 }, {"_index": 3,"id": 1}]);
})

});
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/CursorPagerSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface PageInfo {
export interface ArgsForward {
first: number
after?: string
page?: number
}

/**
Expand All @@ -48,6 +49,7 @@ export interface ArgsForward {
export interface ArgsBackward {
last: number,
before?: string
page?: number
}


Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/DataSourcePager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ export function dataSourcePager<NodeType,
const resultPlusOne = await ds.after(afterId, args.first + 1, args);

const hasNextPage = resultPlusOne?.length > args.first;
const hasPreviousPage = !!args.after;
let hasPreviousPage = !!args.after;
if (args.page) hasPreviousPage = args.page > 1;

let count;
if (fetchTotalCountInResolver) count = await totalCount(args, ds);
Expand All @@ -110,7 +111,8 @@ export function dataSourcePager<NodeType,
const resultPlusOne = await ds.before(beforeId, args.last + 1, args);

const hasNextPage = resultPlusOne?.length > args.last;
const hasPreviousPage = !!args.before;
let hasPreviousPage = !!args.before;
if (args.page) hasPreviousPage = args.page > 1;

let count;
if (fetchTotalCountInResolver) count = await totalCount(args, ds);
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/datasource/OffsetDataSourceWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ export class OffsetDataSourceWrapper<NodeType,
}

async after(afterIndex: number | undefined, size: number, args: ArgsForwardType): Promise<NodeType[]> {
const start = afterIndex != null ? afterIndex + 1 : 0;
let start = afterIndex != null ? afterIndex + 1 : 0;
start = args.page && args.page > 1 ? ((args.page - 1) * (size - 1)) : start;
return this.ds.after(start, size, args).then(data => this.addIndexField(start, data));
}

async before(beforeIndex: number | undefined, size: number, args: ArgsBackwardType): Promise<NodeType[]> {
const start = beforeIndex != null ? beforeIndex + 1 : 0;
let start = beforeIndex != null ? beforeIndex + 1 : 0;
start = args.page && args.page > 1 ? ((args.page - 1) * (size - 1)) : start;
return this.ds.before(start, size, args).then(data => this.addIndexField(start, data));
}

Expand Down
2 changes: 1 addition & 1 deletion packages/mongodb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@
"devDependencies": {
"@types/node": "^18.15.11",
"mongodb": "^5.1.0",
"mongodb-memory-server": "^9.0.0"
"mongodb-memory-server": "^9.1.1"
}
}

0 comments on commit 773b31f

Please sign in to comment.