@@ -3,223 +3,211 @@ import { GraphQLESLintRule } from '../types';
3
3
import { validateDoc } from './validate-against-schema' ;
4
4
import { requireGraphQLSchemaFromContext } from '../utils' ;
5
5
6
- import { ExecutableDefinitionsRule } from 'graphql/validation/rules/ExecutableDefinitionsRule' ;
7
- import { FieldsOnCorrectTypeRule } from 'graphql/validation/rules/FieldsOnCorrectTypeRule' ;
8
- import { FragmentsOnCompositeTypesRule } from 'graphql/validation/rules/FragmentsOnCompositeTypesRule' ;
9
- import { KnownArgumentNamesRule } from 'graphql/validation/rules/KnownArgumentNamesRule' ;
10
- import { KnownDirectivesRule } from 'graphql/validation/rules/KnownDirectivesRule' ;
11
- import { KnownFragmentNamesRule } from 'graphql/validation/rules/KnownFragmentNamesRule' ;
12
- import { KnownTypeNamesRule } from 'graphql/validation/rules/KnownTypeNamesRule' ;
13
- import { LoneAnonymousOperationRule } from 'graphql/validation/rules/LoneAnonymousOperationRule' ;
14
- import { LoneSchemaDefinition } from 'graphql/validation/rules/LoneSchemaDefinition' ;
15
- import { NoFragmentCyclesRule } from 'graphql/validation/rules/NoFragmentCyclesRule' ;
16
- import { NoUndefinedVariablesRule } from 'graphql/validation/rules/NoUndefinedVariablesRule' ;
17
- import { NoUnusedFragmentsRule } from 'graphql/validation/rules/NoUnusedFragmentsRule' ;
18
- import { NoUnusedVariablesRule } from 'graphql/validation/rules/NoUnusedVariablesRule' ;
19
- import { OverlappingFieldsCanBeMergedRule } from 'graphql/validation/rules/OverlappingFieldsCanBeMergedRule' ;
20
- import { PossibleFragmentSpreadsRule } from 'graphql/validation/rules/PossibleFragmentSpreadsRule' ;
21
- import { PossibleTypeExtensionsRule } from 'graphql/validation/rules/PossibleTypeExtensionsRule' ;
22
- import { ProvidedRequiredArgumentsRule } from 'graphql/validation/rules/ProvidedRequiredArgumentsRule' ;
23
- import { ScalarLeafsRule } from 'graphql/validation/rules/ScalarLeafsRule' ;
24
- import { SingleFieldSubscriptionsRule } from 'graphql/validation/rules/SingleFieldSubscriptionsRule' ;
25
- import { UniqueArgumentNamesRule } from 'graphql/validation/rules/UniqueArgumentNamesRule' ;
26
- import { UniqueDirectiveNamesRule } from 'graphql/validation/rules/UniqueDirectiveNamesRule' ;
27
- import { UniqueDirectivesPerLocationRule } from 'graphql/validation/rules/UniqueDirectivesPerLocationRule' ;
28
- import { UniqueEnumValueNamesRule } from 'graphql/validation/rules/UniqueEnumValueNamesRule' ;
29
- import { UniqueFieldDefinitionNamesRule } from 'graphql/validation/rules/UniqueFieldDefinitionNamesRule' ;
30
- import { UniqueInputFieldNamesRule } from 'graphql/validation/rules/UniqueInputFieldNamesRule' ;
31
- import { UniqueOperationTypesRule } from 'graphql/validation/rules/UniqueOperationTypesRule' ;
32
- import { UniqueTypeNamesRule } from 'graphql/validation/rules/UniqueTypeNamesRule' ;
33
- import { UniqueVariableNamesRule } from 'graphql/validation/rules/UniqueVariableNamesRule' ;
34
- import { ValuesOfCorrectTypeRule } from 'graphql/validation/rules/ValuesOfCorrectTypeRule' ;
35
- import { VariablesAreInputTypesRule } from 'graphql/validation/rules/VariablesAreInputTypesRule' ;
36
- import { VariablesInAllowedPositionRule } from 'graphql/validation/rules/VariablesInAllowedPositionRule' ;
37
-
38
6
const validationToRule = (
39
7
name : string ,
40
- rule : ValidationRule ,
8
+ ruleName : string ,
41
9
meta : GraphQLESLintRule [ 'meta' ]
42
- ) : Record < typeof name , GraphQLESLintRule < any , true > > =>
43
- rule
44
- ? {
45
- [ name ] : {
46
- meta : {
47
- ...meta ,
48
- docs : {
49
- category : 'Validation' ,
50
- requiresSchema : true ,
51
- requiresSiblings : false ,
52
- url : `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${ name } .md` ,
53
- ...meta . docs ,
54
- description :
55
- meta . docs . description +
56
- `\n\n> This rule is a wrapper around a \`graphql-js\` validation function. [You can find it's source code here](https://github.com/graphql/graphql-js/blob/master/src/validation/rules/${ rule . name } .js).` ,
57
- } ,
58
- } ,
59
- create : context => {
60
- return {
61
- Document ( node ) {
62
- const schema = requireGraphQLSchemaFromContext ( name , context ) ;
63
- validateDoc ( node , context , schema , node . rawNode ( ) , [ rule ] , rule . name ) ;
64
- } ,
65
- } ;
66
- } ,
10
+ ) : Record < typeof name , GraphQLESLintRule < any , true > > => {
11
+ let ruleFn : null | ValidationRule = null ;
12
+
13
+ try {
14
+ ruleFn = require ( `graphql/validation/rules/${ ruleName } Rule` ) [ `${ ruleName } Rule` ] ;
15
+ } catch ( e ) {
16
+ try {
17
+ ruleFn = require ( `graphql/validation/rules/${ ruleName } ` ) [ `${ ruleName } Rule` ] ;
18
+ } catch ( e ) {
19
+ ruleFn = require ( 'graphql/validation' ) [ `${ ruleName } Rule` ] ;
20
+ }
21
+ }
22
+
23
+ return {
24
+ [ name ] : {
25
+ meta : {
26
+ ...meta ,
27
+ docs : {
28
+ category : 'Validation' ,
29
+ requiresSchema : true ,
30
+ requiresSiblings : false ,
31
+ url : `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${ name } .md` ,
32
+ ...meta . docs ,
33
+ description :
34
+ meta . docs . description +
35
+ `\n\n> This rule is a wrapper around a \`graphql-js\` validation function. [You can find it's source code here](https://github.com/graphql/graphql-js/blob/master/src/validation/rules/${ ruleName } .js).` ,
67
36
} ,
68
- }
69
- : { } ;
37
+ } ,
38
+ create : context => {
39
+ return {
40
+ Document ( node ) {
41
+ if ( ! ruleFn ) {
42
+ // eslint-disable-next-line no-console
43
+ console . warn (
44
+ `You rule "${ name } " depends on a GraphQL validation rule ("${ ruleName } ") but it's not available in the "graphql-js" version you are using. Skipping...`
45
+ ) ;
46
+
47
+ return ;
48
+ }
49
+
50
+ const schema = requireGraphQLSchemaFromContext ( name , context ) ;
51
+ validateDoc ( node , context , schema , node . rawNode ( ) , [ ruleFn ] , ruleName ) ;
52
+ } ,
53
+ } ;
54
+ } ,
55
+ } ,
56
+ } ;
57
+ } ;
70
58
71
59
export const GRAPHQL_JS_VALIDATIONS : Record < string , GraphQLESLintRule > = {
72
- ...validationToRule ( 'executable-definitions' , ExecutableDefinitionsRule , {
60
+ ...validationToRule ( 'executable-definitions' , 'ExecutableDefinitions' , {
73
61
docs : {
74
62
description : `A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.` ,
75
63
} ,
76
64
} ) ,
77
- ...validationToRule ( 'fields-on-correct-type' , FieldsOnCorrectTypeRule , {
65
+ ...validationToRule ( 'fields-on-correct-type' , 'FieldsOnCorrectType' , {
78
66
docs : {
79
67
description : `A GraphQL document is only valid if all fields selected are defined by the parent type, or are an allowed meta field such as __typename.` ,
80
68
} ,
81
69
} ) ,
82
- ...validationToRule ( 'fragments-on-composite-type' , FragmentsOnCompositeTypesRule , {
70
+ ...validationToRule ( 'fragments-on-composite-type' , 'FragmentsOnCompositeTypes' , {
83
71
docs : {
84
72
description : `Fragments use a type condition to determine if they apply, since fragments can only be spread into a composite type (object, interface, or union), the type condition must also be a composite type.` ,
85
73
} ,
86
74
} ) ,
87
- ...validationToRule ( 'known-argument-names' , KnownArgumentNamesRule , {
75
+ ...validationToRule ( 'known-argument-names' , 'KnownArgumentNames' , {
88
76
docs : {
89
77
description : `A GraphQL field is only valid if all supplied arguments are defined by that field.` ,
90
78
} ,
91
79
} ) ,
92
- ...validationToRule ( 'known-directives' , KnownDirectivesRule , {
80
+ ...validationToRule ( 'known-directives' , 'KnownDirectives' , {
93
81
docs : {
94
82
description : `A GraphQL document is only valid if all \`@directives\` are known by the schema and legally positioned.` ,
95
83
} ,
96
84
} ) ,
97
- ...validationToRule ( 'known-fragment-names' , KnownFragmentNamesRule , {
85
+ ...validationToRule ( 'known-fragment-names' , 'KnownFragmentNames' , {
98
86
docs : {
99
87
description : `A GraphQL document is only valid if all \`...Fragment\` fragment spreads refer to fragments defined in the same document.` ,
100
88
} ,
101
89
} ) ,
102
- ...validationToRule ( 'known-type-names' , KnownTypeNamesRule , {
90
+ ...validationToRule ( 'known-type-names' , 'KnownTypeNames' , {
103
91
docs : {
104
92
description : `A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.` ,
105
93
} ,
106
94
} ) ,
107
- ...validationToRule ( 'lone-anonymous-operation' , LoneAnonymousOperationRule , {
95
+ ...validationToRule ( 'lone-anonymous-operation' , 'LoneAnonymousOperation' , {
108
96
docs : {
109
97
description : `A GraphQL document is only valid if when it contains an anonymous operation (the query short-hand) that it contains only that one operation definition.` ,
110
98
} ,
111
99
} ) ,
112
- ...validationToRule ( 'lone-schema-definition' , LoneSchemaDefinition , {
100
+ ...validationToRule ( 'lone-schema-definition' , ' LoneSchemaDefinition' , {
113
101
docs : {
114
102
description : `A GraphQL document is only valid if it contains only one schema definition.` ,
115
103
} ,
116
104
} ) ,
117
- ...validationToRule ( 'no-fragment-cycles' , NoFragmentCyclesRule , {
105
+ ...validationToRule ( 'no-fragment-cycles' , 'NoFragmentCycles' , {
118
106
docs : {
119
107
description : `A GraphQL fragment is only valid when it does not have cycles in fragments usage.` ,
120
108
} ,
121
109
} ) ,
122
- ...validationToRule ( 'no-undefined-variables' , NoUndefinedVariablesRule , {
110
+ ...validationToRule ( 'no-undefined-variables' , 'NoUndefinedVariables' , {
123
111
docs : {
124
112
description : `A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.` ,
125
113
} ,
126
114
} ) ,
127
- ...validationToRule ( 'no-unused-fragments' , NoUnusedFragmentsRule , {
115
+ ...validationToRule ( 'no-unused-fragments' , 'NoUnusedFragments' , {
128
116
docs : {
129
117
description : `A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.` ,
130
118
} ,
131
119
} ) ,
132
- ...validationToRule ( 'no-unused-variables' , NoUnusedVariablesRule , {
120
+ ...validationToRule ( 'no-unused-variables' , 'NoUnusedVariables' , {
133
121
docs : {
134
122
description : `A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.` ,
135
123
} ,
136
124
} ) ,
137
- ...validationToRule ( 'overlapping-fields-can-be-merged' , OverlappingFieldsCanBeMergedRule , {
125
+ ...validationToRule ( 'overlapping-fields-can-be-merged' , 'OverlappingFieldsCanBeMerged' , {
138
126
docs : {
139
127
description : `A selection set is only valid if all fields (including spreading any fragments) either correspond to distinct response names or can be merged without ambiguity.` ,
140
128
} ,
141
129
} ) ,
142
- ...validationToRule ( 'possible-fragment-spread' , PossibleFragmentSpreadsRule , {
130
+ ...validationToRule ( 'possible-fragment-spread' , 'PossibleFragmentSpreads' , {
143
131
docs : {
144
132
description : `A fragment spread is only valid if the type condition could ever possibly be true: if there is a non-empty intersection of the possible parent types, and possible types which pass the type condition.` ,
145
133
} ,
146
134
} ) ,
147
- ...validationToRule ( 'possible-type-extension' , PossibleTypeExtensionsRule , {
135
+ ...validationToRule ( 'possible-type-extension' , 'PossibleTypeExtensions' , {
148
136
docs : {
149
137
description : `A type extension is only valid if the type is defined and has the same kind.` ,
150
138
} ,
151
139
} ) ,
152
- ...validationToRule ( 'provided-required-arguments' , ProvidedRequiredArgumentsRule , {
140
+ ...validationToRule ( 'provided-required-arguments' , 'ProvidedRequiredArguments' , {
153
141
docs : {
154
142
description : `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.` ,
155
143
} ,
156
144
} ) ,
157
- ...validationToRule ( 'scalar-leafs' , ScalarLeafsRule , {
145
+ ...validationToRule ( 'scalar-leafs' , 'ScalarLeafs' , {
158
146
docs : {
159
147
description : `A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.` ,
160
148
} ,
161
149
} ) ,
162
- ...validationToRule ( 'one-field-subscriptions' , SingleFieldSubscriptionsRule , {
150
+ ...validationToRule ( 'one-field-subscriptions' , 'SingleFieldSubscriptions' , {
163
151
docs : {
164
152
description : `A GraphQL subscription is valid only if it contains a single root field.` ,
165
153
} ,
166
154
} ) ,
167
- ...validationToRule ( 'unique-argument-names' , UniqueArgumentNamesRule , {
155
+ ...validationToRule ( 'unique-argument-names' , 'UniqueArgumentNames' , {
168
156
docs : {
169
157
description : `A GraphQL field or directive is only valid if all supplied arguments are uniquely named.` ,
170
158
} ,
171
159
} ) ,
172
- ...validationToRule ( 'unique-directive-names' , UniqueDirectiveNamesRule , {
160
+ ...validationToRule ( 'unique-directive-names' , 'UniqueDirectiveNames' , {
173
161
docs : {
174
162
description : `A GraphQL document is only valid if all defined directives have unique names.` ,
175
163
} ,
176
164
} ) ,
177
- ...validationToRule ( 'unique-directive-names-per-location' , UniqueDirectivesPerLocationRule , {
165
+ ...validationToRule ( 'unique-directive-names-per-location' , 'UniqueDirectivesPerLocation' , {
178
166
docs : {
179
167
description : `A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.` ,
180
168
} ,
181
169
} ) ,
182
- ...validationToRule ( 'unique-enum-value-names' , UniqueEnumValueNamesRule , {
170
+ ...validationToRule ( 'unique-enum-value-names' , 'UniqueEnumValueNames' , {
183
171
docs : {
184
172
description : `A GraphQL enum type is only valid if all its values are uniquely named.` ,
185
173
} ,
186
174
} ) ,
187
- ...validationToRule ( 'unique-field-definition-names' , UniqueFieldDefinitionNamesRule , {
175
+ ...validationToRule ( 'unique-field-definition-names' , 'UniqueFieldDefinitionNames' , {
188
176
docs : {
189
177
description : `A GraphQL complex type is only valid if all its fields are uniquely named.` ,
190
178
} ,
191
179
} ) ,
192
- ...validationToRule ( 'unique-input-field-names' , UniqueInputFieldNamesRule , {
180
+ ...validationToRule ( 'unique-input-field-names' , 'UniqueInputFieldNames' , {
193
181
docs : {
194
182
description : `A GraphQL input object value is only valid if all supplied fields are uniquely named.` ,
195
183
} ,
196
184
} ) ,
197
- ...validationToRule ( 'unique-operation-types' , UniqueOperationTypesRule , {
185
+ ...validationToRule ( 'unique-operation-types' , 'UniqueOperationTypes' , {
198
186
docs : {
199
187
description : `A GraphQL document is only valid if it has only one type per operation.` ,
200
188
} ,
201
189
} ) ,
202
- ...validationToRule ( 'unique-type-names' , UniqueTypeNamesRule , {
190
+ ...validationToRule ( 'unique-type-names' , 'UniqueTypeNames' , {
203
191
docs : {
204
192
description : `A GraphQL document is only valid if all defined types have unique names.` ,
205
193
} ,
206
194
} ) ,
207
- ...validationToRule ( 'unique-variable-names' , UniqueVariableNamesRule , {
195
+ ...validationToRule ( 'unique-variable-names' , 'UniqueVariableNames' , {
208
196
docs : {
209
197
description : `A GraphQL operation is only valid if all its variables are uniquely named.` ,
210
198
} ,
211
199
} ) ,
212
- ...validationToRule ( 'value-literals-of-correct-type' , ValuesOfCorrectTypeRule , {
200
+ ...validationToRule ( 'value-literals-of-correct-type' , 'ValuesOfCorrectType' , {
213
201
docs : {
214
202
description : `A GraphQL document is only valid if all value literals are of the type expected at their position.` ,
215
203
} ,
216
204
} ) ,
217
- ...validationToRule ( 'variables-are-input-types' , VariablesAreInputTypesRule , {
205
+ ...validationToRule ( 'variables-are-input-types' , 'VariablesAreInputTypes' , {
218
206
docs : {
219
207
description : `A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).` ,
220
208
} ,
221
209
} ) ,
222
- ...validationToRule ( 'variables-in-allowed-position' , VariablesInAllowedPositionRule , {
210
+ ...validationToRule ( 'variables-in-allowed-position' , 'VariablesInAllowedPosition' , {
223
211
docs : {
224
212
description : `Variables passed to field arguments conform to type.` ,
225
213
} ,
0 commit comments