Skip to content

Commit 571abf5

Browse files
authored
fix(auto-pagination): handle multiple fields correctly (#71)
* fix(auto-pagination): handle multiple fields correctly * .. * Better solution * Add unit tests
1 parent c51436c commit 571abf5

File tree

3 files changed

+78
-61
lines changed

3 files changed

+78
-61
lines changed

.changeset/sharp-poems-move.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphprotocol/client-auto-pagination': patch
3+
---
4+
5+
fix(auto-pagination): handle multiple fields correctly

packages/auto-pagination/__tests__/auto-pagination.test.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,8 @@ describe('Auto Pagination', () => {
5050
schema: wrappedSchema,
5151
document: parse(query),
5252
})
53-
expect(result).toEqual({
54-
data: {
55-
users: users.slice(0, 10),
56-
},
57-
})
53+
expect(result.data?.users).toHaveLength(10)
54+
expect(result.data?.users).toEqual(users.slice(0, 10))
5855
})
5956
it('should respect skip argument', async () => {
6057
const query = /* GraphQL */ `
@@ -69,10 +66,23 @@ describe('Auto Pagination', () => {
6966
schema: wrappedSchema,
7067
document: parse(query),
7168
})
72-
expect(result).toEqual({
73-
data: {
74-
users: users.slice(1, 10),
75-
},
69+
expect(result.data?.users).toHaveLength(10)
70+
expect(result.data?.users).toEqual(users.slice(1, 11))
71+
})
72+
it('should work with the values under the limit', async () => {
73+
const query = /* GraphQL */ `
74+
query {
75+
users(first: 2, skip: 2) {
76+
id
77+
name
78+
}
79+
}
80+
`
81+
const result = await execute({
82+
schema: wrappedSchema,
83+
document: parse(query),
7684
})
85+
expect(result.data?.users).toHaveLength(2)
86+
expect(result.data?.users).toEqual(users.slice(2, 4))
7787
})
7888
})

packages/auto-pagination/src/index.ts

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
isListType,
1010
isNonNullType,
1111
Kind,
12+
print,
1213
SelectionNode,
1314
visit,
1415
} from 'graphql'
@@ -89,67 +90,68 @@ export default class AutoPaginationTransform implements MeshTransform {
8990
if (selectionNode.kind === Kind.FIELD) {
9091
if (
9192
!selectionNode.name.value.startsWith('_') &&
92-
getQueryFieldNames(delegationContext.transformedSchema).includes(selectionNode.name.value)
93+
getQueryFieldNames(delegationContext.transformedSchema).includes(selectionNode.name.value) &&
94+
!selectionNode.arguments?.some((argNode) => argNode.name.value === 'id')
9395
) {
94-
if (!selectionNode.arguments?.some((argNode) => argNode.name.value === 'id')) {
95-
const firstArg = selectionNode.arguments?.find(
96-
(argNode) => argNode.name.value === this.config.firstArgumentName,
97-
)
98-
const skipArg = selectionNode.arguments?.find(
99-
(argNode) => argNode.name.value === this.config.skipArgumentName,
100-
)?.value as IntValueNode | undefined
101-
if (firstArg != null && firstArg.value.kind === Kind.INT) {
102-
const numberOfTotalRecords = parseInt(firstArg.value.value)
103-
if (numberOfTotalRecords > this.config.limitOfRecords) {
104-
const fieldName = selectionNode.name.value
105-
const aliasName = selectionNode.alias?.value || fieldName
106-
let skip: number
107-
for (
108-
skip = skipArg?.value ? parseInt(skipArg.value) : 0;
109-
skip < numberOfTotalRecords;
110-
skip += this.config.limitOfRecords
111-
) {
112-
newSelections.push({
113-
...selectionNode,
114-
alias: {
115-
kind: Kind.NAME,
116-
value: `splitted_${skip}_${aliasName}`,
96+
const firstArg = selectionNode.arguments?.find(
97+
(argNode) => argNode.name.value === this.config.firstArgumentName,
98+
)
99+
const skipArg = selectionNode.arguments?.find(
100+
(argNode) => argNode.name.value === this.config.skipArgumentName,
101+
)?.value as IntValueNode | undefined
102+
if (firstArg != null && firstArg.value.kind === Kind.INT) {
103+
const numberOfTotalRecords = parseInt(firstArg.value.value)
104+
if (numberOfTotalRecords > this.config.limitOfRecords) {
105+
const fieldName = selectionNode.name.value
106+
const aliasName = selectionNode.alias?.value || fieldName
107+
const initialSkip = skipArg?.value ? parseInt(skipArg.value) : 0
108+
let skip: number
109+
for (
110+
skip = initialSkip;
111+
numberOfTotalRecords - skip + initialSkip > 0;
112+
skip += this.config.limitOfRecords
113+
) {
114+
newSelections.push({
115+
...selectionNode,
116+
alias: {
117+
kind: Kind.NAME,
118+
value: `splitted_${skip}_${aliasName}`,
119+
},
120+
arguments: [
121+
{
122+
kind: Kind.ARGUMENT,
123+
name: {
124+
kind: Kind.NAME,
125+
value: this.config.firstArgumentName,
126+
},
127+
value: {
128+
kind: Kind.INT,
129+
value: Math.min(
130+
numberOfTotalRecords - skip + initialSkip,
131+
this.config.limitOfRecords,
132+
).toString(),
133+
},
117134
},
118-
arguments: [
119-
{
120-
kind: Kind.ARGUMENT,
121-
name: {
122-
kind: Kind.NAME,
123-
value: this.config.firstArgumentName,
124-
},
125-
value: {
126-
kind: Kind.INT,
127-
value: Math.min(numberOfTotalRecords - skip, this.config.limitOfRecords).toString(),
128-
},
135+
{
136+
kind: Kind.ARGUMENT,
137+
name: {
138+
kind: Kind.NAME,
139+
value: this.config.skipArgumentName,
129140
},
130-
{
131-
kind: Kind.ARGUMENT,
132-
name: {
133-
kind: Kind.NAME,
134-
value: this.config.skipArgumentName,
135-
},
136-
value: {
137-
kind: Kind.INT,
138-
value: skip.toString(),
139-
},
141+
value: {
142+
kind: Kind.INT,
143+
value: skip.toString(),
140144
},
141-
],
142-
})
143-
}
145+
},
146+
],
147+
})
144148
}
149+
continue
145150
}
146-
} else {
147-
newSelections.push(selectionNode)
148151
}
149-
} else {
150-
newSelections.push(selectionNode)
151152
}
152153
}
154+
newSelections.push(selectionNode)
153155
}
154156
return {
155157
...selectionSet,

0 commit comments

Comments
 (0)