@graphql-eslint/eslint-plugin 3.0.0-alpha-7462f3d.0 → 3.0.0-alpha-636cc2a.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 +76 -117
- package/configs/operations-all.d.ts +19 -0
- package/configs/operations-recommended.d.ts +50 -0
- package/configs/schema-all.d.ts +17 -0
- package/configs/schema-recommended.d.ts +46 -0
- package/docs/README.md +9 -15
- 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 +180 -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/no-duplicate-fields.md +3 -1
- 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 +4 -15
- package/docs/rules/no-scalar-result-type-on-mutation.md +1 -1
- package/docs/rules/no-typename-prefix.md +2 -2
- 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 +38 -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 +329 -208
- package/index.mjs +329 -208
- 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 +112 -114
- 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/no-root-type.d.ts +1 -1
- 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 -102
- package/configs/recommended.d.ts +0 -71
package/index.js
CHANGED
@@ -18,12 +18,88 @@ 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/require-description': ['error', { types: true, DirectiveDefinition: true }],
|
65
|
+
'@graphql-eslint/strict-id-in-types': 'error',
|
66
|
+
'@graphql-eslint/unique-directive-names': 'error',
|
67
|
+
'@graphql-eslint/unique-directive-names-per-location': 'error',
|
68
|
+
'@graphql-eslint/unique-enum-value-names': 'error',
|
69
|
+
'@graphql-eslint/unique-field-definition-names': 'error',
|
70
|
+
'@graphql-eslint/unique-operation-types': 'error',
|
71
|
+
'@graphql-eslint/unique-type-names': 'error',
|
72
|
+
},
|
73
|
+
};
|
74
|
+
|
75
|
+
/*
|
76
|
+
* 🚨 IMPORTANT! Do not manually modify this file. Run: `yarn generate-configs`
|
77
|
+
*/
|
78
|
+
const schemaAllConfig = {
|
79
|
+
extends: ['plugin:@graphql-eslint/base', 'plugin:@graphql-eslint/schema-recommended'],
|
80
|
+
rules: {
|
81
|
+
'@graphql-eslint/alphabetize': [
|
82
|
+
'error',
|
83
|
+
{
|
84
|
+
fields: ['ObjectTypeDefinition', 'InterfaceTypeDefinition', 'InputObjectTypeDefinition'],
|
85
|
+
values: ['EnumTypeDefinition'],
|
86
|
+
arguments: ['FieldDefinition', 'Field', 'DirectiveDefinition', 'Directive'],
|
87
|
+
},
|
88
|
+
],
|
89
|
+
'@graphql-eslint/input-name': 'error',
|
90
|
+
'@graphql-eslint/no-root-type': 'off',
|
91
|
+
'@graphql-eslint/no-scalar-result-type-on-mutation': 'error',
|
92
|
+
'@graphql-eslint/no-unused-fields': 'off',
|
93
|
+
'@graphql-eslint/require-deprecation-date': 'error',
|
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
104
|
'@graphql-eslint/executable-definitions': 'error',
|
29
105
|
'@graphql-eslint/fields-on-correct-type': 'error',
|
@@ -33,58 +109,35 @@ const recommendedConfig = {
|
|
33
109
|
'@graphql-eslint/known-fragment-names': 'error',
|
34
110
|
'@graphql-eslint/known-type-names': 'error',
|
35
111
|
'@graphql-eslint/lone-anonymous-operation': 'error',
|
36
|
-
'@graphql-eslint/lone-schema-definition': 'error',
|
37
112
|
'@graphql-eslint/naming-convention': [
|
38
113
|
'error',
|
39
114
|
{
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
style: 'PascalCase',
|
46
|
-
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
47
|
-
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
48
|
-
},
|
49
|
-
FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
|
50
|
-
'FieldDefinition[parent.name.value=Query]': {
|
51
|
-
forbiddenPrefixes: ['query', 'get'],
|
52
|
-
forbiddenSuffixes: ['Query'],
|
53
|
-
},
|
54
|
-
'FieldDefinition[parent.name.value=Mutation]': {
|
55
|
-
forbiddenPrefixes: ['mutation'],
|
56
|
-
forbiddenSuffixes: ['Mutation'],
|
57
|
-
},
|
58
|
-
'FieldDefinition[parent.name.value=Subscription]': {
|
59
|
-
forbiddenPrefixes: ['subscription'],
|
60
|
-
forbiddenSuffixes: ['Subscription'],
|
61
|
-
},
|
115
|
+
VariableDefinition: 'camelCase',
|
116
|
+
OperationDefinition: {
|
117
|
+
style: 'PascalCase',
|
118
|
+
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
119
|
+
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
62
120
|
},
|
121
|
+
FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
|
63
122
|
},
|
64
123
|
],
|
65
124
|
'@graphql-eslint/no-anonymous-operations': 'error',
|
66
|
-
'@graphql-eslint/no-
|
125
|
+
'@graphql-eslint/no-deprecated': 'error',
|
126
|
+
'@graphql-eslint/no-duplicate-fields': 'error',
|
67
127
|
'@graphql-eslint/no-fragment-cycles': 'error',
|
68
|
-
'@graphql-eslint/no-typename-prefix': 'error',
|
69
128
|
'@graphql-eslint/no-undefined-variables': 'error',
|
70
129
|
'@graphql-eslint/no-unused-fragments': 'error',
|
71
130
|
'@graphql-eslint/no-unused-variables': 'error',
|
72
131
|
'@graphql-eslint/one-field-subscriptions': 'error',
|
73
132
|
'@graphql-eslint/overlapping-fields-can-be-merged': 'error',
|
74
133
|
'@graphql-eslint/possible-fragment-spread': 'error',
|
75
|
-
'@graphql-eslint/possible-type-extension': 'error',
|
76
134
|
'@graphql-eslint/provided-required-arguments': 'error',
|
77
|
-
'@graphql-eslint/require-
|
135
|
+
'@graphql-eslint/require-id-when-available': 'error',
|
78
136
|
'@graphql-eslint/scalar-leafs': 'error',
|
79
|
-
'@graphql-eslint/
|
137
|
+
'@graphql-eslint/selection-set-depth': ['error', { maxDepth: 7 }],
|
80
138
|
'@graphql-eslint/unique-argument-names': 'error',
|
81
|
-
'@graphql-eslint/unique-directive-names': 'error',
|
82
139
|
'@graphql-eslint/unique-directive-names-per-location': 'error',
|
83
|
-
'@graphql-eslint/unique-enum-value-names': 'error',
|
84
|
-
'@graphql-eslint/unique-field-definition-names': 'error',
|
85
140
|
'@graphql-eslint/unique-input-field-names': 'error',
|
86
|
-
'@graphql-eslint/unique-operation-types': 'error',
|
87
|
-
'@graphql-eslint/unique-type-names': 'error',
|
88
141
|
'@graphql-eslint/unique-variable-names': 'error',
|
89
142
|
'@graphql-eslint/value-literals-of-correct-type': 'error',
|
90
143
|
'@graphql-eslint/variables-are-input-types': 'error',
|
@@ -95,43 +148,32 @@ const recommendedConfig = {
|
|
95
148
|
/*
|
96
149
|
* 🚨 IMPORTANT! Do not manually modify this file. Run: `yarn generate-configs`
|
97
150
|
*/
|
98
|
-
const
|
99
|
-
|
151
|
+
const operationsAllConfig = {
|
152
|
+
extends: ['plugin:@graphql-eslint/base', 'plugin:@graphql-eslint/operations-recommended'],
|
100
153
|
rules: {
|
101
|
-
...recommendedConfig.rules,
|
102
154
|
'@graphql-eslint/alphabetize': [
|
103
155
|
'error',
|
104
156
|
{
|
105
|
-
fields: ['ObjectTypeDefinition', 'InterfaceTypeDefinition', 'InputObjectTypeDefinition'],
|
106
|
-
values: ['EnumTypeDefinition'],
|
107
157
|
selections: ['OperationDefinition', 'FragmentDefinition'],
|
108
158
|
variables: ['OperationDefinition'],
|
109
|
-
arguments: ['
|
159
|
+
arguments: ['Field', 'Directive'],
|
110
160
|
},
|
111
161
|
],
|
112
|
-
'@graphql-eslint/
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
'@graphql-eslint/no-duplicate-fields': 'error',
|
117
|
-
'@graphql-eslint/no-hashtag-description': 'error',
|
118
|
-
'@graphql-eslint/no-root-type': ['error', { disallow: ['subscription'] }],
|
119
|
-
'@graphql-eslint/no-scalar-result-type-on-mutation': 'error',
|
120
|
-
'@graphql-eslint/no-unreachable-types': 'error',
|
121
|
-
'@graphql-eslint/no-unused-fields': 'error',
|
122
|
-
'@graphql-eslint/require-deprecation-date': 'error',
|
123
|
-
'@graphql-eslint/require-description': ['error', { types: true, overrides: { DirectiveDefinition: true } }],
|
124
|
-
'@graphql-eslint/require-field-of-type-query-in-mutation-result': 'error',
|
125
|
-
'@graphql-eslint/require-id-when-available': 'error',
|
126
|
-
'@graphql-eslint/selection-set-depth': 'error',
|
162
|
+
'@graphql-eslint/match-document-filename': [
|
163
|
+
'error',
|
164
|
+
{ query: 'kebab-case', mutation: 'kebab-case', subscription: 'kebab-case', fragment: 'kebab-case' },
|
165
|
+
],
|
127
166
|
'@graphql-eslint/unique-fragment-name': 'error',
|
128
167
|
'@graphql-eslint/unique-operation-name': 'error',
|
129
168
|
},
|
130
169
|
};
|
131
170
|
|
132
171
|
const configs = {
|
133
|
-
|
134
|
-
recommended:
|
172
|
+
base,
|
173
|
+
'schema-recommended': schemaRecommendedConfig,
|
174
|
+
'schema-all': schemaAllConfig,
|
175
|
+
'operations-recommended': operationsRecommendedConfig,
|
176
|
+
'operations-all': operationsAllConfig,
|
135
177
|
};
|
136
178
|
|
137
179
|
function requireSiblingsOperations(ruleName, context) {
|
@@ -344,7 +386,6 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
|
|
344
386
|
docs: {
|
345
387
|
...docs,
|
346
388
|
graphQLJSRuleName: ruleName,
|
347
|
-
category: 'Validation',
|
348
389
|
recommended: true,
|
349
390
|
requiresSchema,
|
350
391
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${name}.md`,
|
@@ -381,16 +422,22 @@ const importFiles = (context) => {
|
|
381
422
|
return _import.processImport(context.getFilename());
|
382
423
|
};
|
383
424
|
const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-definitions', 'ExecutableDefinitions', {
|
425
|
+
category: 'Operations',
|
384
426
|
description: `A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.`,
|
385
427
|
}), validationToRule('fields-on-correct-type', 'FieldsOnCorrectType', {
|
428
|
+
category: 'Operations',
|
386
429
|
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`.',
|
387
430
|
}), validationToRule('fragments-on-composite-type', 'FragmentsOnCompositeTypes', {
|
431
|
+
category: 'Operations',
|
388
432
|
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.`,
|
389
433
|
}), validationToRule('known-argument-names', 'KnownArgumentNames', {
|
434
|
+
category: ['Schema', 'Operations'],
|
390
435
|
description: `A GraphQL field is only valid if all supplied arguments are defined by that field.`,
|
391
436
|
}), validationToRule('known-directives', 'KnownDirectives', {
|
437
|
+
category: ['Schema', 'Operations'],
|
392
438
|
description: `A GraphQL document is only valid if all \`@directives\` are known by the schema and legally positioned.`,
|
393
439
|
}), validationToRule('known-fragment-names', 'KnownFragmentNames', {
|
440
|
+
category: 'Operations',
|
394
441
|
description: `A GraphQL document is only valid if all \`...Fragment\` fragment spreads refer to fragments defined in the same document.`,
|
395
442
|
examples: [
|
396
443
|
{
|
@@ -457,17 +504,23 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
457
504
|
},
|
458
505
|
],
|
459
506
|
}, importFiles), validationToRule('known-type-names', 'KnownTypeNames', {
|
507
|
+
category: ['Schema', 'Operations'],
|
460
508
|
description: `A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.`,
|
461
509
|
}), validationToRule('lone-anonymous-operation', 'LoneAnonymousOperation', {
|
510
|
+
category: 'Operations',
|
462
511
|
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.`,
|
463
512
|
}), validationToRule('lone-schema-definition', 'LoneSchemaDefinition', {
|
513
|
+
category: 'Schema',
|
464
514
|
description: `A GraphQL document is only valid if it contains only one schema definition.`,
|
465
515
|
requiresSchema: false,
|
466
516
|
}), validationToRule('no-fragment-cycles', 'NoFragmentCycles', {
|
517
|
+
category: 'Operations',
|
467
518
|
description: `A GraphQL fragment is only valid when it does not have cycles in fragments usage.`,
|
468
519
|
}), validationToRule('no-undefined-variables', 'NoUndefinedVariables', {
|
520
|
+
category: 'Operations',
|
469
521
|
description: `A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.`,
|
470
522
|
}, importFiles), validationToRule('no-unused-fragments', 'NoUnusedFragments', {
|
523
|
+
category: 'Operations',
|
471
524
|
description: `A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.`,
|
472
525
|
requiresSiblings: true,
|
473
526
|
}, context => {
|
@@ -497,49 +550,68 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
497
550
|
};
|
498
551
|
return getParentNode(context.getFilename());
|
499
552
|
}), validationToRule('no-unused-variables', 'NoUnusedVariables', {
|
553
|
+
category: 'Operations',
|
500
554
|
description: `A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.`,
|
501
555
|
}, importFiles), validationToRule('overlapping-fields-can-be-merged', 'OverlappingFieldsCanBeMerged', {
|
556
|
+
category: 'Operations',
|
502
557
|
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.`,
|
503
558
|
}), validationToRule('possible-fragment-spread', 'PossibleFragmentSpreads', {
|
559
|
+
category: 'Operations',
|
504
560
|
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.`,
|
505
561
|
}), validationToRule('possible-type-extension', 'PossibleTypeExtensions', {
|
562
|
+
category: 'Schema',
|
506
563
|
description: `A type extension is only valid if the type is defined and has the same kind.`,
|
507
564
|
requiresSchema: false,
|
508
565
|
}), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
|
566
|
+
category: ['Schema', 'Operations'],
|
509
567
|
description: `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.`,
|
510
568
|
}), validationToRule('scalar-leafs', 'ScalarLeafs', {
|
569
|
+
category: 'Operations',
|
511
570
|
description: `A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.`,
|
512
571
|
}), validationToRule('one-field-subscriptions', 'SingleFieldSubscriptions', {
|
572
|
+
category: 'Operations',
|
513
573
|
description: `A GraphQL subscription is valid only if it contains a single root field.`,
|
514
574
|
}), validationToRule('unique-argument-names', 'UniqueArgumentNames', {
|
575
|
+
category: 'Operations',
|
515
576
|
description: `A GraphQL field or directive is only valid if all supplied arguments are uniquely named.`,
|
516
577
|
}), validationToRule('unique-directive-names', 'UniqueDirectiveNames', {
|
578
|
+
category: 'Schema',
|
517
579
|
description: `A GraphQL document is only valid if all defined directives have unique names.`,
|
518
580
|
requiresSchema: false,
|
519
581
|
}), validationToRule('unique-directive-names-per-location', 'UniqueDirectivesPerLocation', {
|
582
|
+
category: ['Schema', 'Operations'],
|
520
583
|
description: `A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.`,
|
521
584
|
}), validationToRule('unique-enum-value-names', 'UniqueEnumValueNames', {
|
585
|
+
category: 'Schema',
|
522
586
|
description: `A GraphQL enum type is only valid if all its values are uniquely named.`,
|
523
587
|
requiresSchema: false,
|
524
588
|
}), validationToRule('unique-field-definition-names', 'UniqueFieldDefinitionNames', {
|
589
|
+
category: 'Schema',
|
525
590
|
description: `A GraphQL complex type is only valid if all its fields are uniquely named.`,
|
526
591
|
requiresSchema: false,
|
527
592
|
}), validationToRule('unique-input-field-names', 'UniqueInputFieldNames', {
|
593
|
+
category: 'Operations',
|
528
594
|
description: `A GraphQL input object value is only valid if all supplied fields are uniquely named.`,
|
529
595
|
requiresSchema: false,
|
530
596
|
}), validationToRule('unique-operation-types', 'UniqueOperationTypes', {
|
597
|
+
category: 'Schema',
|
531
598
|
description: `A GraphQL document is only valid if it has only one type per operation.`,
|
532
599
|
requiresSchema: false,
|
533
600
|
}), validationToRule('unique-type-names', 'UniqueTypeNames', {
|
601
|
+
category: 'Schema',
|
534
602
|
description: `A GraphQL document is only valid if all defined types have unique names.`,
|
535
603
|
requiresSchema: false,
|
536
604
|
}), validationToRule('unique-variable-names', 'UniqueVariableNames', {
|
605
|
+
category: 'Operations',
|
537
606
|
description: `A GraphQL operation is only valid if all its variables are uniquely named.`,
|
538
607
|
}), validationToRule('value-literals-of-correct-type', 'ValuesOfCorrectType', {
|
608
|
+
category: 'Operations',
|
539
609
|
description: `A GraphQL document is only valid if all value literals are of the type expected at their position.`,
|
540
610
|
}), validationToRule('variables-are-input-types', 'VariablesAreInputTypes', {
|
611
|
+
category: 'Operations',
|
541
612
|
description: `A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).`,
|
542
613
|
}), validationToRule('variables-in-allowed-position', 'VariablesInAllowedPosition', {
|
614
|
+
category: 'Operations',
|
543
615
|
description: `Variables passed to field arguments conform to type.`,
|
544
616
|
}));
|
545
617
|
|
@@ -565,7 +637,7 @@ const rule = {
|
|
565
637
|
meta: {
|
566
638
|
type: 'suggestion',
|
567
639
|
docs: {
|
568
|
-
category: '
|
640
|
+
category: ['Schema', 'Operations'],
|
569
641
|
description: 'Enforce arrange in alphabetical order for type fields, enum values, input object fields, operation selections and more.',
|
570
642
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/alphabetize.md',
|
571
643
|
examples: [
|
@@ -644,15 +716,22 @@ const rule = {
|
|
644
716
|
`,
|
645
717
|
},
|
646
718
|
],
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
719
|
+
configOptions: {
|
720
|
+
schema: [
|
721
|
+
{
|
722
|
+
fields: fieldsEnum,
|
723
|
+
values: valuesEnum,
|
724
|
+
arguments: argumentsEnum,
|
725
|
+
},
|
726
|
+
],
|
727
|
+
operations: [
|
728
|
+
{
|
729
|
+
selections: selectionsEnum,
|
730
|
+
variables: variablesEnum,
|
731
|
+
arguments: [graphql.Kind.FIELD, graphql.Kind.DIRECTIVE],
|
732
|
+
},
|
733
|
+
],
|
734
|
+
},
|
656
735
|
},
|
657
736
|
messages: {
|
658
737
|
[ALPHABETIZE]: '"{{ currName }}" should be before "{{ prevName }}"',
|
@@ -817,34 +896,32 @@ const rule$1 = {
|
|
817
896
|
},
|
818
897
|
],
|
819
898
|
description: 'Require all comments to follow the same style (either block or inline).',
|
820
|
-
category: '
|
899
|
+
category: 'Schema',
|
821
900
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/description-style.md',
|
901
|
+
recommended: true,
|
822
902
|
},
|
823
903
|
schema: [
|
824
904
|
{
|
825
905
|
type: 'object',
|
906
|
+
additionalProperties: false,
|
826
907
|
properties: {
|
827
908
|
style: {
|
828
|
-
type: 'string',
|
829
909
|
enum: ['block', 'inline'],
|
830
|
-
default: '
|
910
|
+
default: 'block',
|
831
911
|
},
|
832
912
|
},
|
833
|
-
additionalProperties: false,
|
834
913
|
},
|
835
914
|
],
|
836
915
|
},
|
837
916
|
create(context) {
|
838
|
-
const { style } = context.options[0] || {
|
839
|
-
const
|
917
|
+
const { style = 'block' } = context.options[0] || {};
|
918
|
+
const isBlock = style === 'block';
|
840
919
|
return {
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
});
|
847
|
-
}
|
920
|
+
[`.description[type=StringValue][block!=${isBlock}]`](node) {
|
921
|
+
context.report({
|
922
|
+
loc: getLocation(node.loc),
|
923
|
+
message: `Unexpected ${isBlock ? 'inline' : 'block'} description`,
|
924
|
+
});
|
848
925
|
},
|
849
926
|
};
|
850
927
|
},
|
@@ -858,7 +935,7 @@ const rule$2 = {
|
|
858
935
|
type: 'suggestion',
|
859
936
|
docs: {
|
860
937
|
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.',
|
861
|
-
category: '
|
938
|
+
category: 'Schema',
|
862
939
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/input-name.md',
|
863
940
|
examples: [
|
864
941
|
{
|
@@ -983,7 +1060,7 @@ const rule$3 = {
|
|
983
1060
|
meta: {
|
984
1061
|
type: 'suggestion',
|
985
1062
|
docs: {
|
986
|
-
category: '
|
1063
|
+
category: 'Operations',
|
987
1064
|
description: 'This rule allows you to enforce that the file name should match the operation name.',
|
988
1065
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/match-document-filename.md`,
|
989
1066
|
examples: [
|
@@ -1057,6 +1134,14 @@ const rule$3 = {
|
|
1057
1134
|
`,
|
1058
1135
|
},
|
1059
1136
|
],
|
1137
|
+
configOptions: [
|
1138
|
+
{
|
1139
|
+
query: CaseStyle.kebabCase,
|
1140
|
+
mutation: CaseStyle.kebabCase,
|
1141
|
+
subscription: CaseStyle.kebabCase,
|
1142
|
+
fragment: CaseStyle.kebabCase,
|
1143
|
+
},
|
1144
|
+
],
|
1060
1145
|
},
|
1061
1146
|
messages: {
|
1062
1147
|
[MATCH_EXTENSION]: `File extension "{{ fileExtension }}" don't match extension "{{ expectedFileExtension }}"`,
|
@@ -1065,27 +1150,29 @@ const rule$3 = {
|
|
1065
1150
|
schema: {
|
1066
1151
|
definitions: {
|
1067
1152
|
asString: {
|
1068
|
-
type: 'string',
|
1069
|
-
description: `One of: ${CASE_STYLES.map(t => `\`${t}\``).join(', ')}`,
|
1070
1153
|
enum: CASE_STYLES,
|
1154
|
+
description: `One of: ${CASE_STYLES.map(t => `\`${t}\``).join(', ')}`,
|
1071
1155
|
},
|
1072
1156
|
asObject: {
|
1073
1157
|
type: 'object',
|
1158
|
+
additionalProperties: false,
|
1074
1159
|
properties: {
|
1075
1160
|
style: {
|
1076
|
-
type: 'string',
|
1077
1161
|
enum: CASE_STYLES,
|
1078
1162
|
},
|
1163
|
+
suffix: {
|
1164
|
+
type: 'string',
|
1165
|
+
},
|
1079
1166
|
},
|
1080
1167
|
},
|
1081
1168
|
},
|
1082
|
-
$schema: 'http://json-schema.org/draft-04/schema#',
|
1083
1169
|
type: 'array',
|
1170
|
+
maxItems: 1,
|
1084
1171
|
items: {
|
1085
1172
|
type: 'object',
|
1173
|
+
additionalProperties: false,
|
1086
1174
|
properties: {
|
1087
1175
|
fileExtension: {
|
1088
|
-
type: 'string',
|
1089
1176
|
enum: ACCEPTED_EXTENSIONS,
|
1090
1177
|
},
|
1091
1178
|
query: schemaOption,
|
@@ -1160,13 +1247,7 @@ const rule$3 = {
|
|
1160
1247
|
},
|
1161
1248
|
};
|
1162
1249
|
|
1163
|
-
const FIELDS_KINDS = [
|
1164
|
-
graphql.Kind.FIELD_DEFINITION,
|
1165
|
-
graphql.Kind.INPUT_VALUE_DEFINITION,
|
1166
|
-
graphql.Kind.VARIABLE_DEFINITION,
|
1167
|
-
graphql.Kind.ARGUMENT,
|
1168
|
-
graphql.Kind.DIRECTIVE_DEFINITION,
|
1169
|
-
];
|
1250
|
+
const FIELDS_KINDS = [graphql.Kind.FIELD_DEFINITION, graphql.Kind.INPUT_VALUE_DEFINITION, graphql.Kind.ARGUMENT, graphql.Kind.DIRECTIVE_DEFINITION];
|
1170
1251
|
const KindToDisplayName = {
|
1171
1252
|
// types
|
1172
1253
|
[graphql.Kind.OBJECT_TYPE_DEFINITION]: 'Type',
|
@@ -1178,13 +1259,13 @@ const KindToDisplayName = {
|
|
1178
1259
|
// fields
|
1179
1260
|
[graphql.Kind.FIELD_DEFINITION]: 'Field',
|
1180
1261
|
[graphql.Kind.INPUT_VALUE_DEFINITION]: 'Input property',
|
1181
|
-
[graphql.Kind.VARIABLE_DEFINITION]: 'Variable',
|
1182
1262
|
[graphql.Kind.ARGUMENT]: 'Argument',
|
1183
1263
|
[graphql.Kind.DIRECTIVE_DEFINITION]: 'Directive',
|
1184
1264
|
// rest
|
1185
1265
|
[graphql.Kind.ENUM_VALUE_DEFINITION]: 'Enumeration value',
|
1186
1266
|
[graphql.Kind.OPERATION_DEFINITION]: 'Operation',
|
1187
1267
|
[graphql.Kind.FRAGMENT_DEFINITION]: 'Fragment',
|
1268
|
+
[graphql.Kind.VARIABLE_DEFINITION]: 'Variable',
|
1188
1269
|
};
|
1189
1270
|
const StyleToRegex = {
|
1190
1271
|
camelCase: /^[a-z][\dA-Za-z]*$/,
|
@@ -1202,7 +1283,7 @@ const rule$4 = {
|
|
1202
1283
|
type: 'suggestion',
|
1203
1284
|
docs: {
|
1204
1285
|
description: 'Require names to follow specified conventions.',
|
1205
|
-
category: '
|
1286
|
+
category: ['Schema', 'Operations'],
|
1206
1287
|
recommended: true,
|
1207
1288
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/naming-convention.md',
|
1208
1289
|
examples: [
|
@@ -1213,6 +1294,24 @@ const rule$4 = {
|
|
1213
1294
|
type user {
|
1214
1295
|
first_name: String!
|
1215
1296
|
}
|
1297
|
+
`,
|
1298
|
+
},
|
1299
|
+
{
|
1300
|
+
title: 'Incorrect',
|
1301
|
+
usage: [{ FragmentDefinition: { style: 'PascalCase', forbiddenSuffixes: ['Fragment'] } }],
|
1302
|
+
code: /* GraphQL */ `
|
1303
|
+
fragment UserFragment on User {
|
1304
|
+
# ...
|
1305
|
+
}
|
1306
|
+
`,
|
1307
|
+
},
|
1308
|
+
{
|
1309
|
+
title: 'Incorrect',
|
1310
|
+
usage: [{ 'FieldDefinition[parent.name.value=Query]': { forbiddenPrefixes: ['get'] } }],
|
1311
|
+
code: /* GraphQL */ `
|
1312
|
+
type Query {
|
1313
|
+
getUsers: [User!]!
|
1314
|
+
}
|
1216
1315
|
`,
|
1217
1316
|
},
|
1218
1317
|
{
|
@@ -1224,23 +1323,31 @@ const rule$4 = {
|
|
1224
1323
|
}
|
1225
1324
|
`,
|
1226
1325
|
},
|
1227
|
-
],
|
1228
|
-
optionsForConfig: [
|
1229
1326
|
{
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1327
|
+
title: 'Correct',
|
1328
|
+
usage: [{ FragmentDefinition: { style: 'PascalCase', forbiddenSuffixes: ['Fragment'] } }],
|
1329
|
+
code: /* GraphQL */ `
|
1330
|
+
fragment UserFields on User {
|
1331
|
+
# ...
|
1332
|
+
}
|
1333
|
+
`,
|
1334
|
+
},
|
1335
|
+
{
|
1336
|
+
title: 'Correct',
|
1337
|
+
usage: [{ 'FieldDefinition[parent.name.value=Query]': { forbiddenPrefixes: ['get'] } }],
|
1338
|
+
code: /* GraphQL */ `
|
1339
|
+
type Query {
|
1340
|
+
users: [User!]!
|
1341
|
+
}
|
1342
|
+
`,
|
1343
|
+
},
|
1344
|
+
],
|
1345
|
+
configOptions: {
|
1346
|
+
schema: [
|
1347
|
+
{
|
1348
|
+
types: 'PascalCase',
|
1349
|
+
fields: 'camelCase',
|
1233
1350
|
EnumValueDefinition: 'UPPER_CASE',
|
1234
|
-
OperationDefinition: {
|
1235
|
-
style: 'PascalCase',
|
1236
|
-
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
1237
|
-
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
1238
|
-
},
|
1239
|
-
FragmentDefinition: {
|
1240
|
-
style: 'PascalCase',
|
1241
|
-
forbiddenPrefixes: ['Fragment'],
|
1242
|
-
forbiddenSuffixes: ['Fragment'],
|
1243
|
-
},
|
1244
1351
|
'FieldDefinition[parent.name.value=Query]': {
|
1245
1352
|
forbiddenPrefixes: ['query', 'get'],
|
1246
1353
|
forbiddenSuffixes: ['Query'],
|
@@ -1254,8 +1361,23 @@ const rule$4 = {
|
|
1254
1361
|
forbiddenSuffixes: ['Subscription'],
|
1255
1362
|
},
|
1256
1363
|
},
|
1257
|
-
|
1258
|
-
|
1364
|
+
],
|
1365
|
+
operations: [
|
1366
|
+
{
|
1367
|
+
VariableDefinition: 'camelCase',
|
1368
|
+
OperationDefinition: {
|
1369
|
+
style: 'PascalCase',
|
1370
|
+
forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
|
1371
|
+
forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
|
1372
|
+
},
|
1373
|
+
FragmentDefinition: {
|
1374
|
+
style: 'PascalCase',
|
1375
|
+
forbiddenPrefixes: ['Fragment'],
|
1376
|
+
forbiddenSuffixes: ['Fragment'],
|
1377
|
+
},
|
1378
|
+
},
|
1379
|
+
],
|
1380
|
+
},
|
1259
1381
|
},
|
1260
1382
|
schema: {
|
1261
1383
|
definitions: {
|
@@ -1293,12 +1415,19 @@ const rule$4 = {
|
|
1293
1415
|
properties: {
|
1294
1416
|
types: {
|
1295
1417
|
...schemaOption$1,
|
1296
|
-
description: `Includes:\n\n${TYPES_KINDS.map(kind => `-
|
1418
|
+
description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1297
1419
|
},
|
1298
1420
|
fields: {
|
1299
1421
|
...schemaOption$1,
|
1300
|
-
description: `Includes:\n\n${FIELDS_KINDS.map(kind => `-
|
1422
|
+
description: `Includes:\n\n${FIELDS_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
1301
1423
|
},
|
1424
|
+
...Object.fromEntries(ALLOWED_KINDS.map(kind => [
|
1425
|
+
kind,
|
1426
|
+
{
|
1427
|
+
...schemaOption$1,
|
1428
|
+
description: `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`,
|
1429
|
+
},
|
1430
|
+
])),
|
1302
1431
|
allowLeadingUnderscore: {
|
1303
1432
|
type: 'boolean',
|
1304
1433
|
default: false,
|
@@ -1307,35 +1436,27 @@ const rule$4 = {
|
|
1307
1436
|
type: 'boolean',
|
1308
1437
|
default: false,
|
1309
1438
|
},
|
1310
|
-
overrides: {
|
1311
|
-
type: 'object',
|
1312
|
-
additionalProperties: false,
|
1313
|
-
description: [
|
1314
|
-
'May contain the following `ASTNode` names:',
|
1315
|
-
'',
|
1316
|
-
...ALLOWED_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`),
|
1317
|
-
'',
|
1318
|
-
"> It's also possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with `ASTNode` name",
|
1319
|
-
'>',
|
1320
|
-
'> Example: pattern property `FieldDefinition[parent.name.value=Query]` will match only fields for type `Query`',
|
1321
|
-
].join('\n'),
|
1322
|
-
patternProperties: {
|
1323
|
-
[`^(${ALLOWED_KINDS.join('|')})(.+)?$`]: schemaOption$1,
|
1324
|
-
},
|
1325
|
-
},
|
1326
1439
|
},
|
1440
|
+
patternProperties: {
|
1441
|
+
[`^(${ALLOWED_KINDS.join('|')})(.+)?$`]: schemaOption$1,
|
1442
|
+
},
|
1443
|
+
description: [
|
1444
|
+
"> It's possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with allowed `ASTNode` names which are described below.",
|
1445
|
+
'>',
|
1446
|
+
'> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector.',
|
1447
|
+
'>',
|
1448
|
+
'> Example: pattern property `FieldDefinition[parent.name.value=Query]` will match only fields for type `Query`.',
|
1449
|
+
].join('\n'),
|
1327
1450
|
},
|
1328
1451
|
},
|
1329
1452
|
},
|
1330
1453
|
create(context) {
|
1331
|
-
const options = {
|
1332
|
-
|
1333
|
-
...context.options[0],
|
1334
|
-
};
|
1454
|
+
const options = context.options[0] || {};
|
1455
|
+
const { allowLeadingUnderscore, allowTrailingUnderscore, types, fields, ...restOptions } = options;
|
1335
1456
|
function normalisePropertyOption(kind) {
|
1336
|
-
let style = options
|
1457
|
+
let style = options[kind];
|
1337
1458
|
if (!style) {
|
1338
|
-
style = TYPES_KINDS.includes(kind) ?
|
1459
|
+
style = TYPES_KINDS.includes(kind) ? types : fields;
|
1339
1460
|
}
|
1340
1461
|
return typeof style === 'object' ? style : { style };
|
1341
1462
|
}
|
@@ -1356,10 +1477,10 @@ const rule$4 = {
|
|
1356
1477
|
}
|
1357
1478
|
function getErrorMessage() {
|
1358
1479
|
let name = nodeName;
|
1359
|
-
if (
|
1480
|
+
if (allowLeadingUnderscore) {
|
1360
1481
|
name = name.replace(/^_*/, '');
|
1361
1482
|
}
|
1362
|
-
if (
|
1483
|
+
if (allowTrailingUnderscore) {
|
1363
1484
|
name = name.replace(/_*$/, '');
|
1364
1485
|
}
|
1365
1486
|
if (prefix && !name.startsWith(prefix)) {
|
@@ -1393,15 +1514,13 @@ const rule$4 = {
|
|
1393
1514
|
});
|
1394
1515
|
};
|
1395
1516
|
const listeners = {};
|
1396
|
-
if (!
|
1517
|
+
if (!allowLeadingUnderscore) {
|
1397
1518
|
listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1398
1519
|
}
|
1399
|
-
if (!
|
1520
|
+
if (!allowTrailingUnderscore) {
|
1400
1521
|
listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
|
1401
1522
|
}
|
1402
|
-
const selectors = new Set([
|
1403
|
-
.flat()
|
1404
|
-
.filter(Boolean));
|
1523
|
+
const selectors = new Set([types && TYPES_KINDS, fields && FIELDS_KINDS, Object.keys(restOptions)].flat().filter(Boolean));
|
1405
1524
|
for (const selector of selectors) {
|
1406
1525
|
listeners[selector] = checkNode(selector);
|
1407
1526
|
}
|
@@ -1414,7 +1533,7 @@ const rule$5 = {
|
|
1414
1533
|
meta: {
|
1415
1534
|
type: 'suggestion',
|
1416
1535
|
docs: {
|
1417
|
-
category: '
|
1536
|
+
category: 'Operations',
|
1418
1537
|
description: 'Require name for your GraphQL operations. This is useful since most GraphQL client libraries are using the operation name for caching purposes.',
|
1419
1538
|
recommended: true,
|
1420
1539
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-anonymous-operations.md',
|
@@ -1463,7 +1582,7 @@ const rule$6 = {
|
|
1463
1582
|
type: 'suggestion',
|
1464
1583
|
docs: {
|
1465
1584
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-case-insensitive-enum-values-duplicates.md',
|
1466
|
-
category: '
|
1585
|
+
category: 'Schema',
|
1467
1586
|
recommended: true,
|
1468
1587
|
description: 'Disallow case-insensitive enum values duplicates.',
|
1469
1588
|
examples: [
|
@@ -1518,7 +1637,7 @@ const rule$7 = {
|
|
1518
1637
|
meta: {
|
1519
1638
|
type: 'suggestion',
|
1520
1639
|
docs: {
|
1521
|
-
category: '
|
1640
|
+
category: 'Operations',
|
1522
1641
|
description: `Enforce that deprecated fields or enum values are not in use by operations.`,
|
1523
1642
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-deprecated.md`,
|
1524
1643
|
requiresSchema: true,
|
@@ -1584,6 +1703,7 @@ const rule$7 = {
|
|
1584
1703
|
`,
|
1585
1704
|
},
|
1586
1705
|
],
|
1706
|
+
recommended: true,
|
1587
1707
|
},
|
1588
1708
|
messages: {
|
1589
1709
|
[NO_DEPRECATED]: `This {{ type }} is marked as deprecated in your GraphQL schema {{ reason }}`,
|
@@ -1636,8 +1756,9 @@ const rule$8 = {
|
|
1636
1756
|
type: 'suggestion',
|
1637
1757
|
docs: {
|
1638
1758
|
description: `Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.`,
|
1639
|
-
category: '
|
1759
|
+
category: 'Operations',
|
1640
1760
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-duplicate-fields.md',
|
1761
|
+
recommended: true,
|
1641
1762
|
examples: [
|
1642
1763
|
{
|
1643
1764
|
title: 'Incorrect',
|
@@ -1738,7 +1859,7 @@ const rule$9 = {
|
|
1738
1859
|
},
|
1739
1860
|
docs: {
|
1740
1861
|
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.',
|
1741
|
-
category: '
|
1862
|
+
category: 'Schema',
|
1742
1863
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-hashtag-description.md',
|
1743
1864
|
examples: [
|
1744
1865
|
{
|
@@ -1775,6 +1896,7 @@ const rule$9 = {
|
|
1775
1896
|
`,
|
1776
1897
|
},
|
1777
1898
|
],
|
1899
|
+
recommended: true,
|
1778
1900
|
},
|
1779
1901
|
type: 'suggestion',
|
1780
1902
|
schema: [],
|
@@ -1803,18 +1925,18 @@ const rule$9 = {
|
|
1803
1925
|
},
|
1804
1926
|
};
|
1805
1927
|
|
1806
|
-
const ROOT_TYPES = ['
|
1928
|
+
const ROOT_TYPES = ['mutation', 'subscription'];
|
1807
1929
|
const rule$a = {
|
1808
1930
|
meta: {
|
1809
1931
|
type: 'suggestion',
|
1810
1932
|
docs: {
|
1811
|
-
category: '
|
1812
|
-
description: 'Disallow using root types
|
1933
|
+
category: 'Schema',
|
1934
|
+
description: 'Disallow using root types `mutation` and/or `subscription`.',
|
1813
1935
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-root-type.md',
|
1814
1936
|
requiresSchema: true,
|
1815
1937
|
examples: [
|
1816
1938
|
{
|
1817
|
-
title: 'Incorrect
|
1939
|
+
title: 'Incorrect',
|
1818
1940
|
usage: [{ disallow: ['mutation', 'subscription'] }],
|
1819
1941
|
code: /* GraphQL */ `
|
1820
1942
|
type Mutation {
|
@@ -1823,16 +1945,7 @@ const rule$a = {
|
|
1823
1945
|
`,
|
1824
1946
|
},
|
1825
1947
|
{
|
1826
|
-
title: '
|
1827
|
-
usage: [{ disallow: ['query'] }],
|
1828
|
-
code: /* GraphQL */ `
|
1829
|
-
type Query {
|
1830
|
-
users: [User!]!
|
1831
|
-
}
|
1832
|
-
`,
|
1833
|
-
},
|
1834
|
-
{
|
1835
|
-
title: 'Correct (`read-only` schema)',
|
1948
|
+
title: 'Correct',
|
1836
1949
|
usage: [{ disallow: ['mutation', 'subscription'] }],
|
1837
1950
|
code: /* GraphQL */ `
|
1838
1951
|
type Query {
|
@@ -1841,7 +1954,6 @@ const rule$a = {
|
|
1841
1954
|
`,
|
1842
1955
|
},
|
1843
1956
|
],
|
1844
|
-
optionsForConfig: [{ disallow: ['subscription'] }],
|
1845
1957
|
},
|
1846
1958
|
schema: {
|
1847
1959
|
type: 'array',
|
@@ -1868,7 +1980,6 @@ const rule$a = {
|
|
1868
1980
|
const schema = requireGraphQLSchemaFromContext('no-root-type', context);
|
1869
1981
|
const disallow = new Set(context.options[0].disallow);
|
1870
1982
|
const rootTypeNames = [
|
1871
|
-
disallow.has('query') && schema.getQueryType(),
|
1872
1983
|
disallow.has('mutation') && schema.getMutationType(),
|
1873
1984
|
disallow.has('subscription') && schema.getSubscriptionType(),
|
1874
1985
|
]
|
@@ -1898,7 +2009,7 @@ const rule$b = {
|
|
1898
2009
|
meta: {
|
1899
2010
|
type: 'suggestion',
|
1900
2011
|
docs: {
|
1901
|
-
category: '
|
2012
|
+
category: 'Schema',
|
1902
2013
|
description: 'Avoid scalar result type on mutation type to make sure to return a valid state.',
|
1903
2014
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-scalar-result-type-on-mutation.md',
|
1904
2015
|
requiresSchema: true,
|
@@ -1955,7 +2066,7 @@ const rule$c = {
|
|
1955
2066
|
meta: {
|
1956
2067
|
type: 'suggestion',
|
1957
2068
|
docs: {
|
1958
|
-
category: '
|
2069
|
+
category: 'Schema',
|
1959
2070
|
description: 'Enforces users to avoid using the type name in a field name while defining your schema.',
|
1960
2071
|
recommended: true,
|
1961
2072
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-typename-prefix.md',
|
@@ -2011,11 +2122,11 @@ const RULE_NAME = 'no-unreachable-types';
|
|
2011
2122
|
const rule$d = {
|
2012
2123
|
meta: {
|
2013
2124
|
messages: {
|
2014
|
-
[UNREACHABLE_TYPE]:
|
2125
|
+
[UNREACHABLE_TYPE]: 'Type "{{ typeName }}" is unreachable',
|
2015
2126
|
},
|
2016
2127
|
docs: {
|
2017
2128
|
description: `Requires all types to be reachable at some level by root level fields.`,
|
2018
|
-
category: '
|
2129
|
+
category: 'Schema',
|
2019
2130
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME}.md`,
|
2020
2131
|
requiresSchema: true,
|
2021
2132
|
examples: [
|
@@ -2046,6 +2157,7 @@ const rule$d = {
|
|
2046
2157
|
`,
|
2047
2158
|
},
|
2048
2159
|
],
|
2160
|
+
recommended: true,
|
2049
2161
|
},
|
2050
2162
|
fixable: 'code',
|
2051
2163
|
type: 'suggestion',
|
@@ -2091,7 +2203,7 @@ const rule$e = {
|
|
2091
2203
|
},
|
2092
2204
|
docs: {
|
2093
2205
|
description: `Requires all fields to be used at some level by siblings operations.`,
|
2094
|
-
category: '
|
2206
|
+
category: 'Schema',
|
2095
2207
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$1}.md`,
|
2096
2208
|
requiresSiblings: true,
|
2097
2209
|
requiresSchema: true,
|
@@ -2277,7 +2389,7 @@ const rule$f = {
|
|
2277
2389
|
meta: {
|
2278
2390
|
type: 'suggestion',
|
2279
2391
|
docs: {
|
2280
|
-
category: '
|
2392
|
+
category: 'Schema',
|
2281
2393
|
description: 'Require deletion date on `@deprecated` directive. Suggest removing deprecated things after deprecated date.',
|
2282
2394
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-deprecation-date.md',
|
2283
2395
|
examples: [
|
@@ -2380,7 +2492,7 @@ const rule$g = {
|
|
2380
2492
|
meta: {
|
2381
2493
|
docs: {
|
2382
2494
|
description: `Require all deprecation directives to specify a reason.`,
|
2383
|
-
category: '
|
2495
|
+
category: 'Schema',
|
2384
2496
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-deprecation-reason.md`,
|
2385
2497
|
recommended: true,
|
2386
2498
|
examples: [
|
@@ -2441,13 +2553,13 @@ const ALLOWED_KINDS$1 = [
|
|
2441
2553
|
const rule$h = {
|
2442
2554
|
meta: {
|
2443
2555
|
docs: {
|
2444
|
-
category: '
|
2556
|
+
category: 'Schema',
|
2445
2557
|
description: 'Enforce descriptions in your type definitions.',
|
2446
2558
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-description.md',
|
2447
2559
|
examples: [
|
2448
2560
|
{
|
2449
2561
|
title: 'Incorrect',
|
2450
|
-
usage: [{ types: true,
|
2562
|
+
usage: [{ types: true, FieldDefinition: true }],
|
2451
2563
|
code: /* GraphQL */ `
|
2452
2564
|
type someTypeName {
|
2453
2565
|
name: String
|
@@ -2456,7 +2568,7 @@ const rule$h = {
|
|
2456
2568
|
},
|
2457
2569
|
{
|
2458
2570
|
title: 'Correct',
|
2459
|
-
usage: [{ types: true,
|
2571
|
+
usage: [{ types: true, FieldDefinition: true }],
|
2460
2572
|
code: /* GraphQL */ `
|
2461
2573
|
"""
|
2462
2574
|
Some type description
|
@@ -2470,14 +2582,13 @@ const rule$h = {
|
|
2470
2582
|
`,
|
2471
2583
|
},
|
2472
2584
|
],
|
2473
|
-
|
2585
|
+
configOptions: [
|
2474
2586
|
{
|
2475
2587
|
types: true,
|
2476
|
-
|
2477
|
-
[graphql.Kind.DIRECTIVE_DEFINITION]: true,
|
2478
|
-
},
|
2588
|
+
[graphql.Kind.DIRECTIVE_DEFINITION]: true,
|
2479
2589
|
},
|
2480
2590
|
],
|
2591
|
+
recommended: true,
|
2481
2592
|
},
|
2482
2593
|
type: 'suggestion',
|
2483
2594
|
messages: {
|
@@ -2494,22 +2605,23 @@ const rule$h = {
|
|
2494
2605
|
properties: {
|
2495
2606
|
types: {
|
2496
2607
|
type: 'boolean',
|
2497
|
-
description: `Includes:\n\n${TYPES_KINDS.map(kind => `-
|
2498
|
-
},
|
2499
|
-
overrides: {
|
2500
|
-
type: 'object',
|
2501
|
-
description: 'Configuration for precise `ASTNode`',
|
2502
|
-
additionalProperties: false,
|
2503
|
-
properties: Object.fromEntries(ALLOWED_KINDS$1.map(kind => [kind, { type: 'boolean' }])),
|
2608
|
+
description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
|
2504
2609
|
},
|
2610
|
+
...Object.fromEntries([...ALLOWED_KINDS$1].sort().map(kind => [
|
2611
|
+
kind,
|
2612
|
+
{
|
2613
|
+
type: 'boolean',
|
2614
|
+
description: `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`,
|
2615
|
+
},
|
2616
|
+
])),
|
2505
2617
|
},
|
2506
2618
|
},
|
2507
2619
|
},
|
2508
2620
|
},
|
2509
2621
|
create(context) {
|
2510
|
-
const { types,
|
2622
|
+
const { types, ...restOptions } = context.options[0];
|
2511
2623
|
const kinds = new Set(types ? TYPES_KINDS : []);
|
2512
|
-
for (const [kind, isEnabled] of Object.entries(
|
2624
|
+
for (const [kind, isEnabled] of Object.entries(restOptions)) {
|
2513
2625
|
if (isEnabled) {
|
2514
2626
|
kinds.add(kind);
|
2515
2627
|
}
|
@@ -2541,7 +2653,7 @@ const rule$i = {
|
|
2541
2653
|
meta: {
|
2542
2654
|
type: 'suggestion',
|
2543
2655
|
docs: {
|
2544
|
-
category: '
|
2656
|
+
category: 'Schema',
|
2545
2657
|
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`.',
|
2546
2658
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$2}.md`,
|
2547
2659
|
requiresSchema: true,
|
@@ -2709,9 +2821,9 @@ const rule$j = {
|
|
2709
2821
|
meta: {
|
2710
2822
|
type: 'suggestion',
|
2711
2823
|
docs: {
|
2712
|
-
category: '
|
2713
|
-
description:
|
2714
|
-
url:
|
2824
|
+
category: 'Operations',
|
2825
|
+
description: 'Enforce selecting specific fields when they are available on the GraphQL type.',
|
2826
|
+
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-id-when-available.md',
|
2715
2827
|
requiresSchema: true,
|
2716
2828
|
requiresSiblings: true,
|
2717
2829
|
examples: [
|
@@ -2751,17 +2863,17 @@ const rule$j = {
|
|
2751
2863
|
`,
|
2752
2864
|
},
|
2753
2865
|
],
|
2866
|
+
recommended: true,
|
2754
2867
|
},
|
2755
2868
|
messages: {
|
2756
|
-
[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 }}".`,
|
2869
|
+
[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 }}".`,
|
2757
2870
|
},
|
2758
2871
|
schema: {
|
2759
2872
|
type: 'array',
|
2760
|
-
additionalItems: false,
|
2761
|
-
minItems: 0,
|
2762
2873
|
maxItems: 1,
|
2763
2874
|
items: {
|
2764
2875
|
type: 'object',
|
2876
|
+
additionalProperties: false,
|
2765
2877
|
properties: {
|
2766
2878
|
fieldName: {
|
2767
2879
|
type: 'string',
|
@@ -2844,9 +2956,9 @@ const rule$j = {
|
|
2844
2956
|
const rule$k = {
|
2845
2957
|
meta: {
|
2846
2958
|
docs: {
|
2847
|
-
category: '
|
2959
|
+
category: 'Operations',
|
2848
2960
|
description: `Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://github.com/stems/graphql-depth-limit).`,
|
2849
|
-
url:
|
2961
|
+
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/selection-set-depth.md',
|
2850
2962
|
requiresSiblings: true,
|
2851
2963
|
examples: [
|
2852
2964
|
{
|
@@ -2889,22 +3001,26 @@ const rule$k = {
|
|
2889
3001
|
`,
|
2890
3002
|
},
|
2891
3003
|
],
|
3004
|
+
recommended: true,
|
3005
|
+
configOptions: [{ maxDepth: 7 }],
|
2892
3006
|
},
|
2893
3007
|
type: 'suggestion',
|
2894
3008
|
schema: {
|
2895
3009
|
type: 'array',
|
2896
|
-
additionalItems: false,
|
2897
3010
|
minItems: 1,
|
2898
3011
|
maxItems: 1,
|
2899
3012
|
items: {
|
2900
3013
|
type: 'object',
|
2901
|
-
|
3014
|
+
additionalProperties: false,
|
3015
|
+
required: ['maxDepth'],
|
2902
3016
|
properties: {
|
2903
3017
|
maxDepth: {
|
2904
3018
|
type: 'number',
|
2905
3019
|
},
|
2906
3020
|
ignore: {
|
2907
3021
|
type: 'array',
|
3022
|
+
uniqueItems: true,
|
3023
|
+
minItems: 1,
|
2908
3024
|
items: {
|
2909
3025
|
type: 'string',
|
2910
3026
|
},
|
@@ -2968,7 +3084,7 @@ const rule$l = {
|
|
2968
3084
|
type: 'suggestion',
|
2969
3085
|
docs: {
|
2970
3086
|
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.',
|
2971
|
-
category: '
|
3087
|
+
category: 'Schema',
|
2972
3088
|
recommended: true,
|
2973
3089
|
url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/strict-id-in-types.md',
|
2974
3090
|
examples: [
|
@@ -3028,13 +3144,15 @@ const rule$l = {
|
|
3028
3144
|
],
|
3029
3145
|
},
|
3030
3146
|
schema: {
|
3031
|
-
$schema: 'http://json-schema.org/draft-04/schema#',
|
3032
3147
|
type: 'array',
|
3148
|
+
maxItems: 1,
|
3033
3149
|
items: {
|
3034
3150
|
type: 'object',
|
3151
|
+
additionalProperties: false,
|
3035
3152
|
properties: {
|
3036
3153
|
acceptedIdNames: {
|
3037
3154
|
type: 'array',
|
3155
|
+
uniqueItems: true,
|
3038
3156
|
items: {
|
3039
3157
|
type: 'string',
|
3040
3158
|
},
|
@@ -3042,6 +3160,7 @@ const rule$l = {
|
|
3042
3160
|
},
|
3043
3161
|
acceptedIdTypes: {
|
3044
3162
|
type: 'array',
|
3163
|
+
uniqueItems: true,
|
3045
3164
|
items: {
|
3046
3165
|
type: 'string',
|
3047
3166
|
},
|
@@ -3052,19 +3171,21 @@ const rule$l = {
|
|
3052
3171
|
properties: {
|
3053
3172
|
types: {
|
3054
3173
|
type: 'array',
|
3174
|
+
uniqueItems: true,
|
3175
|
+
minItems: 1,
|
3055
3176
|
description: 'This is used to exclude types with names that match one of the specified values.',
|
3056
3177
|
items: {
|
3057
3178
|
type: 'string',
|
3058
3179
|
},
|
3059
|
-
default: [],
|
3060
3180
|
},
|
3061
3181
|
suffixes: {
|
3062
3182
|
type: 'array',
|
3183
|
+
uniqueItems: true,
|
3184
|
+
minItems: 1,
|
3063
3185
|
description: 'This is used to exclude types with names with suffixes that match one of the specified values.',
|
3064
3186
|
items: {
|
3065
3187
|
type: 'string',
|
3066
3188
|
},
|
3067
|
-
default: [],
|
3068
3189
|
},
|
3069
3190
|
},
|
3070
3191
|
},
|
@@ -3144,7 +3265,7 @@ const rule$m = {
|
|
3144
3265
|
meta: {
|
3145
3266
|
type: 'suggestion',
|
3146
3267
|
docs: {
|
3147
|
-
category: '
|
3268
|
+
category: 'Operations',
|
3148
3269
|
description: `Enforce unique fragment names across your project.`,
|
3149
3270
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$3}.md`,
|
3150
3271
|
requiresSiblings: true,
|
@@ -3203,7 +3324,7 @@ const rule$n = {
|
|
3203
3324
|
meta: {
|
3204
3325
|
type: 'suggestion',
|
3205
3326
|
docs: {
|
3206
|
-
category: '
|
3327
|
+
category: 'Operations',
|
3207
3328
|
description: `Enforce unique operation names across your project.`,
|
3208
3329
|
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$4}.md`,
|
3209
3330
|
requiresSiblings: true,
|