@graphql-eslint/eslint-plugin 3.0.1 → 3.1.1-alpha-f19a99b.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/docs/README.md CHANGED
@@ -4,67 +4,66 @@ Each rule has emojis denoting:
4
4
 
5
5
  - 🚀 `graphql-eslint` rule
6
6
  - 🔮 `graphql-js` rule
7
- - 🔧 if some problems reported by the rule are automatically fixable by the `--fix` [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) option
8
7
 
9
8
  <!-- 🚨 IMPORTANT! Do not manually modify this table. Run: `yarn generate:docs` -->
10
9
  <!-- prettier-ignore-start -->
11
- Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|Description|&nbsp;&nbsp;&nbsp;&nbsp;Config&nbsp;&nbsp;&nbsp;&nbsp;|🚀&nbsp;/&nbsp;🔮|🔧
12
- -|-|:-:|:-:|-
13
- [alphabetize](rules/alphabetize.md)|Enforce arrange in alphabetical order for type fields, enum values, input object fields, operation selections and more.|![all][]|🚀|
14
- [description-style](rules/description-style.md)|Require all comments to follow the same style (either block or inline).|![recommended][]|🚀|
15
- [executable-definitions](rules/executable-definitions.md)|A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.|![recommended][]|🔮|
16
- [fields-on-correct-type](rules/fields-on-correct-type.md)|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`.|![recommended][]|🔮|
17
- [fragments-on-composite-type](rules/fragments-on-composite-type.md)|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.|![recommended][]|🔮|
18
- [input-name](rules/input-name.md)|Require mutation argument to be always called "input" and input type to be called Mutation name + "Input".|![all][]|🚀|
19
- [known-argument-names](rules/known-argument-names.md)|A GraphQL field is only valid if all supplied arguments are defined by that field.|![recommended][]|🔮|
20
- [known-directives](rules/known-directives.md)|A GraphQL document is only valid if all `@directives` are known by the schema and legally positioned.|![recommended][]|🔮|
21
- [known-fragment-names](rules/known-fragment-names.md)|A GraphQL document is only valid if all `...Fragment` fragment spreads refer to fragments defined in the same document.|![recommended][]|🔮|
22
- [known-type-names](rules/known-type-names.md)|A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.|![recommended][]|🔮|
23
- [lone-anonymous-operation](rules/lone-anonymous-operation.md)|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.|![recommended][]|🔮|
24
- [lone-schema-definition](rules/lone-schema-definition.md)|A GraphQL document is only valid if it contains only one schema definition.|![recommended][]|🔮|
25
- [match-document-filename](rules/match-document-filename.md)|This rule allows you to enforce that the file name should match the operation name.|![all][]|🚀|
26
- [naming-convention](rules/naming-convention.md)|Require names to follow specified conventions.|![recommended][]|🚀|
27
- [no-anonymous-operations](rules/no-anonymous-operations.md)|Require name for your GraphQL operations. This is useful since most GraphQL client libraries are using the operation name for caching purposes.|![recommended][]|🚀|
28
- [no-case-insensitive-enum-values-duplicates](rules/no-case-insensitive-enum-values-duplicates.md)|Disallow case-insensitive enum values duplicates.|![recommended][]|🚀|
29
- [no-deprecated](rules/no-deprecated.md)|Enforce that deprecated fields or enum values are not in use by operations.|![recommended][]|🚀|
30
- [no-duplicate-fields](rules/no-duplicate-fields.md)|Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.|![recommended][]|🚀|
31
- [no-fragment-cycles](rules/no-fragment-cycles.md)|A GraphQL fragment is only valid when it does not have cycles in fragments usage.|![recommended][]|🔮|
32
- [no-hashtag-description](rules/no-hashtag-description.md)|Requires to use `"""` or `"` for adding a GraphQL description instead of `#`.|![recommended][]|🚀|
33
- [no-root-type](rules/no-root-type.md)|Disallow using root types `mutation` and/or `subscription`.||🚀|
34
- [no-scalar-result-type-on-mutation](rules/no-scalar-result-type-on-mutation.md)|Avoid scalar result type on mutation type to make sure to return a valid state.|![all][]|🚀|
35
- [no-typename-prefix](rules/no-typename-prefix.md)|Enforces users to avoid using the type name in a field name while defining your schema.|![recommended][]|🚀|
36
- [no-undefined-variables](rules/no-undefined-variables.md)|A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.|![recommended][]|🔮|
37
- [no-unreachable-types](rules/no-unreachable-types.md)|Requires all types to be reachable at some level by root level fields.|![recommended][]|🚀|🔧
38
- [no-unused-fields](rules/no-unused-fields.md)|Requires all fields to be used at some level by siblings operations.||🚀|🔧
39
- [no-unused-fragments](rules/no-unused-fragments.md)|A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.|![recommended][]|🔮|
40
- [no-unused-variables](rules/no-unused-variables.md)|A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.|![recommended][]|🔮|
41
- [one-field-subscriptions](rules/one-field-subscriptions.md)|A GraphQL subscription is valid only if it contains a single root field.|![recommended][]|🔮|
42
- [overlapping-fields-can-be-merged](rules/overlapping-fields-can-be-merged.md)|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.|![recommended][]|🔮|
43
- [possible-fragment-spread](rules/possible-fragment-spread.md)|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.|![recommended][]|🔮|
44
- [possible-type-extension](rules/possible-type-extension.md)|A type extension is only valid if the type is defined and has the same kind.||🔮|
45
- [provided-required-arguments](rules/provided-required-arguments.md)|A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.|![recommended][]|🔮|
46
- [require-deprecation-date](rules/require-deprecation-date.md)|Require deletion date on `@deprecated` directive. Suggest removing deprecated things after deprecated date.|![all][]|🚀|
47
- [require-deprecation-reason](rules/require-deprecation-reason.md)|Require all deprecation directives to specify a reason.|![recommended][]|🚀|
48
- [require-description](rules/require-description.md)|Enforce descriptions in your type definitions.|![recommended][]|🚀|
49
- [require-field-of-type-query-in-mutation-result](rules/require-field-of-type-query-in-mutation-result.md)|Allow the client in one round-trip not only to call mutation but also to get a wagon of data to update their application.|![all][]|🚀|
50
- [require-id-when-available](rules/require-id-when-available.md)|Enforce selecting specific fields when they are available on the GraphQL type.|![recommended][]|🚀|
51
- [scalar-leafs](rules/scalar-leafs.md)|A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.|![recommended][]|🔮|
52
- [selection-set-depth](rules/selection-set-depth.md)|Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://github.com/stems/graphql-depth-limit).|![recommended][]|🚀|
53
- [strict-id-in-types](rules/strict-id-in-types.md)|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.|![recommended][]|🚀|
54
- [unique-argument-names](rules/unique-argument-names.md)|A GraphQL field or directive is only valid if all supplied arguments are uniquely named.|![recommended][]|🔮|
55
- [unique-directive-names](rules/unique-directive-names.md)|A GraphQL document is only valid if all defined directives have unique names.|![recommended][]|🔮|
56
- [unique-directive-names-per-location](rules/unique-directive-names-per-location.md)|A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.|![recommended][]|🔮|
57
- [unique-enum-value-names](rules/unique-enum-value-names.md)|A GraphQL enum type is only valid if all its values are uniquely named.||🔮|
58
- [unique-field-definition-names](rules/unique-field-definition-names.md)|A GraphQL complex type is only valid if all its fields are uniquely named.|![recommended][]|🔮|
59
- [unique-fragment-name](rules/unique-fragment-name.md)|Enforce unique fragment names across your project.|![all][]|🚀|
60
- [unique-input-field-names](rules/unique-input-field-names.md)|A GraphQL input object value is only valid if all supplied fields are uniquely named.|![recommended][]|🔮|
61
- [unique-operation-name](rules/unique-operation-name.md)|Enforce unique operation names across your project.|![all][]|🚀|
62
- [unique-operation-types](rules/unique-operation-types.md)|A GraphQL document is only valid if it has only one type per operation.|![recommended][]|🔮|
63
- [unique-type-names](rules/unique-type-names.md)|A GraphQL document is only valid if all defined types have unique names.|![recommended][]|🔮|
64
- [unique-variable-names](rules/unique-variable-names.md)|A GraphQL operation is only valid if all its variables are uniquely named.|![recommended][]|🔮|
65
- [value-literals-of-correct-type](rules/value-literals-of-correct-type.md)|A GraphQL document is only valid if all value literals are of the type expected at their position.|![recommended][]|🔮|
66
- [variables-are-input-types](rules/variables-are-input-types.md)|A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).|![recommended][]|🔮|
67
- [variables-in-allowed-position](rules/variables-in-allowed-position.md)|Variables passed to field arguments conform to type.|![recommended][]|🔮|
10
+ Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|Description|&nbsp;&nbsp;&nbsp;&nbsp;Config&nbsp;&nbsp;&nbsp;&nbsp;|🚀&nbsp;/&nbsp;🔮
11
+ -|-|:-:|:-:
12
+ [alphabetize](rules/alphabetize.md)|Enforce arrange in alphabetical order for type fields, enum values, input object fields, operation selections and more.|![all][]|🚀
13
+ [description-style](rules/description-style.md)|Require all comments to follow the same style (either block or inline).|![recommended][]|🚀
14
+ [executable-definitions](rules/executable-definitions.md)|A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.|![recommended][]|🔮
15
+ [fields-on-correct-type](rules/fields-on-correct-type.md)|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`.|![recommended][]|🔮
16
+ [fragments-on-composite-type](rules/fragments-on-composite-type.md)|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.|![recommended][]|🔮
17
+ [input-name](rules/input-name.md)|Require mutation argument to be always called "input" and input type to be called Mutation name + "Input".|![all][]|🚀
18
+ [known-argument-names](rules/known-argument-names.md)|A GraphQL field is only valid if all supplied arguments are defined by that field.|![recommended][]|🔮
19
+ [known-directives](rules/known-directives.md)|A GraphQL document is only valid if all `@directives` are known by the schema and legally positioned.|![recommended][]|🔮
20
+ [known-fragment-names](rules/known-fragment-names.md)|A GraphQL document is only valid if all `...Fragment` fragment spreads refer to fragments defined in the same document.|![recommended][]|🔮
21
+ [known-type-names](rules/known-type-names.md)|A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.|![recommended][]|🔮
22
+ [lone-anonymous-operation](rules/lone-anonymous-operation.md)|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.|![recommended][]|🔮
23
+ [lone-schema-definition](rules/lone-schema-definition.md)|A GraphQL document is only valid if it contains only one schema definition.|![recommended][]|🔮
24
+ [match-document-filename](rules/match-document-filename.md)|This rule allows you to enforce that the file name should match the operation name.|![all][]|🚀
25
+ [naming-convention](rules/naming-convention.md)|Require names to follow specified conventions.|![recommended][]|🚀
26
+ [no-anonymous-operations](rules/no-anonymous-operations.md)|Require name for your GraphQL operations. This is useful since most GraphQL client libraries are using the operation name for caching purposes.|![recommended][]|🚀
27
+ [no-case-insensitive-enum-values-duplicates](rules/no-case-insensitive-enum-values-duplicates.md)|Disallow case-insensitive enum values duplicates.|![recommended][]|🚀
28
+ [no-deprecated](rules/no-deprecated.md)|Enforce that deprecated fields or enum values are not in use by operations.|![recommended][]|🚀
29
+ [no-duplicate-fields](rules/no-duplicate-fields.md)|Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.|![recommended][]|🚀
30
+ [no-fragment-cycles](rules/no-fragment-cycles.md)|A GraphQL fragment is only valid when it does not have cycles in fragments usage.|![recommended][]|🔮
31
+ [no-hashtag-description](rules/no-hashtag-description.md)|Requires to use `"""` or `"` for adding a GraphQL description instead of `#`.|![recommended][]|🚀
32
+ [no-root-type](rules/no-root-type.md)|Disallow using root types `mutation` and/or `subscription`.||🚀
33
+ [no-scalar-result-type-on-mutation](rules/no-scalar-result-type-on-mutation.md)|Avoid scalar result type on mutation type to make sure to return a valid state.|![all][]|🚀
34
+ [no-typename-prefix](rules/no-typename-prefix.md)|Enforces users to avoid using the type name in a field name while defining your schema.|![recommended][]|🚀
35
+ [no-undefined-variables](rules/no-undefined-variables.md)|A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.|![recommended][]|🔮
36
+ [no-unreachable-types](rules/no-unreachable-types.md)|Requires all types to be reachable at some level by root level fields.|![recommended][]|🚀
37
+ [no-unused-fields](rules/no-unused-fields.md)|Requires all fields to be used at some level by siblings operations.||🚀
38
+ [no-unused-fragments](rules/no-unused-fragments.md)|A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.|![recommended][]|🔮
39
+ [no-unused-variables](rules/no-unused-variables.md)|A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.|![recommended][]|🔮
40
+ [one-field-subscriptions](rules/one-field-subscriptions.md)|A GraphQL subscription is valid only if it contains a single root field.|![recommended][]|🔮
41
+ [overlapping-fields-can-be-merged](rules/overlapping-fields-can-be-merged.md)|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.|![recommended][]|🔮
42
+ [possible-fragment-spread](rules/possible-fragment-spread.md)|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.|![recommended][]|🔮
43
+ [possible-type-extension](rules/possible-type-extension.md)|A type extension is only valid if the type is defined and has the same kind.||🔮
44
+ [provided-required-arguments](rules/provided-required-arguments.md)|A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.|![recommended][]|🔮
45
+ [require-deprecation-date](rules/require-deprecation-date.md)|Require deletion date on `@deprecated` directive. Suggest removing deprecated things after deprecated date.|![all][]|🚀
46
+ [require-deprecation-reason](rules/require-deprecation-reason.md)|Require all deprecation directives to specify a reason.|![recommended][]|🚀
47
+ [require-description](rules/require-description.md)|Enforce descriptions in your type definitions.|![recommended][]|🚀
48
+ [require-field-of-type-query-in-mutation-result](rules/require-field-of-type-query-in-mutation-result.md)|Allow the client in one round-trip not only to call mutation but also to get a wagon of data to update their application.|![all][]|🚀
49
+ [require-id-when-available](rules/require-id-when-available.md)|Enforce selecting specific fields when they are available on the GraphQL type.|![recommended][]|🚀
50
+ [scalar-leafs](rules/scalar-leafs.md)|A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.|![recommended][]|🔮
51
+ [selection-set-depth](rules/selection-set-depth.md)|Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://github.com/stems/graphql-depth-limit).|![recommended][]|🚀
52
+ [strict-id-in-types](rules/strict-id-in-types.md)|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.|![recommended][]|🚀
53
+ [unique-argument-names](rules/unique-argument-names.md)|A GraphQL field or directive is only valid if all supplied arguments are uniquely named.|![recommended][]|🔮
54
+ [unique-directive-names](rules/unique-directive-names.md)|A GraphQL document is only valid if all defined directives have unique names.|![recommended][]|🔮
55
+ [unique-directive-names-per-location](rules/unique-directive-names-per-location.md)|A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.|![recommended][]|🔮
56
+ [unique-enum-value-names](rules/unique-enum-value-names.md)|A GraphQL enum type is only valid if all its values are uniquely named.||🔮
57
+ [unique-field-definition-names](rules/unique-field-definition-names.md)|A GraphQL complex type is only valid if all its fields are uniquely named.|![recommended][]|🔮
58
+ [unique-fragment-name](rules/unique-fragment-name.md)|Enforce unique fragment names across your project.|![all][]|🚀
59
+ [unique-input-field-names](rules/unique-input-field-names.md)|A GraphQL input object value is only valid if all supplied fields are uniquely named.|![recommended][]|🔮
60
+ [unique-operation-name](rules/unique-operation-name.md)|Enforce unique operation names across your project.|![all][]|🚀
61
+ [unique-operation-types](rules/unique-operation-types.md)|A GraphQL document is only valid if it has only one type per operation.|![recommended][]|🔮
62
+ [unique-type-names](rules/unique-type-names.md)|A GraphQL document is only valid if all defined types have unique names.|![recommended][]|🔮
63
+ [unique-variable-names](rules/unique-variable-names.md)|A GraphQL operation is only valid if all its variables are uniquely named.|![recommended][]|🔮
64
+ [value-literals-of-correct-type](rules/value-literals-of-correct-type.md)|A GraphQL document is only valid if all value literals are of the type expected at their position.|![recommended][]|🔮
65
+ [variables-are-input-types](rules/variables-are-input-types.md)|A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).|![recommended][]|🔮
66
+ [variables-in-allowed-position](rules/variables-in-allowed-position.md)|Variables passed to field arguments conform to type.|![recommended][]|🔮
68
67
  <!-- prettier-ignore-end -->
