@graphql-eslint/eslint-plugin 3.1.0-alpha-878c908.0 → 3.1.0-alpha-27dcb49.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/docs/rules/require-id-when-available.md +1 -16
- package/index.js +120 -124
- package/index.mjs +120 -124
- package/package.json +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)
|
@@ -54,25 +54,10 @@ query user {
|
|
54
54
|
|
55
55
|
The schema defines the following properties:
|
56
56
|
|
57
|
-
### `fieldName`
|
58
|
-
|
59
|
-
The object must be one of the following types:
|
60
|
-
|
61
|
-
* `asString`
|
62
|
-
* `asArray`
|
57
|
+
### `fieldName` (string)
|
63
58
|
|
64
59
|
Default: `"id"`
|
65
60
|
|
66
|
-
---
|
67
|
-
|
68
|
-
# Sub Schemas
|
69
|
-
|
70
|
-
The schema defines the following additional types:
|
71
|
-
|
72
|
-
## `asString` (string)
|
73
|
-
|
74
|
-
## `asArray` (array)
|
75
|
-
|
76
61
|
## Resources
|
77
62
|
|
78
63
|
- [Rule source](../../packages/plugin/src/rules/require-id-when-available.ts)
|
package/index.js
CHANGED
@@ -2106,7 +2106,22 @@ const rule$c = {
|
|
2106
2106
|
};
|
2107
2107
|
|
2108
2108
|
const UNREACHABLE_TYPE = 'UNREACHABLE_TYPE';
|
2109
|
-
const
|
2109
|
+
const RULE_ID = 'no-unreachable-types';
|
2110
|
+
const KINDS = [
|
2111
|
+
graphql.Kind.DIRECTIVE_DEFINITION,
|
2112
|
+
graphql.Kind.OBJECT_TYPE_DEFINITION,
|
2113
|
+
graphql.Kind.OBJECT_TYPE_EXTENSION,
|
2114
|
+
graphql.Kind.INTERFACE_TYPE_DEFINITION,
|
2115
|
+
graphql.Kind.INTERFACE_TYPE_EXTENSION,
|
2116
|
+
graphql.Kind.SCALAR_TYPE_DEFINITION,
|
2117
|
+
graphql.Kind.SCALAR_TYPE_EXTENSION,
|
2118
|
+
graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION,
|
2119
|
+
graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION,
|
2120
|
+
graphql.Kind.UNION_TYPE_DEFINITION,
|
2121
|
+
graphql.Kind.UNION_TYPE_EXTENSION,
|
2122
|
+
graphql.Kind.ENUM_TYPE_DEFINITION,
|
2123
|
+
graphql.Kind.ENUM_TYPE_EXTENSION,
|
2124
|
+
];
|
2110
2125
|
const rule$d = {
|
2111
2126
|
meta: {
|
2112
2127
|
messages: {
|
@@ -2115,7 +2130,7 @@ const rule$d = {
|
|
2115
2130
|
docs: {
|
2116
2131
|
description: `Requires all types to be reachable at some level by root level fields.`,
|
2117
2132
|
category: 'Schema',
|
2118
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${
|
2133
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
|
2119
2134
|
requiresSchema: true,
|
2120
2135
|
examples: [
|
2121
2136
|
{
|
@@ -2147,43 +2162,36 @@ const rule$d = {
|
|
2147
2162
|
],
|
2148
2163
|
recommended: true,
|
2149
2164
|
},
|
2150
|
-
fixable: 'code',
|
2151
2165
|
type: 'suggestion',
|
2152
2166
|
schema: [],
|
2167
|
+
hasSuggestions: true,
|
2153
2168
|
},
|
2154
2169
|
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
|
-
}
|
2170
|
+
const reachableTypes = requireReachableTypesFromContext(RULE_ID, context);
|
2171
|
+
const selector = KINDS.join(',');
|
2167
2172
|
return {
|
2168
|
-
|
2169
|
-
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
|
2177
|
-
|
2178
|
-
|
2179
|
-
|
2180
|
-
|
2173
|
+
[selector](node) {
|
2174
|
+
const typeName = node.name.value;
|
2175
|
+
if (!reachableTypes.has(typeName)) {
|
2176
|
+
context.report({
|
2177
|
+
loc: getLocation(node.name.loc, typeName, { offsetStart: node.kind === graphql.Kind.DIRECTIVE_DEFINITION ? 2 : 1 }),
|
2178
|
+
messageId: UNREACHABLE_TYPE,
|
2179
|
+
data: { typeName },
|
2180
|
+
suggest: [
|
2181
|
+
{
|
2182
|
+
desc: `Remove ${typeName}`,
|
2183
|
+
fix: fixer => fixer.remove(node),
|
2184
|
+
},
|
2185
|
+
],
|
2186
|
+
});
|
2187
|
+
}
|
2188
|
+
},
|
2181
2189
|
};
|
2182
2190
|
},
|
2183
2191
|
};
|
2184
2192
|
|
2185
2193
|
const UNUSED_FIELD = 'UNUSED_FIELD';
|
2186
|
-
const
|
2194
|
+
const RULE_ID$1 = 'no-unused-fields';
|
2187
2195
|
const rule$e = {
|
2188
2196
|
meta: {
|
2189
2197
|
messages: {
|
@@ -2192,7 +2200,7 @@ const rule$e = {
|
|
2192
2200
|
docs: {
|
2193
2201
|
description: `Requires all fields to be used at some level by siblings operations.`,
|
2194
2202
|
category: 'Schema',
|
2195
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${
|
2203
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID$1}.md`,
|
2196
2204
|
requiresSiblings: true,
|
2197
2205
|
requiresSchema: true,
|
2198
2206
|
examples: [
|
@@ -2239,12 +2247,12 @@ const rule$e = {
|
|
2239
2247
|
},
|
2240
2248
|
],
|
2241
2249
|
},
|
2242
|
-
fixable: 'code',
|
2243
2250
|
type: 'suggestion',
|
2244
2251
|
schema: [],
|
2252
|
+
hasSuggestions: true,
|
2245
2253
|
},
|
2246
2254
|
create(context) {
|
2247
|
-
const usedFields = requireUsedFieldsFromContext(
|
2255
|
+
const usedFields = requireUsedFieldsFromContext(RULE_ID$1, context);
|
2248
2256
|
return {
|
2249
2257
|
FieldDefinition(node) {
|
2250
2258
|
var _a;
|
@@ -2258,22 +2266,18 @@ const rule$e = {
|
|
2258
2266
|
loc: getLocation(node.loc, fieldName),
|
2259
2267
|
messageId: UNUSED_FIELD,
|
2260
2268
|
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
|
-
},
|
2269
|
+
suggest: [
|
2270
|
+
{
|
2271
|
+
desc: `Remove "${fieldName}" field`,
|
2272
|
+
fix(fixer) {
|
2273
|
+
const sourceCode = context.getSourceCode();
|
2274
|
+
const tokenBefore = sourceCode.getTokenBefore(node);
|
2275
|
+
const tokenAfter = sourceCode.getTokenAfter(node);
|
2276
|
+
const isEmptyType = tokenBefore.type === '{' && tokenAfter.type === '}';
|
2277
|
+
return isEmptyType ? fixer.remove(node.parent) : fixer.remove(node);
|
2278
|
+
},
|
2279
|
+
},
|
2280
|
+
],
|
2277
2281
|
});
|
2278
2282
|
},
|
2279
2283
|
};
|
@@ -2636,14 +2640,14 @@ const rule$h = {
|
|
2636
2640
|
},
|
2637
2641
|
};
|
2638
2642
|
|
2639
|
-
const RULE_NAME
|
2643
|
+
const RULE_NAME = 'require-field-of-type-query-in-mutation-result';
|
2640
2644
|
const rule$i = {
|
2641
2645
|
meta: {
|
2642
2646
|
type: 'suggestion',
|
2643
2647
|
docs: {
|
2644
2648
|
category: 'Schema',
|
2645
2649
|
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
|
2650
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME}.md`,
|
2647
2651
|
requiresSchema: true,
|
2648
2652
|
examples: [
|
2649
2653
|
{
|
@@ -2678,7 +2682,7 @@ const rule$i = {
|
|
2678
2682
|
schema: [],
|
2679
2683
|
},
|
2680
2684
|
create(context) {
|
2681
|
-
const schema = requireGraphQLSchemaFromContext(RULE_NAME
|
2685
|
+
const schema = requireGraphQLSchemaFromContext(RULE_NAME, context);
|
2682
2686
|
const mutationType = schema.getMutationType();
|
2683
2687
|
const queryType = schema.getQueryType();
|
2684
2688
|
if (!mutationType || !queryType) {
|
@@ -2852,22 +2856,9 @@ const rule$j = {
|
|
2852
2856
|
recommended: true,
|
2853
2857
|
},
|
2854
2858
|
messages: {
|
2855
|
-
[REQUIRE_ID_WHEN_AVAILABLE]:
|
2856
|
-
`Field {{ fieldName }} must be selected when it's available on a type. Please make sure to include it in your selection set!`,
|
2857
|
-
`If you are using fragments, make sure that all used fragments {{ checkedFragments }}specifies the field {{ fieldName }}.`,
|
2858
|
-
].join('\n'),
|
2859
|
+
[REQUIRE_ID_WHEN_AVAILABLE]: `Field "{{ fieldName }}" must be selected when it's available on a type. Please make sure to include it in your selection set!\nIf you are using fragments, make sure that all used fragments {{ checkedFragments }} specifies the field "{{ fieldName }}".`,
|
2859
2860
|
},
|
2860
2861
|
schema: {
|
2861
|
-
definitions: {
|
2862
|
-
asString: {
|
2863
|
-
type: 'string',
|
2864
|
-
},
|
2865
|
-
asArray: {
|
2866
|
-
type: 'array',
|
2867
|
-
minItems: 1,
|
2868
|
-
uniqueItems: true,
|
2869
|
-
},
|
2870
|
-
},
|
2871
2862
|
type: 'array',
|
2872
2863
|
maxItems: 1,
|
2873
2864
|
items: {
|
@@ -2875,7 +2866,7 @@ const rule$j = {
|
|
2875
2866
|
additionalProperties: false,
|
2876
2867
|
properties: {
|
2877
2868
|
fieldName: {
|
2878
|
-
|
2869
|
+
type: 'string',
|
2879
2870
|
default: DEFAULT_ID_FIELD_NAME,
|
2880
2871
|
},
|
2881
2872
|
},
|
@@ -2883,64 +2874,69 @@ const rule$j = {
|
|
2883
2874
|
},
|
2884
2875
|
},
|
2885
2876
|
create(context) {
|
2886
|
-
requireGraphQLSchemaFromContext('require-id-when-available', context);
|
2887
|
-
const siblings = requireSiblingsOperations('require-id-when-available', context);
|
2888
|
-
const { fieldName = DEFAULT_ID_FIELD_NAME } = context.options[0] || {};
|
2889
|
-
const idNames = Array.isArray(fieldName) ? fieldName : [fieldName];
|
2890
|
-
const isFound = (s) => s.kind === graphql.Kind.FIELD && idNames.includes(s.name.value);
|
2891
2877
|
return {
|
2892
2878
|
SelectionSet(node) {
|
2893
2879
|
var _a, _b;
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
const rawType = getBaseType(typeInfo.gqlType);
|
2899
|
-
const isObjectType = rawType instanceof graphql.GraphQLObjectType;
|
2900
|
-
const isInterfaceType = rawType instanceof graphql.GraphQLInterfaceType;
|
2901
|
-
if (!isObjectType && !isInterfaceType) {
|
2880
|
+
requireGraphQLSchemaFromContext('require-id-when-available', context);
|
2881
|
+
const siblings = requireSiblingsOperations('require-id-when-available', context);
|
2882
|
+
const fieldName = (context.options[0] || {}).fieldName || DEFAULT_ID_FIELD_NAME;
|
2883
|
+
if (!node.selections || node.selections.length === 0) {
|
2902
2884
|
return;
|
2903
2885
|
}
|
2904
|
-
const
|
2905
|
-
|
2906
|
-
|
2907
|
-
|
2908
|
-
|
2909
|
-
|
2910
|
-
|
2911
|
-
|
2912
|
-
|
2913
|
-
|
2914
|
-
|
2915
|
-
|
2916
|
-
|
2917
|
-
|
2918
|
-
|
2919
|
-
|
2920
|
-
|
2921
|
-
|
2922
|
-
|
2886
|
+
const typeInfo = node.typeInfo();
|
2887
|
+
if (typeInfo && typeInfo.gqlType) {
|
2888
|
+
const rawType = getBaseType(typeInfo.gqlType);
|
2889
|
+
if (rawType instanceof graphql.GraphQLObjectType || rawType instanceof graphql.GraphQLInterfaceType) {
|
2890
|
+
const fields = rawType.getFields();
|
2891
|
+
const hasIdFieldInType = !!fields[fieldName];
|
2892
|
+
const checkedFragmentSpreads = new Set();
|
2893
|
+
if (hasIdFieldInType) {
|
2894
|
+
let found = false;
|
2895
|
+
for (const selection of node.selections) {
|
2896
|
+
if (selection.kind === 'Field' && selection.name.value === fieldName) {
|
2897
|
+
found = true;
|
2898
|
+
}
|
2899
|
+
else if (selection.kind === 'InlineFragment') {
|
2900
|
+
found = (((_a = selection.selectionSet) === null || _a === void 0 ? void 0 : _a.selections) || []).some(s => s.kind === 'Field' && s.name.value === fieldName);
|
2901
|
+
}
|
2902
|
+
else if (selection.kind === 'FragmentSpread') {
|
2903
|
+
const foundSpread = siblings.getFragment(selection.name.value);
|
2904
|
+
if (foundSpread[0]) {
|
2905
|
+
checkedFragmentSpreads.add(foundSpread[0].document.name.value);
|
2906
|
+
found = (((_b = foundSpread[0].document.selectionSet) === null || _b === void 0 ? void 0 : _b.selections) || []).some(s => s.kind === 'Field' && s.name.value === fieldName);
|
2907
|
+
}
|
2908
|
+
}
|
2909
|
+
if (found) {
|
2910
|
+
break;
|
2911
|
+
}
|
2912
|
+
}
|
2913
|
+
const { parent } = node;
|
2914
|
+
const hasIdFieldInInterfaceSelectionSet = parent &&
|
2915
|
+
parent.kind === 'InlineFragment' &&
|
2916
|
+
parent.parent &&
|
2917
|
+
parent.parent.kind === 'SelectionSet' &&
|
2918
|
+
parent.parent.selections.some(s => s.kind === 'Field' && s.name.value === fieldName);
|
2919
|
+
if (!found && !hasIdFieldInInterfaceSelectionSet) {
|
2920
|
+
context.report({
|
2921
|
+
loc: {
|
2922
|
+
start: {
|
2923
|
+
line: node.loc.start.line,
|
2924
|
+
column: node.loc.start.column - 1,
|
2925
|
+
},
|
2926
|
+
end: {
|
2927
|
+
line: node.loc.end.line,
|
2928
|
+
column: node.loc.end.column - 1,
|
2929
|
+
},
|
2930
|
+
},
|
2931
|
+
messageId: REQUIRE_ID_WHEN_AVAILABLE,
|
2932
|
+
data: {
|
2933
|
+
checkedFragments: checkedFragmentSpreads.size === 0 ? '' : `(${Array.from(checkedFragmentSpreads).join(', ')})`,
|
2934
|
+
fieldName,
|
2935
|
+
},
|
2936
|
+
});
|
2937
|
+
}
|
2923
2938
|
}
|
2924
2939
|
}
|
2925
|
-
if (found) {
|
2926
|
-
break;
|
2927
|
-
}
|
2928
|
-
}
|
2929
|
-
const { parent } = node;
|
2930
|
-
const hasIdFieldInInterfaceSelectionSet = parent &&
|
2931
|
-
parent.kind === graphql.Kind.INLINE_FRAGMENT &&
|
2932
|
-
parent.parent &&
|
2933
|
-
parent.parent.kind === graphql.Kind.SELECTION_SET &&
|
2934
|
-
parent.parent.selections.some(s => isFound(s));
|
2935
|
-
if (!found && !hasIdFieldInInterfaceSelectionSet) {
|
2936
|
-
context.report({
|
2937
|
-
loc: getLocation(node.loc),
|
2938
|
-
messageId: REQUIRE_ID_WHEN_AVAILABLE,
|
2939
|
-
data: {
|
2940
|
-
checkedFragments: checkedFragmentSpreads.size === 0 ? '' : `(${[...checkedFragmentSpreads].join(', ')}) `,
|
2941
|
-
fieldName: idNames.map(name => `"${name}"`).join(' or '),
|
2942
|
-
},
|
2943
|
-
});
|
2944
2940
|
}
|
2945
2941
|
},
|
2946
2942
|
};
|
@@ -3032,7 +3028,7 @@ const rule$k = {
|
|
3032
3028
|
// eslint-disable-next-line no-console
|
3033
3029
|
console.warn(`Rule "selection-set-depth" works best with siblings operations loaded. For more info: http://bit.ly/graphql-eslint-operations`);
|
3034
3030
|
}
|
3035
|
-
const
|
3031
|
+
const maxDepth = context.options[0].maxDepth;
|
3036
3032
|
const ignore = context.options[0].ignore || [];
|
3037
3033
|
const checkFn = depthLimit(maxDepth, { ignore });
|
3038
3034
|
return {
|
@@ -3229,7 +3225,7 @@ const rule$l = {
|
|
3229
3225
|
},
|
3230
3226
|
};
|
3231
3227
|
|
3232
|
-
const RULE_NAME$
|
3228
|
+
const RULE_NAME$1 = 'unique-fragment-name';
|
3233
3229
|
const UNIQUE_FRAGMENT_NAME = 'UNIQUE_FRAGMENT_NAME';
|
3234
3230
|
const checkNode = (context, node, ruleName, messageId) => {
|
3235
3231
|
const documentName = node.name.value;
|
@@ -3261,7 +3257,7 @@ const rule$m = {
|
|
3261
3257
|
docs: {
|
3262
3258
|
category: 'Operations',
|
3263
3259
|
description: `Enforce unique fragment names across your project.`,
|
3264
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$
|
3260
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$1}.md`,
|
3265
3261
|
requiresSiblings: true,
|
3266
3262
|
examples: [
|
3267
3263
|
{
|
@@ -3306,13 +3302,13 @@ const rule$m = {
|
|
3306
3302
|
create(context) {
|
3307
3303
|
return {
|
3308
3304
|
FragmentDefinition(node) {
|
3309
|
-
checkNode(context, node, RULE_NAME$
|
3305
|
+
checkNode(context, node, RULE_NAME$1, UNIQUE_FRAGMENT_NAME);
|
3310
3306
|
},
|
3311
3307
|
};
|
3312
3308
|
},
|
3313
3309
|
};
|
3314
3310
|
|
3315
|
-
const RULE_NAME$
|
3311
|
+
const RULE_NAME$2 = 'unique-operation-name';
|
3316
3312
|
const UNIQUE_OPERATION_NAME = 'UNIQUE_OPERATION_NAME';
|
3317
3313
|
const rule$n = {
|
3318
3314
|
meta: {
|
@@ -3320,7 +3316,7 @@ const rule$n = {
|
|
3320
3316
|
docs: {
|
3321
3317
|
category: 'Operations',
|
3322
3318
|
description: `Enforce unique operation names across your project.`,
|
3323
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$
|
3319
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$2}.md`,
|
3324
3320
|
requiresSiblings: true,
|
3325
3321
|
examples: [
|
3326
3322
|
{
|
@@ -3369,7 +3365,7 @@ const rule$n = {
|
|
3369
3365
|
create(context) {
|
3370
3366
|
return {
|
3371
3367
|
'OperationDefinition[name!=undefined]'(node) {
|
3372
|
-
checkNode(context, node, RULE_NAME$
|
3368
|
+
checkNode(context, node, RULE_NAME$2, UNIQUE_OPERATION_NAME);
|
3373
3369
|
},
|
3374
3370
|
};
|
3375
3371
|
},
|
package/index.mjs
CHANGED
@@ -2100,7 +2100,22 @@ const rule$c = {
|
|
2100
2100
|
};
|
2101
2101
|
|
2102
2102
|
const UNREACHABLE_TYPE = 'UNREACHABLE_TYPE';
|
2103
|
-
const
|
2103
|
+
const RULE_ID = 'no-unreachable-types';
|
2104
|
+
const KINDS = [
|
2105
|
+
Kind.DIRECTIVE_DEFINITION,
|
2106
|
+
Kind.OBJECT_TYPE_DEFINITION,
|
2107
|
+
Kind.OBJECT_TYPE_EXTENSION,
|
2108
|
+
Kind.INTERFACE_TYPE_DEFINITION,
|
2109
|
+
Kind.INTERFACE_TYPE_EXTENSION,
|
2110
|
+
Kind.SCALAR_TYPE_DEFINITION,
|
2111
|
+
Kind.SCALAR_TYPE_EXTENSION,
|
2112
|
+
Kind.INPUT_OBJECT_TYPE_DEFINITION,
|
2113
|
+
Kind.INPUT_OBJECT_TYPE_EXTENSION,
|
2114
|
+
Kind.UNION_TYPE_DEFINITION,
|
2115
|
+
Kind.UNION_TYPE_EXTENSION,
|
2116
|
+
Kind.ENUM_TYPE_DEFINITION,
|
2117
|
+
Kind.ENUM_TYPE_EXTENSION,
|
2118
|
+
];
|
2104
2119
|
const rule$d = {
|
2105
2120
|
meta: {
|
2106
2121
|
messages: {
|
@@ -2109,7 +2124,7 @@ const rule$d = {
|
|
2109
2124
|
docs: {
|
2110
2125
|
description: `Requires all types to be reachable at some level by root level fields.`,
|
2111
2126
|
category: 'Schema',
|
2112
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${
|
2127
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
|
2113
2128
|
requiresSchema: true,
|
2114
2129
|
examples: [
|
2115
2130
|
{
|
@@ -2141,43 +2156,36 @@ const rule$d = {
|
|
2141
2156
|
],
|
2142
2157
|
recommended: true,
|
2143
2158
|
},
|
2144
|
-
fixable: 'code',
|
2145
2159
|
type: 'suggestion',
|
2146
2160
|
schema: [],
|
2161
|
+
hasSuggestions: true,
|
2147
2162
|
},
|
2148
2163
|
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
|
-
}
|
2164
|
+
const reachableTypes = requireReachableTypesFromContext(RULE_ID, context);
|
2165
|
+
const selector = KINDS.join(',');
|
2161
2166
|
return {
|
2162
|
-
|
2163
|
-
|
2164
|
-
|
2165
|
-
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2169
|
-
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2167
|
+
[selector](node) {
|
2168
|
+
const typeName = node.name.value;
|
2169
|
+
if (!reachableTypes.has(typeName)) {
|
2170
|
+
context.report({
|
2171
|
+
loc: getLocation(node.name.loc, typeName, { offsetStart: node.kind === Kind.DIRECTIVE_DEFINITION ? 2 : 1 }),
|
2172
|
+
messageId: UNREACHABLE_TYPE,
|
2173
|
+
data: { typeName },
|
2174
|
+
suggest: [
|
2175
|
+
{
|
2176
|
+
desc: `Remove ${typeName}`,
|
2177
|
+
fix: fixer => fixer.remove(node),
|
2178
|
+
},
|
2179
|
+
],
|
2180
|
+
});
|
2181
|
+
}
|
2182
|
+
},
|
2175
2183
|
};
|
2176
2184
|
},
|
2177
2185
|
};
|
2178
2186
|
|
2179
2187
|
const UNUSED_FIELD = 'UNUSED_FIELD';
|
2180
|
-
const
|
2188
|
+
const RULE_ID$1 = 'no-unused-fields';
|
2181
2189
|
const rule$e = {
|
2182
2190
|
meta: {
|
2183
2191
|
messages: {
|
@@ -2186,7 +2194,7 @@ const rule$e = {
|
|
2186
2194
|
docs: {
|
2187
2195
|
description: `Requires all fields to be used at some level by siblings operations.`,
|
2188
2196
|
category: 'Schema',
|
2189
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${
|
2197
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID$1}.md`,
|
2190
2198
|
requiresSiblings: true,
|
2191
2199
|
requiresSchema: true,
|
2192
2200
|
examples: [
|
@@ -2233,12 +2241,12 @@ const rule$e = {
|
|
2233
2241
|
},
|
2234
2242
|
],
|
2235
2243
|
},
|
2236
|
-
fixable: 'code',
|
2237
2244
|
type: 'suggestion',
|
2238
2245
|
schema: [],
|
2246
|
+
hasSuggestions: true,
|
2239
2247
|
},
|
2240
2248
|
create(context) {
|
2241
|
-
const usedFields = requireUsedFieldsFromContext(
|
2249
|
+
const usedFields = requireUsedFieldsFromContext(RULE_ID$1, context);
|
2242
2250
|
return {
|
2243
2251
|
FieldDefinition(node) {
|
2244
2252
|
var _a;
|
@@ -2252,22 +2260,18 @@ const rule$e = {
|
|
2252
2260
|
loc: getLocation(node.loc, fieldName),
|
2253
2261
|
messageId: UNUSED_FIELD,
|
2254
2262
|
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
|
-
},
|
2263
|
+
suggest: [
|
2264
|
+
{
|
2265
|
+
desc: `Remove "${fieldName}" field`,
|
2266
|
+
fix(fixer) {
|
2267
|
+
const sourceCode = context.getSourceCode();
|
2268
|
+
const tokenBefore = sourceCode.getTokenBefore(node);
|
2269
|
+
const tokenAfter = sourceCode.getTokenAfter(node);
|
2270
|
+
const isEmptyType = tokenBefore.type === '{' && tokenAfter.type === '}';
|
2271
|
+
return isEmptyType ? fixer.remove(node.parent) : fixer.remove(node);
|
2272
|
+
},
|
2273
|
+
},
|
2274
|
+
],
|
2271
2275
|
});
|
2272
2276
|
},
|
2273
2277
|
};
|
@@ -2630,14 +2634,14 @@ const rule$h = {
|
|
2630
2634
|
},
|
2631
2635
|
};
|
2632
2636
|
|
2633
|
-
const RULE_NAME
|
2637
|
+
const RULE_NAME = 'require-field-of-type-query-in-mutation-result';
|
2634
2638
|
const rule$i = {
|
2635
2639
|
meta: {
|
2636
2640
|
type: 'suggestion',
|
2637
2641
|
docs: {
|
2638
2642
|
category: 'Schema',
|
2639
2643
|
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
|
2644
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME}.md`,
|
2641
2645
|
requiresSchema: true,
|
2642
2646
|
examples: [
|
2643
2647
|
{
|
@@ -2672,7 +2676,7 @@ const rule$i = {
|
|
2672
2676
|
schema: [],
|
2673
2677
|
},
|
2674
2678
|
create(context) {
|
2675
|
-
const schema = requireGraphQLSchemaFromContext(RULE_NAME
|
2679
|
+
const schema = requireGraphQLSchemaFromContext(RULE_NAME, context);
|
2676
2680
|
const mutationType = schema.getMutationType();
|
2677
2681
|
const queryType = schema.getQueryType();
|
2678
2682
|
if (!mutationType || !queryType) {
|
@@ -2846,22 +2850,9 @@ const rule$j = {
|
|
2846
2850
|
recommended: true,
|
2847
2851
|
},
|
2848
2852
|
messages: {
|
2849
|
-
[REQUIRE_ID_WHEN_AVAILABLE]:
|
2850
|
-
`Field {{ fieldName }} must be selected when it's available on a type. Please make sure to include it in your selection set!`,
|
2851
|
-
`If you are using fragments, make sure that all used fragments {{ checkedFragments }}specifies the field {{ fieldName }}.`,
|
2852
|
-
].join('\n'),
|
2853
|
+
[REQUIRE_ID_WHEN_AVAILABLE]: `Field "{{ fieldName }}" must be selected when it's available on a type. Please make sure to include it in your selection set!\nIf you are using fragments, make sure that all used fragments {{ checkedFragments }} specifies the field "{{ fieldName }}".`,
|
2853
2854
|
},
|
2854
2855
|
schema: {
|
2855
|
-
definitions: {
|
2856
|
-
asString: {
|
2857
|
-
type: 'string',
|
2858
|
-
},
|
2859
|
-
asArray: {
|
2860
|
-
type: 'array',
|
2861
|
-
minItems: 1,
|
2862
|
-
uniqueItems: true,
|
2863
|
-
},
|
2864
|
-
},
|
2865
2856
|
type: 'array',
|
2866
2857
|
maxItems: 1,
|
2867
2858
|
items: {
|
@@ -2869,7 +2860,7 @@ const rule$j = {
|
|
2869
2860
|
additionalProperties: false,
|
2870
2861
|
properties: {
|
2871
2862
|
fieldName: {
|
2872
|
-
|
2863
|
+
type: 'string',
|
2873
2864
|
default: DEFAULT_ID_FIELD_NAME,
|
2874
2865
|
},
|
2875
2866
|
},
|
@@ -2877,64 +2868,69 @@ const rule$j = {
|
|
2877
2868
|
},
|
2878
2869
|
},
|
2879
2870
|
create(context) {
|
2880
|
-
requireGraphQLSchemaFromContext('require-id-when-available', context);
|
2881
|
-
const siblings = requireSiblingsOperations('require-id-when-available', context);
|
2882
|
-
const { fieldName = DEFAULT_ID_FIELD_NAME } = context.options[0] || {};
|
2883
|
-
const idNames = Array.isArray(fieldName) ? fieldName : [fieldName];
|
2884
|
-
const isFound = (s) => s.kind === Kind.FIELD && idNames.includes(s.name.value);
|
2885
2871
|
return {
|
2886
2872
|
SelectionSet(node) {
|
2887
2873
|
var _a, _b;
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
const rawType = getBaseType(typeInfo.gqlType);
|
2893
|
-
const isObjectType = rawType instanceof GraphQLObjectType;
|
2894
|
-
const isInterfaceType = rawType instanceof GraphQLInterfaceType;
|
2895
|
-
if (!isObjectType && !isInterfaceType) {
|
2874
|
+
requireGraphQLSchemaFromContext('require-id-when-available', context);
|
2875
|
+
const siblings = requireSiblingsOperations('require-id-when-available', context);
|
2876
|
+
const fieldName = (context.options[0] || {}).fieldName || DEFAULT_ID_FIELD_NAME;
|
2877
|
+
if (!node.selections || node.selections.length === 0) {
|
2896
2878
|
return;
|
2897
2879
|
}
|
2898
|
-
const
|
2899
|
-
|
2900
|
-
|
2901
|
-
|
2902
|
-
|
2903
|
-
|
2904
|
-
|
2905
|
-
|
2906
|
-
|
2907
|
-
|
2908
|
-
|
2909
|
-
|
2910
|
-
|
2911
|
-
|
2912
|
-
|
2913
|
-
|
2914
|
-
|
2915
|
-
|
2916
|
-
|
2880
|
+
const typeInfo = node.typeInfo();
|
2881
|
+
if (typeInfo && typeInfo.gqlType) {
|
2882
|
+
const rawType = getBaseType(typeInfo.gqlType);
|
2883
|
+
if (rawType instanceof GraphQLObjectType || rawType instanceof GraphQLInterfaceType) {
|
2884
|
+
const fields = rawType.getFields();
|
2885
|
+
const hasIdFieldInType = !!fields[fieldName];
|
2886
|
+
const checkedFragmentSpreads = new Set();
|
2887
|
+
if (hasIdFieldInType) {
|
2888
|
+
let found = false;
|
2889
|
+
for (const selection of node.selections) {
|
2890
|
+
if (selection.kind === 'Field' && selection.name.value === fieldName) {
|
2891
|
+
found = true;
|
2892
|
+
}
|
2893
|
+
else if (selection.kind === 'InlineFragment') {
|
2894
|
+
found = (((_a = selection.selectionSet) === null || _a === void 0 ? void 0 : _a.selections) || []).some(s => s.kind === 'Field' && s.name.value === fieldName);
|
2895
|
+
}
|
2896
|
+
else if (selection.kind === 'FragmentSpread') {
|
2897
|
+
const foundSpread = siblings.getFragment(selection.name.value);
|
2898
|
+
if (foundSpread[0]) {
|
2899
|
+
checkedFragmentSpreads.add(foundSpread[0].document.name.value);
|
2900
|
+
found = (((_b = foundSpread[0].document.selectionSet) === null || _b === void 0 ? void 0 : _b.selections) || []).some(s => s.kind === 'Field' && s.name.value === fieldName);
|
2901
|
+
}
|
2902
|
+
}
|
2903
|
+
if (found) {
|
2904
|
+
break;
|
2905
|
+
}
|
2906
|
+
}
|
2907
|
+
const { parent } = node;
|
2908
|
+
const hasIdFieldInInterfaceSelectionSet = parent &&
|
2909
|
+
parent.kind === 'InlineFragment' &&
|
2910
|
+
parent.parent &&
|
2911
|
+
parent.parent.kind === 'SelectionSet' &&
|
2912
|
+
parent.parent.selections.some(s => s.kind === 'Field' && s.name.value === fieldName);
|
2913
|
+
if (!found && !hasIdFieldInInterfaceSelectionSet) {
|
2914
|
+
context.report({
|
2915
|
+
loc: {
|
2916
|
+
start: {
|
2917
|
+
line: node.loc.start.line,
|
2918
|
+
column: node.loc.start.column - 1,
|
2919
|
+
},
|
2920
|
+
end: {
|
2921
|
+
line: node.loc.end.line,
|
2922
|
+
column: node.loc.end.column - 1,
|
2923
|
+
},
|
2924
|
+
},
|
2925
|
+
messageId: REQUIRE_ID_WHEN_AVAILABLE,
|
2926
|
+
data: {
|
2927
|
+
checkedFragments: checkedFragmentSpreads.size === 0 ? '' : `(${Array.from(checkedFragmentSpreads).join(', ')})`,
|
2928
|
+
fieldName,
|
2929
|
+
},
|
2930
|
+
});
|
2931
|
+
}
|
2917
2932
|
}
|
2918
2933
|
}
|
2919
|
-
if (found) {
|
2920
|
-
break;
|
2921
|
-
}
|
2922
|
-
}
|
2923
|
-
const { parent } = node;
|
2924
|
-
const hasIdFieldInInterfaceSelectionSet = parent &&
|
2925
|
-
parent.kind === Kind.INLINE_FRAGMENT &&
|
2926
|
-
parent.parent &&
|
2927
|
-
parent.parent.kind === Kind.SELECTION_SET &&
|
2928
|
-
parent.parent.selections.some(s => isFound(s));
|
2929
|
-
if (!found && !hasIdFieldInInterfaceSelectionSet) {
|
2930
|
-
context.report({
|
2931
|
-
loc: getLocation(node.loc),
|
2932
|
-
messageId: REQUIRE_ID_WHEN_AVAILABLE,
|
2933
|
-
data: {
|
2934
|
-
checkedFragments: checkedFragmentSpreads.size === 0 ? '' : `(${[...checkedFragmentSpreads].join(', ')}) `,
|
2935
|
-
fieldName: idNames.map(name => `"${name}"`).join(' or '),
|
2936
|
-
},
|
2937
|
-
});
|
2938
2934
|
}
|
2939
2935
|
},
|
2940
2936
|
};
|
@@ -3026,7 +3022,7 @@ const rule$k = {
|
|
3026
3022
|
// eslint-disable-next-line no-console
|
3027
3023
|
console.warn(`Rule "selection-set-depth" works best with siblings operations loaded. For more info: http://bit.ly/graphql-eslint-operations`);
|
3028
3024
|
}
|
3029
|
-
const
|
3025
|
+
const maxDepth = context.options[0].maxDepth;
|
3030
3026
|
const ignore = context.options[0].ignore || [];
|
3031
3027
|
const checkFn = depthLimit(maxDepth, { ignore });
|
3032
3028
|
return {
|
@@ -3223,7 +3219,7 @@ const rule$l = {
|
|
3223
3219
|
},
|
3224
3220
|
};
|
3225
3221
|
|
3226
|
-
const RULE_NAME$
|
3222
|
+
const RULE_NAME$1 = 'unique-fragment-name';
|
3227
3223
|
const UNIQUE_FRAGMENT_NAME = 'UNIQUE_FRAGMENT_NAME';
|
3228
3224
|
const checkNode = (context, node, ruleName, messageId) => {
|
3229
3225
|
const documentName = node.name.value;
|
@@ -3255,7 +3251,7 @@ const rule$m = {
|
|
3255
3251
|
docs: {
|
3256
3252
|
category: 'Operations',
|
3257
3253
|
description: `Enforce unique fragment names across your project.`,
|
3258
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$
|
3254
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$1}.md`,
|
3259
3255
|
requiresSiblings: true,
|
3260
3256
|
examples: [
|
3261
3257
|
{
|
@@ -3300,13 +3296,13 @@ const rule$m = {
|
|
3300
3296
|
create(context) {
|
3301
3297
|
return {
|
3302
3298
|
FragmentDefinition(node) {
|
3303
|
-
checkNode(context, node, RULE_NAME$
|
3299
|
+
checkNode(context, node, RULE_NAME$1, UNIQUE_FRAGMENT_NAME);
|
3304
3300
|
},
|
3305
3301
|
};
|
3306
3302
|
},
|
3307
3303
|
};
|
3308
3304
|
|
3309
|
-
const RULE_NAME$
|
3305
|
+
const RULE_NAME$2 = 'unique-operation-name';
|
3310
3306
|
const UNIQUE_OPERATION_NAME = 'UNIQUE_OPERATION_NAME';
|
3311
3307
|
const rule$n = {
|
3312
3308
|
meta: {
|
@@ -3314,7 +3310,7 @@ const rule$n = {
|
|
3314
3310
|
docs: {
|
3315
3311
|
category: 'Operations',
|
3316
3312
|
description: `Enforce unique operation names across your project.`,
|
3317
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$
|
3313
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_NAME$2}.md`,
|
3318
3314
|
requiresSiblings: true,
|
3319
3315
|
examples: [
|
3320
3316
|
{
|
@@ -3363,7 +3359,7 @@ const rule$n = {
|
|
3363
3359
|
create(context) {
|
3364
3360
|
return {
|
3365
3361
|
'OperationDefinition[name!=undefined]'(node) {
|
3366
|
-
checkNode(context, node, RULE_NAME$
|
3362
|
+
checkNode(context, node, RULE_NAME$2, UNIQUE_OPERATION_NAME);
|
3367
3363
|
},
|
3368
3364
|
};
|
3369
3365
|
},
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@graphql-eslint/eslint-plugin",
|
3
|
-
"version": "3.1.0-alpha-
|
3
|
+
"version": "3.1.0-alpha-27dcb49.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"
|