Skip to content

Commit a69f0be

Browse files
author
Dimitri POSTOLOV
authored
[breaking change] 🎉 graphql-eslint v3 (#662)
1 parent f8ae140 commit a69f0be

File tree

129 files changed

+2254
-1479
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+2254
-1479
lines changed

.changeset/chatty-shoes-hunt.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@graphql-eslint/eslint-plugin': major
3+
---
4+
5+
feat: split `recommended` config to two configs `schema-recommended` and `operations-recommended`
6+
7+
`recommended` and `all` configs were divided to 4 configs `schema-recommended`
8+
, `operations-recommended`, `schema-all` and `operations-all`. This was done in order to
9+
use `recommended` and `all` configs in `schema-only` projects where it is not possible to provide operations.

.changeset/polite-pillows-pump.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-eslint/eslint-plugin': major
3+
---
4+
5+
feat: `description-style` now have default description style `block`

.changeset/tame-geese-lick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-eslint/eslint-plugin': major
3+
---
4+
5+
feat: remove `query` option in `no-root-type` as it's impossible to have write-only schema

.changeset/thick-dancers-jump.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
'@graphql-eslint/eslint-plugin': major
3+
---
4+
5+
feat: rename `avoid` prefix in rules to `no`, remove `avoid-operation-name-prefix`
6+
and `no-operation-name-suffix`
7+
8+
All rules that had a `avoid` prefix now have a `no` prefix. Rules `avoid-operation-name-prefix`
9+
and `no-operation-name-suffix` were removed because the same things can be validated
10+
by `naming-convention` rule.
11+
12+
Before
13+
14+
```json
15+
{
16+
"@graphql-eslint/avoid-operation-name-prefix": [
17+
"error",
18+
{
19+
"keywords": ["Query", "Mutation", "Subscription", "Get"]
20+
}
21+
],
22+
"@graphql-eslint/no-operation-name-suffix": "error"
23+
}
24+
```
25+
26+
After
27+
28+
```json
29+
{
30+
"@graphql-eslint/naming-convention": [
31+
"error",
32+
{
33+
"OperationDefinition": {
34+
"style": "PascalCase",
35+
"forbiddenPrefixes": ["Query", "Mutation", "Subscription", "Get"],
36+
"forbiddenSuffixes": ["Query", "Mutation", "Subscription"]
37+
}
38+
}
39+
]
40+
}
41+
```

.changeset/three-shoes-relax.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
'@graphql-eslint/eslint-plugin': major
3+
---
4+
5+
feat: add new options for `naming-convention` rule
6+
7+
Options for `naming-convention` are changed. New option `types` includes the following kinds:
8+
9+
- `ObjectTypeDefinition`
10+
- `InterfaceTypeDefinition`
11+
- `EnumTypeDefinition`
12+
- `ScalarTypeDefinition`
13+
- `InputObjectTypeDefinition`
14+
- `UnionTypeDefinition`
15+
16+
Added new options:
17+
18+
- `Argument`
19+
- `DirectiveDefinition`
20+
- `VariableDefinition`
21+
22+
Option `QueryDefinition` was removed in favor of `AST` specific
23+
selector `FieldDefinition[parent.name.value=Query]`.
24+
25+
Before
26+
27+
```json
28+
{
29+
"@graphql-eslint/naming-convention": [
30+
"error",
31+
{
32+
"ObjectTypeDefinition": "PascalCase",
33+
"InterfaceTypeDefinition": "PascalCase",
34+
"EnumTypeDefinition": "PascalCase",
35+
"ScalarTypeDefinition": "PascalCase",
36+
"InputObjectTypeDefinition": "PascalCase",
37+
"UnionTypeDefinition": "PascalCase",
38+
"FieldDefinition": "camelCase",
39+
"InputValueDefinition": "camelCase",
40+
"QueryDefinition": {
41+
"forbiddenPrefixes": ["get"]
42+
},
43+
"leadingUnderscore": "allow",
44+
"trailingUnderscore": "allow"
45+
}
46+
]
47+
}
48+
```
49+
50+
After
51+
52+
```json
53+
{
54+
"@graphql-eslint/naming-convention": [
55+
"error",
56+
{
57+
"types": "PascalCase",
58+
"FieldDefinition": "camelCase",
59+
"InputValueDefinition": "camelCase",
60+
"FieldDefinition[parent.name.value=Query]": {
61+
"forbiddenPrefixes": ["get"]
62+
},
63+
"allowLeadingUnderscore": true,
64+
"allowTrailingUnderscore": true
65+
}
66+
]
67+
}
68+
```

.changeset/twenty-bottles-care.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
'@graphql-eslint/eslint-plugin': major
3+
---
4+
5+
feat: add new options for `require-description` rule
6+
7+
Options for `require-description` are changed. New option `types` includes the following kinds:
8+
9+
- `ObjectTypeDefinition`
10+
- `InterfaceTypeDefinition`
11+
- `EnumTypeDefinition`
12+
- `ScalarTypeDefinition` (new in v3)
13+
- `InputObjectTypeDefinition`
14+
- `UnionTypeDefinition`
15+
16+
Before
17+
18+
```json
19+
{
20+
"@graphql-eslint/require-description": [
21+
"error",
22+
{
23+
"on": [
24+
"ObjectTypeDefinition",
25+
"InterfaceTypeDefinition",
26+
"EnumTypeDefinition",
27+
"InputObjectTypeDefinition",
28+
"UnionTypeDefinition",
29+
"FieldDefinition",
30+
"InputValueDefinition",
31+
"EnumValueDefinition",
32+
"DirectiveDefinition"
33+
]
34+
}
35+
]
36+
}
37+
```
38+
39+
After
40+
41+
```json
42+
{
43+
"@graphql-eslint/require-description": [
44+
"error",
45+
{
46+
"types": true,
47+
"FieldDefinition": true,
48+
"InputValueDefinition": true,
49+
"EnumValueDefinition": true,
50+
"DirectiveDefinition": true
51+
}
52+
]
53+
}
54+
```

.eslintrc.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ module.exports = {
2525
'@typescript-eslint/ban-types': 'off',
2626
'unicorn/prefer-array-some': 'error',
2727
'unicorn/prefer-includes': 'error',
28+
'unicorn/no-useless-fallback-in-spread': 'error',
29+
'unicorn/better-regex': 'error',
2830
},
2931
overrides: [
3032
{

README.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
This project integrates GraphQL and ESLint, for a better developer experience.
22

3-
<p align="left">
4-
<img height="150" src="./logo.png">
5-
</p>
3+
<img height="150" src="./logo.png">
64

75
[![npm version](https://badge.fury.io/js/%40graphql-eslint%2Feslint-plugin.svg)](https://badge.fury.io/js/%40graphql-eslint%2Feslint-plugin)
86

@@ -182,13 +180,26 @@ You can find a list of [ESLint directives here](https://eslint.org/docs/2.13.1/u
182180

183181
You can find a complete list of [all available rules here](docs/README.md).
184182

183+
## Deprecated Rules
184+
185+
See [docs/deprecated-rules.md](docs/deprecated-rules.md).
186+
185187
## Available Configs
186188

187-
This plugin exports a [`recommended` config](packages/plugin/src/configs/recommended.ts) that enforces good practices and an [`all` config](packages/plugin/src/configs/all.ts) that makes use of all rules (except for deprecated ones).
189+
<!-- prettier-ignore-start -->
190+
|Name|Description|
191+
|:-:|-|
192+
|[`schema-recommended`](packages/plugin/src/configs/schema-recommended.ts)|enables all recommended rules|
193+
|[`operations-recommended`](packages/plugin/src/configs/operations-recommended.ts) |enables all recommended rules|
194+
|[`schema-all`](packages/plugin/src/configs/schema-all.ts)|enables all rules, except for those that require `parserOptions.operations` option)|
195+
|[`operations-all`](packages/plugin/src/configs/operations-all.ts)|enables all rules|
196+
<!-- prettier-ignore-end -->
188197

189-
Enable it in your `.eslintrc` file with the `extends` option.
198+
## Config usage
190199

191-
> These configs under the hood set `parser` as `@graphql-eslint/eslint-plugin` and add `@graphql-eslint` to `plugins` array, so you don't need to specify them.
200+
For example, to enable the `schema-recommended` config, enable it in your `.eslintrc` file with the `extends` option:
201+
202+
> All configs under the hood set `parser` as `@graphql-eslint/eslint-plugin` and add `@graphql-eslint` to `plugins` array, so you don't need to specify them.
192203

193204
```diff
194205
{
@@ -201,7 +212,7 @@ Enable it in your `.eslintrc` file with the `extends` option.
201212
"files": ["*.graphql"],
202213
- "parser": "@graphql-eslint/eslint-plugin",
203214
- "plugins": ["@graphql-eslint"],
204-
+ "extends": "plugin:@graphql-eslint/recommended" // or plugin:@graphql-eslint/all
215+
+ "extends": "plugin:@graphql-eslint/schema-recommended"
205216
}
206217
]
207218
}
@@ -248,7 +259,11 @@ Please help to vote up if you want to speed up the progress.
248259

249260
## Further Reading
250261

251-
If you wish to learn more about this project, how the parser works, how to add custom rules and more, [please refer to the docs directory](docs/README.md).
262+
If you wish to learn more about this project, how the parser works, how to add custom rules and more please refer to the below links:
263+
264+
- [Writing Custom Rules](docs/custom-rules.md)
265+
- [How the parser works?](docs/parser.md)
266+
- [`parserOptions`](docs/parser-options.md)
252267

253268
## Contributions
254269

docs/README.md

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ Each rule has emojis denoting:
1212
Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|Description|🚀&nbsp;/&nbsp;🔮|🔧|✅
1313
-|-|:-:|-|-
1414
[alphabetize](rules/alphabetize.md)|Enforce arrange in alphabetical order for type fields, enum values, input object fields, operation selections and more.|🚀||
15-
[avoid-duplicate-fields](rules/avoid-duplicate-fields.md)|Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.|🚀||
16-
[avoid-operation-name-prefix](rules/avoid-operation-name-prefix.md)|Enforce/avoid operation name prefix, useful if you wish to avoid prefix in your root fields, or avoid using REST terminology in your schema.|🚀||
17-
[avoid-scalar-result-type-on-mutation](rules/avoid-scalar-result-type-on-mutation.md)|Avoid scalar result type on mutation type to make sure to return a valid state.|🚀||
18-
[avoid-typename-prefix](rules/avoid-typename-prefix.md)|Enforces users to avoid using the type name in a field name while defining your schema.|🚀||✅
19-
[description-style](rules/description-style.md)|Require all comments to follow the same style (either block or inline).|🚀||
15+
[description-style](rules/description-style.md)|Require all comments to follow the same style (either block or inline).|🚀||✅
2016
[executable-definitions](rules/executable-definitions.md)|A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.|🔮||✅
2117
[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`.|🔮||✅
2218
[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.|🔮||✅
@@ -31,28 +27,30 @@ Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs
3127
[naming-convention](rules/naming-convention.md)|Require names to follow specified conventions.|🚀||✅
3228
[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.|🚀||✅
3329
[no-case-insensitive-enum-values-duplicates](rules/no-case-insensitive-enum-values-duplicates.md)|Disallow case-insensitive enum values duplicates.|🚀|🔧|✅
34-
[no-deprecated](rules/no-deprecated.md)|Enforce that deprecated fields or enum values are not in use by operations.|🚀||
30+
[no-deprecated](rules/no-deprecated.md)|Enforce that deprecated fields or enum values are not in use by operations.|🚀||✅
31+
[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.|🚀||✅
3532
[no-fragment-cycles](rules/no-fragment-cycles.md)|A GraphQL fragment is only valid when it does not have cycles in fragments usage.|🔮||✅
36-
[no-hashtag-description](rules/no-hashtag-description.md)|Requires to use `"""` or `"` for adding a GraphQL description instead of `#`.|🚀||
37-
[no-operation-name-suffix](rules/no-operation-name-suffix.md)|Makes sure you are not adding the operation type to the name of the operation.|🚀|🔧|✅
38-
[no-root-type](rules/no-root-type.md)|Disallow using root types for `read-only` or `write-only` schemas.|🚀||
33+
[no-hashtag-description](rules/no-hashtag-description.md)|Requires to use `"""` or `"` for adding a GraphQL description instead of `#`.|🚀||✅
34+
[no-root-type](rules/no-root-type.md)|Disallow using root types `mutation` and/or `subscription`.|🚀||
35+
[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.|🚀||
36+
[no-typename-prefix](rules/no-typename-prefix.md)|Enforces users to avoid using the type name in a field name while defining your schema.|🚀||✅
3937
[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.|🔮||✅
40-
[no-unreachable-types](rules/no-unreachable-types.md)|Requires all types to be reachable at some level by root level fields.|🚀|🔧|
38+
[no-unreachable-types](rules/no-unreachable-types.md)|Requires all types to be reachable at some level by root level fields.|🚀|🔧|
4139
[no-unused-fields](rules/no-unused-fields.md)|Requires all fields to be used at some level by siblings operations.|🚀|🔧|
4240
[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.|🔮||✅
4341
[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.|🔮||✅
4442
[one-field-subscriptions](rules/one-field-subscriptions.md)|A GraphQL subscription is valid only if it contains a single root field.|🔮||✅
4543
[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.|🔮||✅
4644
[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.|🔮||✅
47-
[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+
[possible-type-extension](rules/possible-type-extension.md)|A type extension is only valid if the type is defined and has the same kind.|🔮||
4846
[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.|🔮||✅
4947
[require-deprecation-date](rules/require-deprecation-date.md)|Require deletion date on `@deprecated` directive. Suggest removing deprecated things after deprecated date.|🚀||
5048
[require-deprecation-reason](rules/require-deprecation-reason.md)|Require all deprecation directives to specify a reason.|🚀||✅
51-
[require-description](rules/require-description.md)|Enforce descriptions in your type definitions.|🚀||
49+
[require-description](rules/require-description.md)|Enforce descriptions in your type definitions.|🚀||
5250
[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.|🚀||
53-
[require-id-when-available](rules/require-id-when-available.md)|Enforce selecting specific fields when they are available on the GraphQL type.|🚀||
51+
[require-id-when-available](rules/require-id-when-available.md)|Enforce selecting specific fields when they are available on the GraphQL type.|🚀||
5452
[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.|🔮||✅
55-
[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).|🚀||
53+
[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).|🚀||
5654
[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.|🚀||✅
5755
[unique-argument-names](rules/unique-argument-names.md)|A GraphQL field or directive is only valid if all supplied arguments are uniquely named.|🔮||✅
5856
[unique-directive-names](rules/unique-directive-names.md)|A GraphQL document is only valid if all defined directives have unique names.|🔮||✅
@@ -69,9 +67,3 @@ Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs
6967
[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).|🔮||✅
7068
[variables-in-allowed-position](rules/variables-in-allowed-position.md)|Variables passed to field arguments conform to type.|🔮||✅
7169
<!-- prettier-ignore-end -->
72-
73-
## Further Reading
74-
75-
- [Writing Custom Rules](custom-rules.md)
76-
- [How the parser works?](parser.md)
77-
- [`parserOptions`](parser-options.md)

docs/deprecated-rules.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Deprecated Rules
2+
3+
## avoid-duplicate-fields
4+
5+
This rule was renamed to [`no-duplicate-fields`](rules/no-duplicate-fields.md).
6+
7+
## avoid-scalar-result-type-on-mutation
8+
9+
This rule was renamed to [`no-scalar-result-type-on-mutation`](rules/no-scalar-result-type-on-mutation.md).
10+
11+
## avoid-typename-prefix
12+
13+
This rule was renamed to [`no-typename-prefix`](rules/no-typename-prefix.md).
14+
15+
## avoid-operation-name-prefix
16+
17+
This rule was removed because the same things can be validated using [`naming-convention`](rules/naming-convention.md).
18+
19+
## no-operation-name-suffix
20+
21+
This rule was removed because the same things can be validated using [`naming-convention`](rules/naming-convention.md).

0 commit comments

Comments
 (0)