Skip to content
This repository was archived by the owner on May 21, 2021. It is now read-only.

Commit 2d46cea

Browse files
authored
feat: connection total count
1 parent f54b709 commit 2d46cea

6 files changed

+64
-15
lines changed

src/relay/connection.factory.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
import {
2-
Connection,
32
ConnectionArguments,
43
getOffsetWithDefault,
54
offsetToCursor
65
} from 'graphql-relay'
76
import { Repository } from 'typeorm'
87

8+
import { Connection } from './connection.interface'
9+
910
export async function connectionFromRepository<T>(
1011
args: ConnectionArguments,
1112
repository: Repository<T>
1213
): Promise<Connection<T>> {
1314
const { before, after, first, last } = args
1415

15-
const total = await repository.count()
16+
const totalCount = await repository.count()
1617

1718
// offsets
18-
const beforeOffset = getOffsetWithDefault(before, total)
19+
const beforeOffset = getOffsetWithDefault(before, totalCount)
1920
const afterOffset = getOffsetWithDefault(after, -1)
2021

2122
let startOffset = Math.max(-1, afterOffset) + 1
22-
let endOffset = Math.min(beforeOffset, total)
23+
let endOffset = Math.min(beforeOffset, totalCount)
2324

2425
if (first) {
2526
endOffset = Math.min(endOffset, startOffset + first)
@@ -44,7 +45,7 @@ export async function connectionFromRepository<T>(
4445
// page info
4546
const { length, 0: firstEdge, [length - 1]: lastEdge } = edges
4647
const lowerBound = after ? afterOffset + 1 : 0
47-
const upperBound = before ? Math.min(beforeOffset, total) : total
48+
const upperBound = before ? Math.min(beforeOffset, totalCount) : totalCount
4849

4950
const pageInfo = {
5051
startCursor: firstEdge ? firstEdge.cursor : null,
@@ -55,6 +56,7 @@ export async function connectionFromRepository<T>(
5556

5657
return {
5758
edges,
58-
pageInfo
59+
pageInfo,
60+
totalCount
5961
}
6062
}

src/relay/connection.generic.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { Connection, Edge } from 'graphql-relay'
1+
import { Edge } from 'graphql-relay'
22
import { ClassType, Field, ObjectType } from 'type-graphql'
33

4+
import { Connection } from './connection.interface'
45
import { PageInfo } from './page-info.object'
56

67
type NodeType<E> = E extends Edge<infer N> ? N : unknown
@@ -18,6 +19,11 @@ export function ConnectionType<E extends Edge<N>, N = NodeType<E>>(
1819

1920
@Field({ description: 'Information to aid in pagination.' })
2021
readonly pageInfo!: PageInfo
22+
23+
@Field({
24+
description: 'Identifies the total count of items in the connection.'
25+
})
26+
readonly totalCount!: number
2127
}
2228

2329
return ConnectionClass

src/relay/connection.interface.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Connection as RelayConnection } from 'graphql-relay'
2+
3+
export interface Connection<T> extends RelayConnection<T> {
4+
readonly totalCount: number
5+
}

src/relay/node.resolver.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ export class NodeResolver {
3838
)
3939
}
4040

41-
return repository.findOne(id)
41+
return await repository.findOne(id)
4242
}
4343

4444
// TODO: use dataloader
4545
@Query(() => Node, {
4646
nullable: true,
4747
description: 'Fetches an object given its global ID.'
4848
})
49-
async node(
49+
node(
5050
@Arg('id', () => ID, { description: 'The global ID of the object.' })
5151
globalId: string,
5252
@Ctx() context: Context
@@ -58,11 +58,11 @@ export class NodeResolver {
5858
nullable: 'items',
5959
description: 'Fetches objects given their global IDs.'
6060
})
61-
async nodes(
61+
nodes(
6262
@Arg('ids', () => [ID], { description: 'The global IDs of the objects.' })
6363
globalIds: Array<string>,
6464
@Ctx() context: Context
65-
): Promise<Array<ReturnType<NodeResolver['fetcher']>>> {
65+
): Array<ReturnType<NodeResolver['fetcher']>> {
6666
return globalIds.map(id => this.fetcher(id, context))
6767
}
6868
}

src/relay/page-info.object.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@ export class PageInfo implements RelayPageInfo {
77
nullable: true,
88
description: 'When paginating backwards, the cursor to continue.'
99
})
10-
startCursor?: ConnectionCursor | null
10+
readonly startCursor?: ConnectionCursor | null
1111

1212
@Field(() => String, {
1313
nullable: true,
1414
description: 'When paginating forwards, the cursor to continue.'
1515
})
16-
endCursor?: ConnectionCursor | null
16+
readonly endCursor?: ConnectionCursor | null
1717

1818
@Field(() => Boolean, {
1919
nullable: true,
2020
description: 'When paginating backwards, are there more items?'
2121
})
22-
hasPreviousPage?: boolean | null
22+
readonly hasPreviousPage?: boolean | null
2323

2424
@Field(() => Boolean, {
2525
nullable: true,
2626
description: 'When paginating forwards, are there more items?'
2727
})
28-
hasNextPage?: boolean | null
28+
readonly hasNextPage?: boolean | null
2929
}

tests/functional/relay/connection.test.ts

+36
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ query users($before: String, $after: String, $first: Int, $last: Int) {
2222
hasPreviousPage
2323
hasNextPage
2424
}
25+
totalCount
2526
}
2627
}
2728
`
@@ -197,4 +198,39 @@ describe('connection', () => {
197198
})
198199
})
199200
})
201+
202+
describe('total count', () => {
203+
test('should return 0', async () => {
204+
const result = await graphql({
205+
schema,
206+
source: USERS_QUERY
207+
})
208+
209+
expect(result.errors).toBeUndefined()
210+
expect(result.data).toBeObject()
211+
expect(result.data).toMatchObject({
212+
users: {
213+
totalCount: 0
214+
}
215+
})
216+
})
217+
218+
test('should return 2', async () => {
219+
await repository.save({ name: 'Calmon Ribeiro' })
220+
await repository.save({ name: 'Michał Lytek' })
221+
222+
const result = await graphql({
223+
schema,
224+
source: USERS_QUERY
225+
})
226+
227+
expect(result.errors).toBeUndefined()
228+
expect(result.data).toBeObject()
229+
expect(result.data).toMatchObject({
230+
users: {
231+
totalCount: 2
232+
}
233+
})
234+
})
235+
})
200236
})

0 commit comments

Comments
 (0)