@graphql-eslint/eslint-plugin 3.0.0-alpha-069461d.0 → 3.0.0-alpha-698204a.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.
Files changed (88) hide show
  1. package/README.md +19 -8
  2. package/configs/base.d.ts +5 -0
  3. package/configs/index.d.ts +59 -91
  4. package/configs/operations-all.d.ts +19 -0
  5. package/configs/{recommended.d.ts → operations-recommended.d.ts} +11 -30
  6. package/configs/schema-all.d.ts +23 -0
  7. package/configs/schema-recommended.d.ts +44 -0
  8. package/docs/README.md +9 -17
  9. package/docs/deprecated-rules.md +21 -0
  10. package/docs/rules/alphabetize.md +1 -1
  11. package/docs/rules/description-style.md +4 -2
  12. package/docs/rules/executable-definitions.md +2 -2
  13. package/docs/rules/fields-on-correct-type.md +2 -2
  14. package/docs/rules/fragments-on-composite-type.md +2 -2
  15. package/docs/rules/input-name.md +1 -1
  16. package/docs/rules/known-argument-names.md +2 -2
  17. package/docs/rules/known-directives.md +2 -2
  18. package/docs/rules/known-fragment-names.md +2 -2
  19. package/docs/rules/known-type-names.md +2 -2
  20. package/docs/rules/lone-anonymous-operation.md +2 -2
  21. package/docs/rules/lone-schema-definition.md +2 -2
  22. package/docs/rules/match-document-filename.md +6 -4
  23. package/docs/rules/naming-convention.md +26 -27
  24. package/docs/rules/no-anonymous-operations.md +2 -2
  25. package/docs/rules/no-case-insensitive-enum-values-duplicates.md +2 -2
  26. package/docs/rules/no-deprecated.md +3 -1
  27. package/docs/rules/{avoid-duplicate-fields.md → no-duplicate-fields.md} +10 -8
  28. package/docs/rules/no-fragment-cycles.md +2 -2
  29. package/docs/rules/no-hashtag-description.md +3 -1
  30. package/docs/rules/no-root-type.md +7 -1
  31. package/docs/rules/{avoid-scalar-result-type-on-mutation.md → no-scalar-result-type-on-mutation.md} +7 -7
  32. package/docs/rules/no-typename-prefix.md +37 -0
  33. package/docs/rules/no-undefined-variables.md +2 -2
  34. package/docs/rules/no-unreachable-types.md +3 -1
  35. package/docs/rules/no-unused-fields.md +1 -1
  36. package/docs/rules/no-unused-fragments.md +2 -2
  37. package/docs/rules/no-unused-variables.md +2 -2
  38. package/docs/rules/one-field-subscriptions.md +2 -2
  39. package/docs/rules/overlapping-fields-can-be-merged.md +2 -2
  40. package/docs/rules/possible-fragment-spread.md +2 -2
  41. package/docs/rules/possible-type-extension.md +2 -2
  42. package/docs/rules/provided-required-arguments.md +2 -2
  43. package/docs/rules/require-deprecation-date.md +1 -1
  44. package/docs/rules/require-deprecation-reason.md +2 -2
  45. package/docs/rules/require-description.md +36 -7
  46. package/docs/rules/require-field-of-type-query-in-mutation-result.md +1 -1
  47. package/docs/rules/require-id-when-available.md +3 -1
  48. package/docs/rules/scalar-leafs.md +2 -2
  49. package/docs/rules/selection-set-depth.md +9 -2
  50. package/docs/rules/strict-id-in-types.md +16 -10
  51. package/docs/rules/unique-argument-names.md +2 -2
  52. package/docs/rules/unique-directive-names-per-location.md +2 -2
  53. package/docs/rules/unique-directive-names.md +2 -2
  54. package/docs/rules/unique-enum-value-names.md +2 -2
  55. package/docs/rules/unique-field-definition-names.md +2 -2
  56. package/docs/rules/unique-fragment-name.md +1 -1
  57. package/docs/rules/unique-input-field-names.md +2 -2
  58. package/docs/rules/unique-operation-name.md +1 -1
  59. package/docs/rules/unique-operation-types.md +2 -2
  60. package/docs/rules/unique-type-names.md +2 -2
  61. package/docs/rules/unique-variable-names.md +2 -2
  62. package/docs/rules/value-literals-of-correct-type.md +2 -2
  63. package/docs/rules/variables-are-input-types.md +2 -2
  64. package/docs/rules/variables-in-allowed-position.md +2 -2
  65. package/index.js +566 -599
  66. package/index.mjs +567 -600
  67. package/package.json +1 -1
  68. package/rules/alphabetize.d.ts +8 -10
  69. package/rules/description-style.d.ts +4 -6
  70. package/rules/index.d.ts +18 -8
  71. package/rules/input-name.d.ts +1 -1
  72. package/rules/match-document-filename.d.ts +8 -10
  73. package/rules/naming-convention.d.ts +1 -1
  74. package/rules/{avoid-duplicate-fields.d.ts → no-duplicate-fields.d.ts} +0 -0
  75. package/rules/{avoid-scalar-result-type-on-mutation.d.ts → no-scalar-result-type-on-mutation.d.ts} +0 -0
  76. package/rules/{avoid-typename-prefix.d.ts → no-typename-prefix.d.ts} +0 -0
  77. package/rules/require-description.d.ts +10 -6
  78. package/rules/require-id-when-available.d.ts +3 -3
  79. package/rules/selection-set-depth.d.ts +3 -3
  80. package/rules/strict-id-in-types.d.ts +6 -8
  81. package/types.d.ts +9 -5
  82. package/utils.d.ts +1 -1
  83. package/configs/all.d.ts +0 -99
  84. package/docs/rules/avoid-operation-name-prefix.md +0 -50
  85. package/docs/rules/avoid-typename-prefix.md +0 -37
  86. package/docs/rules/no-operation-name-suffix.md +0 -38
  87. package/rules/avoid-operation-name-prefix.d.ts +0 -9
  88. package/rules/no-operation-name-suffix.d.ts +0 -3
