-
Notifications
You must be signed in to change notification settings - Fork 1
/
hasNextPageStrategies.js
129 lines (113 loc) · 3.16 KB
/
hasNextPageStrategies.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import pg from 'pg'
import Fastify from 'fastify'
import mercurius from 'mercurius'
import SQL from '@nearform/sql'
import { makeExecutableSchema } from '@graphql-tools/schema'
import { connectionDirective } from '../index.js'
const app = Fastify({
logger: true
})
const pool = new pg.Pool({
host: 'localhost',
post: '5432',
user: 'docker',
password: 'docker',
database: 'docker'
})
const typeConnectionMap = {
Film: {
edgeProps: {
PeopleFilm: { roles: '[String!]!', performance: 'Int!' }
}
}
}
const { connectionDirectiveTypeDefs, connectionDirectiveTransformer } =
connectionDirective(typeConnectionMap)
const typeDefs = `
type People {
id: ID!
name: String!
type: String!
films: [Film!]! @connection(prefix: "PeopleFilm")
}
type Film {
id: ID!
name: String!
released: Int!
}
type Query {
people: [People!]! @connection
films: [Film!]! @connection
}
`
const resolvers = {
Query: {
people: async (root, { first, after }) => {
const query = SQL`
select *
from people
${after ? SQL`where id > ${after}` : SQL``}
order by id
limit ${first}`
const res = await pool.query(query.text, query.values)
// Basic usage where we allow the library to determine
// 'hasNextPage' values based on the requested page size
// and the dataset returned
return res.rows
},
films: async (root, { first, after }) => {
const query = SQL`
select
*,
count(*) over () as remaining_count
from films
${after ? SQL`where id > ${after}` : SQL``}
order by id
limit ${first}`
const res = await pool.query(query.text, query.values)
// Using a window function we can retrieve the remaining
// rows and compare this to the requested page size
// to provide an accurate hasNextPage value
return {
edges: res.rows,
pageInfo: {
hasNextPage: res.rows?.[0].remaining_count > first
}
}
}
},
People: {
films: async (root, { first, after }) => {
const query = SQL`
select pf.roles, pf.performance, pf.rel_type, f.*
from people_films pf
join films f on f.id = pf.film_id
where pf.people_id = ${root.id}
${after ? SQL`and f.id > ${after}` : SQL``}
order by f.id
limit ${first + 1}`
const res = await pool.query(query.text, query.values)
// Here we +1 to the first value. This causes us to provide
// 1 more value than requested to the response formatter.
// The request response will only include the request number
// of records but we can determine there is another page by
// comparing the dataset length with the users `first` value
return {
edges: res.rows,
pageInfo: {
hasNextPage: res.rows.length > first
}
}
}
}
}
const schema = makeExecutableSchema({
typeDefs: [connectionDirectiveTypeDefs, typeDefs],
resolvers
})
const connectionSchema = connectionDirectiveTransformer(schema)
app.register(mercurius, {
schema: connectionSchema,
graphiql: true
})
await app.listen({ port: 3000 })