1
1
import Parse from 'parse/node' ;
2
+ import { offsetToCursor , cursorToOffset } from 'graphql-relay' ;
2
3
import rest from '../../rest' ;
3
4
import { transformQueryInputToParse } from '../transformers/query' ;
4
5
@@ -51,8 +52,11 @@ const findObjects = async (
51
52
className ,
52
53
where ,
53
54
order ,
54
- skip ,
55
- limit ,
55
+ skipInput ,
56
+ first ,
57
+ after ,
58
+ last ,
59
+ before ,
56
60
keys ,
57
61
include ,
58
62
includeAll ,
@@ -70,9 +74,48 @@ const findObjects = async (
70
74
}
71
75
transformQueryInputToParse ( where , fields , className ) ;
72
76
77
+ const skipAndLimitCalculation = calculateSkipAndLimit (
78
+ skipInput ,
79
+ first ,
80
+ after ,
81
+ last ,
82
+ before ,
83
+ config . maxLimit
84
+ ) ;
85
+ let { skip } = skipAndLimitCalculation ;
86
+ const { limit, needToPreCount } = skipAndLimitCalculation ;
87
+ let preCount = undefined ;
88
+ if ( needToPreCount ) {
89
+ const preCountOptions = {
90
+ limit : 0 ,
91
+ count : true ,
92
+ } ;
93
+ if ( readPreference ) {
94
+ preCountOptions . readPreference = readPreference ;
95
+ }
96
+ if ( Object . keys ( where ) . length > 0 && subqueryReadPreference ) {
97
+ preCountOptions . subqueryReadPreference = subqueryReadPreference ;
98
+ }
99
+ preCount = ( await rest . find (
100
+ config ,
101
+ auth ,
102
+ className ,
103
+ where ,
104
+ preCountOptions ,
105
+ info . clientSDK
106
+ ) ) . count ;
107
+ if ( ( skip || 0 ) + limit < preCount ) {
108
+ skip = preCount - limit ;
109
+ }
110
+ }
111
+
73
112
const options = { } ;
74
113
75
- if ( selectedFields . includes ( 'results' ) ) {
114
+ if (
115
+ selectedFields . find (
116
+ field => field . startsWith ( 'edges.' ) || field . startsWith ( 'pageInfo.' )
117
+ )
118
+ ) {
76
119
if ( limit || limit === 0 ) {
77
120
options . limit = limit ;
78
121
}
@@ -104,7 +147,12 @@ const findObjects = async (
104
147
options . limit = 0 ;
105
148
}
106
149
107
- if ( selectedFields . includes ( 'count' ) ) {
150
+ if (
151
+ ( selectedFields . includes ( 'count' ) ||
152
+ selectedFields . includes ( 'pageInfo.hasPreviousPage' ) ||
153
+ selectedFields . includes ( 'pageInfo.hasNextPage' ) ) &&
154
+ ! needToPreCount
155
+ ) {
108
156
options . count = true ;
109
157
}
110
158
@@ -115,14 +163,126 @@ const findObjects = async (
115
163
options . subqueryReadPreference = subqueryReadPreference ;
116
164
}
117
165
118
- return await rest . find (
119
- config ,
120
- auth ,
121
- className ,
122
- where ,
123
- options ,
124
- info . clientSDK
125
- ) ;
166
+ let results , count ;
167
+ if ( options . count || ! options . limit || ( options . limit && options . limit > 0 ) ) {
168
+ const findResult = await rest . find (
169
+ config ,
170
+ auth ,
171
+ className ,
172
+ where ,
173
+ options ,
174
+ info . clientSDK
175
+ ) ;
176
+ results = findResult . results ;
177
+ count = findResult . count ;
178
+ }
179
+
180
+ let edges = null ;
181
+ let pageInfo = null ;
182
+ if ( results ) {
183
+ edges = results . map ( ( result , index ) => ( {
184
+ cursor : offsetToCursor ( ( skip || 0 ) + index ) ,
185
+ node : result ,
186
+ } ) ) ;
187
+
188
+ pageInfo = {
189
+ hasPreviousPage :
190
+ ( ( preCount && preCount > 0 ) || ( count && count > 0 ) ) &&
191
+ skip !== undefined &&
192
+ skip > 0 ,
193
+ startCursor : offsetToCursor ( skip || 0 ) ,
194
+ endCursor : offsetToCursor ( ( skip || 0 ) + ( results . length || 1 ) - 1 ) ,
195
+ hasNextPage : ( preCount || count ) > ( skip || 0 ) + results . length ,
196
+ } ;
197
+ }
198
+
199
+ return {
200
+ edges,
201
+ pageInfo,
202
+ count : preCount || count ,
203
+ } ;
204
+ } ;
205
+
206
+ const calculateSkipAndLimit = (
207
+ skipInput ,
208
+ first ,
209
+ after ,
210
+ last ,
211
+ before ,
212
+ maxLimit
213
+ ) => {
214
+ let skip = undefined ;
215
+ let limit = undefined ;
216
+ let needToPreCount = false ;
217
+ if ( skipInput || skipInput === 0 ) {
218
+ if ( skipInput < 0 ) {
219
+ throw new Parse . Error (
220
+ Parse . Error . INVALID_QUERY ,
221
+ 'Skip should be a positive number'
222
+ ) ;
223
+ }
224
+ skip = skipInput ;
225
+ }
226
+ if ( after ) {
227
+ after = cursorToOffset ( after ) ;
228
+ if ( ( ! after && after !== 0 ) || after < 0 ) {
229
+ throw new Parse . Error (
230
+ Parse . Error . INVALID_QUERY ,
231
+ 'After is not a valid cursor'
232
+ ) ;
233
+ }
234
+ skip = ( skip || 0 ) + ( after + 1 ) ;
235
+ }
236
+ if ( first || first === 0 ) {
237
+ if ( first < 0 ) {
238
+ throw new Parse . Error (
239
+ Parse . Error . INVALID_QUERY ,
240
+ 'First should be a positive number'
241
+ ) ;
242
+ }
243
+ limit = first ;
244
+ }
245
+ if ( before || before === 0 ) {
246
+ before = cursorToOffset ( before ) ;
247
+ if ( ( ! before && before !== 0 ) || before < 0 ) {
248
+ throw new Parse . Error (
249
+ Parse . Error . INVALID_QUERY ,
250
+ 'Before is not a valid cursor'
251
+ ) ;
252
+ }
253
+ if ( ( skip || 0 ) >= before ) {
254
+ limit = 0 ;
255
+ } else if ( ( ! limit && limit !== 0 ) || ( skip || 0 ) + limit > before ) {
256
+ limit = before - ( skip || 0 ) ;
257
+ }
258
+ }
259
+ if ( last || last === 0 ) {
260
+ if ( last < 0 ) {
261
+ throw new Parse . Error (
262
+ Parse . Error . INVALID_QUERY ,
263
+ 'Last should be a positive number'
264
+ ) ;
265
+ }
266
+ if ( last > maxLimit ) {
267
+ last = maxLimit ;
268
+ }
269
+ if ( limit || limit === 0 ) {
270
+ if ( last < limit ) {
271
+ skip = ( skip || 0 ) + ( limit - last ) ;
272
+ limit = last ;
273
+ }
274
+ } else if ( last === 0 ) {
275
+ limit = 0 ;
276
+ } else {
277
+ limit = last ;
278
+ needToPreCount = true ;
279
+ }
280
+ }
281
+ return {
282
+ skip,
283
+ limit,
284
+ needToPreCount,
285
+ } ;
126
286
} ;
127
287
128
- export { getObject , findObjects } ;
288
+ export { getObject , findObjects , calculateSkipAndLimit } ;
0 commit comments