7
7
* @flow strict
8
8
*/
9
9
10
- import type { ValidationContext } from '../ValidationContext' ;
10
+ import type {
11
+ ValidationContext ,
12
+ SDLValidationContext ,
13
+ } from '../ValidationContext' ;
11
14
import { GraphQLError } from '../../error/GraphQLError' ;
15
+ import { Kind } from '../../language/kinds' ;
12
16
import inspect from '../../jsutils/inspect' ;
13
17
import keyMap from '../../jsutils/keyMap' ;
14
18
import { isNonNullType } from '../../type/definition' ;
@@ -28,12 +32,13 @@ export function missingFieldArgMessage(
28
32
export function missingDirectiveArgMessage (
29
33
directiveName : string ,
30
34
argName : string ,
31
- type : string ,
35
+ type ?: ? string ,
32
36
) : string {
33
- return (
34
- `Directive "@${ directiveName } " argument "${ argName } " of type ` +
35
- `"${ type } " is required but not provided.`
36
- ) ;
37
+ let msg = `Directive "@${ directiveName } " argument "${ argName } "` ;
38
+ if ( type ) {
39
+ msg += ' of type ' + type ;
40
+ }
41
+ return msg + ' is required but not provided.' ;
37
42
}
38
43
39
44
/**
@@ -46,12 +51,13 @@ export function ProvidedRequiredArguments(
46
51
context : ValidationContext ,
47
52
) : ASTVisitor {
48
53
return {
54
+ ...ProvidedRequiredArgumentsOnDirectives ( context ) ,
49
55
Field : {
50
56
// Validate on leave to allow for deeper errors to appear first.
51
57
leave ( node ) {
52
58
const fieldDef = context . getFieldDef ( ) ;
53
59
if ( ! fieldDef ) {
54
- return false ;
60
+ return ;
55
61
}
56
62
const argNodes = node . arguments || [ ] ;
57
63
@@ -77,34 +83,63 @@ export function ProvidedRequiredArguments(
77
83
}
78
84
} ,
79
85
} ,
86
+ } ;
87
+ }
88
+
89
+ // @internal
90
+ export function ProvidedRequiredArgumentsOnDirectives (
91
+ context : ValidationContext | SDLValidationContext ,
92
+ ) : ASTVisitor {
93
+ const requiredArgsMap = Object . create ( null ) ;
94
+ const schema = context . getSchema ( ) ;
80
95
96
+ if ( schema ) {
97
+ for ( const directive of schema . getDirectives ( ) ) {
98
+ const requredArgs = directive . args . filter (
99
+ arg => isNonNullType ( arg . type ) && arg . defaultValue === undefined ,
100
+ ) ;
101
+ requiredArgsMap [ directive . name ] = requredArgs . map ( arg => arg . name ) ;
102
+ }
103
+ }
104
+
105
+ const astDefinitions = context . getDocument ( ) . definitions ;
106
+ for ( const def of astDefinitions ) {
107
+ if ( def . kind === Kind . DIRECTIVE_DEFINITION ) {
108
+ const requredArgs = ( def . arguments || [ ] ) . filter (
109
+ arg => arg . type . kind === Kind . NON_NULL_TYPE && arg . defaultValue == null ,
110
+ ) ;
111
+
112
+ requiredArgsMap [ def . name . value ] = requredArgs . map ( arg => arg . name . value ) ;
113
+ }
114
+ }
115
+
116
+ return {
81
117
Directive : {
82
118
// Validate on leave to allow for deeper errors to appear first.
83
119
leave ( node ) {
84
- const directiveDef = context . getDirective ( ) ;
85
- if ( ! directiveDef ) {
86
- return false ;
87
- }
88
- const argNodes = node . arguments || [ ] ;
120
+ const directiveName = node . name . value ;
121
+ const requiredArgs = requiredArgsMap [ directiveName ] ;
122
+ if ( requiredArgs ) {
123
+ const argNodes = node . arguments || [ ] ;
124
+ const argNodeMap = keyMap ( argNodes , arg => arg . name . value ) ;
125
+ for ( const argName of requiredArgs ) {
126
+ if ( ! argNodeMap [ argName ] ) {
127
+ const directiveDef = schema && schema . getDirective ( directiveName ) ;
128
+ const argDef =
129
+ directiveDef &&
130
+ directiveDef . args . find ( arg => arg . name === argName ) ;
89
131
90
- const argNodeMap = keyMap ( argNodes , arg => arg . name . value ) ;
91
- for ( const argDef of directiveDef . args ) {
92
- const argNode = argNodeMap [ argDef . name ] ;
93
- if (
94
- ! argNode &&
95
- isNonNullType ( argDef . type ) &&
96
- argDef . defaultValue === undefined
97
- ) {
98
- context . reportError (
99
- new GraphQLError (
100
- missingDirectiveArgMessage (
101
- node . name . value ,
102
- argDef . name ,
103
- inspect ( argDef . type ) ,
132
+ context . reportError (
133
+ new GraphQLError (
134
+ missingDirectiveArgMessage (
135
+ directiveName ,
136
+ argName ,
137
+ argDef && inspect ( argDef . type ) ,
138
+ ) ,
139
+ [ node ] ,
104
140
) ,
105
- [ node ] ,
106
- ) ,
107
- ) ;
141
+ ) ;
142
+ }
108
143
}
109
144
}
110
145
} ,
0 commit comments