package/index.js CHANGED
@@ -18,22 +18,21 @@ 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 recommendedConfig = {
25
- parser: '@graphql-eslint/eslint-plugin',
26
- plugins: ['@graphql-eslint'],
29
+ const schemaRecommendedConfig = {
30
+ extends: ['plugin:@graphql-eslint/base'],
27
31
  rules: {
28
- '@graphql-eslint/avoid-typename-prefix': 'error',
29
- '@graphql-eslint/executable-definitions': 'error',
30
- '@graphql-eslint/fields-on-correct-type': 'error',
31
- '@graphql-eslint/fragments-on-composite-type': 'error',
32
+ '@graphql-eslint/description-style': 'error',
32
33
  '@graphql-eslint/known-argument-names': 'error',
33
34
  '@graphql-eslint/known-directives': 'error',
34
- '@graphql-eslint/known-fragment-names': 'error',
35
35
  '@graphql-eslint/known-type-names': 'error',
36
- '@graphql-eslint/lone-anonymous-operation': 'error',
37
36
  '@graphql-eslint/lone-schema-definition': 'error',
38
37
  '@graphql-eslint/naming-convention': [
39
38
  'error',
@@ -42,12 +41,6 @@ const recommendedConfig = {
42
41
  fields: 'camelCase',
43
42
  overrides: {
44
43
  EnumValueDefinition: 'UPPER_CASE',
45
- OperationDefinition: {
46
- style: 'PascalCase',
47
- forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
48
- forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
49
- },
50
- FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
51
44
  'FieldDefinition[parent.name.value=Query]': {
52
45
  forbiddenPrefixes: ['query', 'get'],
53
46
  forbiddenSuffixes: ['Query'],
@@ -63,29 +56,93 @@ const recommendedConfig = {
63
56
  },
64
57
  },
65
58
  ],
66
- '@graphql-eslint/no-anonymous-operations': 'error',
67
59
  '@graphql-eslint/no-case-insensitive-enum-values-duplicates': 'error',
60
+ '@graphql-eslint/no-hashtag-description': 'error',
61
+ '@graphql-eslint/no-typename-prefix': 'error',
62
+ '@graphql-eslint/no-unreachable-types': 'error',
63
+ '@graphql-eslint/possible-type-extension': 'error',
64
+ '@graphql-eslint/provided-required-arguments': 'error',
65
+ '@graphql-eslint/require-deprecation-reason': 'error',
66
+ '@graphql-eslint/strict-id-in-types': 'error',
67
+ '@graphql-eslint/unique-directive-names': 'error',
68
+ '@graphql-eslint/unique-directive-names-per-location': 'error',
69
+ '@graphql-eslint/unique-enum-value-names': 'error',
70
+ '@graphql-eslint/unique-field-definition-names': 'error',
71
+ '@graphql-eslint/unique-operation-types': 'error',
72
+ '@graphql-eslint/unique-type-names': 'error',
73
+ },
74
+ };
75
+
76
+ /*
77
+ * 🚨 IMPORTANT! Do not manually modify this file. Run: `yarn generate-configs`
78
+ */
79
+ const schemaAllConfig = {
80
+ extends: ['plugin:@graphql-eslint/base', 'plugin:@graphql-eslint/schema-recommended'],
81
+ rules: {
82
+ '@graphql-eslint/alphabetize': [
83
+ 'error',
84
+ {
85
+ fields: ['ObjectTypeDefinition', 'InterfaceTypeDefinition', 'InputObjectTypeDefinition'],
86
+ values: ['EnumTypeDefinition'],
87
+ arguments: ['FieldDefinition', 'Field', 'DirectiveDefinition', 'Directive'],
88
+ },
89
+ ],
90
+ '@graphql-eslint/input-name': 'error',
91
+ '@graphql-eslint/no-root-type': 'off',
92
+ '@graphql-eslint/no-scalar-result-type-on-mutation': 'error',
93
+ '@graphql-eslint/no-unused-fields': 'off',
94
+ '@graphql-eslint/require-deprecation-date': 'error',
95
+ '@graphql-eslint/require-description': ['error', { types: true, overrides: { DirectiveDefinition: true } }],
96
+ '@graphql-eslint/require-field-of-type-query-in-mutation-result': 'error',
97
+ },
98
+ };
99
+
100
+ /*
101
+ * 🚨 IMPORTANT! Do not manually modify this file. Run: `yarn generate-configs`
102
+ */
103
+ const operationsRecommendedConfig = {
104
+ extends: ['plugin:@graphql-eslint/base'],
105
+ rules: {
106
+ '@graphql-eslint/executable-definitions': 'error',
107
+ '@graphql-eslint/fields-on-correct-type': 'error',
108
+ '@graphql-eslint/fragments-on-composite-type': 'error',
109
+ '@graphql-eslint/known-argument-names': 'error',
110
+ '@graphql-eslint/known-directives': 'error',
111
+ '@graphql-eslint/known-fragment-names': 'error',
112
+ '@graphql-eslint/known-type-names': 'error',
113
+ '@graphql-eslint/lone-anonymous-operation': 'error',
114
+ '@graphql-eslint/naming-convention': [
115
+ 'error',
116
+ {
117
+ overrides: {
118
+ Argument: 'camelCase',
119
+ VariableDefinition: 'camelCase',
120
+ OperationDefinition: {
121
+ style: 'PascalCase',
122
+ forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
123
+ forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
124
+ },
125
+ FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
126
+ },
127
+ },
128
+ ],
129
+ '@graphql-eslint/no-anonymous-operations': 'error',
130
+ '@graphql-eslint/no-deprecated': 'error',
131
+ '@graphql-eslint/no-duplicate-fields': 'error',
68
132
  '@graphql-eslint/no-fragment-cycles': 'error',
69
- '@graphql-eslint/no-operation-name-suffix': 'error',
70
133
  '@graphql-eslint/no-undefined-variables': 'error',
71
134
  '@graphql-eslint/no-unused-fragments': 'error',
72
135
  '@graphql-eslint/no-unused-variables': 'error',
73
136
  '@graphql-eslint/one-field-subscriptions': 'error',
74
137
  '@graphql-eslint/overlapping-fields-can-be-merged': 'error',
75
138
  '@graphql-eslint/possible-fragment-spread': 'error',
76
- '@graphql-eslint/possible-type-extension': 'error',
77
139
  '@graphql-eslint/provided-required-arguments': 'error',
78
- '@graphql-eslint/require-deprecation-reason': 'error',
140
+ '@graphql-eslint/require-id-when-available': 'error',
79
141
  '@graphql-eslint/scalar-leafs': 'error',
80
- '@graphql-eslint/strict-id-in-types': 'error',
142
+ '@graphql-eslint/selection-set-depth': ['error', { maxDepth: 7 }],
81
143
  '@graphql-eslint/unique-argument-names': 'error',
82
- '@graphql-eslint/unique-directive-names': 'error',
83
144
  '@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
145
  '@graphql-eslint/unique-input-field-names': 'error',
87
- '@graphql-eslint/unique-operation-types': 'error',
88
- '@graphql-eslint/unique-type-names': 'error',
89
146
  '@graphql-eslint/unique-variable-names': 'error',
90
147
  '@graphql-eslint/value-literals-of-correct-type': 'error',
91
148
  '@graphql-eslint/variables-are-input-types': 'error',
@@ -96,44 +153,32 @@ const recommendedConfig = {
96
153
  /*
97
154
  * 🚨 IMPORTANT! Do not manually modify this file. Run: `yarn generate-configs`
98
155
  */
99
- const allConfig = {
100
- ...recommendedConfig,
156
+ const operationsAllConfig = {
157
+ extends: ['plugin:@graphql-eslint/base', 'plugin:@graphql-eslint/operations-recommended'],
101
158
  rules: {
102
- ...recommendedConfig.rules,
103
159
  '@graphql-eslint/alphabetize': [
104
160
  'error',
105
161
  {
106
- fields: ['ObjectTypeDefinition', 'InterfaceTypeDefinition', 'InputObjectTypeDefinition'],
107
- values: ['EnumTypeDefinition'],
108
162
  selections: ['OperationDefinition', 'FragmentDefinition'],
109
163
  variables: ['OperationDefinition'],
110
- arguments: ['FieldDefinition', 'Field', 'DirectiveDefinition', 'Directive'],
164
+ arguments: ['Field', 'Directive'],
111
165
  },
112
166
  ],
113
- '@graphql-eslint/avoid-duplicate-fields': 'error',
114
- '@graphql-eslint/avoid-operation-name-prefix': 'error',
115
- '@graphql-eslint/avoid-scalar-result-type-on-mutation': 'error',
116
- '@graphql-eslint/description-style': 'error',
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',
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',
167
+ '@graphql-eslint/match-document-filename': [
168
+ 'error',
169
+ { query: 'kebab-case', mutation: 'kebab-case', subscription: 'kebab-case', fragment: 'kebab-case' },
170
+ ],
129
171
  '@graphql-eslint/unique-fragment-name': 'error',
130
172
  '@graphql-eslint/unique-operation-name': 'error',
131
173
  },
132
174
  };
133
175
 
134
176
  const configs = {
135
- all: allConfig,
136
- recommended: recommendedConfig,
177
+ base,
178
+ 'schema-recommended': schemaRecommendedConfig,
179
+ 'schema-all': schemaAllConfig,
180
+ 'operations-recommended': operationsRecommendedConfig,
181
+ 'operations-all': operationsAllConfig,
137
182
  };
138
183
 
139
184
  function requireSiblingsOperations(ruleName, context) {
@@ -346,7 +391,6 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
346
391
  docs: {
347
392
  ...docs,
348
393
  graphQLJSRuleName: ruleName,
349
- category: 'Validation',
350
394
  recommended: true,
351
395
  requiresSchema,
352
396
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${name}.md`,
@@ -383,16 +427,22 @@ const importFiles = (context) => {
383
427
  return _import.processImport(context.getFilename());
384
428
  };
385
429
  const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-definitions', 'ExecutableDefinitions', {
430
+ category: 'Operations',
386
431
  description: `A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.`,
387
432
  }), validationToRule('fields-on-correct-type', 'FieldsOnCorrectType', {
433
+ category: 'Operations',
388
434
  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
435
  }), validationToRule('fragments-on-composite-type', 'FragmentsOnCompositeTypes', {
436
+ category: 'Operations',
390
437
  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
438
  }), validationToRule('known-argument-names', 'KnownArgumentNames', {
439
+ category: ['Schema', 'Operations'],
392
440
  description: `A GraphQL field is only valid if all supplied arguments are defined by that field.`,
393
441
  }), validationToRule('known-directives', 'KnownDirectives', {
442
+ category: ['Schema', 'Operations'],
394
443
  description: `A GraphQL document is only valid if all \`@directives\` are known by the schema and legally positioned.`,
395
444
  }), validationToRule('known-fragment-names', 'KnownFragmentNames', {
445
+ category: 'Operations',
396
446
  description: `A GraphQL document is only valid if all \`...Fragment\` fragment spreads refer to fragments defined in the same document.`,
397
447
  examples: [
398
448
  {
@@ -459,17 +509,23 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
459
509
  },
460
510
  ],
461
511
  }, importFiles), validationToRule('known-type-names', 'KnownTypeNames', {
512
+ category: ['Schema', 'Operations'],
462
513
  description: `A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.`,
463
514
  }), validationToRule('lone-anonymous-operation', 'LoneAnonymousOperation', {
515
+ category: 'Operations',
464
516
  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
517
  }), validationToRule('lone-schema-definition', 'LoneSchemaDefinition', {
518
+ category: 'Schema',
466
519
  description: `A GraphQL document is only valid if it contains only one schema definition.`,
467
520
  requiresSchema: false,
468
521
  }), validationToRule('no-fragment-cycles', 'NoFragmentCycles', {
522
+ category: 'Operations',
469
523
  description: `A GraphQL fragment is only valid when it does not have cycles in fragments usage.`,
470
524
  }), validationToRule('no-undefined-variables', 'NoUndefinedVariables', {
525
+ category: 'Operations',
471
526
  description: `A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.`,
472
527
  }, importFiles), validationToRule('no-unused-fragments', 'NoUnusedFragments', {
528
+ category: 'Operations',
473
529
  description: `A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.`,
474
530
  requiresSiblings: true,
475
531
  }, context => {
@@ -499,49 +555,68 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
499
555
  };
500
556
  return getParentNode(context.getFilename());
501
557
  }), validationToRule('no-unused-variables', 'NoUnusedVariables', {
558
+ category: 'Operations',
502
559
  description: `A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.`,
503
560
  }, importFiles), validationToRule('overlapping-fields-can-be-merged', 'OverlappingFieldsCanBeMerged', {
561
+ category: 'Operations',
504
562
  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
563
  }), validationToRule('possible-fragment-spread', 'PossibleFragmentSpreads', {
564
+ category: 'Operations',
506
565
  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
566
  }), validationToRule('possible-type-extension', 'PossibleTypeExtensions', {
567
+ category: 'Schema',
508
568
  description: `A type extension is only valid if the type is defined and has the same kind.`,
509
569
  requiresSchema: false,
510
570
  }), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
571
+ category: ['Schema', 'Operations'],
511
572
  description: `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.`,
512
573
  }), validationToRule('scalar-leafs', 'ScalarLeafs', {
574
+ category: 'Operations',
513
575
  description: `A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.`,
514
576
  }), validationToRule('one-field-subscriptions', 'SingleFieldSubscriptions', {
577
+ category: 'Operations',
515
578
  description: `A GraphQL subscription is valid only if it contains a single root field.`,
516
579
  }), validationToRule('unique-argument-names', 'UniqueArgumentNames', {
580
+ category: 'Operations',
517
581
  description: `A GraphQL field or directive is only valid if all supplied arguments are uniquely named.`,
518
582
  }), validationToRule('unique-directive-names', 'UniqueDirectiveNames', {
583
+ category: 'Schema',
519
584
  description: `A GraphQL document is only valid if all defined directives have unique names.`,
520
585
  requiresSchema: false,
521
586
  }), validationToRule('unique-directive-names-per-location', 'UniqueDirectivesPerLocation', {
587
+ category: ['Schema', 'Operations'],
522
588
  description: `A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.`,
523
589
  }), validationToRule('unique-enum-value-names', 'UniqueEnumValueNames', {
590
+ category: 'Schema',
524
591
  description: `A GraphQL enum type is only valid if all its values are uniquely named.`,
525
592
  requiresSchema: false,
526
593
  }), validationToRule('unique-field-definition-names', 'UniqueFieldDefinitionNames', {
594
+ category: 'Schema',
527
595
  description: `A GraphQL complex type is only valid if all its fields are uniquely named.`,
528
596
  requiresSchema: false,
529
597
  }), validationToRule('unique-input-field-names', 'UniqueInputFieldNames', {
598
+ category: 'Operations',
530
599
  description: `A GraphQL input object value is only valid if all supplied fields are uniquely named.`,
531
600
  requiresSchema: false,
532
601
  }), validationToRule('unique-operation-types', 'UniqueOperationTypes', {
602
+ category: 'Schema',
533
603
  description: `A GraphQL document is only valid if it has only one type per operation.`,
534
604
  requiresSchema: false,
535
605
  }), validationToRule('unique-type-names', 'UniqueTypeNames', {
606
+ category: 'Schema',
536
607
  description: `A GraphQL document is only valid if all defined types have unique names.`,
537
608
  requiresSchema: false,
538
609
  }), validationToRule('unique-variable-names', 'UniqueVariableNames', {
610
+ category: 'Operations',
539
611
  description: `A GraphQL operation is only valid if all its variables are uniquely named.`,
540
612
  }), validationToRule('value-literals-of-correct-type', 'ValuesOfCorrectType', {
613
+ category: 'Operations',
541
614
  description: `A GraphQL document is only valid if all value literals are of the type expected at their position.`,
542
615
  }), validationToRule('variables-are-input-types', 'VariablesAreInputTypes', {
616
+ category: 'Operations',
543
617
  description: `A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).`,
544
618
  }), validationToRule('variables-in-allowed-position', 'VariablesInAllowedPosition', {
619
+ category: 'Operations',
545
620
  description: `Variables passed to field arguments conform to type.`,
546
621
  }));
547
622
 
@@ -567,7 +642,7 @@ const rule = {
567
642
  meta: {
568
643
  type: 'suggestion',
569
644
  docs: {
570
- category: 'Best Practices',
645
+ category: ['Schema', 'Operations'],
571
646
  description: 'Enforce arrange in alphabetical order for type fields, enum values, input object fields, operation selections and more.',
572
647
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/alphabetize.md',
573
648
  examples: [
@@ -646,15 +721,22 @@ const rule = {
646
721
  `,
647
722
  },
648
723
  ],
649
- optionsForConfig: [
650
- {
651
- fields: fieldsEnum,
652
- values: valuesEnum,
653
- selections: selectionsEnum,
654
- variables: variablesEnum,
655
- arguments: argumentsEnum,
656
- },
657
- ],
724
+ configOptions: {
725
+ schema: [
726
+ {
727
+ fields: fieldsEnum,
728
+ values: valuesEnum,
729
+ arguments: argumentsEnum,
730
+ },
731
+ ],
732
+ operations: [
733
+ {
734
+ selections: selectionsEnum,
735
+ variables: variablesEnum,
736
+ arguments: [graphql.Kind.FIELD, graphql.Kind.DIRECTIVE],
737
+ },
738
+ ],
739
+ },
658
740
  },
659
741
  messages: {
660
742
  [ALPHABETIZE]: '"{{ currName }}" should be before "{{ prevName }}"',
@@ -792,307 +874,7 @@ const rule = {
792
874
  },
793
875
  };
794
876
 
795
- const AVOID_DUPLICATE_FIELDS = 'AVOID_DUPLICATE_FIELDS';
796
877
  const rule$1 = {
797
- meta: {
798
- type: 'suggestion',
799
- 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
- examples: [
804
- {
805
- title: 'Incorrect',
806
- code: /* GraphQL */ `
807
- query {
808
- user {
809
- name
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
- }
828
- }
829
- `,
830
- },
831
- {
832
- title: 'Incorrect',
833
- code: /* GraphQL */ `
834
- query (
835
- $first: Int!
836
- $first: Int! # duplicate variable
837
- ) {
838
- users(first: $first, skip: 50) {
839
- id
840
- }
841
- }
842
- `,
843
- },
844
- ],
845
- },
846
- messages: {
847
- [AVOID_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times`,
848
- },
849
- schema: [],
850
- },
851
- create(context) {
852
- function checkNode(usedFields, fieldName, type, node) {
853
- if (usedFields.has(fieldName)) {
854
- context.report({
855
- loc: getLocation((node.kind === graphql.Kind.FIELD && node.alias ? node.alias : node).loc, fieldName, {
856
- offsetEnd: node.kind === graphql.Kind.VARIABLE_DEFINITION ? 0 : 1,
857
- }),
858
- messageId: AVOID_DUPLICATE_FIELDS,
859
- data: {
860
- type,
861
- fieldName,
862
- },
863
- });
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
- },
891
- };
892
- },
893
- };
894
-
895
- const AVOID_OPERATION_NAME_PREFIX = 'AVOID_OPERATION_NAME_PREFIX';
896
- const rule$2 = {
897
- meta: {
898
- type: 'suggestion',
899
- docs: {
900
- description: 'Enforce/avoid operation name prefix, useful if you wish to avoid prefix in your root fields, or avoid using REST terminology in your schema.',
901
- category: 'Stylistic Issues',
902
- url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/avoid-operation-name-prefix.md',
903
- examples: [
904
- {
905
- title: 'Incorrect',
906
- usage: [{ keywords: ['get'] }],
907
- code: /* GraphQL */ `
908
- query getUserDetails {
909
- # ...
910
- }`,
911
- },
912
- {
913
- title: 'Correct',
914
- usage: [{ keywords: ['get'] }],
915
- code: /* GraphQL */ `
916
- query userDetails {
917
- # ...
918
- }`,
919
- },
920
- ],
921
- },
922
- messages: {
923
- [AVOID_OPERATION_NAME_PREFIX]: `Forbidden operation name prefix: "{{ invalidPrefix }}"`,
924
- },
925
- schema: [
926
- {
927
- additionalProperties: false,
928
- type: 'object',
929
- required: ['keywords'],
930
- properties: {
931
- caseSensitive: {
932
- default: false,
933
- type: 'boolean',
934
- },
935
- keywords: {
936
- additionalItems: false,
937
- type: 'array',
938
- minItems: 1,
939
- items: {
940
- type: 'string',
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
878
  meta: {
1097
879
  type: 'suggestion',
1098
880
  docs: {
@@ -1119,20 +901,20 @@ const rule$5 = {
1119
901
  },
1120
902
  ],
1121
903
  description: 'Require all comments to follow the same style (either block or inline).',
1122
- category: 'Stylistic Issues',
904
+ category: 'Schema',
1123
905
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/description-style.md',
906
+ recommended: true,
1124
907
  },
1125
908
  schema: [
1126
909
  {
1127
910
  type: 'object',
911
+ additionalProperties: false,
1128
912
  properties: {
1129
913
  style: {
1130
- type: 'string',
1131
914
  enum: ['block', 'inline'],
1132
915
  default: 'inline',
1133
916
  },
1134
917
  },
1135
- additionalProperties: false,
1136
918
  },
1137
919
  ],
1138
920
  },
@@ -1155,12 +937,12 @@ const rule$5 = {
1155
937
  const isObjectType = (node) => [graphql.Kind.OBJECT_TYPE_DEFINITION, graphql.Kind.OBJECT_TYPE_EXTENSION].includes(node.type);
1156
938
  const isQueryType = (node) => isObjectType(node) && node.name.value === 'Query';
1157
939
  const isMutationType = (node) => isObjectType(node) && node.name.value === 'Mutation';
1158
- const rule$6 = {
940
+ const rule$2 = {
1159
941
  meta: {
1160
942
  type: 'suggestion',
1161
943
  docs: {
1162
944
  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',
945
+ category: 'Schema',
1164
946
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/input-name.md',
1165
947
  examples: [
1166
948
  {
@@ -1281,11 +1063,11 @@ const CASE_STYLES = [
1281
1063
  const schemaOption = {
1282
1064
  oneOf: [{ $ref: '#/definitions/asString' }, { $ref: '#/definitions/asObject' }],
1283
1065
  };
1284
- const rule$7 = {
1066
+ const rule$3 = {
1285
1067
  meta: {
1286
1068
  type: 'suggestion',
1287
1069
  docs: {
1288
- category: 'Best Practices',
1070
+ category: 'Operations',
1289
1071
  description: 'This rule allows you to enforce that the file name should match the operation name.',
1290
1072
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/match-document-filename.md`,
1291
1073
  examples: [
@@ -1359,6 +1141,14 @@ const rule$7 = {
1359
1141
  `,
1360
1142
  },
1361
1143
  ],
1144
+ configOptions: [
1145
+ {
1146
+ query: CaseStyle.kebabCase,
1147
+ mutation: CaseStyle.kebabCase,
1148
+ subscription: CaseStyle.kebabCase,
1149
+ fragment: CaseStyle.kebabCase,
1150
+ },
1151
+ ],
1362
1152
  },
1363
1153
  messages: {
1364
1154
  [MATCH_EXTENSION]: `File extension "{{ fileExtension }}" don't match extension "{{ expectedFileExtension }}"`,
@@ -1367,27 +1157,29 @@ const rule$7 = {
1367
1157
  schema: {
1368
1158
  definitions: {
1369
1159
  asString: {
1370
- type: 'string',
1371
- description: `One of: ${CASE_STYLES.map(t => `\`${t}\``).join(', ')}`,
1372
1160
  enum: CASE_STYLES,
1161
+ description: `One of: ${CASE_STYLES.map(t => `\`${t}\``).join(', ')}`,
1373
1162
  },
1374
1163
  asObject: {
1375
1164
  type: 'object',
1165
+ additionalProperties: false,
1376
1166
  properties: {
1377
1167
  style: {
1378
- type: 'string',
1379
1168
  enum: CASE_STYLES,
1380
1169
  },
1170
+ suffix: {
1171
+ type: 'string',
1172
+ },
1381
1173
  },
1382
1174
  },
1383
1175
  },
1384
- $schema: 'http://json-schema.org/draft-04/schema#',
1385
1176
  type: 'array',
1177
+ maxItems: 1,
1386
1178
  items: {
1387
1179
  type: 'object',
1180
+ additionalProperties: false,
1388
1181
  properties: {
1389
1182
  fileExtension: {
1390
- type: 'string',
1391
1183
  enum: ACCEPTED_EXTENSIONS,
1392
1184
  },
1393
1185
  query: schemaOption,
@@ -1462,13 +1254,7 @@ const rule$7 = {
1462
1254
  },
1463
1255
  };
1464
1256
 
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
- ];
1257
+ const FIELDS_KINDS = [graphql.Kind.FIELD_DEFINITION, graphql.Kind.INPUT_VALUE_DEFINITION, graphql.Kind.ARGUMENT, graphql.Kind.DIRECTIVE_DEFINITION];
1472
1258
  const KindToDisplayName = {
1473
1259
  // types
1474
1260
  [graphql.Kind.OBJECT_TYPE_DEFINITION]: 'Type',
@@ -1480,13 +1266,13 @@ const KindToDisplayName = {
1480
1266
  // fields
1481
1267
  [graphql.Kind.FIELD_DEFINITION]: 'Field',
1482
1268
  [graphql.Kind.INPUT_VALUE_DEFINITION]: 'Input property',
1483
- [graphql.Kind.VARIABLE_DEFINITION]: 'Variable',
1484
1269
  [graphql.Kind.ARGUMENT]: 'Argument',
1485
1270
  [graphql.Kind.DIRECTIVE_DEFINITION]: 'Directive',
1486
1271
  // rest
1487
1272
  [graphql.Kind.ENUM_VALUE_DEFINITION]: 'Enumeration value',
1488
1273
  [graphql.Kind.OPERATION_DEFINITION]: 'Operation',
1489
1274
  [graphql.Kind.FRAGMENT_DEFINITION]: 'Fragment',
1275
+ [graphql.Kind.VARIABLE_DEFINITION]: 'Variable',
1490
1276
  };
1491
1277
  const StyleToRegex = {
1492
1278
  camelCase: /^[a-z][\dA-Za-z]*$/,
@@ -1499,12 +1285,12 @@ const ALLOWED_STYLES = Object.keys(StyleToRegex);
1499
1285
  const schemaOption$1 = {
1500
1286
  oneOf: [{ $ref: '#/definitions/asString' }, { $ref: '#/definitions/asObject' }],
1501
1287
  };
1502
- const rule$8 = {
1288
+ const rule$4 = {
1503
1289
  meta: {
1504
1290
  type: 'suggestion',
1505
1291
  docs: {
1506
1292
  description: 'Require names to follow specified conventions.',
1507
- category: 'Best Practices',
1293
+ category: ['Schema', 'Operations'],
1508
1294
  recommended: true,
1509
1295
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/naming-convention.md',
1510
1296
  examples: [
@@ -1527,37 +1313,47 @@ const rule$8 = {
1527
1313
  `,
1528
1314
  },
1529
1315
  ],
1530
- optionsForConfig: [
1531
- {
1532
- types: 'PascalCase',
1533
- fields: 'camelCase',
1534
- overrides: {
1535
- 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
- 'FieldDefinition[parent.name.value=Query]': {
1547
- forbiddenPrefixes: ['query', 'get'],
1548
- forbiddenSuffixes: ['Query'],
1549
- },
1550
- 'FieldDefinition[parent.name.value=Mutation]': {
1551
- forbiddenPrefixes: ['mutation'],
1552
- forbiddenSuffixes: ['Mutation'],
1316
+ configOptions: {
1317
+ schema: [
1318
+ {
1319
+ types: 'PascalCase',
1320
+ fields: 'camelCase',
1321
+ overrides: {
1322
+ EnumValueDefinition: 'UPPER_CASE',
1323
+ 'FieldDefinition[parent.name.value=Query]': {
1324
+ forbiddenPrefixes: ['query', 'get'],
1325
+ forbiddenSuffixes: ['Query'],
1326
+ },
1327
+ 'FieldDefinition[parent.name.value=Mutation]': {
1328
+ forbiddenPrefixes: ['mutation'],
1329
+ forbiddenSuffixes: ['Mutation'],
1330
+ },
1331
+ 'FieldDefinition[parent.name.value=Subscription]': {
1332
+ forbiddenPrefixes: ['subscription'],
1333
+ forbiddenSuffixes: ['Subscription'],
1334
+ },
1553
1335
  },
1554
- 'FieldDefinition[parent.name.value=Subscription]': {
1555
- forbiddenPrefixes: ['subscription'],
1556
- forbiddenSuffixes: ['Subscription'],
1336
+ },
1337
+ ],
1338
+ operations: [
1339
+ {
1340
+ overrides: {
1341
+ Argument: 'camelCase',
1342
+ VariableDefinition: 'camelCase',
1343
+ OperationDefinition: {
1344
+ style: 'PascalCase',
1345
+ forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
1346
+ forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
1347
+ },
1348
+ FragmentDefinition: {
1349
+ style: 'PascalCase',
1350
+ forbiddenPrefixes: ['Fragment'],
1351
+ forbiddenSuffixes: ['Fragment'],
1352
+ },
1557
1353
  },
1558
1354
  },
1559
- },
1560
- ],
1355
+ ],
1356
+ },
1561
1357
  },
1562
1358
  schema: {
1563
1359
  definitions: {
@@ -1595,11 +1391,11 @@ const rule$8 = {
1595
1391
  properties: {
1596
1392
  types: {
1597
1393
  ...schemaOption$1,
1598
- description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
1394
+ description: `Includes:\n\n${TYPES_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`).join('\n')}`,
1599
1395
  },
1600
1396
  fields: {
1601
1397
  ...schemaOption$1,
1602
- description: `Includes:\n\n${FIELDS_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
1398
+ description: `Includes:\n\n${FIELDS_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`).join('\n')}`,
1603
1399
  },
1604
1400
  allowLeadingUnderscore: {
1605
1401
  type: 'boolean',
@@ -1615,7 +1411,7 @@ const rule$8 = {
1615
1411
  description: [
1616
1412
  'May contain the following `ASTNode` names:',
1617
1413
  '',
1618
- ...ALLOWED_KINDS.map(kind => `- \`${kind}\``),
1414
+ ...ALLOWED_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`),
1619
1415
  '',
1620
1416
  "> It's also possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with `ASTNode` name",
1621
1417
  '>',
@@ -1712,11 +1508,11 @@ const rule$8 = {
1712
1508
  };
1713
1509
 
1714
1510
  const NO_ANONYMOUS_OPERATIONS = 'NO_ANONYMOUS_OPERATIONS';
1715
- const rule$9 = {
1511
+ const rule$5 = {
1716
1512
  meta: {
1717
1513
  type: 'suggestion',
1718
1514
  docs: {
1719
- category: 'Best Practices',
1515
+ category: 'Operations',
1720
1516
  description: 'Require name for your GraphQL operations. This is useful since most GraphQL client libraries are using the operation name for caching purposes.',
1721
1517
  recommended: true,
1722
1518
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-anonymous-operations.md',
@@ -1760,12 +1556,12 @@ const rule$9 = {
1760
1556
  };
1761
1557
 
1762
1558
  const ERROR_MESSAGE_ID = 'NO_CASE_INSENSITIVE_ENUM_VALUES_DUPLICATES';
1763
- const rule$a = {
1559
+ const rule$6 = {
1764
1560
  meta: {
1765
1561
  type: 'suggestion',
1766
1562
  docs: {
1767
1563
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-case-insensitive-enum-values-duplicates.md',
1768
- category: 'Best Practices',
1564
+ category: 'Schema',
1769
1565
  recommended: true,
1770
1566
  description: 'Disallow case-insensitive enum values duplicates.',
1771
1567
  examples: [
@@ -1816,11 +1612,11 @@ const rule$a = {
1816
1612
  };
1817
1613
 
1818
1614
  const NO_DEPRECATED = 'NO_DEPRECATED';
1819
- const rule$b = {
1615
+ const rule$7 = {
1820
1616
  meta: {
1821
1617
  type: 'suggestion',
1822
1618
  docs: {
1823
- category: 'Best Practices',
1619
+ category: 'Operations',
1824
1620
  description: `Enforce that deprecated fields or enum values are not in use by operations.`,
1825
1621
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-deprecated.md`,
1826
1622
  requiresSchema: true,
@@ -1886,6 +1682,7 @@ const rule$b = {
1886
1682
  `,
1887
1683
  },
1888
1684
  ],
1685
+ recommended: true,
1889
1686
  },
1890
1687
  messages: {
1891
1688
  [NO_DEPRECATED]: `This {{ type }} is marked as deprecated in your GraphQL schema {{ reason }}`,
@@ -1912,19 +1709,120 @@ const rule$b = {
1912
1709
  }
1913
1710
  },
1914
1711
  Field(node) {
1915
- requireGraphQLSchemaFromContext('no-deprecated', context);
1916
- const typeInfo = node.typeInfo();
1917
- if (typeInfo && typeInfo.fieldDef) {
1918
- if (typeInfo.fieldDef.deprecationReason) {
1919
- const fieldName = node.name.value;
1920
- context.report({
1921
- loc: getLocation(node.loc, fieldName),
1922
- messageId: NO_DEPRECATED,
1923
- data: {
1924
- type: 'field',
1925
- reason: typeInfo.fieldDef.deprecationReason ? `(reason: ${typeInfo.fieldDef.deprecationReason})` : '',
1926
- },
1927
- });
1712
+ requireGraphQLSchemaFromContext('no-deprecated', context);
1713
+ const typeInfo = node.typeInfo();
1714
+ if (typeInfo && typeInfo.fieldDef) {
1715
+ if (typeInfo.fieldDef.deprecationReason) {
1716
+ const fieldName = node.name.value;
1717
+ context.report({
1718
+ loc: getLocation(node.loc, fieldName),
1719
+ messageId: NO_DEPRECATED,
1720
+ data: {
1721
+ type: 'field',
1722
+ reason: typeInfo.fieldDef.deprecationReason ? `(reason: ${typeInfo.fieldDef.deprecationReason})` : '',
1723
+ },
1724
+ });
1725
+ }
1726
+ }
1727
+ },
1728
+ };
1729
+ },
1730
+ };
1731
+
1732
+ const NO_DUPLICATE_FIELDS = 'NO_DUPLICATE_FIELDS';
1733
+ const rule$8 = {
1734
+ meta: {
1735
+ type: 'suggestion',
1736
+ docs: {
1737
+ description: `Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.`,
1738
+ category: 'Operations',
1739
+ url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-duplicate-fields.md',
1740
+ recommended: true,
1741
+ examples: [
1742
+ {
1743
+ title: 'Incorrect',
1744
+ code: /* GraphQL */ `
1745
+ query {
1746
+ user {
1747
+ name
1748
+ email
1749
+ name # duplicate field
1750
+ }
1751
+ }
1752
+ `,
1753
+ },
1754
+ {
1755
+ title: 'Incorrect',
1756
+ code: /* GraphQL */ `
1757
+ query {
1758
+ users(
1759
+ first: 100
1760
+ skip: 50
1761
+ after: "cji629tngfgou0b73kt7vi5jo"
1762
+ first: 100 # duplicate argument
1763
+ ) {
1764
+ id
1765
+ }
1766
+ }
1767
+ `,
1768
+ },
1769
+ {
1770
+ title: 'Incorrect',
1771
+ code: /* GraphQL */ `
1772
+ query (
1773
+ $first: Int!
1774
+ $first: Int! # duplicate variable
1775
+ ) {
1776
+ users(first: $first, skip: 50) {
1777
+ id
1778
+ }
1779
+ }
1780
+ `,
1781
+ },
1782
+ ],
1783
+ },
1784
+ messages: {
1785
+ [NO_DUPLICATE_FIELDS]: `{{ type }} "{{ fieldName }}" defined multiple times`,
1786
+ },
1787
+ schema: [],
1788
+ },
1789
+ create(context) {
1790
+ function checkNode(usedFields, fieldName, type, node) {
1791
+ if (usedFields.has(fieldName)) {
1792
+ context.report({
1793
+ loc: getLocation((node.kind === graphql.Kind.FIELD && node.alias ? node.alias : node).loc, fieldName, {
1794
+ offsetEnd: node.kind === graphql.Kind.VARIABLE_DEFINITION ? 0 : 1,
1795
+ }),
1796
+ messageId: NO_DUPLICATE_FIELDS,
1797
+ data: {
1798
+ type,
1799
+ fieldName,
1800
+ },
1801
+ });
1802
+ }
1803
+ else {
1804
+ usedFields.add(fieldName);
1805
+ }
1806
+ }
1807
+ return {
1808
+ OperationDefinition(node) {
1809
+ const set = new Set();
1810
+ for (const varDef of node.variableDefinitions) {
1811
+ checkNode(set, varDef.variable.name.value, 'Operation variable', varDef);
1812
+ }
1813
+ },
1814
+ Field(node) {
1815
+ const set = new Set();
1816
+ for (const arg of node.arguments) {
1817
+ checkNode(set, arg.name.value, 'Field argument', arg);
1818
+ }
1819
+ },
1820
+ SelectionSet(node) {
1821
+ var _a;
1822
+ const set = new Set();
1823
+ for (const selection of node.selections) {
1824
+ if (selection.kind === graphql.Kind.FIELD) {
1825
+ checkNode(set, ((_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) || selection.name.value, 'Field', selection);
1928
1826
  }
1929
1827
  }
1930
1828
  },
@@ -1933,14 +1831,14 @@ const rule$b = {
1933
1831
  };
1934
1832
 
1935
1833
  const HASHTAG_COMMENT = 'HASHTAG_COMMENT';
1936
- const rule$c = {
1834
+ const rule$9 = {
1937
1835
  meta: {
1938
1836
  messages: {
1939
1837
  [HASHTAG_COMMENT]: 'Using hashtag (#) for adding GraphQL descriptions is not allowed. Prefer using """ for multiline, or " for a single line description.',
1940
1838
  },
1941
1839
  docs: {
1942
1840
  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: 'Best Practices',
1841
+ category: 'Schema',
1944
1842
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-hashtag-description.md',
1945
1843
  examples: [
1946
1844
  {
@@ -1977,6 +1875,7 @@ const rule$c = {
1977
1875
  `,
1978
1876
  },
1979
1877
  ],
1878
+ recommended: true,
1980
1879
  },
1981
1880
  type: 'suggestion',
1982
1881
  schema: [],
@@ -2005,79 +1904,12 @@ const rule$c = {
2005
1904
  },
2006
1905
  };
2007
1906
 
2008
- const NO_OPERATION_NAME_SUFFIX = 'NO_OPERATION_NAME_SUFFIX';
2009
- const rule$d = {
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
1907
  const ROOT_TYPES = ['query', 'mutation', 'subscription'];
2076
- const rule$e = {
1908
+ const rule$a = {
2077
1909
  meta: {
2078
1910
  type: 'suggestion',
2079
1911
  docs: {
2080
- category: 'Validation',
1912
+ category: 'Schema',
2081
1913
  description: 'Disallow using root types for `read-only` or `write-only` schemas.',
2082
1914
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-root-type.md',
2083
1915
  requiresSchema: true,
@@ -2110,7 +1942,6 @@ const rule$e = {
2110
1942
  `,
2111
1943
  },
2112
1944
  ],
2113
- optionsForConfig: [{ disallow: ['subscription'] }],
2114
1945
  },
2115
1946
  schema: {
2116
1947
  type: 'array',
@@ -2163,16 +1994,128 @@ const rule$e = {
2163
1994
  },
2164
1995
  };
2165
1996
 
1997
+ const rule$b = {
1998
+ meta: {
1999
+ type: 'suggestion',
2000
+ docs: {
2001
+ category: 'Schema',
2002
+ description: 'Avoid scalar result type on mutation type to make sure to return a valid state.',
2003
+ url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-scalar-result-type-on-mutation.md',
2004
+ requiresSchema: true,
2005
+ examples: [
2006
+ {
2007
+ title: 'Incorrect',
2008
+ code: /* GraphQL */ `
2009
+ type Mutation {
2010
+ createUser: Boolean
2011
+ }
2012
+ `,
2013
+ },
2014
+ {
2015
+ title: 'Correct',
2016
+ code: /* GraphQL */ `
2017
+ type Mutation {
2018
+ createUser: User!
2019
+ }
2020
+ `,
2021
+ },
2022
+ ],
2023
+ },
2024
+ schema: [],
2025
+ },
2026
+ create(context) {
2027
+ const schema = requireGraphQLSchemaFromContext('no-scalar-result-type-on-mutation', context);
2028
+ const mutationType = schema.getMutationType();
2029
+ if (!mutationType) {
2030
+ return {};
2031
+ }
2032
+ const selector = [
2033
+ `:matches(${graphql.Kind.OBJECT_TYPE_DEFINITION}, ${graphql.Kind.OBJECT_TYPE_EXTENSION})[name.value=${mutationType.name}]`,
2034
+ '>',
2035
+ graphql.Kind.FIELD_DEFINITION,
2036
+ graphql.Kind.NAMED_TYPE,
2037
+ ].join(' ');
2038
+ return {
2039
+ [selector](node) {
2040
+ const typeName = node.name.value;
2041
+ const graphQLType = schema.getType(typeName);
2042
+ if (graphql.isScalarType(graphQLType)) {
2043
+ context.report({
2044
+ loc: getLocation(node.loc, typeName),
2045
+ message: `Unexpected scalar result type "${typeName}"`,
2046
+ });
2047
+ }
2048
+ },
2049
+ };
2050
+ },
2051
+ };
2052
+
2053
+ const NO_TYPENAME_PREFIX = 'NO_TYPENAME_PREFIX';
2054
+ const rule$c = {
2055
+ meta: {
2056
+ type: 'suggestion',
2057
+ docs: {
2058
+ category: 'Schema',
2059
+ description: 'Enforces users to avoid using the type name in a field name while defining your schema.',
2060
+ recommended: true,
2061
+ url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-typename-prefix.md',
2062
+ examples: [
2063
+ {
2064
+ title: 'Incorrect',
2065
+ code: /* GraphQL */ `
2066
+ type User {
2067
+ userId: ID!
2068
+ }
2069
+ `,
2070
+ },
2071
+ {
2072
+ title: 'Correct',
2073
+ code: /* GraphQL */ `
2074
+ type User {
2075
+ id: ID!
2076
+ }
2077
+ `,
2078
+ },
2079
+ ],
2080
+ },
2081
+ messages: {
2082
+ [NO_TYPENAME_PREFIX]: `Field "{{ fieldName }}" starts with the name of the parent type "{{ typeName }}"`,
2083
+ },
2084
+ schema: [],
2085
+ },
2086
+ create(context) {
2087
+ return {
2088
+ 'ObjectTypeDefinition, ObjectTypeExtension, InterfaceTypeDefinition, InterfaceTypeExtension'(node) {
2089
+ const typeName = node.name.value;
2090
+ const lowerTypeName = typeName.toLowerCase();
2091
+ for (const field of node.fields) {
2092
+ const fieldName = field.name.value;
2093
+ if (fieldName.toLowerCase().startsWith(lowerTypeName)) {
2094
+ context.report({
2095
+ data: {
2096
+ fieldName,
2097
+ typeName,
2098
+ },
2099
+ messageId: NO_TYPENAME_PREFIX,
2100
+ loc: getLocation(field.loc, lowerTypeName),
2101
+ });
2102
+ }
2103
+ }
2104
+ },
2105
+ };
2106
+ },
2107
+ };
2108
+
2166
2109
  const UNREACHABLE_TYPE = 'UNREACHABLE_TYPE';
2167
2110
  const RULE_NAME = 'no-unreachable-types';
2168
- const rule$f = {
2111
+ const rule$d = {
2169
2112
  meta: {
2170
2113
  messages: {
2171
- [UNREACHABLE_TYPE]: `Type "{{ typeName }}" is unreachable`,
2114
+ [UNREACHABLE_TYPE]: 'Type "{{ typeName }}" is unreachable',
2172
2115
  },
2173
2116
  docs: {
2174
2117
  description: `Requires all types to be reachable at some level by root level fields.`,
2175
- category: 'Best Practices',
2118
+ category: 'Schema',
2176
2119
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME}.md`,
2177
2120
  requiresSchema: true,
2178
2121
  examples: [
@@ -2203,6 +2146,7 @@ const rule$f = {
2203
2146
  `,
2204
2147
  },
2205
2148
  ],
2149
+ recommended: true,
2206
2150
  },
2207
2151
  fixable: 'code',
2208
2152
  type: 'suggestion',
@@ -2241,14 +2185,14 @@ const rule$f = {
2241
2185
 
2242
2186
  const UNUSED_FIELD = 'UNUSED_FIELD';
2243
2187
  const RULE_NAME$1 = 'no-unused-fields';
2244
- const rule$g = {
2188
+ const rule$e = {
2245
2189
  meta: {
2246
2190
  messages: {
2247
2191
  [UNUSED_FIELD]: `Field "{{fieldName}}" is unused`,
2248
2192
  },
2249
2193
  docs: {
2250
2194
  description: `Requires all fields to be used at some level by siblings operations.`,
2251
- category: 'Best Practices',
2195
+ category: 'Schema',
2252
2196
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$1}.md`,
2253
2197
  requiresSiblings: true,
2254
2198
  requiresSchema: true,
@@ -2430,11 +2374,11 @@ const MESSAGE_REQUIRE_DATE = 'MESSAGE_REQUIRE_DATE';
2430
2374
  const MESSAGE_INVALID_FORMAT = 'MESSAGE_INVALID_FORMAT';
2431
2375
  const MESSAGE_INVALID_DATE = 'MESSAGE_INVALID_DATE';
2432
2376
  const MESSAGE_CAN_BE_REMOVED = 'MESSAGE_CAN_BE_REMOVED';
2433
- const rule$h = {
2377
+ const rule$f = {
2434
2378
  meta: {
2435
2379
  type: 'suggestion',
2436
2380
  docs: {
2437
- category: 'Best Practices',
2381
+ category: 'Schema',
2438
2382
  description: 'Require deletion date on `@deprecated` directive. Suggest removing deprecated things after deprecated date.',
2439
2383
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-deprecation-date.md',
2440
2384
  examples: [
@@ -2533,11 +2477,11 @@ const rule$h = {
2533
2477
  },
2534
2478
  };
2535
2479
 
2536
- const rule$i = {
2480
+ const rule$g = {
2537
2481
  meta: {
2538
2482
  docs: {
2539
2483
  description: `Require all deprecation directives to specify a reason.`,
2540
- category: 'Best Practices',
2484
+ category: 'Schema',
2541
2485
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-deprecation-reason.md`,
2542
2486
  recommended: true,
2543
2487
  examples: [
@@ -2588,41 +2532,23 @@ const rule$i = {
2588
2532
  };
2589
2533
 
2590
2534
  const REQUIRE_DESCRIPTION_ERROR = 'REQUIRE_DESCRIPTION_ERROR';
2591
- const DESCRIBABLE_NODES = [
2592
- graphql.Kind.SCHEMA_DEFINITION,
2593
- graphql.Kind.OBJECT_TYPE_DEFINITION,
2535
+ const ALLOWED_KINDS$1 = [
2536
+ ...TYPES_KINDS,
2594
2537
  graphql.Kind.FIELD_DEFINITION,
2595
2538
  graphql.Kind.INPUT_VALUE_DEFINITION,
2596
- graphql.Kind.INTERFACE_TYPE_DEFINITION,
2597
- graphql.Kind.UNION_TYPE_DEFINITION,
2598
- graphql.Kind.ENUM_TYPE_DEFINITION,
2599
2539
  graphql.Kind.ENUM_VALUE_DEFINITION,
2600
- graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION,
2601
2540
  graphql.Kind.DIRECTIVE_DEFINITION,
2602
2541
  ];
2603
- function verifyRule(context, node) {
2604
- if (node) {
2605
- if (!node.description || !node.description.value || node.description.value.trim().length === 0) {
2606
- context.report({
2607
- loc: getLocation(('name' in node ? node.name : node).loc, 'name' in node ? node.name.value : 'schema'),
2608
- messageId: REQUIRE_DESCRIPTION_ERROR,
2609
- data: {
2610
- nodeType: node.kind,
2611
- },
2612
- });
2613
- }
2614
- }
2615
- }
2616
- const rule$j = {
2542
+ const rule$h = {
2617
2543
  meta: {
2618
2544
  docs: {
2619
- category: 'Best Practices',
2620
- description: `Enforce descriptions in your type definitions.`,
2621
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-description.md`,
2545
+ category: 'Schema',
2546
+ description: 'Enforce descriptions in your type definitions.',
2547
+ url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-description.md',
2622
2548
  examples: [
2623
2549
  {
2624
2550
  title: 'Incorrect',
2625
- usage: [{ on: [graphql.Kind.OBJECT_TYPE_DEFINITION, graphql.Kind.FIELD_DEFINITION] }],
2551
+ usage: [{ types: true, overrides: { FieldDefinition: true } }],
2626
2552
  code: /* GraphQL */ `
2627
2553
  type someTypeName {
2628
2554
  name: String
@@ -2631,7 +2557,7 @@ const rule$j = {
2631
2557
  },
2632
2558
  {
2633
2559
  title: 'Correct',
2634
- usage: [{ on: [graphql.Kind.OBJECT_TYPE_DEFINITION, graphql.Kind.FIELD_DEFINITION] }],
2560
+ usage: [{ types: true, overrides: { FieldDefinition: true } }],
2635
2561
  code: /* GraphQL */ `
2636
2562
  """
2637
2563
  Some type description
@@ -2645,44 +2571,78 @@ const rule$j = {
2645
2571
  `,
2646
2572
  },
2647
2573
  ],
2574
+ configOptions: [
2575
+ {
2576
+ types: true,
2577
+ overrides: {
2578
+ [graphql.Kind.DIRECTIVE_DEFINITION]: true,
2579
+ },
2580
+ },
2581
+ ],
2648
2582
  },
2649
2583
  type: 'suggestion',
2650
2584
  messages: {
2651
- [REQUIRE_DESCRIPTION_ERROR]: `Description is required for nodes of type "{{ nodeType }}"`,
2585
+ [REQUIRE_DESCRIPTION_ERROR]: 'Description is required for nodes of type "{{ nodeType }}"',
2652
2586
  },
2653
2587
  schema: {
2654
2588
  type: 'array',
2655
- additionalItems: false,
2656
2589
  minItems: 1,
2657
2590
  maxItems: 1,
2658
2591
  items: {
2659
2592
  type: 'object',
2660
- require: ['on'],
2593
+ additionalProperties: false,
2594
+ minProperties: 1,
2661
2595
  properties: {
2662
- on: {
2663
- type: 'array',
2664
- minItems: 1,
2665
- additionalItems: false,
2666
- items: {
2667
- type: 'string',
2668
- enum: DESCRIBABLE_NODES,
2669
- },
2596
+ types: {
2597
+ type: 'boolean',
2598
+ description: `Includes:\n\n${TYPES_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`).join('\n')}`,
2599
+ },
2600
+ overrides: {
2601
+ type: 'object',
2602
+ description: 'Configuration for precise `ASTNode`',
2603
+ additionalProperties: false,
2604
+ properties: Object.fromEntries(ALLOWED_KINDS$1.map(kind => [kind, { type: 'boolean' }])),
2670
2605
  },
2671
2606
  },
2672
2607
  },
2673
2608
  },
2674
2609
  },
2675
2610
  create(context) {
2676
- return Object.fromEntries(context.options[0].on.map(optionKey => [optionKey, node => verifyRule(context, node)]));
2611
+ const { types, overrides = {} } = context.options[0];
2612
+ const kinds = new Set(types ? TYPES_KINDS : []);
2613
+ for (const [kind, isEnabled] of Object.entries(overrides)) {
2614
+ if (isEnabled) {
2615
+ kinds.add(kind);
2616
+ }
2617
+ else {
2618
+ kinds.delete(kind);
2619
+ }
2620
+ }
2621
+ const selector = [...kinds].join(',');
2622
+ return {
2623
+ [selector](node) {
2624
+ var _a;
2625
+ const description = ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || '';
2626
+ if (description.trim().length === 0) {
2627
+ context.report({
2628
+ loc: getLocation(node.name.loc, node.name.value),
2629
+ messageId: REQUIRE_DESCRIPTION_ERROR,
2630
+ data: {
2631
+ nodeType: node.kind,
2632
+ },
2633
+ });
2634
+ }
2635
+ },
2636
+ };
2677
2637
  },
2678
2638
  };
2679
2639
 
2680
2640
  const RULE_NAME$2 = 'require-field-of-type-query-in-mutation-result';
2681
- const rule$k = {
2641
+ const rule$i = {
2682
2642
  meta: {
2683
2643
  type: 'suggestion',
2684
2644
  docs: {
2685
- category: 'Best Practices',
2645
+ category: 'Schema',
2686
2646
  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`.',
2687
2647
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$2}.md`,
2688
2648
  requiresSchema: true,
@@ -2846,13 +2806,13 @@ const convertNode = (typeInfo) => (node, key, parent) => {
2846
2806
 
2847
2807
  const REQUIRE_ID_WHEN_AVAILABLE = 'REQUIRE_ID_WHEN_AVAILABLE';
2848
2808
  const DEFAULT_ID_FIELD_NAME = 'id';
2849
- const rule$l = {
2809
+ const rule$j = {
2850
2810
  meta: {
2851
2811
  type: 'suggestion',
2852
2812
  docs: {
2853
- category: 'Best Practices',
2854
- description: `Enforce selecting specific fields when they are available on the GraphQL type.`,
2855
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-id-when-available.md`,
2813
+ category: 'Operations',
2814
+ description: 'Enforce selecting specific fields when they are available on the GraphQL type.',
2815
+ url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/require-id-when-available.md',
2856
2816
  requiresSchema: true,
2857
2817
  requiresSiblings: true,
2858
2818
  examples: [
@@ -2892,17 +2852,17 @@ const rule$l = {
2892
2852
  `,
2893
2853
  },
2894
2854
  ],
2855
+ recommended: true,
2895
2856
  },
2896
2857
  messages: {
2897
- [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 }}".`,
2858
+ [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 }}".`,
2898
2859
  },
2899
2860
  schema: {
2900
2861
  type: 'array',
2901
- additionalItems: false,
2902
- minItems: 0,
2903
2862
  maxItems: 1,
2904
2863
  items: {
2905
2864
  type: 'object',
2865
+ additionalProperties: false,
2906
2866
  properties: {
2907
2867
  fieldName: {
2908
2868
  type: 'string',
@@ -2982,12 +2942,12 @@ const rule$l = {
2982
2942
  },
2983
2943
  };
2984
2944
 
2985
- const rule$m = {
2945
+ const rule$k = {
2986
2946
  meta: {
2987
2947
  docs: {
2988
- category: 'Best Practices',
2948
+ category: 'Operations',
2989
2949
  description: `Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://github.com/stems/graphql-depth-limit).`,
2990
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/selection-set-depth.md`,
2950
+ url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/selection-set-depth.md',
2991
2951
  requiresSiblings: true,
2992
2952
  examples: [
2993
2953
  {
@@ -3030,22 +2990,26 @@ const rule$m = {
3030
2990
  `,
3031
2991
  },
3032
2992
  ],
2993
+ recommended: true,
2994
+ configOptions: [{ maxDepth: 7 }],
3033
2995
  },
3034
2996
  type: 'suggestion',
3035
2997
  schema: {
3036
2998
  type: 'array',
3037
- additionalItems: false,
3038
2999
  minItems: 1,
3039
3000
  maxItems: 1,
3040
3001
  items: {
3041
3002
  type: 'object',
3042
- require: ['maxDepth'],
3003
+ additionalProperties: false,
3004
+ required: ['maxDepth'],
3043
3005
  properties: {
3044
3006
  maxDepth: {
3045
3007
  type: 'number',
3046
3008
  },
3047
3009
  ignore: {
3048
3010
  type: 'array',
3011
+ uniqueItems: true,
3012
+ minItems: 1,
3049
3013
  items: {
3050
3014
  type: 'string',
3051
3015
  },
@@ -3104,12 +3068,12 @@ const shouldIgnoreNode = ({ node, exceptions }) => {
3104
3068
  }
3105
3069
  return false;
3106
3070
  };
3107
- const rule$n = {
3071
+ const rule$l = {
3108
3072
  meta: {
3109
3073
  type: 'suggestion',
3110
3074
  docs: {
3111
3075
  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.',
3112
- category: 'Best Practices',
3076
+ category: 'Schema',
3113
3077
  recommended: true,
3114
3078
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/strict-id-in-types.md',
3115
3079
  examples: [
@@ -3169,13 +3133,15 @@ const rule$n = {
3169
3133
  ],
3170
3134
  },
3171
3135
  schema: {
3172
- $schema: 'http://json-schema.org/draft-04/schema#',
3173
3136
  type: 'array',
3137
+ maxItems: 1,
3174
3138
  items: {
3175
3139
  type: 'object',
3140
+ additionalProperties: false,
3176
3141
  properties: {
3177
3142
  acceptedIdNames: {
3178
3143
  type: 'array',
3144
+ uniqueItems: true,
3179
3145
  items: {
3180
3146
  type: 'string',
3181
3147
  },
@@ -3183,6 +3149,7 @@ const rule$n = {
3183
3149
  },
3184
3150
  acceptedIdTypes: {
3185
3151
  type: 'array',
3152
+ uniqueItems: true,
3186
3153
  items: {
3187
3154
  type: 'string',
3188
3155
  },
@@ -3193,19 +3160,21 @@ const rule$n = {
3193
3160
  properties: {
3194
3161
  types: {
3195
3162
  type: 'array',
3163
+ uniqueItems: true,
3164
+ minItems: 1,
3196
3165
  description: 'This is used to exclude types with names that match one of the specified values.',
3197
3166
  items: {
3198
3167
  type: 'string',
3199
3168
  },
3200
- default: [],
3201
3169
  },
3202
3170
  suffixes: {
3203
3171
  type: 'array',
3172
+ uniqueItems: true,
3173
+ minItems: 1,
3204
3174
  description: 'This is used to exclude types with names with suffixes that match one of the specified values.',
3205
3175
  items: {
3206
3176
  type: 'string',
3207
3177
  },
3208
- default: [],
3209
3178
  },
3210
3179
  },
3211
3180
  },
@@ -3281,11 +3250,11 @@ const checkNode = (context, node, ruleName, messageId) => {
3281
3250
  });
3282
3251
  }
3283
3252
  };
3284
- const rule$o = {
3253
+ const rule$m = {
3285
3254
  meta: {
3286
3255
  type: 'suggestion',
3287
3256
  docs: {
3288
- category: 'Best Practices',
3257
+ category: 'Operations',
3289
3258
  description: `Enforce unique fragment names across your project.`,
3290
3259
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$3}.md`,
3291
3260
  requiresSiblings: true,
@@ -3340,11 +3309,11 @@ const rule$o = {
3340
3309
 
3341
3310
  const RULE_NAME$4 = 'unique-operation-name';
3342
3311
  const UNIQUE_OPERATION_NAME = 'UNIQUE_OPERATION_NAME';
3343
- const rule$p = {
3312
+ const rule$n = {
3344
3313
  meta: {
3345
3314
  type: 'suggestion',
3346
3315
  docs: {
3347
- category: 'Best Practices',
3316
+ category: 'Operations',
3348
3317
  description: `Enforce unique operation names across your project.`,
3349
3318
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$4}.md`,
3350
3319
  requiresSiblings: true,
@@ -3407,31 +3376,29 @@ const rule$p = {
3407
3376
  const rules = {
3408
3377
  ...GRAPHQL_JS_VALIDATIONS,
3409
3378
  alphabetize: rule,
3410
- 'avoid-duplicate-fields': rule$1,
3411
- 'avoid-operation-name-prefix': rule$2,
3412
- 'avoid-scalar-result-type-on-mutation': rule$3,
3413
- 'avoid-typename-prefix': rule$4,
3414
- 'description-style': rule$5,
3415
- 'input-name': rule$6,
3416
- 'match-document-filename': rule$7,
3417
- 'naming-convention': rule$8,
3418
- 'no-anonymous-operations': rule$9,
3419
- 'no-case-insensitive-enum-values-duplicates': rule$a,
3420
- 'no-deprecated': rule$b,
3421
- 'no-hashtag-description': rule$c,
3422
- 'no-operation-name-suffix': rule$d,
3423
- 'no-root-type': rule$e,
3424
- 'no-unreachable-types': rule$f,
3425
- 'no-unused-fields': rule$g,
3426
- 'require-deprecation-date': rule$h,
3427
- 'require-deprecation-reason': rule$i,
3428
- 'require-description': rule$j,
3429
- 'require-field-of-type-query-in-mutation-result': rule$k,
3430
- 'require-id-when-available': rule$l,
3431
- 'selection-set-depth': rule$m,
3432
- 'strict-id-in-types': rule$n,
3433
- 'unique-fragment-name': rule$o,
3434
- 'unique-operation-name': rule$p,
3379
+ 'description-style': rule$1,
3380
+ 'input-name': rule$2,
3381
+ 'match-document-filename': rule$3,
3382
+ 'naming-convention': rule$4,
3383
+ 'no-anonymous-operations': rule$5,
3384
+ 'no-case-insensitive-enum-values-duplicates': rule$6,
3385
+ 'no-deprecated': rule$7,
3386
+ 'no-duplicate-fields': rule$8,
3387
+ 'no-hashtag-description': rule$9,
3388
+ 'no-root-type': rule$a,
3389
+ 'no-scalar-result-type-on-mutation': rule$b,
3390
+ 'no-typename-prefix': rule$c,
3391
+ 'no-unreachable-types': rule$d,
3392
+ 'no-unused-fields': rule$e,
3393
+ 'require-deprecation-date': rule$f,
3394
+ 'require-deprecation-reason': rule$g,
3395
+ 'require-description': rule$h,
3396
+ 'require-field-of-type-query-in-mutation-result': rule$i,
3397
+ 'require-id-when-available': rule$j,
3398
+ 'selection-set-depth': rule$k,
3399
+ 'strict-id-in-types': rule$l,
3400
+ 'unique-fragment-name': rule$m,
3401
+ 'unique-operation-name': rule$n,
3435
3402
  };
3436
3403
 
3437
3404
  const RELEVANT_KEYWORDS = ['gql', 'graphql', '/* GraphQL */'];