@@ -116,9 +116,6 @@ module.exports = class QueryValidationVisitor {
116
116
const argTypeDef = this . currentrFieldDef . args . find ( d => d . name === argName )
117
117
const value = valueFromAST ( arg . value , argTypeDef . type , this . variableValues )
118
118
119
- // nothing to validate
120
- if ( ! value ) return
121
-
122
119
let variableName
123
120
124
121
if ( arg . value . kind === Kind . VARIABLE ) variableName = arg . value . name . value
@@ -128,12 +125,18 @@ module.exports = class QueryValidationVisitor {
128
125
if ( isNonNullType ( valueTypeDef ) ) valueTypeDef = valueTypeDef . ofType
129
126
130
127
if ( isInputObjectType ( valueTypeDef ) ) {
128
+ // nothing to validate
129
+ if ( ! value ) return
130
+
131
131
const inputObjectTypeDef = getNamedType ( valueTypeDef )
132
132
133
133
validateInputTypeValue ( this . context , inputObjectTypeDef , argName , variableName , value , this . currentField , variableName )
134
134
} else if ( isListType ( valueTypeDef ) ) {
135
135
validateArrayTypeValue ( this . context , valueTypeDef , argTypeDef , value , this . currentField , argName , variableName , variableName )
136
136
} else {
137
+ // nothing to validate
138
+ if ( ! value ) return
139
+
137
140
const fieldNameForError = variableName || this . currentField . name . value + '.' + argName
138
141
139
142
validateScalarTypeValue ( this . context , this . currentField , argTypeDef , valueTypeDef , value , variableName , argName , fieldNameForError , '' )
@@ -177,17 +180,44 @@ function validateArrayTypeValue (context, valueTypeDef, typeDefWithDirective, va
177
180
178
181
if ( isNonNullType ( valueTypeDefArray ) ) valueTypeDefArray = valueTypeDefArray . ofType
179
182
180
- value . forEach ( ( element , index ) => {
181
- const iFieldNameFullIndexed = iFieldNameFull ? `${ iFieldNameFull } [${ index ++ } ]` : `[${ index ++ } ]`
183
+ // Validate array/list size
184
+ const directiveArgumentMap = getDirectiveValues ( constraintDirectiveTypeDefsObj , typeDefWithDirective . astNode )
185
+
186
+ if ( directiveArgumentMap ) {
187
+ let errMessageBase
182
188
183
- if ( isInputObjectType ( valueTypeDefArray ) ) {
184
- validateInputTypeValue ( context , valueTypeDefArray , argName , variableName , element , currentField , iFieldNameFullIndexed )
189
+ if ( variableName ) {
190
+ errMessageBase = `Variable "$ ${ variableName } " at " ${ iFieldNameFull } " `
185
191
} else {
186
- const atMessage = ` at "${ iFieldNameFullIndexed } "`
192
+ errMessageBase = `Argument "${ argName } " of "${ currentField . name . value } " `
193
+ }
187
194
188
- validateScalarTypeValue ( context , currentField , typeDefWithDirective , valueTypeDef , element , variableName , argName , iFieldNameFullIndexed , atMessage )
195
+ if ( directiveArgumentMap . minItems && ( ! value || value . length < directiveArgumentMap . minItems ) ) {
196
+ context . reportError ( new ValidationError ( iFieldNameFull ,
197
+ errMessageBase + `must be at least ${ directiveArgumentMap . minItems } in length` ,
198
+ [ { arg : 'minItems' , value : directiveArgumentMap . minItems } ] ) )
199
+ }
200
+ if ( directiveArgumentMap . maxItems && value && value . length > directiveArgumentMap . maxItems ) {
201
+ context . reportError ( new ValidationError ( iFieldNameFull ,
202
+ errMessageBase + `must be no more than ${ directiveArgumentMap . maxItems } in length` ,
203
+ [ { arg : 'maxItems' , value : directiveArgumentMap . maxItems } ] ) )
189
204
}
190
- } )
205
+ }
206
+
207
+ // Validate array content
208
+ if ( value ) {
209
+ value . forEach ( ( element , index ) => {
210
+ const iFieldNameFullIndexed = iFieldNameFull ? `${ iFieldNameFull } [${ index ++ } ]` : `[${ index ++ } ]`
211
+
212
+ if ( isInputObjectType ( valueTypeDefArray ) ) {
213
+ validateInputTypeValue ( context , valueTypeDefArray , argName , variableName , element , currentField , iFieldNameFullIndexed )
214
+ } else {
215
+ const atMessage = ` at "${ iFieldNameFullIndexed } "`
216
+
217
+ validateScalarTypeValue ( context , currentField , typeDefWithDirective , valueTypeDef , element , variableName , argName , iFieldNameFullIndexed , atMessage )
218
+ }
219
+ } )
220
+ }
191
221
}
192
222
193
223
class InputObjectValidationVisitor {
@@ -213,20 +243,24 @@ class InputObjectValidationVisitor {
213
243
const iFieldNameFull = ( this . parentNames ? this . parentNames + '.' + iFieldName : iFieldName )
214
244
const value = this . value [ iFieldName ]
215
245
216
- if ( value ) {
217
- let valueTypeAst = node . type
246
+ let valueTypeAst = node . type
218
247
219
- if ( valueTypeAst . kind === Kind . NON_NULL_TYPE ) { valueTypeAst = valueTypeAst . type }
248
+ if ( valueTypeAst . kind === Kind . NON_NULL_TYPE ) { valueTypeAst = valueTypeAst . type }
220
249
221
- const valueTypeDef = typeFromAST ( this . context . getSchema ( ) , valueTypeAst )
250
+ const valueTypeDef = typeFromAST ( this . context . getSchema ( ) , valueTypeAst )
222
251
223
- if ( isInputObjectType ( valueTypeDef ) ) {
224
- validateInputTypeValue ( this . context , valueTypeDef , this . argName , this . variableName , value , this . currentField , iFieldNameFull )
225
- } else if ( isListType ( valueTypeDef ) ) {
226
- validateArrayTypeValue ( this . context , valueTypeDef , iFieldTypeDef , value , this . currentField , this . argName , this . variableName , iFieldNameFull )
227
- } else {
228
- validateScalarTypeValue ( this . context , this . currentField , iFieldTypeDef , valueTypeDef , value , this . variableName , this . argName , iFieldNameFull , ` at "${ iFieldNameFull } "` )
229
- }
252
+ if ( isInputObjectType ( valueTypeDef ) ) {
253
+ // nothing to validate
254
+ if ( ! value ) return
255
+
256
+ validateInputTypeValue ( this . context , valueTypeDef , this . argName , this . variableName , value , this . currentField , iFieldNameFull )
257
+ } else if ( isListType ( valueTypeDef ) ) {
258
+ validateArrayTypeValue ( this . context , valueTypeDef , iFieldTypeDef , value , this . currentField , this . argName , this . variableName , iFieldNameFull )
259
+ } else {
260
+ // nothing to validate
261
+ if ( ! value ) return
262
+
263
+ validateScalarTypeValue ( this . context , this . currentField , iFieldTypeDef , valueTypeDef , value , this . variableName , this . argName , iFieldNameFull , ` at "${ iFieldNameFull } "` )
230
264
}
231
265
}
232
266
}
0 commit comments