Skip to content

Commit 13fd2fa

Browse files
authored
Try to fix compatibility issues (#298)
1 parent 37ae455 commit 13fd2fa

File tree

2 files changed

+84
-91
lines changed

2 files changed

+84
-91
lines changed

.changeset/strange-apes-lick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-eslint/eslint-plugin': patch
3+
---
4+
5+
Fix compatibility issues with graphql v14

packages/plugin/src/rules/graphql-js-validation.ts

Lines changed: 79 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -3,223 +3,211 @@ import { GraphQLESLintRule } from '../types';
33
import { validateDoc } from './validate-against-schema';
44
import { requireGraphQLSchemaFromContext } from '../utils';
55

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-
386
const validationToRule = (
397
name: string,
40-
rule: ValidationRule,
8+
ruleName: string,
419
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).`,
6736
},
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+
};
7058

7159
export const GRAPHQL_JS_VALIDATIONS: Record<string, GraphQLESLintRule> = {
72-
...validationToRule('executable-definitions', ExecutableDefinitionsRule, {
60+
...validationToRule('executable-definitions', 'ExecutableDefinitions', {
7361
docs: {
7462
description: `A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.`,
7563
},
7664
}),
77-
...validationToRule('fields-on-correct-type', FieldsOnCorrectTypeRule, {
65+
...validationToRule('fields-on-correct-type', 'FieldsOnCorrectType', {
7866
docs: {
7967
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.`,
8068
},
8169
}),
82-
...validationToRule('fragments-on-composite-type', FragmentsOnCompositeTypesRule, {
70+
...validationToRule('fragments-on-composite-type', 'FragmentsOnCompositeTypes', {
8371
docs: {
8472
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.`,
8573
},
8674
}),
87-
...validationToRule('known-argument-names', KnownArgumentNamesRule, {
75+
...validationToRule('known-argument-names', 'KnownArgumentNames', {
8876
docs: {
8977
description: `A GraphQL field is only valid if all supplied arguments are defined by that field.`,
9078
},
9179
}),
92-
...validationToRule('known-directives', KnownDirectivesRule, {
80+
...validationToRule('known-directives', 'KnownDirectives', {
9381
docs: {
9482
description: `A GraphQL document is only valid if all \`@directives\` are known by the schema and legally positioned.`,
9583
},
9684
}),
97-
...validationToRule('known-fragment-names', KnownFragmentNamesRule, {
85+
...validationToRule('known-fragment-names', 'KnownFragmentNames', {
9886
docs: {
9987
description: `A GraphQL document is only valid if all \`...Fragment\` fragment spreads refer to fragments defined in the same document.`,
10088
},
10189
}),
102-
...validationToRule('known-type-names', KnownTypeNamesRule, {
90+
...validationToRule('known-type-names', 'KnownTypeNames', {
10391
docs: {
10492
description: `A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.`,
10593
},
10694
}),
107-
...validationToRule('lone-anonymous-operation', LoneAnonymousOperationRule, {
95+
...validationToRule('lone-anonymous-operation', 'LoneAnonymousOperation', {
10896
docs: {
10997
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.`,
11098
},
11199
}),
112-
...validationToRule('lone-schema-definition', LoneSchemaDefinition, {
100+
...validationToRule('lone-schema-definition', 'LoneSchemaDefinition', {
113101
docs: {
114102
description: `A GraphQL document is only valid if it contains only one schema definition.`,
115103
},
116104
}),
117-
...validationToRule('no-fragment-cycles', NoFragmentCyclesRule, {
105+
...validationToRule('no-fragment-cycles', 'NoFragmentCycles', {
118106
docs: {
119107
description: `A GraphQL fragment is only valid when it does not have cycles in fragments usage.`,
120108
},
121109
}),
122-
...validationToRule('no-undefined-variables', NoUndefinedVariablesRule, {
110+
...validationToRule('no-undefined-variables', 'NoUndefinedVariables', {
123111
docs: {
124112
description: `A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.`,
125113
},
126114
}),
127-
...validationToRule('no-unused-fragments', NoUnusedFragmentsRule, {
115+
...validationToRule('no-unused-fragments', 'NoUnusedFragments', {
128116
docs: {
129117
description: `A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.`,
130118
},
131119
}),
132-
...validationToRule('no-unused-variables', NoUnusedVariablesRule, {
120+
...validationToRule('no-unused-variables', 'NoUnusedVariables', {
133121
docs: {
134122
description: `A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.`,
135123
},
136124
}),
137-
...validationToRule('overlapping-fields-can-be-merged', OverlappingFieldsCanBeMergedRule, {
125+
...validationToRule('overlapping-fields-can-be-merged', 'OverlappingFieldsCanBeMerged', {
138126
docs: {
139127
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.`,
140128
},
141129
}),
142-
...validationToRule('possible-fragment-spread', PossibleFragmentSpreadsRule, {
130+
...validationToRule('possible-fragment-spread', 'PossibleFragmentSpreads', {
143131
docs: {
144132
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.`,
145133
},
146134
}),
147-
...validationToRule('possible-type-extension', PossibleTypeExtensionsRule, {
135+
...validationToRule('possible-type-extension', 'PossibleTypeExtensions', {
148136
docs: {
149137
description: `A type extension is only valid if the type is defined and has the same kind.`,
150138
},
151139
}),
152-
...validationToRule('provided-required-arguments', ProvidedRequiredArgumentsRule, {
140+
...validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
153141
docs: {
154142
description: `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.`,
155143
},
156144
}),
157-
...validationToRule('scalar-leafs', ScalarLeafsRule, {
145+
...validationToRule('scalar-leafs', 'ScalarLeafs', {
158146
docs: {
159147
description: `A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.`,
160148
},
161149
}),
162-
...validationToRule('one-field-subscriptions', SingleFieldSubscriptionsRule, {
150+
...validationToRule('one-field-subscriptions', 'SingleFieldSubscriptions', {
163151
docs: {
164152
description: `A GraphQL subscription is valid only if it contains a single root field.`,
165153
},
166154
}),
167-
...validationToRule('unique-argument-names', UniqueArgumentNamesRule, {
155+
...validationToRule('unique-argument-names', 'UniqueArgumentNames', {
168156
docs: {
169157
description: `A GraphQL field or directive is only valid if all supplied arguments are uniquely named.`,
170158
},
171159
}),
172-
...validationToRule('unique-directive-names', UniqueDirectiveNamesRule, {
160+
...validationToRule('unique-directive-names', 'UniqueDirectiveNames', {
173161
docs: {
174162
description: `A GraphQL document is only valid if all defined directives have unique names.`,
175163
},
176164
}),
177-
...validationToRule('unique-directive-names-per-location', UniqueDirectivesPerLocationRule, {
165+
...validationToRule('unique-directive-names-per-location', 'UniqueDirectivesPerLocation', {
178166
docs: {
179167
description: `A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.`,
180168
},
181169
}),
182-
...validationToRule('unique-enum-value-names', UniqueEnumValueNamesRule, {
170+
...validationToRule('unique-enum-value-names', 'UniqueEnumValueNames', {
183171
docs: {
184172
description: `A GraphQL enum type is only valid if all its values are uniquely named.`,
185173
},
186174
}),
187-
...validationToRule('unique-field-definition-names', UniqueFieldDefinitionNamesRule, {
175+
...validationToRule('unique-field-definition-names', 'UniqueFieldDefinitionNames', {
188176
docs: {
189177
description: `A GraphQL complex type is only valid if all its fields are uniquely named.`,
190178
},
191179
}),
192-
...validationToRule('unique-input-field-names', UniqueInputFieldNamesRule, {
180+
...validationToRule('unique-input-field-names', 'UniqueInputFieldNames', {
193181
docs: {
194182
description: `A GraphQL input object value is only valid if all supplied fields are uniquely named.`,
195183
},
196184
}),
197-
...validationToRule('unique-operation-types', UniqueOperationTypesRule, {
185+
...validationToRule('unique-operation-types', 'UniqueOperationTypes', {
198186
docs: {
199187
description: `A GraphQL document is only valid if it has only one type per operation.`,
200188
},
201189
}),
202-
...validationToRule('unique-type-names', UniqueTypeNamesRule, {
190+
...validationToRule('unique-type-names', 'UniqueTypeNames', {
203191
docs: {
204192
description: `A GraphQL document is only valid if all defined types have unique names.`,
205193
},
206194
}),
207-
...validationToRule('unique-variable-names', UniqueVariableNamesRule, {
195+
...validationToRule('unique-variable-names', 'UniqueVariableNames', {
208196
docs: {
209197
description: `A GraphQL operation is only valid if all its variables are uniquely named.`,
210198
},
211199
}),
212-
...validationToRule('value-literals-of-correct-type', ValuesOfCorrectTypeRule, {
200+
...validationToRule('value-literals-of-correct-type', 'ValuesOfCorrectType', {
213201
docs: {
214202
description: `A GraphQL document is only valid if all value literals are of the type expected at their position.`,
215203
},
216204
}),
217-
...validationToRule('variables-are-input-types', VariablesAreInputTypesRule, {
205+
...validationToRule('variables-are-input-types', 'VariablesAreInputTypes', {
218206
docs: {
219207
description: `A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).`,
220208
},
221209
}),
222-
...validationToRule('variables-in-allowed-position', VariablesInAllowedPositionRule, {
210+
...validationToRule('variables-in-allowed-position', 'VariablesInAllowedPosition', {
223211
docs: {
224212
description: `Variables passed to field arguments conform to type.`,
225213
},

0 commit comments

Comments
 (0)