1
1
import { resolver } from 'graphql-sequelize'
2
- import { Model } from 'sequelize'
2
+ import { FindOptions , Model } from 'sequelize'
3
3
import removeUnusedAttributes from './removeUnusedAttributes'
4
4
import { GlobalBeforeHook , ModelDeclarationType } from './types/types'
5
5
6
- function allowOrderOnAssociations ( findOptions : any , model : any ) {
6
+ function allowOrderOnAssociations ( findOptions : FindOptions < any > , model : any ) {
7
7
if ( typeof findOptions . order === 'undefined' ) {
8
8
return findOptions
9
9
}
@@ -16,7 +16,8 @@ function allowOrderOnAssociations(findOptions: any, model: any) {
16
16
// By default we take the direction detected by GraphQL-sequelize
17
17
// It will be 'ASC' if 'reverse:' was not specified.
18
18
// But this will only work for the first field.
19
- let direction = index === 0 ? findOptions . order [ 0 ] [ 1 ] : 'ASC'
19
+ let direction =
20
+ index === 0 && findOptions . order ? findOptions . order [ 0 ] [ 1 ] : 'ASC'
20
21
// When reverse is not already removed by graphql-sequelize
21
22
// we try to detect it ourselves. Happens for multiple fields sort.
22
23
if ( singleOrder . search ( 'reverse:' ) === 0 ) {
@@ -35,7 +36,10 @@ function allowOrderOnAssociations(findOptions: any, model: any) {
35
36
`Association ${ associationName } unknown on model ${ model . name } order`
36
37
)
37
38
}
38
- if ( typeof findOptions . include === 'undefined' ) {
39
+ if (
40
+ typeof findOptions . include === 'undefined' ||
41
+ typeof findOptions . include === 'string'
42
+ ) {
39
43
findOptions . include = [ ]
40
44
}
41
45
@@ -47,7 +51,10 @@ function allowOrderOnAssociations(findOptions: any, model: any) {
47
51
modelInclude . as = model . associations [ associationName ] . as
48
52
}
49
53
50
- findOptions . include . push ( modelInclude )
54
+ // Type assertion to specify the type of findOptions.include as an array
55
+ if ( 'push' in findOptions . include ) {
56
+ findOptions . include . push ( modelInclude )
57
+ }
51
58
52
59
const modelSort : any = {
53
60
model : model . associations [ associationName ] . target ,
@@ -89,23 +96,25 @@ function allowOrderOnAssociations(findOptions: any, model: any) {
89
96
* to
90
97
* order = [['id', 'ASC'], ['fullname', 'DESC']
91
98
*/
92
- findOptions . order . map ( ( order : any ) => {
93
- // Handle multiple sort fields.
94
- if ( order [ 0 ] . search ( ',' ) === - 1 ) {
95
- checkForAssociationSort ( order [ 0 ] , 0 )
96
- return
97
- }
98
- const multipleOrder = order [ 0 ] . split ( ',' )
99
- for ( const index in multipleOrder ) {
100
- checkForAssociationSort ( multipleOrder [ index ] , parseInt ( index ) )
101
- }
102
- } )
99
+ if ( 'map' in findOptions . order ) {
100
+ findOptions . order . map ( ( order : any ) => {
101
+ // Handle multiple sort fields.
102
+ if ( order [ 0 ] . search ( ',' ) === - 1 ) {
103
+ checkForAssociationSort ( order [ 0 ] , 0 )
104
+ return
105
+ }
106
+ const multipleOrder = order [ 0 ] . split ( ',' )
107
+ for ( const index in multipleOrder ) {
108
+ checkForAssociationSort ( multipleOrder [ index ] , parseInt ( index ) )
109
+ }
110
+ } )
111
+ }
103
112
findOptions . order = processedOrder
104
113
return findOptions
105
114
}
106
115
107
116
const argsAdvancedProcessing = (
108
- findOptions : any ,
117
+ findOptions : FindOptions < any > ,
109
118
args : any ,
110
119
context : any ,
111
120
info : any ,
@@ -135,7 +144,7 @@ async function trimAndOptimizeFindOptions({
135
144
info,
136
145
models,
137
146
} : {
138
- findOptions : any
147
+ findOptions : FindOptions < any >
139
148
graphqlTypeDeclaration : any
140
149
info : any
141
150
models : any
@@ -151,6 +160,28 @@ async function trimAndOptimizeFindOptions({
151
160
models
152
161
)
153
162
163
+ // As sequelize-dataloader does not support the include option, we have to remove it.
164
+ // It does not differenciate between an empty include and an include with models so we have to remove it.
165
+ if (
166
+ trimedFindOptions . include &&
167
+ typeof trimedFindOptions . include === 'object' &&
168
+ 'length' in trimedFindOptions . include &&
169
+ trimedFindOptions . include . length === 0
170
+ ) {
171
+ delete trimedFindOptions . include
172
+ }
173
+
174
+ // As sequelize-dataloader does not support the where option, we have to remove it.
175
+ // It does not differenciate between an empty where and a where with properties so we have to remove it.
176
+ if (
177
+ trimedFindOptions . where &&
178
+ // Symbols like [Op.and] are not returned by Object.keys and must be handled separately.
179
+ Object . getOwnPropertySymbols ( trimedFindOptions . where ) . length === 0 &&
180
+ Object . keys ( trimedFindOptions . where ) . length === 0
181
+ ) {
182
+ delete trimedFindOptions . where
183
+ }
184
+
154
185
if (
155
186
// If we have a list with a limit and an offset
156
187
trimedFindOptions . limit &&
@@ -230,7 +261,7 @@ export default function createListResolver(
230
261
? graphqlTypeDeclaration . list . contextToOptions
231
262
: undefined ,
232
263
before : async ( findOptions : any , args : any , context : any , info : any ) => {
233
- let processedFindOptions = argsAdvancedProcessing (
264
+ let processedFindOptions : FindOptions < any > = argsAdvancedProcessing (
234
265
findOptions ,
235
266
args ,
236
267
context ,
0 commit comments