69
68
  [recommended]: https://img.shields.io/badge/-recommended-green.svg
70
69
  [all]: https://img.shields.io/badge/-all-blue.svg
@@ -2,8 +2,6 @@
2
2
 
3
3
  ✅ The `"extends": "plugin:@graphql-eslint/schema-recommended"` property in a configuration file enables this rule.
4
4
 
5
- 🔧 The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#--fix) can automatically fix some of the problems reported by this rule.
6
-
7
5
  - Category: `Schema`
8
6
  - Rule name: `@graphql-eslint/no-unreachable-types`
9
7
  - Requires GraphQL Schema: `true` [ℹ️](../../README.md#extended-linting-rules-with-graphql-schema)
@@ -1,7 +1,5 @@
1
1
  # `no-unused-fields`
2
2
 
3
- 🔧 The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#--fix) can automatically fix some of the problems reported by this rule.
4
-
5
3
  - Category: `Schema`
6
4
  - Rule name: `@graphql-eslint/no-unused-fields`
7
5
  - Requires GraphQL Schema: `true` [ℹ️](../../README.md#extended-linting-rules-with-graphql-schema)
package/index.js CHANGED
@@ -335,30 +335,42 @@ function getLocation(loc, fieldName = '', offset) {
335
335
  };
336
336
  }
337
337
 
338
- function extractRuleName(stack) {
339
- const match = (stack || '').match(/validation[/\\]rules[/\\](.*?)\.js:/) || [];
340
- return match[1] || null;
341
- }
342
- function validateDoc(sourceNode, context, schema, documentNode, rules, ruleName = null) {
343
- var _a;
344
- if (((_a = documentNode === null || documentNode === void 0 ? void 0 : documentNode.definitions) === null || _a === void 0 ? void 0 : _a.length) > 0) {
345
- try {
346
- const validationErrors = schema ? graphql.validate(schema, documentNode, rules) : validate.validateSDL(documentNode, null, rules);
347
- for (const error of validationErrors) {
348
- const validateRuleName = ruleName || `[${extractRuleName(error.stack)}]`;
349
- context.report({
350
- loc: getLocation({ start: error.locations[0] }),
351
- message: ruleName ? error.message : `${validateRuleName} ${error.message}`,
352
- });
353
- }
354
- }
355
- catch (e) {
338
+ function validateDoc(sourceNode, context, schema, documentNode, rules) {
339
+ if (documentNode.definitions.length === 0) {
340
+ return;
341
+ }
342
+ try {
343
+ const validationErrors = schema
344
+ ? graphql.validate(schema, documentNode, rules)
345
+ : validate.validateSDL(documentNode, null, rules);
346
+ for (const error of validationErrors) {
347
+ /*
348
+ * TODO: Fix ESTree-AST converter because currently it's incorrectly convert loc.end
349
+ * Example: loc.end always equal loc.start
350
+ * {
351
+ * token: {
352
+ * type: 'Name',
353
+ * loc: { start: { line: 4, column: 13 }, end: { line: 4, column: 13 } },
354
+ * value: 'veryBad',
355
+ * range: [ 40, 47 ]
356
+ * }
357
+ * }
358
+ */
359
+ const { line, column } = error.locations[0];
360
+ const ancestors = context.getAncestors();
361
+ const token = ancestors[0].tokens.find(token => token.loc.start.line === line && token.loc.start.column === column);
356
362
  context.report({
357
- node: sourceNode,
358
- message: e.message,
363
+ loc: getLocation({ start: error.locations[0] }, token === null || token === void 0 ? void 0 : token.value),
364
+ message: error.message,
359
365
  });
360
366
  }
361
367
  }
368
+ catch (e) {
369
+ context.report({
370
+ node: sourceNode,
371
+ message: e.message,
372
+ });
373
+ }
362
374
  }
363
375
  const isGraphQLImportFile = rawSDL => {
364
376
  const trimmedRawSDL = rawSDL.trimLeft();
@@ -405,7 +417,7 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
405
417
  if (isRealFile && getDocumentNode) {
406
418
  documentNode = getDocumentNode(context);
407
419
  }
408
- validateDoc(node, context, schema, documentNode || node.rawNode(), [ruleFn], ruleName);
420
+ validateDoc(node, context, schema, documentNode || node.rawNode(), [ruleFn]);
409
421
  },
410
422
  };
411
423
  },
@@ -1845,7 +1857,7 @@ const HASHTAG_COMMENT = 'HASHTAG_COMMENT';
1845
1857
  const rule$9 = {
1846
1858
  meta: {
1847
1859
  messages: {
1848
- [HASHTAG_COMMENT]: 'Using hashtag (#) for adding GraphQL descriptions is not allowed. Prefer using """ for multiline, or " for a single line description.',
1860
+ [HASHTAG_COMMENT]: `Using hashtag (#) for adding GraphQL descriptions is not allowed. Prefer using """ for multiline, or " for a single line description.`,
1849
1861
  },
1850
1862
  docs: {
1851
1863
  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.',
@@ -1892,14 +1904,15 @@ const rule$9 = {
1892
1904
  schema: [],
1893
1905
  },
1894
1906
  create(context) {
1907
+ const selector = `${graphql.Kind.DOCUMENT}[definitions.0.kind!=/^(${graphql.Kind.OPERATION_DEFINITION}|${graphql.Kind.FRAGMENT_DEFINITION})$/]`;
1895
1908
  return {
1896
- Document(node) {
1909
+ [selector](node) {
1897
1910
  const rawNode = node.rawNode();
1898
1911
  let token = rawNode.loc.startToken;
1899
1912
  while (token !== null) {
1900
1913
  const { kind, prev, next, value, line, column } = token;
1901
1914
  if (kind === graphql.TokenKind.COMMENT && prev && next) {
1902
- const isEslintComment = value.trimLeft().startsWith('eslint');
1915
+ const isEslintComment = value.trimStart().startsWith('eslint');
1903
1916
  const linesAfter = next.line - line;
1904
1917
  if (!isEslintComment && line !== prev.line && next.kind === graphql.TokenKind.NAME && linesAfter < 2) {
1905
1918
  context.report({
@@ -2106,7 +2119,22 @@ const rule$c = {
2106
2119
  };
2107
2120
 
2108
2121
  const UNREACHABLE_TYPE = 'UNREACHABLE_TYPE';
2109
- const RULE_NAME = 'no-unreachable-types';
2122
+ const RULE_ID = 'no-unreachable-types';
2123
+ const KINDS = [
2124
+ graphql.Kind.DIRECTIVE_DEFINITION,
2125
+ graphql.Kind.OBJECT_TYPE_DEFINITION,
2126
+ graphql.Kind.OBJECT_TYPE_EXTENSION,
2127
+ graphql.Kind.INTERFACE_TYPE_DEFINITION,
2128
+ graphql.Kind.INTERFACE_TYPE_EXTENSION,
2129
+ graphql.Kind.SCALAR_TYPE_DEFINITION,
2130
+ graphql.Kind.SCALAR_TYPE_EXTENSION,
2131
+ graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION,
2132
+ graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION,
2133
+ graphql.Kind.UNION_TYPE_DEFINITION,
2134
+ graphql.Kind.UNION_TYPE_EXTENSION,
2135
+ graphql.Kind.ENUM_TYPE_DEFINITION,
2136
+ graphql.Kind.ENUM_TYPE_EXTENSION,
2137
+ ];
2110
2138
  const rule$d = {
2111
2139
  meta: {
2112
2140
  messages: {
@@ -2115,7 +2143,7 @@ const rule$d = {
2115
2143
  docs: {
2116
2144
  description: `Requires all types to be reachable at some level by root level fields.`,
2117
2145
  category: 'Schema',
2118
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME}.md`,
2146
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
2119
2147
  requiresSchema: true,
2120
2148
  examples: [
2121
2149
  {
@@ -2147,43 +2175,36 @@ const rule$d = {
2147
2175
  ],
2148
2176
  recommended: true,
2149
2177
  },
2150
- fixable: 'code',
2151
2178
  type: 'suggestion',
2152
2179
  schema: [],
2180
+ hasSuggestions: true,
2153
2181
  },
2154
2182
  create(context) {
2155
- const reachableTypes = requireReachableTypesFromContext(RULE_NAME, context);
2156
- function ensureReachability(node) {
2157
- const typeName = node.name.value;
2158
- if (!reachableTypes.has(typeName)) {
2159
- context.report({
2160
- loc: getLocation(node.name.loc, typeName, { offsetStart: node.kind === graphql.Kind.DIRECTIVE_DEFINITION ? 2 : 1 }),
2161
- messageId: UNREACHABLE_TYPE,
2162
- data: { typeName },
2163
- fix: fixer => fixer.remove(node),
2164
- });
2165
- }
2166
- }
2183
+ const reachableTypes = requireReachableTypesFromContext(RULE_ID, context);
2184
+ const selector = KINDS.join(',');
2167
2185
  return {
2168
- DirectiveDefinition: ensureReachability,
2169
- ObjectTypeDefinition: ensureReachability,
2170
- ObjectTypeExtension: ensureReachability,
2171
- InterfaceTypeDefinition: ensureReachability,
2172
- InterfaceTypeExtension: ensureReachability,
2173
- ScalarTypeDefinition: ensureReachability,
2174
- ScalarTypeExtension: ensureReachability,
2175
- InputObjectTypeDefinition: ensureReachability,
2176
- InputObjectTypeExtension: ensureReachability,
2177
- UnionTypeDefinition: ensureReachability,
2178
- UnionTypeExtension: ensureReachability,
2179
- EnumTypeDefinition: ensureReachability,
2180
- EnumTypeExtension: ensureReachability,
2186
+ [selector](node) {
2187
+ const typeName = node.name.value;
2188
+ if (!reachableTypes.has(typeName)) {
2189
+ context.report({
2190
+ loc: getLocation(node.name.loc, typeName, { offsetStart: node.kind === graphql.Kind.DIRECTIVE_DEFINITION ? 2 : 1 }),
2191
+ messageId: UNREACHABLE_TYPE,
2192
+ data: { typeName },
2193
+ suggest: [
2194
+ {
2195
+ desc: `Remove ${typeName}`,
2196
+ fix: fixer => fixer.remove(node),
2197
+ },
2198
+ ],
2199
+ });
2200
+ }
2201
+ },
2181
2202
  };
2182
2203
  },
2183
2204
  };
2184
2205
 
2185
2206
  const UNUSED_FIELD = 'UNUSED_FIELD';
2186
- const RULE_NAME$1 = 'no-unused-fields';
2207
+ const RULE_ID$1 = 'no-unused-fields';
2187
2208
  const rule$e = {
2188
2209
  meta: {
2189
2210
  messages: {
@@ -2192,7 +2213,7 @@ const rule$e = {
2192
2213
  docs: {
2193
2214
  description: `Requires all fields to be used at some level by siblings operations.`,
2194
2215
  category: 'Schema',
2195
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$1}.md`,
2216
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID$1}.md`,
2196
2217
  requiresSiblings: true,
2197
2218
  requiresSchema: true,
2198
2219
  examples: [
@@ -2239,12 +2260,12 @@ const rule$e = {
2239
2260
  },
2240
2261
  ],
2241
2262
  },
2242
- fixable: 'code',
2243
2263
  type: 'suggestion',
2244
2264
  schema: [],
2265
+ hasSuggestions: true,
2245
2266
  },
2246
2267
  create(context) {
2247
- const usedFields = requireUsedFieldsFromContext(RULE_NAME$1, context);
2268
+ const usedFields = requireUsedFieldsFromContext(RULE_ID$1, context);
2248
2269
  return {
2249
2270
  FieldDefinition(node) {
2250
2271
  var _a;
@@ -2258,22 +2279,18 @@ const rule$e = {
2258
2279
  loc: getLocation(node.loc, fieldName),
2259
2280
  messageId: UNUSED_FIELD,
2260
2281
  data: { fieldName },
2261
- fix(fixer) {
2262
- const sourceCode = context.getSourceCode();
2263
- const tokenBefore = sourceCode.getTokenBefore(node);
2264
- const tokenAfter = sourceCode.getTokenAfter(node);
2265
- const isEmptyType = tokenBefore.type === '{' && tokenAfter.type === '}';
2266
- if (isEmptyType) {
2267
- // Remove type
2268
- const { parent } = node;
2269
- const parentBeforeToken = sourceCode.getTokenBefore(parent);
2270
- return parentBeforeToken
2271
- ? fixer.removeRange([parentBeforeToken.range[1], parent.range[1]])
2272
- : fixer.remove(parent);
2273
- }
2274
- // Remove whitespace before token
2275
- return fixer.removeRange([tokenBefore.range[1], node.range[1]]);
2276
- },
2282
+ suggest: [
2283
+ {
2284
+ desc: `Remove "${fieldName}" field`,
2285
+ fix(fixer) {
2286
+ const sourceCode = context.getSourceCode();
2287
+ const tokenBefore = sourceCode.getTokenBefore(node);
2288
+ const tokenAfter = sourceCode.getTokenAfter(node);
2289
+ const isEmptyType = tokenBefore.type === '{' && tokenAfter.type === '}';
2290
+ return isEmptyType ? fixer.remove(node.parent) : fixer.remove(node);
2291
+ },
2292
+ },
2293
+ ],
2277
2294
  });
2278
2295
  },
2279
2296
  };
@@ -2636,14 +2653,14 @@ const rule$h = {
2636
2653
  },
2637
2654
  };
2638
2655
 
2639
- const RULE_NAME$2 = 'require-field-of-type-query-in-mutation-result';
2656
+ const RULE_NAME = 'require-field-of-type-query-in-mutation-result';
2640
2657
  const rule$i = {
2641
2658
  meta: {
2642
2659
  type: 'suggestion',
2643
2660
  docs: {
2644
2661
  category: 'Schema',
2645
2662
  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`.',
2646
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$2}.md`,
2663
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME}.md`,
2647
2664
  requiresSchema: true,
2648
2665
  examples: [
2649
2666
  {
@@ -2678,7 +2695,7 @@ const rule$i = {
2678
2695
  schema: [],
2679
2696
  },
2680
2697
  create(context) {
2681
- const schema = requireGraphQLSchemaFromContext(RULE_NAME$2, context);
2698
+ const schema = requireGraphQLSchemaFromContext(RULE_NAME, context);
2682
2699
  const mutationType = schema.getMutationType();
2683
2700
  const queryType = schema.getQueryType();
2684
2701
  if (!mutationType || !queryType) {
@@ -3221,7 +3238,7 @@ const rule$l = {
3221
3238
  },
3222
3239
  };
3223
3240
 
3224
- const RULE_NAME$3 = 'unique-fragment-name';
3241
+ const RULE_NAME$1 = 'unique-fragment-name';
3225
3242
  const UNIQUE_FRAGMENT_NAME = 'UNIQUE_FRAGMENT_NAME';
3226
3243
  const checkNode = (context, node, ruleName, messageId) => {
3227
3244
  const documentName = node.name.value;
@@ -3253,7 +3270,7 @@ const rule$m = {
3253
3270
  docs: {
3254
3271
  category: 'Operations',
3255
3272
  description: `Enforce unique fragment names across your project.`,
3256
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$3}.md`,
3273
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$1}.md`,
3257
3274
  requiresSiblings: true,
3258
3275
  examples: [
3259
3276
  {
@@ -3298,13 +3315,13 @@ const rule$m = {
3298
3315
  create(context) {
3299
3316
  return {
3300
3317
  FragmentDefinition(node) {
3301
- checkNode(context, node, RULE_NAME$3, UNIQUE_FRAGMENT_NAME);
3318
+ checkNode(context, node, RULE_NAME$1, UNIQUE_FRAGMENT_NAME);
3302
3319
  },
3303
3320
  };
3304
3321
  },
3305
3322
  };
3306
3323
 
3307
- const RULE_NAME$4 = 'unique-operation-name';
3324
+ const RULE_NAME$2 = 'unique-operation-name';
3308
3325
  const UNIQUE_OPERATION_NAME = 'UNIQUE_OPERATION_NAME';
3309
3326
  const rule$n = {
3310
3327
  meta: {
@@ -3312,7 +3329,7 @@ const rule$n = {
3312
3329
  docs: {
3313
3330
  category: 'Operations',
3314
3331
  description: `Enforce unique operation names across your project.`,
3315
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$4}.md`,
3332
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$2}.md`,
3316
3333
  requiresSiblings: true,
3317
3334
  examples: [
3318
3335
  {
@@ -3361,7 +3378,7 @@ const rule$n = {
3361
3378
  create(context) {
3362
3379
  return {
3363
3380
  'OperationDefinition[name!=undefined]'(node) {
3364
- checkNode(context, node, RULE_NAME$4, UNIQUE_OPERATION_NAME);
3381
+ checkNode(context, node, RULE_NAME$2, UNIQUE_OPERATION_NAME);
3365
3382
  },
3366
3383
  };
3367
3384
  },
package/index.mjs CHANGED
@@ -329,30 +329,42 @@ function getLocation(loc, fieldName = '', offset) {
329
329
  };
330
330
  }
331
331
 
332
- function extractRuleName(stack) {
333
- const match = (stack || '').match(/validation[/\\]rules[/\\](.*?)\.js:/) || [];
334
- return match[1] || null;
335
- }
336
- function validateDoc(sourceNode, context, schema, documentNode, rules, ruleName = null) {
337
- var _a;
338
- if (((_a = documentNode === null || documentNode === void 0 ? void 0 : documentNode.definitions) === null || _a === void 0 ? void 0 : _a.length) > 0) {
339
- try {
340
- const validationErrors = schema ? validate(schema, documentNode, rules) : validateSDL(documentNode, null, rules);
341
- for (const error of validationErrors) {
342
- const validateRuleName = ruleName || `[${extractRuleName(error.stack)}]`;
343
- context.report({
344
- loc: getLocation({ start: error.locations[0] }),
345
- message: ruleName ? error.message : `${validateRuleName} ${error.message}`,
346
- });
347
- }
348
- }
349
- catch (e) {
332
+ function validateDoc(sourceNode, context, schema, documentNode, rules) {
333
+ if (documentNode.definitions.length === 0) {
334
+ return;
335
+ }
336
+ try {
337
+ const validationErrors = schema
338
+ ? validate(schema, documentNode, rules)
339
+ : validateSDL(documentNode, null, rules);
340
+ for (const error of validationErrors) {
341
+ /*
342
+ * TODO: Fix ESTree-AST converter because currently it's incorrectly convert loc.end
343
+ * Example: loc.end always equal loc.start
344
+ * {
345
+ * token: {
346
+ * type: 'Name',
347
+ * loc: { start: { line: 4, column: 13 }, end: { line: 4, column: 13 } },
348
+ * value: 'veryBad',
349
+ * range: [ 40, 47 ]
350
+ * }
351
+ * }
352
+ */
353
+ const { line, column } = error.locations[0];
354
+ const ancestors = context.getAncestors();
355
+ const token = ancestors[0].tokens.find(token => token.loc.start.line === line && token.loc.start.column === column);
350
356
  context.report({
351
- node: sourceNode,
352
- message: e.message,
357
+ loc: getLocation({ start: error.locations[0] }, token === null || token === void 0 ? void 0 : token.value),
358
+ message: error.message,
353
359
  });
354
360
  }
355
361
  }
362
+ catch (e) {
363
+ context.report({
364
+ node: sourceNode,
365
+ message: e.message,
366
+ });
367
+ }
356
368
  }
357
369
  const isGraphQLImportFile = rawSDL => {
358
370
  const trimmedRawSDL = rawSDL.trimLeft();
@@ -399,7 +411,7 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
399
411
  if (isRealFile && getDocumentNode) {
400
412
  documentNode = getDocumentNode(context);
401
413
  }
402
- validateDoc(node, context, schema, documentNode || node.rawNode(), [ruleFn], ruleName);
414
+ validateDoc(node, context, schema, documentNode || node.rawNode(), [ruleFn]);
403
415
  },
404
416
  };
405
417
  },
@@ -1839,7 +1851,7 @@ const HASHTAG_COMMENT = 'HASHTAG_COMMENT';
1839
1851
  const rule$9 = {
1840
1852
  meta: {
1841
1853
  messages: {
1842
- [HASHTAG_COMMENT]: 'Using hashtag (#) for adding GraphQL descriptions is not allowed. Prefer using """ for multiline, or " for a single line description.',
1854
+ [HASHTAG_COMMENT]: `Using hashtag (#) for adding GraphQL descriptions is not allowed. Prefer using """ for multiline, or " for a single line description.`,
1843
1855
  },
1844
1856
  docs: {
1845
1857
  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.',
@@ -1886,14 +1898,15 @@ const rule$9 = {
1886
1898
  schema: [],
1887
1899
  },
1888
1900
  create(context) {
1901
+ const selector = `${Kind.DOCUMENT}[definitions.0.kind!=/^(${Kind.OPERATION_DEFINITION}|${Kind.FRAGMENT_DEFINITION})$/]`;
1889
1902
  return {
1890
- Document(node) {
1903
+ [selector](node) {
1891
1904
  const rawNode = node.rawNode();
1892
1905
  let token = rawNode.loc.startToken;
1893
1906
  while (token !== null) {
1894
1907
  const { kind, prev, next, value, line, column } = token;
1895
1908
  if (kind === TokenKind.COMMENT && prev && next) {
1896
- const isEslintComment = value.trimLeft().startsWith('eslint');
1909
+ const isEslintComment = value.trimStart().startsWith('eslint');
1897
1910
  const linesAfter = next.line - line;
1898
1911
  if (!isEslintComment && line !== prev.line && next.kind === TokenKind.NAME && linesAfter < 2) {
1899
1912
  context.report({
@@ -2100,7 +2113,22 @@ const rule$c = {
2100
2113
  };
2101
2114
 
2102
2115
  const UNREACHABLE_TYPE = 'UNREACHABLE_TYPE';
2103
- const RULE_NAME = 'no-unreachable-types';
2116
+ const RULE_ID = 'no-unreachable-types';
2117
+ const KINDS = [
2118
+ Kind.DIRECTIVE_DEFINITION,
2119
+ Kind.OBJECT_TYPE_DEFINITION,
2120
+ Kind.OBJECT_TYPE_EXTENSION,
2121
+ Kind.INTERFACE_TYPE_DEFINITION,
2122
+ Kind.INTERFACE_TYPE_EXTENSION,
2123
+ Kind.SCALAR_TYPE_DEFINITION,
2124
+ Kind.SCALAR_TYPE_EXTENSION,
2125
+ Kind.INPUT_OBJECT_TYPE_DEFINITION,
2126
+ Kind.INPUT_OBJECT_TYPE_EXTENSION,
2127
+ Kind.UNION_TYPE_DEFINITION,
2128
+ Kind.UNION_TYPE_EXTENSION,
2129
+ Kind.ENUM_TYPE_DEFINITION,
2130
+ Kind.ENUM_TYPE_EXTENSION,
2131
+ ];
2104
2132
  const rule$d = {
2105
2133
  meta: {
2106
2134
  messages: {
@@ -2109,7 +2137,7 @@ const rule$d = {
2109
2137
  docs: {
2110
2138
  description: `Requires all types to be reachable at some level by root level fields.`,
2111
2139
  category: 'Schema',
2112
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME}.md`,
2140
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
2113
2141
  requiresSchema: true,
2114
2142
  examples: [
2115
2143
  {
@@ -2141,43 +2169,36 @@ const rule$d = {
2141
2169
  ],
2142
2170
  recommended: true,
2143
2171
  },
2144
- fixable: 'code',
2145
2172
  type: 'suggestion',
2146
2173
  schema: [],
2174
+ hasSuggestions: true,
2147
2175
  },
2148
2176
  create(context) {
2149
- const reachableTypes = requireReachableTypesFromContext(RULE_NAME, context);
2150
- function ensureReachability(node) {
2151
- const typeName = node.name.value;
2152
- if (!reachableTypes.has(typeName)) {
2153
- context.report({
2154
- loc: getLocation(node.name.loc, typeName, { offsetStart: node.kind === Kind.DIRECTIVE_DEFINITION ? 2 : 1 }),
2155
- messageId: UNREACHABLE_TYPE,
2156
- data: { typeName },
2157
- fix: fixer => fixer.remove(node),
2158
- });
2159
- }
2160
- }
2177
+ const reachableTypes = requireReachableTypesFromContext(RULE_ID, context);
2178
+ const selector = KINDS.join(',');
2161
2179
  return {
2162
- DirectiveDefinition: ensureReachability,
2163
- ObjectTypeDefinition: ensureReachability,
2164
- ObjectTypeExtension: ensureReachability,
2165
- InterfaceTypeDefinition: ensureReachability,
2166
- InterfaceTypeExtension: ensureReachability,
2167
- ScalarTypeDefinition: ensureReachability,
2168
- ScalarTypeExtension: ensureReachability,
2169
- InputObjectTypeDefinition: ensureReachability,
2170
- InputObjectTypeExtension: ensureReachability,
2171
- UnionTypeDefinition: ensureReachability,
2172
- UnionTypeExtension: ensureReachability,
2173
- EnumTypeDefinition: ensureReachability,
2174
- EnumTypeExtension: ensureReachability,
2180
+ [selector](node) {
2181
+ const typeName = node.name.value;
2182
+ if (!reachableTypes.has(typeName)) {
2183
+ context.report({
2184
+ loc: getLocation(node.name.loc, typeName, { offsetStart: node.kind === Kind.DIRECTIVE_DEFINITION ? 2 : 1 }),
2185
+ messageId: UNREACHABLE_TYPE,
2186
+ data: { typeName },
2187
+ suggest: [
2188
+ {
2189
+ desc: `Remove ${typeName}`,
2190
+ fix: fixer => fixer.remove(node),
2191
+ },
2192
+ ],
2193
+ });
2194
+ }
2195
+ },
2175
2196
  };
2176
2197
  },
2177
2198
  };
2178
2199
 
2179
2200
  const UNUSED_FIELD = 'UNUSED_FIELD';
2180
- const RULE_NAME$1 = 'no-unused-fields';
2201
+ const RULE_ID$1 = 'no-unused-fields';
2181
2202
  const rule$e = {
2182
2203
  meta: {
2183
2204
  messages: {
@@ -2186,7 +2207,7 @@ const rule$e = {
2186
2207
  docs: {
2187
2208
  description: `Requires all fields to be used at some level by siblings operations.`,
2188
2209
  category: 'Schema',
2189
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$1}.md`,
2210
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID$1}.md`,
2190
2211
  requiresSiblings: true,
2191
2212
  requiresSchema: true,
2192
2213
  examples: [
@@ -2233,12 +2254,12 @@ const rule$e = {
2233
2254
  },
2234
2255
  ],
2235
2256
  },
2236
- fixable: 'code',
2237
2257
  type: 'suggestion',
2238
2258
  schema: [],
2259
+ hasSuggestions: true,
2239
2260
  },
2240
2261
  create(context) {
2241
- const usedFields = requireUsedFieldsFromContext(RULE_NAME$1, context);
2262
+ const usedFields = requireUsedFieldsFromContext(RULE_ID$1, context);
2242
2263
  return {
2243
2264
  FieldDefinition(node) {
2244
2265
  var _a;
@@ -2252,22 +2273,18 @@ const rule$e = {
2252
2273
  loc: getLocation(node.loc, fieldName),
2253
2274
  messageId: UNUSED_FIELD,
2254
2275
  data: { fieldName },
2255
- fix(fixer) {
2256
- const sourceCode = context.getSourceCode();
2257
- const tokenBefore = sourceCode.getTokenBefore(node);
2258
- const tokenAfter = sourceCode.getTokenAfter(node);
2259
- const isEmptyType = tokenBefore.type === '{' && tokenAfter.type === '}';
2260
- if (isEmptyType) {
2261
- // Remove type
2262
- const { parent } = node;
2263
- const parentBeforeToken = sourceCode.getTokenBefore(parent);
2264
- return parentBeforeToken
2265
- ? fixer.removeRange([parentBeforeToken.range[1], parent.range[1]])
2266
- : fixer.remove(parent);
2267
- }
2268
- // Remove whitespace before token
2269
- return fixer.removeRange([tokenBefore.range[1], node.range[1]]);
2270
- },
2276
+ suggest: [
2277
+ {
2278
+ desc: `Remove "${fieldName}" field`,
2279
+ fix(fixer) {
2280
+ const sourceCode = context.getSourceCode();
2281
+ const tokenBefore = sourceCode.getTokenBefore(node);
2282
+ const tokenAfter = sourceCode.getTokenAfter(node);
2283
+ const isEmptyType = tokenBefore.type === '{' && tokenAfter.type === '}';
2284
+ return isEmptyType ? fixer.remove(node.parent) : fixer.remove(node);
2285
+ },
2286
+ },
2287
+ ],
2271
2288
  });
2272
2289
  },
2273
2290
  };
@@ -2630,14 +2647,14 @@ const rule$h = {
2630
2647
  },
2631
2648
  };
2632
2649
 
2633
- const RULE_NAME$2 = 'require-field-of-type-query-in-mutation-result';
2650
+ const RULE_NAME = 'require-field-of-type-query-in-mutation-result';
2634
2651
  const rule$i = {
2635
2652
  meta: {
2636
2653
  type: 'suggestion',
2637
2654
  docs: {
2638
2655
  category: 'Schema',
2639
2656
  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`.',
2640
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$2}.md`,
2657
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME}.md`,
2641
2658
  requiresSchema: true,
2642
2659
  examples: [
2643
2660
  {
@@ -2672,7 +2689,7 @@ const rule$i = {
2672
2689
  schema: [],
2673
2690
  },
2674
2691
  create(context) {
2675
- const schema = requireGraphQLSchemaFromContext(RULE_NAME$2, context);
2692
+ const schema = requireGraphQLSchemaFromContext(RULE_NAME, context);
2676
2693
  const mutationType = schema.getMutationType();
2677
2694
  const queryType = schema.getQueryType();
2678
2695
  if (!mutationType || !queryType) {
@@ -3215,7 +3232,7 @@ const rule$l = {
3215
3232
  },
3216
3233
  };
3217
3234
 
3218
- const RULE_NAME$3 = 'unique-fragment-name';
3235
+ const RULE_NAME$1 = 'unique-fragment-name';
3219
3236
  const UNIQUE_FRAGMENT_NAME = 'UNIQUE_FRAGMENT_NAME';
3220
3237
  const checkNode = (context, node, ruleName, messageId) => {
3221
3238
  const documentName = node.name.value;
@@ -3247,7 +3264,7 @@ const rule$m = {
3247
3264
  docs: {
3248
3265
  category: 'Operations',
3249
3266
  description: `Enforce unique fragment names across your project.`,
3250
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$3}.md`,
3267
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$1}.md`,
3251
3268
  requiresSiblings: true,
3252
3269
  examples: [
3253
3270
  {
@@ -3292,13 +3309,13 @@ const rule$m = {
3292
3309
  create(context) {
3293
3310
  return {
3294
3311
  FragmentDefinition(node) {
3295
- checkNode(context, node, RULE_NAME$3, UNIQUE_FRAGMENT_NAME);
3312
+ checkNode(context, node, RULE_NAME$1, UNIQUE_FRAGMENT_NAME);
3296
3313
  },
3297
3314
  };
3298
3315
  },
3299
3316
  };
3300
3317
 
3301
- const RULE_NAME$4 = 'unique-operation-name';
3318
+ const RULE_NAME$2 = 'unique-operation-name';
3302
3319
  const UNIQUE_OPERATION_NAME = 'UNIQUE_OPERATION_NAME';
3303
3320
  const rule$n = {
3304
3321
  meta: {
@@ -3306,7 +3323,7 @@ const rule$n = {
3306
3323
  docs: {
3307
3324
  category: 'Operations',
3308
3325
  description: `Enforce unique operation names across your project.`,
3309
- url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$4}.md`,
3326
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$2}.md`,
3310
3327
  requiresSiblings: true,
3311
3328
  examples: [
3312
3329
  {
@@ -3355,7 +3372,7 @@ const rule$n = {
3355
3372
  create(context) {
3356
3373
  return {
3357
3374
  'OperationDefinition[name!=undefined]'(node) {
3358
- checkNode(context, node, RULE_NAME$4, UNIQUE_OPERATION_NAME);
3375
+ checkNode(context, node, RULE_NAME$2, UNIQUE_OPERATION_NAME);
3359
3376
  },
3360
3377
  };
3361
3378
  },
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@graphql-eslint/eslint-plugin",
3
- "version": "3.0.1",
3
+ "version": "3.1.1-alpha-f19a99b.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
6
  "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
7
7
  },
8
8
  "dependencies": {
9
9
  "@babel/code-frame": "7.16.0",
10
- "@graphql-tools/code-file-loader": "7.2.2",
10
+ "@graphql-tools/code-file-loader": "7.2.3",
11
11
  "@graphql-tools/graphql-tag-pluck": "7.1.4",
12
- "@graphql-tools/import": "6.6.1",
13
- "@graphql-tools/utils": "8.5.3",
12
+ "@graphql-tools/import": "6.6.2",
13
+ "@graphql-tools/utils": "8.5.4",
14
14
  "graphql-config": "4.1.0",
15
15
  "graphql-depth-limit": "1.1.0",
16
16
  "lodash.lowercase": "4.3.0"
@@ -1,5 +1,5 @@
1
1
  import { GraphQLSchema, DocumentNode, ASTNode, ValidationRule } from 'graphql';
2
2
  import { GraphQLESLintRule, GraphQLESLintRuleContext } from '../types';
3
3
  import { GraphQLESTreeNode } from '../estree-parser';
4
- export declare function validateDoc(sourceNode: GraphQLESTreeNode<ASTNode>, context: GraphQLESLintRuleContext, schema: GraphQLSchema | null, documentNode: DocumentNode, rules: ReadonlyArray<ValidationRule>, ruleName?: string | null): void;
4
+ export declare function validateDoc(sourceNode: GraphQLESTreeNode<ASTNode>, context: GraphQLESLintRuleContext, schema: GraphQLSchema | null, documentNode: DocumentNode, rules: ReadonlyArray<ValidationRule>): void;
5
5
  export declare const GRAPHQL_JS_VALIDATIONS: Record<string, GraphQLESLintRule<any[], false>>;