@graphql-eslint/eslint-plugin 3.0.0-alpha-0a66b90.0 → 3.0.0-alpha-2918431.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -8
- package/configs/base.d.ts +5 -0
- package/configs/index.d.ts +78 -121
- package/configs/operations-all.d.ts +19 -0
- package/configs/operations-recommended.d.ts +51 -0
- package/configs/schema-all.d.ts +21 -0
- package/configs/schema-recommended.d.ts +42 -0
- package/docs/README.md +10 -18
- package/docs/deprecated-rules.md +21 -0
- package/docs/rules/alphabetize.md +1 -1
- package/docs/rules/description-style.md +5 -3
- package/docs/rules/executable-definitions.md +2 -2
- package/docs/rules/fields-on-correct-type.md +2 -2
- package/docs/rules/fragments-on-composite-type.md +2 -2
- package/docs/rules/input-name.md +1 -1
- package/docs/rules/known-argument-names.md +2 -2
- package/docs/rules/known-directives.md +2 -2
- package/docs/rules/known-fragment-names.md +2 -2
- package/docs/rules/known-type-names.md +2 -2
- package/docs/rules/lone-anonymous-operation.md +2 -2
- package/docs/rules/lone-schema-definition.md +2 -2
- package/docs/rules/match-document-filename.md +6 -4
- package/docs/rules/naming-convention.md +140 -41
- package/docs/rules/no-anonymous-operations.md +2 -2
- package/docs/rules/no-case-insensitive-enum-values-duplicates.md +2 -2
- package/docs/rules/no-deprecated.md +3 -1
- package/docs/rules/{avoid-duplicate-fields.md → no-duplicate-fields.md} +10 -8
- package/docs/rules/no-fragment-cycles.md +2 -2
- package/docs/rules/no-hashtag-description.md +3 -1
- package/docs/rules/no-root-type.md +9 -14
- package/docs/rules/{avoid-scalar-result-type-on-mutation.md → no-scalar-result-type-on-mutation.md} +7 -7
- package/docs/rules/no-typename-prefix.md +37 -0
- package/docs/rules/no-undefined-variables.md +2 -2
- package/docs/rules/no-unreachable-types.md +3 -1
- package/docs/rules/no-unused-fields.md +1 -1
- package/docs/rules/no-unused-fragments.md +2 -2
- package/docs/rules/no-unused-variables.md +2 -2
- package/docs/rules/one-field-subscriptions.md +2 -2
- package/docs/rules/overlapping-fields-can-be-merged.md +2 -2
- package/docs/rules/possible-fragment-spread.md +2 -2
- package/docs/rules/possible-type-extension.md +2 -2
- package/docs/rules/provided-required-arguments.md +2 -2
- package/docs/rules/require-deprecation-date.md +1 -1
- package/docs/rules/require-deprecation-reason.md +2 -2
- package/docs/rules/require-description.md +36 -22
- package/docs/rules/require-field-of-type-query-in-mutation-result.md +1 -1
- package/docs/rules/require-id-when-available.md +3 -1
- package/docs/rules/scalar-leafs.md +2 -2
- package/docs/rules/selection-set-depth.md +9 -2
- package/docs/rules/strict-id-in-types.md +16 -10
- package/docs/rules/unique-argument-names.md +2 -2
- package/docs/rules/unique-directive-names-per-location.md +2 -2
- package/docs/rules/unique-directive-names.md +2 -2
- package/docs/rules/unique-enum-value-names.md +2 -2
- package/docs/rules/unique-field-definition-names.md +2 -2
- package/docs/rules/unique-fragment-name.md +1 -1
- package/docs/rules/unique-input-field-names.md +2 -2
- package/docs/rules/unique-operation-name.md +1 -1
- package/docs/rules/unique-operation-types.md +2 -2
- package/docs/rules/unique-type-names.md +2 -2
- package/docs/rules/unique-variable-names.md +2 -2
- package/docs/rules/value-literals-of-correct-type.md +2 -2
- package/docs/rules/variables-are-input-types.md +2 -2
- package/docs/rules/variables-in-allowed-position.md +2 -2
- package/index.js +651 -724
- package/index.mjs +652 -725
- package/package.json +1 -1
- package/rules/alphabetize.d.ts +8 -10
- package/rules/description-style.d.ts +4 -6
- package/rules/index.d.ts +115 -119
- package/rules/input-name.d.ts +1 -1
- package/rules/match-document-filename.d.ts +8 -10
- package/rules/naming-convention.d.ts +3 -4
- package/rules/{avoid-duplicate-fields.d.ts → no-duplicate-fields.d.ts} +0 -0
- package/rules/no-root-type.d.ts +1 -1
- package/rules/{avoid-scalar-result-type-on-mutation.d.ts → no-scalar-result-type-on-mutation.d.ts} +0 -0
- package/rules/{avoid-typename-prefix.d.ts → no-typename-prefix.d.ts} +0 -0
- package/rules/require-description.d.ts +2 -3
- package/rules/require-id-when-available.d.ts +3 -3
- package/rules/selection-set-depth.d.ts +3 -3
- package/rules/strict-id-in-types.d.ts +6 -8
- package/types.d.ts +9 -5
- package/configs/all.d.ts +0 -104
- package/configs/recommended.d.ts +0 -72
- package/docs/rules/avoid-operation-name-prefix.md +0 -50
- package/docs/rules/avoid-typename-prefix.md +0 -37
- package/docs/rules/no-operation-name-suffix.md +0 -38
- package/rules/avoid-operation-name-prefix.d.ts +0 -9
- package/rules/no-operation-name-suffix.d.ts +0 -3
package/index.js
CHANGED
@@ -18,14 +18,89 @@ const codeFileLoader = require('@graphql-tools/code-file-loader');
|
|
18
18
|
const eslint = require('eslint');
|
19
19
|
const codeFrame = require('@babel/code-frame');
|
20
20
|
|
21
|
+
const base = {
|
22
|
+
parser: '@graphql-eslint/eslint-plugin',
|
23
|
+
plugins: ['@graphql-eslint'],
|
24
|
+
};
|
25
|
+
|
21
26
|
/*
|
22
27
|
* 🚨 IMPORTANT! Do not manually modify this file. Run: `yarn generate-configs`
|
23
28
|
*/
|
24
|
-
const
|
25
|
-
|
26
|
-
|
29
|
+
const schemaRecommendedConfig = {
|
30
|
+
extends: ['plugin:@graphql-eslint/base'],
|
31
|
+
rules: {
|
32
|
+
'@graphql-eslint/description-style': 'error',
|
33
|
+
'@graphql-eslint/known-argument-names': 'error',
|
34
|
+
'@graphql-eslint/known-directives': 'error',
|
35
|
+
'@graphql-eslint/known-type-names': 'error',
|
36
|
+
'@graphql-eslint/lone-schema-definition': 'error',
|
37
|
+
'@graphql-eslint/naming-convention': [
|
38
|
+
'error',
|
39
|
+
{
|
40
|
+
types: 'PascalCase',
|
41
|
+
fields: 'camelCase',
|
42
|
+
EnumValueDefinition: 'UPPER_CASE',
|
43
|
+
'FieldDefinition[parent.name.value=Query]': {
|
44
|
+
forbiddenPrefixes: ['query', 'get'],
|
45
|
+
forbiddenSuffixes: ['Query'],
|
46
|
+
},
|
47
|
+
'FieldDefinition[parent.name.value=Mutation]': {
|
48
|
+
forbiddenPrefixes: ['mutation'],
|
49
|
+
forbiddenSuffixes: ['Mutation'],
|
50
|
+
},
|
51
|
+
'FieldDefinition[parent.name.value=Subscription]': {
|
52
|
+
forbiddenPrefixes: ['subscription'],
|
53
|
+
forbiddenSuffixes: ['Subscription'],
|
54
|
+
},
|
55
|
+
},
|
56
|
+
],
|
57
|
+
'@graphql-eslint/no-case-insensitive-enum-values-duplicates': 'error',
|
58
|
+
'@graphql-eslint/no-hashtag-description': 'error',
|
59
|
+
'@graphql-eslint/no-typename-prefix': 'error',
|
60
|
+
'@graphql-eslint/no-unreachable-types': 'error',
|
61
|
+
'@graphql-eslint/possible-type-extension': 'error',
|
62
|
+
'@graphql-eslint/provided-required-arguments': 'error',
|
63
|
+
'@graphql-eslint/require-deprecation-reason': 'error',
|
64
|
+
'@graphql-eslint/strict-id-in-types': 'error',
|
65
|
+
'@graphql-eslint/unique-directive-names': 'error',
|
66
|
+
'@graphql-eslint/unique-directive-names-per-location': 'error',
|
67
|
+
'@graphql-eslint/unique-enum-value-names': 'error',
|
68
|
+
'@graphql-eslint/unique-field-definition-names': 'error',
|
69
|
+
'@graphql-eslint/unique-operation-types': 'error',
|
70
|
+
'@graphql-eslint/unique-type-names': 'error',
|
71
|
+
},
|
72
|
+
};
|
73
|
+
|
74
|
+
/*
|
75
|
+
* 🚨 IMPORTANT! Do not manually modify this file. Run: `yarn generate-configs`
|
76
|
+
*/
|
77
|
+
const schemaAllConfig = {
|
78
|
+
extends: ['plugin:@graphql-eslint/base', 'plugin:@graphql-eslint/schema-recommended'],
|
79
|
+
rules: {
|
80
|
+
'@graphql-eslint/alphabetize': [
|
81
|
+
'error',
|
82
|
+
{
|
83
|
+
fields: ['ObjectTypeDefinition', 'InterfaceTypeDefinition', 'InputObjectTypeDefinition'],
|
84
|
+
values: ['EnumTypeDefinition'],
|
85
|
+
arguments: ['FieldDefinition', 'Field', 'DirectiveDefinition', 'Directive'],
|
86
|
+
},
|
87
|
+
],
|
88
|
+
'@graphql-eslint/input-name': 'error',
|
89
|
+
'@graphql-eslint/no-root-type': 'off',
|
90
|
+
'@graphql-eslint/no-scalar-result-type-on-mutation': 'error',
|
91
|
+
'@graphql-eslint/no-unused-fields': 'off',
|
92
|
+
'@graphql-eslint/require-deprecation-date': 'error',
|
93
|
+
'@graphql-eslint/require-description': ['error', { types: true, DirectiveDefinition: true }],
|
94
|
+
'@graphql-eslint/require-field-of-type-query-in-mutation-result': 'error',
|
95
|
+
},
|
96
|
+
};
|
97
|
+
|
98
|
+
/*
|
99
|
+
* 🚨 IMPORTANT! Do not manually modify this file. Run: `yarn generate-configs`
|
100
|
+
*/
|
101
|
+
const operationsRecommendedConfig = {
|
102
|
+
extends: ['plugin:@graphql-eslint/base'],
|
27
103
|
rules: {
|
28
|
-
'@graphql-eslint/avoid-typename-prefix': 'error',
|
29
104
|
'@graphql-eslint/executable-definitions': 'error',
|
30
105
|
'@graphql-eslint/fields-on-correct-type': 'error',
|
31
106
|
'@graphql-eslint/fragments-on-composite-type': 'error',
|
@@ -34,58 +109,36 @@ const recommendedConfig = {
|
|
34
109
|
'@graphql-eslint/known-fragment-names': 'error',
|
35
110
|
'@graphql-eslint/known-type-names': 'error',
|
36
111
|
'@graphql-eslint/lone-anonymous-operation': 'error',
|
37
|
-
'@graphql-eslint/lone-schema-definition': 'error',
|
38
112
|
'@graphql-eslint/naming-convention': [
|
39
113
|
'error',
|
40
114
|
{
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
},
|
50
|
-
FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
|
51
|
-
'FieldDefinition[parent.name.value=Query]': {
|
52
|
-
forbiddenPrefixes: ['query', 'get'],
|
53
|
-
forbiddenSuffixes: ['Query'],
|
54
|
-
},
|
55
|
-
'FieldDefinition[parent.name.value=Mutation]': {
|
56
|
-
forbiddenPrefixes: ['mutation'],
|
57
|
-
forbiddenSuffixes: ['Mutation'],
|
58
|
-
},
|
59
|
-
'FieldDefinition[parent.name.value=Subscription]': {
|
60
|
-
forbiddenPrefixes: ['subscription'],
|
61
|
-
forbiddenSuffixes: ['Subscription'],
|
62
|
-
},
|
63
|
-
},
|
115
|
+
Argument: 'camelCase',
|
116
|
+
VariableDefinition: 'camelCase',
|
117
|
+
OperationDefinition: {
|
118
|
+
style: 'PascalCase',
|
119
|
+
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
120
|
+
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
121
|
+
},
|
122
|
+
FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
|
64
123
|
},
|
65
124
|
],
|
66
125
|
'@graphql-eslint/no-anonymous-operations': 'error',
|
67
|
-
'@graphql-eslint/no-
|
126
|
+
'@graphql-eslint/no-deprecated': 'error',
|
127
|
+
'@graphql-eslint/no-duplicate-fields': 'error',
|
68
128
|
'@graphql-eslint/no-fragment-cycles': 'error',
|
69
|
-
'@graphql-eslint/no-operation-name-suffix': 'error',
|
70
129
|
'@graphql-eslint/no-undefined-variables': 'error',
|
71
130
|
'@graphql-eslint/no-unused-fragments': 'error',
|
72
131
|
'@graphql-eslint/no-unused-variables': 'error',
|
73
132
|
'@graphql-eslint/one-field-subscriptions': 'error',
|
74
133
|
'@graphql-eslint/overlapping-fields-can-be-merged': 'error',
|
75
134
|
'@graphql-eslint/possible-fragment-spread': 'error',
|
76
|
-
'@graphql-eslint/possible-type-extension': 'error',
|
77
135
|
'@graphql-eslint/provided-required-arguments': 'error',
|
78
|
-
'@graphql-eslint/require-
|
136
|
+
'@graphql-eslint/require-id-when-available': 'error',
|
79
137
|
'@graphql-eslint/scalar-leafs': 'error',
|
80
|
-
'@graphql-eslint/
|
138
|
+
'@graphql-eslint/selection-set-depth': ['error', { maxDepth: 7 }],
|
81
139
|
'@graphql-eslint/unique-argument-names': 'error',
|
82
|
-
'@graphql-eslint/unique-directive-names': 'error',
|
83
140
|
'@graphql-eslint/unique-directive-names-per-location': 'error',
|
84
|
-
'@graphql-eslint/unique-enum-value-names': 'error',
|
85
|
-
'@graphql-eslint/unique-field-definition-names': 'error',
|
86
141
|
'@graphql-eslint/unique-input-field-names': 'error',
|
87
|
-
'@graphql-eslint/unique-operation-types': 'error',
|
88
|
-
'@graphql-eslint/unique-type-names': 'error',
|
89
142
|
'@graphql-eslint/unique-variable-names': 'error',
|
90
143
|
'@graphql-eslint/value-literals-of-correct-type': 'error',
|
91
144
|
'@graphql-eslint/variables-are-input-types': 'error',
|
@@ -96,44 +149,32 @@ const recommendedConfig = {
|
|
96
149
|
/*
|
97
150
|
* 🚨 IMPORTANT! Do not manually modify this file. Run: `yarn generate-configs`
|
98
151
|
*/
|
99
|
-
const
|
100
|
-
|
152
|
+
const operationsAllConfig = {
|
153
|
+
extends: ['plugin:@graphql-eslint/base', 'plugin:@graphql-eslint/operations-recommended'],
|
101
154
|
rules: {
|
102
|
-
...recommendedConfig.rules,
|
103
155
|
'@graphql-eslint/alphabetize': [
|
104
156
|
'error',
|
105
157
|
{
|
106
|
-
fields: ['ObjectTypeDefinition', 'InterfaceTypeDefinition', 'InputObjectTypeDefinition'],
|
107
|
-
values: ['EnumTypeDefinition'],
|
108
158
|
selections: ['OperationDefinition', 'FragmentDefinition'],
|
109
159
|
variables: ['OperationDefinition'],
|
110
|
-
arguments: ['
|
160
|
+
arguments: ['Field', 'Directive'],
|
111
161
|
},
|
112
162
|
],
|
113
|
-
'@graphql-eslint/
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
'@graphql-eslint/input-name': 'error',
|
118
|
-
'@graphql-eslint/match-document-filename': 'error',
|
119
|
-
'@graphql-eslint/no-deprecated': 'error',
|
120
|
-
'@graphql-eslint/no-hashtag-description': 'error',
|
121
|
-
'@graphql-eslint/no-root-type': ['error', { disallow: ['subscription'] }],
|
122
|
-
'@graphql-eslint/no-unreachable-types': 'error',
|
123
|
-
'@graphql-eslint/no-unused-fields': 'error',
|
124
|
-
'@graphql-eslint/require-deprecation-date': 'error',
|
125
|
-
'@graphql-eslint/require-description': ['error', { types: true, overrides: { DirectiveDefinition: true } }],
|
126
|
-
'@graphql-eslint/require-field-of-type-query-in-mutation-result': 'error',
|
127
|
-
'@graphql-eslint/require-id-when-available': 'error',
|
128
|
-
'@graphql-eslint/selection-set-depth': 'error',
|
163
|
+
'@graphql-eslint/match-document-filename': [
|
164
|
+
'error',
|
165
|
+
{ query: 'kebab-case', mutation: 'kebab-case', subscription: 'kebab-case', fragment: 'kebab-case' },
|
166
|
+
],
|
129
167
|
'@graphql-eslint/unique-fragment-name': 'error',
|
130
168
|
'@graphql-eslint/unique-operation-name': 'error',
|
131
169
|
},
|
132
170
|
};
|
133
171
|
|
134
172
|
const configs = {
|
135
|
-
|
136
|
-
recommended:
|
173
|
+
base,
|
174
|
+
'schema-recommended': schemaRecommendedConfig,
|
175
|
+
'schema-all': schemaAllConfig,
|
176
|
+
'operations-recommended': operationsRecommendedConfig,
|
177
|
+
'operations-all': operationsAllConfig,
|
137
178
|
};
|
138
179
|
|
139
180
|
function requireSiblingsOperations(ruleName, context) {
|
@@ -346,7 +387,6 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
|
|
346
387
|
docs: {
|
347
388
|
...docs,
|
348
389
|
graphQLJSRuleName: ruleName,
|
349
|
-
category: 'Validation',
|
350
390
|
recommended: true,
|
351
391
|
requiresSchema,
|
352
392
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${name}.md`,
|
@@ -383,16 +423,22 @@ const importFiles = (context) => {
|
|
383
423
|
return _import.processImport(context.getFilename());
|
384
424
|
};
|
385
425
|
const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-definitions', 'ExecutableDefinitions', {
|
426
|
+
category: 'Operations',
|
386
427
|
description: `A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.`,
|
387
428
|
}), validationToRule('fields-on-correct-type', 'FieldsOnCorrectType', {
|
429
|
+
category: 'Operations',
|
388
430
|
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`.',
|
389
431
|
}), validationToRule('fragments-on-composite-type', 'FragmentsOnCompositeTypes', {
|
432
|
+
category: 'Operations',
|
390
433
|
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.`,
|
391
434
|
}), validationToRule('known-argument-names', 'KnownArgumentNames', {
|
435
|
+
category: ['Schema', 'Operations'],
|
392
436
|
description: `A GraphQL field is only valid if all supplied arguments are defined by that field.`,
|
393
437
|
}), validationToRule('known-directives', 'KnownDirectives', {
|
438
|
+
category: ['Schema', 'Operations'],
|
394
439
|
description: `A GraphQL document is only valid if all \`@directives\` are known by the schema and legally positioned.`,
|
395
440
|
}), validationToRule('known-fragment-names', 'KnownFragmentNames', {
|
441
|
+
category: 'Operations',
|
396
442
|
description: `A GraphQL document is only valid if all \`...Fragment\` fragment spreads refer to fragments defined in the same document.`,
|
397
443
|
examples: [
|
398
444
|
{
|
@@ -459,17 +505,23 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
459
505
|
},
|
460
506
|
],
|
461
507
|
}, importFiles), validationToRule('known-type-names', 'KnownTypeNames', {
|
508
|
+
category: ['Schema', 'Operations'],
|
462
509
|
description: `A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.`,
|
463
510
|
}), validationToRule('lone-anonymous-operation', 'LoneAnonymousOperation', {
|
511
|
+
category: 'Operations',
|
464
512
|
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.`,
|
465
513
|
}), validationToRule('lone-schema-definition', 'LoneSchemaDefinition', {
|
514
|
+
category: 'Schema',
|
466
515
|
description: `A GraphQL document is only valid if it contains only one schema definition.`,
|
467
516
|
requiresSchema: false,
|
468
517
|
}), validationToRule('no-fragment-cycles', 'NoFragmentCycles', {
|
518
|
+
category: 'Operations',
|
469
519
|
description: `A GraphQL fragment is only valid when it does not have cycles in fragments usage.`,
|
470
520
|
}), validationToRule('no-undefined-variables', 'NoUndefinedVariables', {
|
521
|
+
category: 'Operations',
|
471
522
|
description: `A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.`,
|
472
523
|
}, importFiles), validationToRule('no-unused-fragments', 'NoUnusedFragments', {
|
524
|
+
category: 'Operations',
|
473
525
|
description: `A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.`,
|
474
526
|
requiresSiblings: true,
|
475
527
|
}, context => {
|
@@ -499,49 +551,68 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
499
551
|
};
|
500
552
|
return getParentNode(context.getFilename());
|
501
553
|
}), validationToRule('no-unused-variables', 'NoUnusedVariables', {
|
554
|
+
category: 'Operations',
|
502
555
|
description: `A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.`,
|
503
556
|
}, importFiles), validationToRule('overlapping-fields-can-be-merged', 'OverlappingFieldsCanBeMerged', {
|
557
|
+
category: 'Operations',
|
504
558
|
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.`,
|
505
559
|
}), validationToRule('possible-fragment-spread', 'PossibleFragmentSpreads', {
|
560
|
+
category: 'Operations',
|
506
561
|
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.`,
|
507
562
|
}), validationToRule('possible-type-extension', 'PossibleTypeExtensions', {
|
563
|
+
category: 'Schema',
|
508
564
|
description: `A type extension is only valid if the type is defined and has the same kind.`,
|
509
565
|
requiresSchema: false,
|
510
566
|
}), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
|
567
|
+
category: ['Schema', 'Operations'],
|
511
568
|
description: `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.`,
|
512
569
|
}), validationToRule('scalar-leafs', 'ScalarLeafs', {
|
570
|
+
category: 'Operations',
|
513
571
|
description: `A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.`,
|
514
572
|
}), validationToRule('one-field-subscriptions', 'SingleFieldSubscriptions', {
|
573
|
+
category: 'Operations',
|
515
574
|
description: `A GraphQL subscription is valid only if it contains a single root field.`,
|
516
575
|
}), validationToRule('unique-argument-names', 'UniqueArgumentNames', {
|
576
|
+
category: 'Operations',
|
517
577
|
description: `A GraphQL field or directive is only valid if all supplied arguments are uniquely named.`,
|
518
578
|
}), validationToRule('unique-directive-names', 'UniqueDirectiveNames', {
|
579
|
+
category: 'Schema',
|
519
580
|
description: `A GraphQL document is only valid if all defined directives have unique names.`,
|
520
581
|
requiresSchema: false,
|
521
582
|
}), validationToRule('unique-directive-names-per-location', 'UniqueDirectivesPerLocation', {
|
583
|
+
category: ['Schema', 'Operations'],
|
522
584
|
description: `A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.`,
|
523
585
|
}), validationToRule('unique-enum-value-names', 'UniqueEnumValueNames', {
|
586
|
+
category: 'Schema',
|
524
587
|
description: `A GraphQL enum type is only valid if all its values are uniquely named.`,
|
525
588
|
requiresSchema: false,
|
526
589
|
}), validationToRule('unique-field-definition-names', 'UniqueFieldDefinitionNames', {
|
590
|
+
category: 'Schema',
|
527
591
|
description: `A GraphQL complex type is only valid if all its fields are uniquely named.`,
|
528
592
|
requiresSchema: false,
|
529
593
|
}), validationToRule('unique-input-field-names', 'UniqueInputFieldNames', {
|
594
|
+
category: 'Operations',
|
530
595
|
description: `A GraphQL input object value is only valid if all supplied fields are uniquely named.`,
|
531
596
|
requiresSchema: false,
|
532
597
|
}), validationToRule('unique-operation-types', 'UniqueOperationTypes', {
|
598
|
+
category: 'Schema',
|
533
599
|
description: `A GraphQL document is only valid if it has only one type per operation.`,
|
534
600
|
requiresSchema: false,
|
535
601
|
}), validationToRule('unique-type-names', 'UniqueTypeNames', {
|
602
|
+
category: 'Schema',
|
536
603
|
description: `A GraphQL document is only valid if all defined types have unique names.`,
|
537
604
|
requiresSchema: false,
|
538
605
|
}), validationToRule('unique-variable-names', 'UniqueVariableNames', {
|
606
|
+
category: 'Operations',
|
539
607
|
description: `A GraphQL operation is only valid if all its variables are uniquely named.`,
|
540
608
|
}), validationToRule('value-literals-of-correct-type', 'ValuesOfCorrectType', {
|
609
|
+
category: 'Operations',
|
541
610
|
description: `A GraphQL document is only valid if all value literals are of the type expected at their position.`,
|
542
611
|
}), validationToRule('variables-are-input-types', 'VariablesAreInputTypes', {
|
612
|
+
category: 'Operations',
|
543
613
|
description: `A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).`,
|
544
614
|
}), validationToRule('variables-in-allowed-position', 'VariablesInAllowedPosition', {
|
615
|
+
category: 'Operations',
|
545
616
|
description: `Variables passed to field arguments conform to type.`,
|
546
617
|
}));
|
547
618
|
|
@@ -567,7 +638,7 @@ const rule = {
|
|
567
638
|
meta: {
|
568
639
|
type: 'suggestion',
|
569
640
|
docs: {
|
570
|
-
category: '
|
641
|
+
category: ['Schema', 'Operations'],
|
571
642
|
description: 'Enforce arrange in alphabetical order for type fields, enum values, input object fields, operation selections and more.',
|
572
643
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/alphabetize.md',
|
573
644
|
examples: [
|
@@ -646,15 +717,22 @@ const rule = {
|
|
646
717
|
`,
|
647
718
|
},
|
648
719
|
],
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
720
|
+
configOptions: {
|
721
|
+
schema: [
|
722
|
+
{
|
723
|
+
fields: fieldsEnum,
|
724
|
+
values: valuesEnum,
|
725
|
+
arguments: argumentsEnum,
|
726
|
+
},
|
727
|
+
],
|
728
|
+
operations: [
|
729
|
+
{
|
730
|
+
selections: selectionsEnum,
|
731
|
+
variables: variablesEnum,
|
732
|
+
arguments: [graphql.Kind.FIELD, graphql.Kind.DIRECTIVE],
|
733
|
+
},
|
734
|
+
],
|
735
|
+
},
|
658
736
|
},
|
659
737
|
messages: {
|
660
738
|
[ALPHABETIZE]: '"{{ currName }}" should be before "{{ prevName }}"',
|
@@ -792,430 +870,128 @@ const rule = {
|
|
792
870
|
},
|
793
871
|
};
|
794
872
|
|
795
|
-
const AVOID_DUPLICATE_FIELDS = 'AVOID_DUPLICATE_FIELDS';
|
796
873
|
const rule$1 = {
|
797
874
|
meta: {
|
798
875
|
type: 'suggestion',
|
799
876
|
docs: {
|
800
|
-
description: `Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.`,
|
801
|
-
category: 'Stylistic Issues',
|
802
|
-
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-duplicate-fields.md',
|
803
877
|
examples: [
|
804
878
|
{
|
805
879
|
title: 'Incorrect',
|
880
|
+
usage: [{ style: 'inline' }],
|
806
881
|
code: /* GraphQL */ `
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
email
|
811
|
-
name # duplicate field
|
812
|
-
}
|
813
|
-
}
|
814
|
-
`,
|
815
|
-
},
|
816
|
-
{
|
817
|
-
title: 'Incorrect',
|
818
|
-
code: /* GraphQL */ `
|
819
|
-
query {
|
820
|
-
users(
|
821
|
-
first: 100
|
822
|
-
skip: 50
|
823
|
-
after: "cji629tngfgou0b73kt7vi5jo"
|
824
|
-
first: 100 # duplicate argument
|
825
|
-
) {
|
826
|
-
id
|
827
|
-
}
|
882
|
+
""" Description """
|
883
|
+
type someTypeName {
|
884
|
+
# ...
|
828
885
|
}
|
829
886
|
`,
|
830
887
|
},
|
831
888
|
{
|
832
|
-
title: '
|
889
|
+
title: 'Correct',
|
890
|
+
usage: [{ style: 'inline' }],
|
833
891
|
code: /* GraphQL */ `
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
) {
|
838
|
-
users(first: $first, skip: 50) {
|
839
|
-
id
|
840
|
-
}
|
892
|
+
" Description "
|
893
|
+
type someTypeName {
|
894
|
+
# ...
|
841
895
|
}
|
842
896
|
`,
|
843
897
|
},
|
844
898
|
],
|
899
|
+
description: 'Require all comments to follow the same style (either block or inline).',
|
900
|
+
category: 'Schema',
|
901
|
+
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/description-style.md',
|
902
|
+
recommended: true,
|
845
903
|
},
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
904
|
+
schema: [
|
905
|
+
{
|
906
|
+
type: 'object',
|
907
|
+
additionalProperties: false,
|
908
|
+
properties: {
|
909
|
+
style: {
|
910
|
+
enum: ['block', 'inline'],
|
911
|
+
default: 'block',
|
912
|
+
},
|
913
|
+
},
|
914
|
+
},
|
915
|
+
],
|
850
916
|
},
|
851
917
|
create(context) {
|
852
|
-
|
853
|
-
|
918
|
+
const { style = 'block' } = context.options[0] || {};
|
919
|
+
const isBlock = style === 'block';
|
920
|
+
return {
|
921
|
+
[`.description[type=StringValue][block!=${isBlock}]`](node) {
|
854
922
|
context.report({
|
855
|
-
loc: getLocation(
|
856
|
-
|
857
|
-
}),
|
858
|
-
messageId: AVOID_DUPLICATE_FIELDS,
|
859
|
-
data: {
|
860
|
-
type,
|
861
|
-
fieldName,
|
862
|
-
},
|
923
|
+
loc: getLocation(node.loc),
|
924
|
+
message: `Unexpected ${isBlock ? 'inline' : 'block'} description`,
|
863
925
|
});
|
864
|
-
}
|
865
|
-
else {
|
866
|
-
usedFields.add(fieldName);
|
867
|
-
}
|
868
|
-
}
|
869
|
-
return {
|
870
|
-
OperationDefinition(node) {
|
871
|
-
const set = new Set();
|
872
|
-
for (const varDef of node.variableDefinitions) {
|
873
|
-
checkNode(set, varDef.variable.name.value, 'Operation variable', varDef);
|
874
|
-
}
|
875
|
-
},
|
876
|
-
Field(node) {
|
877
|
-
const set = new Set();
|
878
|
-
for (const arg of node.arguments) {
|
879
|
-
checkNode(set, arg.name.value, 'Field argument', arg);
|
880
|
-
}
|
881
|
-
},
|
882
|
-
SelectionSet(node) {
|
883
|
-
var _a;
|
884
|
-
const set = new Set();
|
885
|
-
for (const selection of node.selections) {
|
886
|
-
if (selection.kind === graphql.Kind.FIELD) {
|
887
|
-
checkNode(set, ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value, 'Field', selection);
|
888
|
-
}
|
889
|
-
}
|
890
926
|
},
|
891
927
|
};
|
892
928
|
},
|
893
929
|
};
|
894
930
|
|
895
|
-
const
|
931
|
+
const isObjectType = (node) => [graphql.Kind.OBJECT_TYPE_DEFINITION, graphql.Kind.OBJECT_TYPE_EXTENSION].includes(node.type);
|
932
|
+
const isQueryType = (node) => isObjectType(node) && node.name.value === 'Query';
|
933
|
+
const isMutationType = (node) => isObjectType(node) && node.name.value === 'Mutation';
|
896
934
|
const rule$2 = {
|
897
935
|
meta: {
|
898
936
|
type: 'suggestion',
|
899
937
|
docs: {
|
900
|
-
description: '
|
901
|
-
category: '
|
902
|
-
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/
|
938
|
+
description: 'Require mutation argument to be always called "input" and input type to be called Mutation name + "Input".\nUsing the same name for all input parameters will make your schemas easier to consume and more predictable. Using the same name as mutation for InputType will make it easier to find mutations that InputType belongs to.',
|
939
|
+
category: 'Schema',
|
940
|
+
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/input-name.md',
|
903
941
|
examples: [
|
904
942
|
{
|
905
943
|
title: 'Incorrect',
|
906
|
-
usage: [{
|
944
|
+
usage: [{ checkInputType: true }],
|
907
945
|
code: /* GraphQL */ `
|
908
|
-
|
909
|
-
|
910
|
-
}
|
946
|
+
type Mutation {
|
947
|
+
SetMessage(message: InputMessage): String
|
948
|
+
}
|
949
|
+
`,
|
911
950
|
},
|
912
951
|
{
|
913
|
-
title: 'Correct',
|
914
|
-
usage: [{
|
952
|
+
title: 'Correct (with checkInputType)',
|
953
|
+
usage: [{ checkInputType: true }],
|
915
954
|
code: /* GraphQL */ `
|
916
|
-
|
917
|
-
|
918
|
-
}
|
955
|
+
type Mutation {
|
956
|
+
SetMessage(input: SetMessageInput): String
|
957
|
+
}
|
958
|
+
`,
|
959
|
+
},
|
960
|
+
{
|
961
|
+
title: 'Correct (without checkInputType)',
|
962
|
+
usage: [{ checkInputType: false }],
|
963
|
+
code: /* GraphQL */ `
|
964
|
+
type Mutation {
|
965
|
+
SetMessage(input: AnyInputTypeName): String
|
966
|
+
}
|
967
|
+
`,
|
919
968
|
},
|
920
969
|
],
|
921
970
|
},
|
922
|
-
messages: {
|
923
|
-
[AVOID_OPERATION_NAME_PREFIX]: `Forbidden operation name prefix: "{{ invalidPrefix }}"`,
|
924
|
-
},
|
925
971
|
schema: [
|
926
972
|
{
|
927
|
-
additionalProperties: false,
|
928
973
|
type: 'object',
|
929
|
-
|
974
|
+
additionalProperties: false,
|
930
975
|
properties: {
|
931
|
-
|
976
|
+
checkInputType: {
|
977
|
+
type: 'boolean',
|
932
978
|
default: false,
|
979
|
+
description: 'Check that the input type name follows the convention <mutationName>Input',
|
980
|
+
},
|
981
|
+
caseSensitiveInputType: {
|
933
982
|
type: 'boolean',
|
983
|
+
default: true,
|
984
|
+
description: 'Allow for case discrepancies in the input type name',
|
934
985
|
},
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
},
|
945
|
-
],
|
946
|
-
},
|
947
|
-
create(context) {
|
948
|
-
return {
|
949
|
-
'OperationDefinition, FragmentDefinition'(node) {
|
950
|
-
const config = context.options[0] || { keywords: [], caseSensitive: false };
|
951
|
-
const caseSensitive = config.caseSensitive;
|
952
|
-
const keywords = config.keywords || [];
|
953
|
-
if (node && node.name && node.name.value !== '') {
|
954
|
-
for (const keyword of keywords) {
|
955
|
-
const testKeyword = caseSensitive ? keyword : keyword.toLowerCase();
|
956
|
-
const testName = caseSensitive ? node.name.value : node.name.value.toLowerCase();
|
957
|
-
if (testName.startsWith(testKeyword)) {
|
958
|
-
const { start } = node.name.loc;
|
959
|
-
context.report({
|
960
|
-
loc: {
|
961
|
-
start: {
|
962
|
-
line: start.line,
|
963
|
-
column: start.column - 1,
|
964
|
-
},
|
965
|
-
end: {
|
966
|
-
line: start.line,
|
967
|
-
column: start.column - 1 + testKeyword.length,
|
968
|
-
},
|
969
|
-
},
|
970
|
-
data: {
|
971
|
-
invalidPrefix: keyword,
|
972
|
-
},
|
973
|
-
messageId: AVOID_OPERATION_NAME_PREFIX,
|
974
|
-
});
|
975
|
-
}
|
976
|
-
}
|
977
|
-
}
|
978
|
-
},
|
979
|
-
};
|
980
|
-
},
|
981
|
-
};
|
982
|
-
|
983
|
-
const rule$3 = {
|
984
|
-
meta: {
|
985
|
-
type: 'suggestion',
|
986
|
-
docs: {
|
987
|
-
category: 'Best Practices',
|
988
|
-
description: 'Avoid scalar result type on mutation type to make sure to return a valid state.',
|
989
|
-
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-scalar-result-type-on-mutation.md',
|
990
|
-
requiresSchema: true,
|
991
|
-
examples: [
|
992
|
-
{
|
993
|
-
title: 'Incorrect',
|
994
|
-
code: /* GraphQL */ `
|
995
|
-
type Mutation {
|
996
|
-
createUser: Boolean
|
997
|
-
}
|
998
|
-
`,
|
999
|
-
},
|
1000
|
-
{
|
1001
|
-
title: 'Correct',
|
1002
|
-
code: /* GraphQL */ `
|
1003
|
-
type Mutation {
|
1004
|
-
createUser: User!
|
1005
|
-
}
|
1006
|
-
`,
|
1007
|
-
},
|
1008
|
-
],
|
1009
|
-
},
|
1010
|
-
schema: [],
|
1011
|
-
},
|
1012
|
-
create(context) {
|
1013
|
-
const schema = requireGraphQLSchemaFromContext('avoid-scalar-result-type-on-mutation', context);
|
1014
|
-
const mutationType = schema.getMutationType();
|
1015
|
-
if (!mutationType) {
|
1016
|
-
return {};
|
1017
|
-
}
|
1018
|
-
const selector = [
|
1019
|
-
`:matches(${graphql.Kind.OBJECT_TYPE_DEFINITION}, ${graphql.Kind.OBJECT_TYPE_EXTENSION})[name.value=${mutationType.name}]`,
|
1020
|
-
'>',
|
1021
|
-
graphql.Kind.FIELD_DEFINITION,
|
1022
|
-
graphql.Kind.NAMED_TYPE,
|
1023
|
-
].join(' ');
|
1024
|
-
return {
|
1025
|
-
[selector](node) {
|
1026
|
-
const typeName = node.name.value;
|
1027
|
-
const graphQLType = schema.getType(typeName);
|
1028
|
-
if (graphql.isScalarType(graphQLType)) {
|
1029
|
-
context.report({
|
1030
|
-
loc: getLocation(node.loc, typeName),
|
1031
|
-
message: `Unexpected scalar result type "${typeName}"`,
|
1032
|
-
});
|
1033
|
-
}
|
1034
|
-
},
|
1035
|
-
};
|
1036
|
-
},
|
1037
|
-
};
|
1038
|
-
|
1039
|
-
const AVOID_TYPENAME_PREFIX = 'AVOID_TYPENAME_PREFIX';
|
1040
|
-
const rule$4 = {
|
1041
|
-
meta: {
|
1042
|
-
type: 'suggestion',
|
1043
|
-
docs: {
|
1044
|
-
category: 'Best Practices',
|
1045
|
-
description: 'Enforces users to avoid using the type name in a field name while defining your schema.',
|
1046
|
-
recommended: true,
|
1047
|
-
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-typename-prefix.md',
|
1048
|
-
examples: [
|
1049
|
-
{
|
1050
|
-
title: 'Incorrect',
|
1051
|
-
code: /* GraphQL */ `
|
1052
|
-
type User {
|
1053
|
-
userId: ID!
|
1054
|
-
}
|
1055
|
-
`,
|
1056
|
-
},
|
1057
|
-
{
|
1058
|
-
title: 'Correct',
|
1059
|
-
code: /* GraphQL */ `
|
1060
|
-
type User {
|
1061
|
-
id: ID!
|
1062
|
-
}
|
1063
|
-
`,
|
1064
|
-
},
|
1065
|
-
],
|
1066
|
-
},
|
1067
|
-
messages: {
|
1068
|
-
[AVOID_TYPENAME_PREFIX]: `Field "{{ fieldName }}" starts with the name of the parent type "{{ typeName }}"`,
|
1069
|
-
},
|
1070
|
-
schema: [],
|
1071
|
-
},
|
1072
|
-
create(context) {
|
1073
|
-
return {
|
1074
|
-
'ObjectTypeDefinition, ObjectTypeExtension, InterfaceTypeDefinition, InterfaceTypeExtension'(node) {
|
1075
|
-
const typeName = node.name.value;
|
1076
|
-
const lowerTypeName = typeName.toLowerCase();
|
1077
|
-
for (const field of node.fields) {
|
1078
|
-
const fieldName = field.name.value;
|
1079
|
-
if (fieldName.toLowerCase().startsWith(lowerTypeName)) {
|
1080
|
-
context.report({
|
1081
|
-
data: {
|
1082
|
-
fieldName,
|
1083
|
-
typeName,
|
1084
|
-
},
|
1085
|
-
messageId: AVOID_TYPENAME_PREFIX,
|
1086
|
-
loc: getLocation(field.loc, lowerTypeName),
|
1087
|
-
});
|
1088
|
-
}
|
1089
|
-
}
|
1090
|
-
},
|
1091
|
-
};
|
1092
|
-
},
|
1093
|
-
};
|
1094
|
-
|
1095
|
-
const rule$5 = {
|
1096
|
-
meta: {
|
1097
|
-
type: 'suggestion',
|
1098
|
-
docs: {
|
1099
|
-
examples: [
|
1100
|
-
{
|
1101
|
-
title: 'Incorrect',
|
1102
|
-
usage: [{ style: 'inline' }],
|
1103
|
-
code: /* GraphQL */ `
|
1104
|
-
""" Description """
|
1105
|
-
type someTypeName {
|
1106
|
-
# ...
|
1107
|
-
}
|
1108
|
-
`,
|
1109
|
-
},
|
1110
|
-
{
|
1111
|
-
title: 'Correct',
|
1112
|
-
usage: [{ style: 'inline' }],
|
1113
|
-
code: /* GraphQL */ `
|
1114
|
-
" Description "
|
1115
|
-
type someTypeName {
|
1116
|
-
# ...
|
1117
|
-
}
|
1118
|
-
`,
|
1119
|
-
},
|
1120
|
-
],
|
1121
|
-
description: 'Require all comments to follow the same style (either block or inline).',
|
1122
|
-
category: 'Stylistic Issues',
|
1123
|
-
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/description-style.md',
|
1124
|
-
},
|
1125
|
-
schema: [
|
1126
|
-
{
|
1127
|
-
type: 'object',
|
1128
|
-
properties: {
|
1129
|
-
style: {
|
1130
|
-
type: 'string',
|
1131
|
-
enum: ['block', 'inline'],
|
1132
|
-
default: 'inline',
|
1133
|
-
},
|
1134
|
-
},
|
1135
|
-
additionalProperties: false,
|
1136
|
-
},
|
1137
|
-
],
|
1138
|
-
},
|
1139
|
-
create(context) {
|
1140
|
-
const { style } = context.options[0] || { style: 'inline' };
|
1141
|
-
const wrongDescriptionType = style === 'block' ? 'inline' : 'block';
|
1142
|
-
return {
|
1143
|
-
'[description.type="StringValue"]': node => {
|
1144
|
-
if (node.description.block !== (style === 'block')) {
|
1145
|
-
context.report({
|
1146
|
-
loc: getLocation(node.description.loc),
|
1147
|
-
message: `Unexpected ${wrongDescriptionType} description`,
|
1148
|
-
});
|
1149
|
-
}
|
1150
|
-
},
|
1151
|
-
};
|
1152
|
-
},
|
1153
|
-
};
|
1154
|
-
|
1155
|
-
const isObjectType = (node) => [graphql.Kind.OBJECT_TYPE_DEFINITION, graphql.Kind.OBJECT_TYPE_EXTENSION].includes(node.type);
|
1156
|
-
const isQueryType = (node) => isObjectType(node) && node.name.value === 'Query';
|
1157
|
-
const isMutationType = (node) => isObjectType(node) && node.name.value === 'Mutation';
|
1158
|
-
const rule$6 = {
|
1159
|
-
meta: {
|
1160
|
-
type: 'suggestion',
|
1161
|
-
docs: {
|
1162
|
-
description: 'Require mutation argument to be always called "input" and input type to be called Mutation name + "Input".\nUsing the same name for all input parameters will make your schemas easier to consume and more predictable. Using the same name as mutation for InputType will make it easier to find mutations that InputType belongs to.',
|
1163
|
-
category: 'Stylistic Issues',
|
1164
|
-
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/input-name.md',
|
1165
|
-
examples: [
|
1166
|
-
{
|
1167
|
-
title: 'Incorrect',
|
1168
|
-
usage: [{ checkInputType: true }],
|
1169
|
-
code: /* GraphQL */ `
|
1170
|
-
type Mutation {
|
1171
|
-
SetMessage(message: InputMessage): String
|
1172
|
-
}
|
1173
|
-
`,
|
1174
|
-
},
|
1175
|
-
{
|
1176
|
-
title: 'Correct (with checkInputType)',
|
1177
|
-
usage: [{ checkInputType: true }],
|
1178
|
-
code: /* GraphQL */ `
|
1179
|
-
type Mutation {
|
1180
|
-
SetMessage(input: SetMessageInput): String
|
1181
|
-
}
|
1182
|
-
`,
|
1183
|
-
},
|
1184
|
-
{
|
1185
|
-
title: 'Correct (without checkInputType)',
|
1186
|
-
usage: [{ checkInputType: false }],
|
1187
|
-
code: /* GraphQL */ `
|
1188
|
-
type Mutation {
|
1189
|
-
SetMessage(input: AnyInputTypeName): String
|
1190
|
-
}
|
1191
|
-
`,
|
1192
|
-
},
|
1193
|
-
],
|
1194
|
-
},
|
1195
|
-
schema: [
|
1196
|
-
{
|
1197
|
-
type: 'object',
|
1198
|
-
additionalProperties: false,
|
1199
|
-
properties: {
|
1200
|
-
checkInputType: {
|
1201
|
-
type: 'boolean',
|
1202
|
-
default: false,
|
1203
|
-
description: 'Check that the input type name follows the convention <mutationName>Input',
|
1204
|
-
},
|
1205
|
-
caseSensitiveInputType: {
|
1206
|
-
type: 'boolean',
|
1207
|
-
default: true,
|
1208
|
-
description: 'Allow for case discrepancies in the input type name',
|
1209
|
-
},
|
1210
|
-
checkQueries: {
|
1211
|
-
type: 'boolean',
|
1212
|
-
default: false,
|
1213
|
-
description: 'Apply the rule to Queries',
|
1214
|
-
},
|
1215
|
-
checkMutations: {
|
1216
|
-
type: 'boolean',
|
1217
|
-
default: true,
|
1218
|
-
description: 'Apply the rule to Mutations',
|
986
|
+
checkQueries: {
|
987
|
+
type: 'boolean',
|
988
|
+
default: false,
|
989
|
+
description: 'Apply the rule to Queries',
|
990
|
+
},
|
991
|
+
checkMutations: {
|
992
|
+
type: 'boolean',
|
993
|
+
default: true,
|
994
|
+
description: 'Apply the rule to Mutations',
|
1219
995
|
},
|
1220
996
|
},
|
1221
997
|
},
|
@@ -1281,11 +1057,11 @@ const CASE_STYLES = [
|
|
1281
1057
|
const schemaOption = {
|
1282
1058
|
oneOf: [{ $ref: '#/definitions/asString' }, { $ref: '#/definitions/asObject' }],
|
1283
1059
|
};
|
1284
|
-
const rule$
|
1060
|
+
const rule$3 = {
|
1285
1061
|
meta: {
|
1286
1062
|
type: 'suggestion',
|
1287
1063
|
docs: {
|
1288
|
-
category: '
|
1064
|
+
category: 'Operations',
|
1289
1065
|
description: 'This rule allows you to enforce that the file name should match the operation name.',
|
1290
1066
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/match-document-filename.md`,
|
1291
1067
|
examples: [
|
@@ -1359,6 +1135,14 @@ const rule$7 = {
|
|
1359
1135
|
`,
|
1360
1136
|
},
|
1361
1137
|
],
|
1138
|
+
configOptions: [
|
1139
|
+
{
|
1140
|
+
query: CaseStyle.kebabCase,
|
1141
|
+
mutation: CaseStyle.kebabCase,
|
1142
|
+
subscription: CaseStyle.kebabCase,
|
1143
|
+
fragment: CaseStyle.kebabCase,
|
1144
|
+
},
|
1145
|
+
],
|
1362
1146
|
},
|
1363
1147
|
messages: {
|
1364
1148
|
[MATCH_EXTENSION]: `File extension "{{ fileExtension }}" don't match extension "{{ expectedFileExtension }}"`,
|
@@ -1367,27 +1151,29 @@ const rule$7 = {
|
|
1367
1151
|
schema: {
|
1368
1152
|
definitions: {
|
1369
1153
|
asString: {
|
1370
|
-
type: 'string',
|
1371
|
-
description: `One of: ${CASE_STYLES.map(t => `\`${t}\``).join(', ')}`,
|
1372
1154
|
enum: CASE_STYLES,
|
1155
|
+
description: `One of: ${CASE_STYLES.map(t => `\`${t}\``).join(', ')}`,
|
1373
1156
|
},
|
1374
1157
|
asObject: {
|
1375
1158
|
type: 'object',
|
1159
|
+
additionalProperties: false,
|
1376
1160
|
properties: {
|
1377
1161
|
style: {
|
1378
|
-
type: 'string',
|
1379
1162
|
enum: CASE_STYLES,
|
1380
1163
|
},
|
1164
|
+
suffix: {
|
1165
|
+
type: 'string',
|
1166
|
+
},
|
1381
1167
|
},
|
1382
1168
|
},
|
1383
1169
|
},
|
1384
|
-
$schema: 'http://json-schema.org/draft-04/schema#',
|
1385
1170
|
type: 'array',
|
1171
|
+
maxItems: 1,
|
1386
1172
|
items: {
|
1387
1173
|
type: 'object',
|
1174
|
+
additionalProperties: false,
|
1388
1175
|
properties: {
|
1389
1176
|
fileExtension: {
|
1390
|
-
type: 'string',
|
1391
1177
|
enum: ACCEPTED_EXTENSIONS,
|
1392
1178
|
},
|
1393
1179
|
query: schemaOption,
|
@@ -1462,13 +1248,7 @@ const rule$7 = {
|
|
1462
1248
|
},
|
1463
1249
|
};
|
1464
1250
|
|
1465
|
-
const FIELDS_KINDS = [
|
1466
|
-
graphql.Kind.FIELD_DEFINITION,
|
1467
|
-
graphql.Kind.INPUT_VALUE_DEFINITION,
|
1468
|
-
graphql.Kind.VARIABLE_DEFINITION,
|
1469
|
-
graphql.Kind.ARGUMENT,
|
1470
|
-
graphql.Kind.DIRECTIVE_DEFINITION,
|
1471
|
-
];
|
1251
|
+
const FIELDS_KINDS = [graphql.Kind.FIELD_DEFINITION, graphql.Kind.INPUT_VALUE_DEFINITION, graphql.Kind.ARGUMENT, graphql.Kind.DIRECTIVE_DEFINITION];
|
1472
1252
|
const KindToDisplayName = {
|
1473
1253
|
// types
|
1474
1254
|
[graphql.Kind.OBJECT_TYPE_DEFINITION]: 'Type',
|
@@ -1480,13 +1260,13 @@ const KindToDisplayName = {
|
|
1480
1260
|
// fields
|
1481
1261
|
[graphql.Kind.FIELD_DEFINITION]: 'Field',
|
1482
1262
|
[graphql.Kind.INPUT_VALUE_DEFINITION]: 'Input property',
|
1483
|
-
[graphql.Kind.VARIABLE_DEFINITION]: 'Variable',
|
1484
1263
|
[graphql.Kind.ARGUMENT]: 'Argument',
|
1485
1264
|
[graphql.Kind.DIRECTIVE_DEFINITION]: 'Directive',
|
1486
1265
|
// rest
|
1487
1266
|
[graphql.Kind.ENUM_VALUE_DEFINITION]: 'Enumeration value',
|
1488
1267
|
[graphql.Kind.OPERATION_DEFINITION]: 'Operation',
|
1489
1268
|
[graphql.Kind.FRAGMENT_DEFINITION]: 'Fragment',
|
1269
|
+
[graphql.Kind.VARIABLE_DEFINITION]: 'Variable',
|
1490
1270
|
};
|
1491
1271
|
const StyleToRegex = {
|
1492
1272
|
camelCase: /^[a-z][\dA-Za-z]*$/,
|
@@ -1499,12 +1279,12 @@ const ALLOWED_STYLES = Object.keys(StyleToRegex);
|
|
1499
1279
|
const schemaOption$1 = {
|
1500
1280
|
oneOf: [{ $ref: '#/definitions/asString' }, { $ref: '#/definitions/asObject' }],
|
1501
1281
|
};
|
1502
|
-
const rule$
|
1282
|
+
const rule$4 = {
|
1503
1283
|
meta: {
|
1504
1284
|
type: 'suggestion',
|
1505
1285
|
docs: {
|
1506
1286
|
description: 'Require names to follow specified conventions.',
|
1507
|
-
category: '
|
1287
|
+
category: ['Schema', 'Operations'],
|
1508
1288
|
recommended: true,
|
1509
1289
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/naming-convention.md',
|
1510
1290
|
examples: [
|
@@ -1527,22 +1307,12 @@ const rule$8 = {
|
|
1527
1307
|
`,
|
1528
1308
|
},
|
1529
1309
|
],
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1310
|
+
configOptions: {
|
1311
|
+
schema: [
|
1312
|
+
{
|
1313
|
+
types: 'PascalCase',
|
1314
|
+
fields: 'camelCase',
|
1535
1315
|
EnumValueDefinition: 'UPPER_CASE',
|
1536
|
-
OperationDefinition: {
|
1537
|
-
style: 'PascalCase',
|
1538
|
-
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
1539
|
-
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
1540
|
-
},
|
1541
|
-
FragmentDefinition: {
|
1542
|
-
style: 'PascalCase',
|
1543
|
-
forbiddenPrefixes: ['Fragment'],
|
1544
|
-
forbiddenSuffixes: ['Fragment'],
|
1545
|
-
},
|
1546
1316
|
'FieldDefinition[parent.name.value=Query]': {
|
1547
1317
|
forbiddenPrefixes: ['query', 'get'],
|
1548
1318
|
forbiddenSuffixes: ['Query'],
|
@@ -1556,8 +1326,24 @@ const rule$8 = {
|
|
1556
1326
|
forbiddenSuffixes: ['Subscription'],
|
1557
1327
|
},
|
1558
1328
|
},
|
1559
|
-
|
1560
|
-
|
1329
|
+
],
|
1330
|
+
operations: [
|
1331
|
+
{
|
1332
|
+
Argument: 'camelCase',
|
1333
|
+
VariableDefinition: 'camelCase',
|
1334
|
+
OperationDefinition: {
|
1335
|
+
style: 'PascalCase',
|
1336
|
+
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
1337
|
+
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
1338
|
+
},
|
1339
|
+
FragmentDefinition: {
|
1340
|
+
style: 'PascalCase',
|
1341
|
+
forbiddenPrefixes: ['Fragment'],
|
1342
|
+
forbiddenSuffixes: ['Fragment'],
|
1343
|
+
},
|
1344
|
+
},
|
1345
|
+
],
|
1346
|
+
},
|
1561
1347
|
},
|
1562
1348
|
schema: {
|
1563
1349
|
definitions: {
|
@@ -1593,14 +1379,6 @@ const rule$8 = {
|
|
1593
1379
|
type: 'object',
|
1594
1380
|
additionalProperties: false,
|
1595
1381
|
properties: {
|
1596
|
-
types: {
|
1597
|
-
...schemaOption$1,
|
1598
|
-
description: `Includes:\n\n${TYPES_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`).join('\n')}`,
|
1599
|
-
},
|
1600
|
-
fields: {
|
1601
|
-
...schemaOption$1,
|
1602
|
-
description: `Includes:\n\n${FIELDS_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`).join('\n')}`,
|
1603
|
-
},
|
1604
1382
|
allowLeadingUnderscore: {
|
1605
1383
|
type: 'boolean',
|
1606
1384
|
default: false,
|
@@ -1609,35 +1387,42 @@ const rule$8 = {
|
|
1609
1387
|
type: 'boolean',
|
1610
1388
|
default: false,
|
1611
1389
|
},
|
1612
|
-
|
1613
|
-
|
1614
|
-
|
1615
|
-
description: [
|
1616
|
-
'May contain the following `ASTNode` names:',
|
1617
|
-
'',
|
1618
|
-
...ALLOWED_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`),
|
1619
|
-
'',
|
1620
|
-
"> It's also possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with `ASTNode` name",
|
1621
|
-
'>',
|
1622
|
-
'> Example: pattern property `FieldDefinition[parent.name.value=Query]` will match only fields for type `Query`',
|
1623
|
-
].join('\n'),
|
1624
|
-
patternProperties: {
|
1625
|
-
[`^(${ALLOWED_KINDS.join('|')})(.+)?$`]: schemaOption$1,
|
1626
|
-
},
|
1390
|
+
types: {
|
1391
|
+
...schemaOption$1,
|
1392
|
+
description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1627
1393
|
},
|
1628
|
-
|
1394
|
+
fields: {
|
1395
|
+
...schemaOption$1,
|
1396
|
+
description: `Includes:\n\n${FIELDS_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1397
|
+
},
|
1398
|
+
...Object.fromEntries(ALLOWED_KINDS.map(kind => [
|
1399
|
+
kind,
|
1400
|
+
{
|
1401
|
+
...schemaOption$1,
|
1402
|
+
description: `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`,
|
1403
|
+
},
|
1404
|
+
])),
|
1405
|
+
},
|
1406
|
+
patternProperties: {
|
1407
|
+
[`^(${ALLOWED_KINDS.join('|')})(.+)?$`]: schemaOption$1,
|
1408
|
+
},
|
1409
|
+
description: [
|
1410
|
+
"> It's possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with allowed `ASTNode` names which are described below.",
|
1411
|
+
'>',
|
1412
|
+
'> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector.',
|
1413
|
+
'>',
|
1414
|
+
'> Example: pattern property `FieldDefinition[parent.name.value=Query]` will match only fields for type `Query`.',
|
1415
|
+
].join('\n'),
|
1629
1416
|
},
|
1630
1417
|
},
|
1631
1418
|
},
|
1632
1419
|
create(context) {
|
1633
|
-
const options = {
|
1634
|
-
|
1635
|
-
...context.options[0],
|
1636
|
-
};
|
1420
|
+
const options = context.options[0] || {};
|
1421
|
+
const { allowLeadingUnderscore, allowTrailingUnderscore, types, fields, ...restOptions } = options;
|
1637
1422
|
function normalisePropertyOption(kind) {
|
1638
|
-
let style = options
|
1423
|
+
let style = options[kind];
|
1639
1424
|
if (!style) {
|
1640
|
-
style = TYPES_KINDS.includes(kind) ?
|
1425
|
+
style = TYPES_KINDS.includes(kind) ? types : fields;
|
1641
1426
|
}
|
1642
1427
|
return typeof style === 'object' ? style : { style };
|
1643
1428
|
}
|
@@ -1658,10 +1443,10 @@ const rule$8 = {
|
|
1658
1443
|
}
|
1659
1444
|
function getErrorMessage() {
|
1660
1445
|
let name = nodeName;
|
1661
|
-
if (
|
1446
|
+
if (allowLeadingUnderscore) {
|
1662
1447
|
name = name.replace(/^_*/, '');
|
1663
1448
|
}
|
1664
|
-
if (
|
1449
|
+
if (allowTrailingUnderscore) {
|
1665
1450
|
name = name.replace(/_*$/, '');
|
1666
1451
|
}
|
1667
1452
|
if (prefix && !name.startsWith(prefix)) {
|
@@ -1695,15 +1480,13 @@ const rule$8 = {
|
|
1695
1480
|
});
|
1696
1481
|
};
|
1697
1482
|
const listeners = {};
|
1698
|
-
if (!
|
1483
|
+
if (!allowLeadingUnderscore) {
|
1699
1484
|
listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1700
1485
|
}
|
1701
|
-
if (!
|
1486
|
+
if (!allowTrailingUnderscore) {
|
1702
1487
|
listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1703
1488
|
}
|
1704
|
-
const selectors = new Set([
|
1705
|
-
.flat()
|
1706
|
-
.filter(Boolean));
|
1489
|
+
const selectors = new Set([types && TYPES_KINDS, fields && FIELDS_KINDS, Object.keys(restOptions)].flat().filter(Boolean));
|
1707
1490
|
for (const selector of selectors) {
|
1708
1491
|
listeners[selector] = checkNode(selector);
|
1709
1492
|
}
|
@@ -1712,11 +1495,11 @@ const rule$8 = {
|
|
1712
1495
|
};
|
1713
1496
|
|
1714
1497
|
const NO_ANONYMOUS_OPERATIONS = 'NO_ANONYMOUS_OPERATIONS';
|
1715
|
-
const rule$
|
1498
|
+
const rule$5 = {
|
1716
1499
|
meta: {
|
1717
1500
|
type: 'suggestion',
|
1718
1501
|
docs: {
|
1719
|
-
category: '
|
1502
|
+
category: 'Operations',
|
1720
1503
|
description: 'Require name for your GraphQL operations. This is useful since most GraphQL client libraries are using the operation name for caching purposes.',
|
1721
1504
|
recommended: true,
|
1722
1505
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-anonymous-operations.md',
|
@@ -1760,12 +1543,12 @@ const rule$9 = {
|
|
1760
1543
|
};
|
1761
1544
|
|
1762
1545
|
const ERROR_MESSAGE_ID = 'NO_CASE_INSENSITIVE_ENUM_VALUES_DUPLICATES';
|
1763
|
-
const rule$
|
1546
|
+
const rule$6 = {
|
1764
1547
|
meta: {
|
1765
1548
|
type: 'suggestion',
|
1766
1549
|
docs: {
|
1767
1550
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-case-insensitive-enum-values-duplicates.md',
|
1768
|
-
category: '
|
1551
|
+
category: 'Schema',
|
1769
1552
|
recommended: true,
|
1770
1553
|
description: 'Disallow case-insensitive enum values duplicates.',
|
1771
1554
|
examples: [
|
@@ -1816,11 +1599,11 @@ const rule$a = {
|
|
1816
1599
|
};
|
1817
1600
|
|
1818
1601
|
const NO_DEPRECATED = 'NO_DEPRECATED';
|
1819
|
-
const rule$
|
1602
|
+
const rule$7 = {
|
1820
1603
|
meta: {
|
1821
1604
|
type: 'suggestion',
|
1822
1605
|
docs: {
|
1823
|
-
category: '
|
1606
|
+
category: 'Operations',
|
1824
1607
|
description: `Enforce that deprecated fields or enum values are not in use by operations.`,
|
1825
1608
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-deprecated.md`,
|
1826
1609
|
requiresSchema: true,
|
@@ -1883,48 +1666,150 @@ const rule$b = {
|
|
1883
1666
|
fullName
|
1884
1667
|
}
|
1885
1668
|
}
|
1886
|
-
`,
|
1887
|
-
},
|
1888
|
-
],
|
1889
|
-
|
1890
|
-
|
1891
|
-
|
1892
|
-
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
1669
|
+
`,
|
1670
|
+
},
|
1671
|
+
],
|
1672
|
+
recommended: true,
|
1673
|
+
},
|
1674
|
+
messages: {
|
1675
|
+
[NO_DEPRECATED]: `This {{ type }} is marked as deprecated in your GraphQL schema {{ reason }}`,
|
1676
|
+
},
|
1677
|
+
schema: [],
|
1678
|
+
},
|
1679
|
+
create(context) {
|
1680
|
+
return {
|
1681
|
+
EnumValue(node) {
|
1682
|
+
requireGraphQLSchemaFromContext('no-deprecated', context);
|
1683
|
+
const typeInfo = node.typeInfo();
|
1684
|
+
if (typeInfo && typeInfo.enumValue) {
|
1685
|
+
if (typeInfo.enumValue.deprecationReason) {
|
1686
|
+
const enumValueName = node.value;
|
1687
|
+
context.report({
|
1688
|
+
loc: getLocation(node.loc, enumValueName),
|
1689
|
+
messageId: NO_DEPRECATED,
|
1690
|
+
data: {
|
1691
|
+
type: 'enum value',
|
1692
|
+
reason: typeInfo.enumValue.deprecationReason ? `(reason: ${typeInfo.enumValue.deprecationReason})` : '',
|
1693
|
+
},
|
1694
|
+
});
|
1695
|
+
}
|
1696
|
+
}
|
1697
|
+
},
|
1698
|
+
Field(node) {
|
1699
|
+
requireGraphQLSchemaFromContext('no-deprecated', context);
|
1700
|
+
const typeInfo = node.typeInfo();
|
1701
|
+
if (typeInfo && typeInfo.fieldDef) {
|
1702
|
+
if (typeInfo.fieldDef.deprecationReason) {
|
1703
|
+
const fieldName = node.name.value;
|
1704
|
+
context.report({
|
1705
|
+
loc: getLocation(node.loc, fieldName),
|
1706
|
+
messageId: NO_DEPRECATED,
|
1707
|
+
data: {
|
1708
|
+
type: 'field',
|
1709
|
+
reason: typeInfo.fieldDef.deprecationReason ? `(reason: ${typeInfo.fieldDef.deprecationReason})` : '',
|
1710
|
+
},
|
1711
|
+
});
|
1712
|
+
}
|
1713
|
+
}
|
1714
|
+
},
|
1715
|
+
};
|
1716
|
+
},
|
1717
|
+
};
|
1718
|
+
|
1719
|
+
const NO_DUPLICATE_FIELDS = 'NO_DUPLICATE_FIELDS';
|
1720
|
+
const rule$8 = {
|
1721
|
+
meta: {
|
1722
|
+
type: 'suggestion',
|
1723
|
+
docs: {
|
1724
|
+
description: `Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.`,
|
1725
|
+
category: 'Operations',
|
1726
|
+
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-duplicate-fields.md',
|
1727
|
+
recommended: true,
|
1728
|
+
examples: [
|
1729
|
+
{
|
1730
|
+
title: 'Incorrect',
|
1731
|
+
code: /* GraphQL */ `
|
1732
|
+
query {
|
1733
|
+
user {
|
1734
|
+
name
|
1735
|
+
email
|
1736
|
+
name # duplicate field
|
1737
|
+
}
|
1738
|
+
}
|
1739
|
+
`,
|
1740
|
+
},
|
1741
|
+
{
|
1742
|
+
title: 'Incorrect',
|
1743
|
+
code: /* GraphQL */ `
|
1744
|
+
query {
|
1745
|
+
users(
|
1746
|
+
first: 100
|
1747
|
+
skip: 50
|
1748
|
+
after: "cji629tngfgou0b73kt7vi5jo"
|
1749
|
+
first: 100 # duplicate argument
|
1750
|
+
) {
|
1751
|
+
id
|
1752
|
+
}
|
1753
|
+
}
|
1754
|
+
`,
|
1755
|
+
},
|
1756
|
+
{
|
1757
|
+
title: 'Incorrect',
|
1758
|
+
code: /* GraphQL */ `
|
1759
|
+
query (
|
1760
|
+
$first: Int!
|
1761
|
+
$first: Int! # duplicate variable
|
1762
|
+
) {
|
1763
|
+
users(first: $first, skip: 50) {
|
1764
|
+
id
|
1765
|
+
}
|
1766
|
+
}
|
1767
|
+
`,
|
1768
|
+
},
|
1769
|
+
],
|
1770
|
+
},
|
1771
|
+
messages: {
|
1772
|
+
[NO_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times`,
|
1773
|
+
},
|
1774
|
+
schema: [],
|
1775
|
+
},
|
1776
|
+
create(context) {
|
1777
|
+
function checkNode(usedFields, fieldName, type, node) {
|
1778
|
+
if (usedFields.has(fieldName)) {
|
1779
|
+
context.report({
|
1780
|
+
loc: getLocation((node.kind === graphql.Kind.FIELD && node.alias ? node.alias : node).loc, fieldName, {
|
1781
|
+
offsetEnd: node.kind === graphql.Kind.VARIABLE_DEFINITION ? 0 : 1,
|
1782
|
+
}),
|
1783
|
+
messageId: NO_DUPLICATE_FIELDS,
|
1784
|
+
data: {
|
1785
|
+
type,
|
1786
|
+
fieldName,
|
1787
|
+
},
|
1788
|
+
});
|
1789
|
+
}
|
1790
|
+
else {
|
1791
|
+
usedFields.add(fieldName);
|
1792
|
+
}
|
1793
|
+
}
|
1896
1794
|
return {
|
1897
|
-
|
1898
|
-
|
1899
|
-
const
|
1900
|
-
|
1901
|
-
if (typeInfo.enumValue.deprecationReason) {
|
1902
|
-
const enumValueName = node.value;
|
1903
|
-
context.report({
|
1904
|
-
loc: getLocation(node.loc, enumValueName),
|
1905
|
-
messageId: NO_DEPRECATED,
|
1906
|
-
data: {
|
1907
|
-
type: 'enum value',
|
1908
|
-
reason: typeInfo.enumValue.deprecationReason ? `(reason: ${typeInfo.enumValue.deprecationReason})` : '',
|
1909
|
-
},
|
1910
|
-
});
|
1911
|
-
}
|
1795
|
+
OperationDefinition(node) {
|
1796
|
+
const set = new Set();
|
1797
|
+
for (const varDef of node.variableDefinitions) {
|
1798
|
+
checkNode(set, varDef.variable.name.value, 'Operation variable', varDef);
|
1912
1799
|
}
|
1913
1800
|
},
|
1914
1801
|
Field(node) {
|
1915
|
-
|
1916
|
-
const
|
1917
|
-
|
1918
|
-
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
},
|
1927
|
-
});
|
1802
|
+
const set = new Set();
|
1803
|
+
for (const arg of node.arguments) {
|
1804
|
+
checkNode(set, arg.name.value, 'Field argument', arg);
|
1805
|
+
}
|
1806
|
+
},
|
1807
|
+
SelectionSet(node) {
|
1808
|
+
var _a;
|
1809
|
+
const set = new Set();
|
1810
|
+
for (const selection of node.selections) {
|
1811
|
+
if (selection.kind === graphql.Kind.FIELD) {
|
1812
|
+
checkNode(set, ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value, 'Field', selection);
|
1928
1813
|
}
|
1929
1814
|
}
|
1930
1815
|
},
|
@@ -1933,14 +1818,14 @@ const rule$b = {
|
|
1933
1818
|
};
|
1934
1819
|
|
1935
1820
|
const HASHTAG_COMMENT = 'HASHTAG_COMMENT';
|
1936
|
-
const rule$
|
1821
|
+
const rule$9 = {
|
1937
1822
|
meta: {
|
1938
1823
|
messages: {
|
1939
1824
|
[HASHTAG_COMMENT]: 'Using hashtag (#) for adding GraphQL descriptions is not allowed. Prefer using """ for multiline, or " for a single line description.',
|
1940
1825
|
},
|
1941
1826
|
docs: {
|
1942
1827
|
description: 'Requires to use `"""` or `"` for adding a GraphQL description instead of `#`.\nAllows to use hashtag for comments, as long as it\'s not attached to an AST definition.',
|
1943
|
-
category: '
|
1828
|
+
category: 'Schema',
|
1944
1829
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-hashtag-description.md',
|
1945
1830
|
examples: [
|
1946
1831
|
{
|
@@ -1977,6 +1862,7 @@ const rule$c = {
|
|
1977
1862
|
`,
|
1978
1863
|
},
|
1979
1864
|
],
|
1865
|
+
recommended: true,
|
1980
1866
|
},
|
1981
1867
|
type: 'suggestion',
|
1982
1868
|
schema: [],
|
@@ -2005,85 +1891,18 @@ const rule$c = {
|
|
2005
1891
|
},
|
2006
1892
|
};
|
2007
1893
|
|
2008
|
-
const
|
2009
|
-
const rule$
|
2010
|
-
meta: {
|
2011
|
-
fixable: 'code',
|
2012
|
-
type: 'suggestion',
|
2013
|
-
docs: {
|
2014
|
-
category: 'Stylistic Issues',
|
2015
|
-
recommended: true,
|
2016
|
-
description: `Makes sure you are not adding the operation type to the name of the operation.`,
|
2017
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-operation-name-suffix.md`,
|
2018
|
-
examples: [
|
2019
|
-
{
|
2020
|
-
title: 'Incorrect',
|
2021
|
-
code: /* GraphQL */ `
|
2022
|
-
query userQuery {
|
2023
|
-
# ...
|
2024
|
-
}
|
2025
|
-
`,
|
2026
|
-
},
|
2027
|
-
{
|
2028
|
-
title: 'Correct',
|
2029
|
-
code: /* GraphQL */ `
|
2030
|
-
query user {
|
2031
|
-
# ...
|
2032
|
-
}
|
2033
|
-
`,
|
2034
|
-
},
|
2035
|
-
],
|
2036
|
-
},
|
2037
|
-
messages: {
|
2038
|
-
[NO_OPERATION_NAME_SUFFIX]: `Unnecessary "{{ invalidSuffix }}" suffix in your operation name!`,
|
2039
|
-
},
|
2040
|
-
schema: [],
|
2041
|
-
},
|
2042
|
-
create(context) {
|
2043
|
-
return {
|
2044
|
-
'OperationDefinition, FragmentDefinition'(node) {
|
2045
|
-
var _a;
|
2046
|
-
const name = ((_a = node.name) === null || _a === void 0 ? void 0 : _a.value) || '';
|
2047
|
-
if (name.length > 0) {
|
2048
|
-
const invalidSuffix = 'operation' in node ? node.operation : 'fragment';
|
2049
|
-
if (name.toLowerCase().endsWith(invalidSuffix)) {
|
2050
|
-
const { start, end } = node.name.loc;
|
2051
|
-
context.report({
|
2052
|
-
loc: {
|
2053
|
-
start: {
|
2054
|
-
column: start.column - 1 + name.length - invalidSuffix.length,
|
2055
|
-
line: start.line,
|
2056
|
-
},
|
2057
|
-
end: {
|
2058
|
-
column: end.column - 1 + name.length,
|
2059
|
-
line: end.line,
|
2060
|
-
},
|
2061
|
-
},
|
2062
|
-
data: {
|
2063
|
-
invalidSuffix,
|
2064
|
-
},
|
2065
|
-
fix: fixer => fixer.removeRange([node.name.range[1] - invalidSuffix.length, node.name.range[1]]),
|
2066
|
-
messageId: NO_OPERATION_NAME_SUFFIX,
|
2067
|
-
});
|
2068
|
-
}
|
2069
|
-
}
|
2070
|
-
},
|
2071
|
-
};
|
2072
|
-
},
|
2073
|
-
};
|
2074
|
-
|
2075
|
-
const ROOT_TYPES = ['query', 'mutation', 'subscription'];
|
2076
|
-
const rule$e = {
|
1894
|
+
const ROOT_TYPES = ['mutation', 'subscription'];
|
1895
|
+
const rule$a = {
|
2077
1896
|
meta: {
|
2078
1897
|
type: 'suggestion',
|
2079
1898
|
docs: {
|
2080
|
-
category: '
|
2081
|
-
description: 'Disallow using root types
|
1899
|
+
category: 'Schema',
|
1900
|
+
description: 'Disallow using root types `mutation` and/or `subscription`.',
|
2082
1901
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-root-type.md',
|
2083
1902
|
requiresSchema: true,
|
2084
1903
|
examples: [
|
2085
1904
|
{
|
2086
|
-
title: 'Incorrect
|
1905
|
+
title: 'Incorrect',
|
2087
1906
|
usage: [{ disallow: ['mutation', 'subscription'] }],
|
2088
1907
|
code: /* GraphQL */ `
|
2089
1908
|
type Mutation {
|
@@ -2092,16 +1911,7 @@ const rule$e = {
|
|
2092
1911
|
`,
|
2093
1912
|
},
|
2094
1913
|
{
|
2095
|
-
title: '
|
2096
|
-
usage: [{ disallow: ['query'] }],
|
2097
|
-
code: /* GraphQL */ `
|
2098
|
-
type Query {
|
2099
|
-
users: [User!]!
|
2100
|
-
}
|
2101
|
-
`,
|
2102
|
-
},
|
2103
|
-
{
|
2104
|
-
title: 'Correct (`read-only` schema)',
|
1914
|
+
title: 'Correct',
|
2105
1915
|
usage: [{ disallow: ['mutation', 'subscription'] }],
|
2106
1916
|
code: /* GraphQL */ `
|
2107
1917
|
type Query {
|
@@ -2110,7 +1920,6 @@ const rule$e = {
|
|
2110
1920
|
`,
|
2111
1921
|
},
|
2112
1922
|
],
|
2113
|
-
optionsForConfig: [{ disallow: ['subscription'] }],
|
2114
1923
|
},
|
2115
1924
|
schema: {
|
2116
1925
|
type: 'array',
|
@@ -2137,7 +1946,6 @@ const rule$e = {
|
|
2137
1946
|
const schema = requireGraphQLSchemaFromContext('no-root-type', context);
|
2138
1947
|
const disallow = new Set(context.options[0].disallow);
|
2139
1948
|
const rootTypeNames = [
|
2140
|
-
disallow.has('query') && schema.getQueryType(),
|
2141
1949
|
disallow.has('mutation') && schema.getMutationType(),
|
2142
1950
|
disallow.has('subscription') && schema.getSubscriptionType(),
|
2143
1951
|
]
|
@@ -2163,16 +1971,128 @@ const rule$e = {
|
|
2163
1971
|
},
|
2164
1972
|
};
|
2165
1973
|
|
1974
|
+
const rule$b = {
|
1975
|
+
meta: {
|
1976
|
+
type: 'suggestion',
|
1977
|
+
docs: {
|
1978
|
+
category: 'Schema',
|
1979
|
+
description: 'Avoid scalar result type on mutation type to make sure to return a valid state.',
|
1980
|
+
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-scalar-result-type-on-mutation.md',
|
1981
|
+
requiresSchema: true,
|
1982
|
+
examples: [
|
1983
|
+
{
|
1984
|
+
title: 'Incorrect',
|
1985
|
+
code: /* GraphQL */ `
|
1986
|
+
type Mutation {
|
1987
|
+
createUser: Boolean
|
1988
|
+
}
|
1989
|
+
`,
|
1990
|
+
},
|
1991
|
+
{
|
1992
|
+
title: 'Correct',
|
1993
|
+
code: /* GraphQL */ `
|
1994
|
+
type Mutation {
|
1995
|
+
createUser: User!
|
1996
|
+
}
|
1997
|
+
`,
|
1998
|
+
},
|
1999
|
+
],
|
2000
|
+
},
|
2001
|
+
schema: [],
|
2002
|
+
},
|
2003
|
+
create(context) {
|
2004
|
+
const schema = requireGraphQLSchemaFromContext('no-scalar-result-type-on-mutation', context);
|
2005
|
+
const mutationType = schema.getMutationType();
|
2006
|
+
if (!mutationType) {
|
2007
|
+
return {};
|
2008
|
+
}
|
2009
|
+
const selector = [
|
2010
|
+
`:matches(${graphql.Kind.OBJECT_TYPE_DEFINITION}, ${graphql.Kind.OBJECT_TYPE_EXTENSION})[name.value=${mutationType.name}]`,
|
2011
|
+
'>',
|
2012
|
+
graphql.Kind.FIELD_DEFINITION,
|
2013
|
+
graphql.Kind.NAMED_TYPE,
|
2014
|
+
].join(' ');
|
2015
|
+
return {
|
2016
|
+
[selector](node) {
|
2017
|
+
const typeName = node.name.value;
|
2018
|
+
const graphQLType = schema.getType(typeName);
|
2019
|
+
if (graphql.isScalarType(graphQLType)) {
|
2020
|
+
context.report({
|
2021
|
+
loc: getLocation(node.loc, typeName),
|
2022
|
+
message: `Unexpected scalar result type "${typeName}"`,
|
2023
|
+
});
|
2024
|
+
}
|
2025
|
+
},
|
2026
|
+
};
|
2027
|
+
},
|
2028
|
+
};
|
2029
|
+
|
2030
|
+
const NO_TYPENAME_PREFIX = 'NO_TYPENAME_PREFIX';
|
2031
|
+
const rule$c = {
|
2032
|
+
meta: {
|
2033
|
+
type: 'suggestion',
|
2034
|
+
docs: {
|
2035
|
+
category: 'Schema',
|
2036
|
+
description: 'Enforces users to avoid using the type name in a field name while defining your schema.',
|
2037
|
+
recommended: true,
|
2038
|
+
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-typename-prefix.md',
|
2039
|
+
examples: [
|
2040
|
+
{
|
2041
|
+
title: 'Incorrect',
|
2042
|
+
code: /* GraphQL */ `
|
2043
|
+
type User {
|
2044
|
+
userId: ID!
|
2045
|
+
}
|
2046
|
+
`,
|
2047
|
+
},
|
2048
|
+
{
|
2049
|
+
title: 'Correct',
|
2050
|
+
code: /* GraphQL */ `
|
2051
|
+
type User {
|
2052
|
+
id: ID!
|
2053
|
+
}
|
2054
|
+
`,
|
2055
|
+
},
|
2056
|
+
],
|
2057
|
+
},
|
2058
|
+
messages: {
|
2059
|
+
[NO_TYPENAME_PREFIX]: `Field "{{ fieldName }}" starts with the name of the parent type "{{ typeName }}"`,
|
2060
|
+
},
|
2061
|
+
schema: [],
|
2062
|
+
},
|
2063
|
+
create(context) {
|
2064
|
+
return {
|
2065
|
+
'ObjectTypeDefinition, ObjectTypeExtension, InterfaceTypeDefinition, InterfaceTypeExtension'(node) {
|
2066
|
+
const typeName = node.name.value;
|
2067
|
+
const lowerTypeName = typeName.toLowerCase();
|
2068
|
+
for (const field of node.fields) {
|
2069
|
+
const fieldName = field.name.value;
|
2070
|
+
if (fieldName.toLowerCase().startsWith(lowerTypeName)) {
|
2071
|
+
context.report({
|
2072
|
+
data: {
|
2073
|
+
fieldName,
|
2074
|
+
typeName,
|
2075
|
+
},
|
2076
|
+
messageId: NO_TYPENAME_PREFIX,
|
2077
|
+
loc: getLocation(field.loc, lowerTypeName),
|
2078
|
+
});
|
2079
|
+
}
|
2080
|
+
}
|
2081
|
+
},
|
2082
|
+
};
|
2083
|
+
},
|
2084
|
+
};
|
2085
|
+
|
2166
2086
|
const UNREACHABLE_TYPE = 'UNREACHABLE_TYPE';
|
2167
2087
|
const RULE_NAME = 'no-unreachable-types';
|
2168
|
-
const rule$
|
2088
|
+
const rule$d = {
|
2169
2089
|
meta: {
|
2170
2090
|
messages: {
|
2171
|
-
[UNREACHABLE_TYPE]:
|
2091
|
+
[UNREACHABLE_TYPE]: 'Type "{{ typeName }}" is unreachable',
|
2172
2092
|
},
|
2173
2093
|
docs: {
|
2174
2094
|
description: `Requires all types to be reachable at some level by root level fields.`,
|
2175
|
-
category: '
|
2095
|
+
category: 'Schema',
|
2176
2096
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME}.md`,
|
2177
2097
|
requiresSchema: true,
|
2178
2098
|
examples: [
|
@@ -2203,6 +2123,7 @@ const rule$f = {
|
|
2203
2123
|
`,
|
2204
2124
|
},
|
2205
2125
|
],
|
2126
|
+
recommended: true,
|
2206
2127
|
},
|
2207
2128
|
fixable: 'code',
|
2208
2129
|
type: 'suggestion',
|
@@ -2241,14 +2162,14 @@ const rule$f = {
|
|
2241
2162
|
|
2242
2163
|
const UNUSED_FIELD = 'UNUSED_FIELD';
|
2243
2164
|
const RULE_NAME$1 = 'no-unused-fields';
|
2244
|
-
const rule$
|
2165
|
+
const rule$e = {
|
2245
2166
|
meta: {
|
2246
2167
|
messages: {
|
2247
2168
|
[UNUSED_FIELD]: `Field "{{fieldName}}" is unused`,
|
2248
2169
|
},
|
2249
2170
|
docs: {
|
2250
2171
|
description: `Requires all fields to be used at some level by siblings operations.`,
|
2251
|
-
category: '
|
2172
|
+
category: 'Schema',
|
2252
2173
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$1}.md`,
|
2253
2174
|
requiresSiblings: true,
|
2254
2175
|
requiresSchema: true,
|
@@ -2430,11 +2351,11 @@ const MESSAGE_REQUIRE_DATE = 'MESSAGE_REQUIRE_DATE';
|
|
2430
2351
|
const MESSAGE_INVALID_FORMAT = 'MESSAGE_INVALID_FORMAT';
|
2431
2352
|
const MESSAGE_INVALID_DATE = 'MESSAGE_INVALID_DATE';
|
2432
2353
|
const MESSAGE_CAN_BE_REMOVED = 'MESSAGE_CAN_BE_REMOVED';
|
2433
|
-
const rule$
|
2354
|
+
const rule$f = {
|
2434
2355
|
meta: {
|
2435
2356
|
type: 'suggestion',
|
2436
2357
|
docs: {
|
2437
|
-
category: '
|
2358
|
+
category: 'Schema',
|
2438
2359
|
description: 'Require deletion date on `@deprecated` directive. Suggest removing deprecated things after deprecated date.',
|
2439
2360
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-deprecation-date.md',
|
2440
2361
|
examples: [
|
@@ -2533,11 +2454,11 @@ const rule$h = {
|
|
2533
2454
|
},
|
2534
2455
|
};
|
2535
2456
|
|
2536
|
-
const rule$
|
2457
|
+
const rule$g = {
|
2537
2458
|
meta: {
|
2538
2459
|
docs: {
|
2539
2460
|
description: `Require all deprecation directives to specify a reason.`,
|
2540
|
-
category: '
|
2461
|
+
category: 'Schema',
|
2541
2462
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-deprecation-reason.md`,
|
2542
2463
|
recommended: true,
|
2543
2464
|
examples: [
|
@@ -2595,16 +2516,16 @@ const ALLOWED_KINDS$1 = [
|
|
2595
2516
|
graphql.Kind.ENUM_VALUE_DEFINITION,
|
2596
2517
|
graphql.Kind.DIRECTIVE_DEFINITION,
|
2597
2518
|
];
|
2598
|
-
const rule$
|
2519
|
+
const rule$h = {
|
2599
2520
|
meta: {
|
2600
2521
|
docs: {
|
2601
|
-
category: '
|
2522
|
+
category: 'Schema',
|
2602
2523
|
description: 'Enforce descriptions in your type definitions.',
|
2603
2524
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-description.md',
|
2604
2525
|
examples: [
|
2605
2526
|
{
|
2606
2527
|
title: 'Incorrect',
|
2607
|
-
usage: [{ types: true,
|
2528
|
+
usage: [{ types: true, FieldDefinition: true }],
|
2608
2529
|
code: /* GraphQL */ `
|
2609
2530
|
type someTypeName {
|
2610
2531
|
name: String
|
@@ -2613,7 +2534,7 @@ const rule$j = {
|
|
2613
2534
|
},
|
2614
2535
|
{
|
2615
2536
|
title: 'Correct',
|
2616
|
-
usage: [{ types: true,
|
2537
|
+
usage: [{ types: true, FieldDefinition: true }],
|
2617
2538
|
code: /* GraphQL */ `
|
2618
2539
|
"""
|
2619
2540
|
Some type description
|
@@ -2627,12 +2548,10 @@ const rule$j = {
|
|
2627
2548
|
`,
|
2628
2549
|
},
|
2629
2550
|
],
|
2630
|
-
|
2551
|
+
configOptions: [
|
2631
2552
|
{
|
2632
2553
|
types: true,
|
2633
|
-
|
2634
|
-
[graphql.Kind.DIRECTIVE_DEFINITION]: true,
|
2635
|
-
},
|
2554
|
+
[graphql.Kind.DIRECTIVE_DEFINITION]: true,
|
2636
2555
|
},
|
2637
2556
|
],
|
2638
2557
|
},
|
@@ -2651,22 +2570,23 @@ const rule$j = {
|
|
2651
2570
|
properties: {
|
2652
2571
|
types: {
|
2653
2572
|
type: 'boolean',
|
2654
|
-
description: `Includes:\n\n${TYPES_KINDS.map(kind => `-
|
2655
|
-
},
|
2656
|
-
overrides: {
|
2657
|
-
type: 'object',
|
2658
|
-
description: 'Configuration for precise `ASTNode`',
|
2659
|
-
additionalProperties: false,
|
2660
|
-
properties: Object.fromEntries(ALLOWED_KINDS$1.map(kind => [kind, { type: 'boolean' }])),
|
2573
|
+
description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
2661
2574
|
},
|
2575
|
+
...Object.fromEntries([...ALLOWED_KINDS$1].sort().map(kind => [
|
2576
|
+
kind,
|
2577
|
+
{
|
2578
|
+
type: 'boolean',
|
2579
|
+
description: `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`,
|
2580
|
+
},
|
2581
|
+
])),
|
2662
2582
|
},
|
2663
2583
|
},
|
2664
2584
|
},
|
2665
2585
|
},
|
2666
2586
|
create(context) {
|
2667
|
-
const { types,
|
2587
|
+
const { types, ...restOptions } = context.options[0];
|
2668
2588
|
const kinds = new Set(types ? TYPES_KINDS : []);
|
2669
|
-
for (const [kind, isEnabled] of Object.entries(
|
2589
|
+
for (const [kind, isEnabled] of Object.entries(restOptions)) {
|
2670
2590
|
if (isEnabled) {
|
2671
2591
|
kinds.add(kind);
|
2672
2592
|
}
|
@@ -2694,11 +2614,11 @@ const rule$j = {
|
|
2694
2614
|
};
|
2695
2615
|
|
2696
2616
|
const RULE_NAME$2 = 'require-field-of-type-query-in-mutation-result';
|
2697
|
-
const rule$
|
2617
|
+
const rule$i = {
|
2698
2618
|
meta: {
|
2699
2619
|
type: 'suggestion',
|
2700
2620
|
docs: {
|
2701
|
-
category: '
|
2621
|
+
category: 'Schema',
|
2702
2622
|
description: 'Allow the client in one round-trip not only to call mutation but also to get a wagon of data to update their application.\n> Currently, no errors are reported for result type `union`, `interface` and `scalar`.',
|
2703
2623
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$2}.md`,
|
2704
2624
|
requiresSchema: true,
|
@@ -2862,13 +2782,13 @@ const convertNode = (typeInfo) => (node, key, parent) => {
|
|
2862
2782
|
|
2863
2783
|
const REQUIRE_ID_WHEN_AVAILABLE = 'REQUIRE_ID_WHEN_AVAILABLE';
|
2864
2784
|
const DEFAULT_ID_FIELD_NAME = 'id';
|
2865
|
-
const rule$
|
2785
|
+
const rule$j = {
|
2866
2786
|
meta: {
|
2867
2787
|
type: 'suggestion',
|
2868
2788
|
docs: {
|
2869
|
-
category: '
|
2870
|
-
description:
|
2871
|
-
url:
|
2789
|
+
category: 'Operations',
|
2790
|
+
description: 'Enforce selecting specific fields when they are available on the GraphQL type.',
|
2791
|
+
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-id-when-available.md',
|
2872
2792
|
requiresSchema: true,
|
2873
2793
|
requiresSiblings: true,
|
2874
2794
|
examples: [
|
@@ -2908,17 +2828,17 @@ const rule$l = {
|
|
2908
2828
|
`,
|
2909
2829
|
},
|
2910
2830
|
],
|
2831
|
+
recommended: true,
|
2911
2832
|
},
|
2912
2833
|
messages: {
|
2913
|
-
[REQUIRE_ID_WHEN_AVAILABLE]: `Field "{{ fieldName }}" must be selected when it's available on a type. Please make sure to include it in your selection set!\nIf you are using fragments, make sure that all used fragments {{checkedFragments}} specifies the field "{{ fieldName }}".`,
|
2834
|
+
[REQUIRE_ID_WHEN_AVAILABLE]: `Field "{{ fieldName }}" must be selected when it's available on a type. Please make sure to include it in your selection set!\nIf you are using fragments, make sure that all used fragments {{ checkedFragments }} specifies the field "{{ fieldName }}".`,
|
2914
2835
|
},
|
2915
2836
|
schema: {
|
2916
2837
|
type: 'array',
|
2917
|
-
additionalItems: false,
|
2918
|
-
minItems: 0,
|
2919
2838
|
maxItems: 1,
|
2920
2839
|
items: {
|
2921
2840
|
type: 'object',
|
2841
|
+
additionalProperties: false,
|
2922
2842
|
properties: {
|
2923
2843
|
fieldName: {
|
2924
2844
|
type: 'string',
|
@@ -2998,12 +2918,12 @@ const rule$l = {
|
|
2998
2918
|
},
|
2999
2919
|
};
|
3000
2920
|
|
3001
|
-
const rule$
|
2921
|
+
const rule$k = {
|
3002
2922
|
meta: {
|
3003
2923
|
docs: {
|
3004
|
-
category: '
|
2924
|
+
category: 'Operations',
|
3005
2925
|
description: `Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://github.com/stems/graphql-depth-limit).`,
|
3006
|
-
url:
|
2926
|
+
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/selection-set-depth.md',
|
3007
2927
|
requiresSiblings: true,
|
3008
2928
|
examples: [
|
3009
2929
|
{
|
@@ -3046,22 +2966,26 @@ const rule$m = {
|
|
3046
2966
|
`,
|
3047
2967
|
},
|
3048
2968
|
],
|
2969
|
+
recommended: true,
|
2970
|
+
configOptions: [{ maxDepth: 7 }],
|
3049
2971
|
},
|
3050
2972
|
type: 'suggestion',
|
3051
2973
|
schema: {
|
3052
2974
|
type: 'array',
|
3053
|
-
additionalItems: false,
|
3054
2975
|
minItems: 1,
|
3055
2976
|
maxItems: 1,
|
3056
2977
|
items: {
|
3057
2978
|
type: 'object',
|
3058
|
-
|
2979
|
+
additionalProperties: false,
|
2980
|
+
required: ['maxDepth'],
|
3059
2981
|
properties: {
|
3060
2982
|
maxDepth: {
|
3061
2983
|
type: 'number',
|
3062
2984
|
},
|
3063
2985
|
ignore: {
|
3064
2986
|
type: 'array',
|
2987
|
+
uniqueItems: true,
|
2988
|
+
minItems: 1,
|
3065
2989
|
items: {
|
3066
2990
|
type: 'string',
|
3067
2991
|
},
|
@@ -3120,12 +3044,12 @@ const shouldIgnoreNode = ({ node, exceptions }) => {
|
|
3120
3044
|
}
|
3121
3045
|
return false;
|
3122
3046
|
};
|
3123
|
-
const rule$
|
3047
|
+
const rule$l = {
|
3124
3048
|
meta: {
|
3125
3049
|
type: 'suggestion',
|
3126
3050
|
docs: {
|
3127
3051
|
description: 'Requires output types to have one unique identifier unless they do not have a logical one. Exceptions can be used to ignore output types that do not have unique identifiers.',
|
3128
|
-
category: '
|
3052
|
+
category: 'Schema',
|
3129
3053
|
recommended: true,
|
3130
3054
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/strict-id-in-types.md',
|
3131
3055
|
examples: [
|
@@ -3185,13 +3109,15 @@ const rule$n = {
|
|
3185
3109
|
],
|
3186
3110
|
},
|
3187
3111
|
schema: {
|
3188
|
-
$schema: 'http://json-schema.org/draft-04/schema#',
|
3189
3112
|
type: 'array',
|
3113
|
+
maxItems: 1,
|
3190
3114
|
items: {
|
3191
3115
|
type: 'object',
|
3116
|
+
additionalProperties: false,
|
3192
3117
|
properties: {
|
3193
3118
|
acceptedIdNames: {
|
3194
3119
|
type: 'array',
|
3120
|
+
uniqueItems: true,
|
3195
3121
|
items: {
|
3196
3122
|
type: 'string',
|
3197
3123
|
},
|
@@ -3199,6 +3125,7 @@ const rule$n = {
|
|
3199
3125
|
},
|
3200
3126
|
acceptedIdTypes: {
|
3201
3127
|
type: 'array',
|
3128
|
+
uniqueItems: true,
|
3202
3129
|
items: {
|
3203
3130
|
type: 'string',
|
3204
3131
|
},
|
@@ -3209,19 +3136,21 @@ const rule$n = {
|
|
3209
3136
|
properties: {
|
3210
3137
|
types: {
|
3211
3138
|
type: 'array',
|
3139
|
+
uniqueItems: true,
|
3140
|
+
minItems: 1,
|
3212
3141
|
description: 'This is used to exclude types with names that match one of the specified values.',
|
3213
3142
|
items: {
|
3214
3143
|
type: 'string',
|
3215
3144
|
},
|
3216
|
-
default: [],
|
3217
3145
|
},
|
3218
3146
|
suffixes: {
|
3219
3147
|
type: 'array',
|
3148
|
+
uniqueItems: true,
|
3149
|
+
minItems: 1,
|
3220
3150
|
description: 'This is used to exclude types with names with suffixes that match one of the specified values.',
|
3221
3151
|
items: {
|
3222
3152
|
type: 'string',
|
3223
3153
|
},
|
3224
|
-
default: [],
|
3225
3154
|
},
|
3226
3155
|
},
|
3227
3156
|
},
|
@@ -3297,11 +3226,11 @@ const checkNode = (context, node, ruleName, messageId) => {
|
|
3297
3226
|
});
|
3298
3227
|
}
|
3299
3228
|
};
|
3300
|
-
const rule$
|
3229
|
+
const rule$m = {
|
3301
3230
|
meta: {
|
3302
3231
|
type: 'suggestion',
|
3303
3232
|
docs: {
|
3304
|
-
category: '
|
3233
|
+
category: 'Operations',
|
3305
3234
|
description: `Enforce unique fragment names across your project.`,
|
3306
3235
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$3}.md`,
|
3307
3236
|
requiresSiblings: true,
|
@@ -3356,11 +3285,11 @@ const rule$o = {
|
|
3356
3285
|
|
3357
3286
|
const RULE_NAME$4 = 'unique-operation-name';
|
3358
3287
|
const UNIQUE_OPERATION_NAME = 'UNIQUE_OPERATION_NAME';
|
3359
|
-
const rule$
|
3288
|
+
const rule$n = {
|
3360
3289
|
meta: {
|
3361
3290
|
type: 'suggestion',
|
3362
3291
|
docs: {
|
3363
|
-
category: '
|
3292
|
+
category: 'Operations',
|
3364
3293
|
description: `Enforce unique operation names across your project.`,
|
3365
3294
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$4}.md`,
|
3366
3295
|
requiresSiblings: true,
|
@@ -3423,31 +3352,29 @@ const rule$p = {
|
|
3423
3352
|
const rules = {
|
3424
3353
|
...GRAPHQL_JS_VALIDATIONS,
|
3425
3354
|
alphabetize: rule,
|
3426
|
-
'
|
3427
|
-
'
|
3428
|
-
'
|
3429
|
-
'
|
3430
|
-
'
|
3431
|
-
'
|
3432
|
-
'
|
3433
|
-
'
|
3434
|
-
'no-
|
3435
|
-
'no-
|
3436
|
-
'no-
|
3437
|
-
'no-
|
3438
|
-
'no-
|
3439
|
-
'no-
|
3440
|
-
'
|
3441
|
-
'
|
3442
|
-
'require-
|
3443
|
-
'require-
|
3444
|
-
'require-
|
3445
|
-
'
|
3446
|
-
'
|
3447
|
-
'
|
3448
|
-
'
|
3449
|
-
'unique-fragment-name': rule$o,
|
3450
|
-
'unique-operation-name': rule$p,
|
3355
|
+
'description-style': rule$1,
|
3356
|
+
'input-name': rule$2,
|
3357
|
+
'match-document-filename': rule$3,
|
3358
|
+
'naming-convention': rule$4,
|
3359
|
+
'no-anonymous-operations': rule$5,
|
3360
|
+
'no-case-insensitive-enum-values-duplicates': rule$6,
|
3361
|
+
'no-deprecated': rule$7,
|
3362
|
+
'no-duplicate-fields': rule$8,
|
3363
|
+
'no-hashtag-description': rule$9,
|
3364
|
+
'no-root-type': rule$a,
|
3365
|
+
'no-scalar-result-type-on-mutation': rule$b,
|
3366
|
+
'no-typename-prefix': rule$c,
|
3367
|
+
'no-unreachable-types': rule$d,
|
3368
|
+
'no-unused-fields': rule$e,
|
3369
|
+
'require-deprecation-date': rule$f,
|
3370
|
+
'require-deprecation-reason': rule$g,
|
3371
|
+
'require-description': rule$h,
|
3372
|
+
'require-field-of-type-query-in-mutation-result': rule$i,
|
3373
|
+
'require-id-when-available': rule$j,
|
3374
|
+
'selection-set-depth': rule$k,
|
3375
|
+
'strict-id-in-types': rule$l,
|
3376
|
+
'unique-fragment-name': rule$m,
|
3377
|
+
'unique-operation-name': rule$n,
|
3451
3378
|
};
|
3452
3379
|
|
3453
3380
|
const RELEVANT_KEYWORDS = ['gql', 'graphql', '/* GraphQL */'];
|