@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 +57 -58
- package/docs/rules/no-unreachable-types.md +0 -2
- package/docs/rules/no-unused-fields.md +0 -2
- package/index.js +98 -81
- package/index.mjs +98 -81
- package/package.json +4 -4
- package/rules/graphql-js-validation.d.ts +1 -1
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 |Description| Config |🚀 / 
|
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 |Description| Config |🚀 / 🔮
|
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
|
339
|
-
|
340
|
-
|
341
|
-
}
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
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
|
-
|
358
|
-
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]
|
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]:
|
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
|
-
|
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.
|
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
|
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/${
|
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(
|
2156
|
-
|
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
|
-
|
2169
|
-
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
|
2177
|
-
|
2178
|
-
|
2179
|
-
|
2180
|
-
|
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
|
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/${
|
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(
|
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
|
-
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
2269
|
-
|
2270
|
-
|
2271
|
-
|
2272
|
-
|
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
|
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
|
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
|
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$
|
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$
|
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$
|
3318
|
+
checkNode(context, node, RULE_NAME$1, UNIQUE_FRAGMENT_NAME);
|
3302
3319
|
},
|
3303
3320
|
};
|
3304
3321
|
},
|
3305
3322
|
};
|
3306
3323
|
|
3307
|
-
const RULE_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$
|
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$
|
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
|
333
|
-
|
334
|
-
|
335
|
-
}
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
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
|
-
|
352
|
-
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]
|
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]:
|
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
|
-
|
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.
|
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
|
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/${
|
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(
|
2150
|
-
|
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
|
-
|
2163
|
-
|
2164
|
-
|
2165
|
-
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2169
|
-
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
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
|
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/${
|
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(
|
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
|
-
|
2256
|
-
|
2257
|
-
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
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
|
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
|
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
|
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$
|
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$
|
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$
|
3312
|
+
checkNode(context, node, RULE_NAME$1, UNIQUE_FRAGMENT_NAME);
|
3296
3313
|
},
|
3297
3314
|
};
|
3298
3315
|
},
|
3299
3316
|
};
|
3300
3317
|
|
3301
|
-
const RULE_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$
|
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$
|
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.
|
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.
|
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.
|
13
|
-
"@graphql-tools/utils": "8.5.
|
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
|
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>>;
|